Admin -> Customize -> Text behaving badly

Getting a load of similar issues to this when attempting to filter on my chatbot prompts.

The really strange part is that behaviour can be fine on one install but not another.

Take the very simple filter of chatbot.prompt on Admin → Customize → Text:

Working install:

Failing install:

NoMethodError (undefined method `scan' for {:basic=>"You are a helpful assistant.", :agent=>"You are a helpful assistant.  You have great tools in the form of functions that give you the power to get newer information. Only use the functions you have been provided with.  The current date and time is %{current_date_time}.  Only respond to the last question, using the prior information as context, if appropriate."}:Hash)
lib/i18n/i18n_interpolation_keys_finder.rb:6:in `find'
app/controllers/admin/site_texts_controller.rb:183:in `record_for'
app/controllers/admin/site_texts_controller.rb:249:in `block in find_translations'
app/controllers/admin/site_texts_controller.rb:234:in `each'
app/controllers/admin/site_texts_controller.rb:234:in `find_translations'
app/controllers/admin/site_texts_controller.rb:34:in `index'
app/controllers/application_controller.rb:422:in `block in with_resolved_locale'
app/controllers/application_controller.rb:422:in `with_resolved_locale'
lib/middleware/omniauth_bypass_middleware.rb:64:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/anonymous_cache.rb:389:in `call'
lib/middleware/gtm_script_nonce_injector.rb:10:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
lib/middleware/enforce_hostname.rb:24:in `call'
lib/middleware/request_tracker.rb:233:in `call'

The locale file in question is this one:

Am I doing anything illegal?

2 Likes

ok

looks like the method in question is expecting text:

but somehow receiving a Hash:

irb(main):001:0> item = {:basic=>"You are a helpful assistant.", :agent=>"You are a helpful assistant.  You have great tools in the form of functions that give you the power to get newer information. Only use the functions you have been provided with.  The current date and time is %{current_date_time}.  Only respond to the last question, using the prior information as context, if appropriate."}
=>
{:basic=>"You are a helpful assistant.",
...
irb(main):002:0> item
=>
{:basic=>"You are a helpful assistant.",
 :agent=>
  "You are a helpful assistant.  You have great tools in the form of functions that give you the power to get newer information. Only use the functions you have been provided with.  The current date and time is %{current_date_time}.  Only respond to the last question, using the prior information as context, if appropriate."}
irb(main):003:0> item.scan
(irb):3:in `<main>': undefined method `scan' for {:basic=>"You are a helpful assistant.", :agent=>"You are a helpful assistant.  You have great tools in the form of functions that give you the power to get newer information. Only use the functions you have been provided with.  The current date and time is %{current_date_time}.  Only respond to the last question, using the prior information as context, if appropriate."}:Hash (NoMethodError)
        from /home/robert/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /home/robert/.rbenv/versions/3.2.1/bin/irb:25:in `load'
        from /home/robert/.rbenv/versions/3.2.1/bin/irb:25:in `<main>'
irb(main):004:0>

Causing it to fall over … I will continue investigation

It’s being called from here, I believe:

I can repro the issue with:

I18nInterpolationKeysFinder.find(I18n.overrides_disabled { I18n.t("chatbot.prompt.system.", locale: :en) })
from the rails console.

I think this line is supposed to prevent the method receiving a Hash, but it’s not working, why?:

1 Like

Moving this to bug, because I think this behaviour is incorrect and for some reason unreliable.

According to the code, if the value is a Hash, it should not be sent to the record_for method (where it would cause an exception as that is expecting text), but in some instances, it is.

Happy to stand corrected.

1 Like

This happens when there’s a translation override for a key that previously was a translatable string, but was converted into a Hash at a later time. That’s exactly what happened with chatbot.prompt.system.

This seems like a regression. I’m pretty sure this used to work in the past.

I can easily reproduce this with a locale file like this:

en:
  foo: "this is foo"

Go to Customize → Text and override “foo” with a different value.

Then, change the locale file to look like this:

en:
  foo:
    basic: "Basic Foo"
    advanced: "Advanced Foo"

Visit Customize → Text again and search for “foo”. Discourse will log the following error.

NoMethodError (undefined method `scan' for {:basic=>"Basic Foo", :advanced=>"Advanced Foo"}:Hash)
lib/i18n/i18n_interpolation_keys_finder.rb:6:in `find'
app/controllers/admin/site_texts_controller.rb:183:in `record_for'
app/controllers/admin/site_texts_controller.rb:249:in `block in find_translations'
app/controllers/admin/site_texts_controller.rb:234:in `each'
app/controllers/admin/site_texts_controller.rb:234:in `find_translations'
app/controllers/admin/site_texts_controller.rb:34:in `index'

Discourse shouldn’t load translation overrides if there’s no corresponding English string.

3 Likes

Thanks @gerhard

That’s exactly what happened: I added another final key in the same bucket.

… And it doesn’t affect new installs.

Is there any kind of rails console workaround?

1 Like
TranslationOverride.where(translation_key: "chatbot.prompt.system").delete_all
TranslationOverride.send(:reload_locale!)
3 Likes

Peeerrrfect. Yes I was going to try that but not at :computer:

Guess I could add that to a migration?!

2 Likes