-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
After upgrade to Rails 7.1, translations that end in a colon return a Hash, not a String #147
Comments
Since a brand new app with the gem works fine, then it looks like there is some extra processing happening on top of the original method in your application. Also, what happens if you call def my_action
raise t(:project_customer_name)
end and check the console |
@timfjord - Using I'm not getting anything using that example method in a controller:
I've found as I've kept digging on this that it appears any translated value that contains an asterisk (*) will bomb out too, which is an issue for me, since I'm translating a lot of Markdown. Here's an example inside of <td><%= t(translation.key) %></td> If the translation value contains an asterisk, I'll get:
|
And where is this error coming from? Is there a stack trace, as it might hint what tool processes the translation |
I'm not getting much of a stack trace, actually. It just takes me to the line in
Maybe Psych is a clue here? You'll notice I'm using slim, but I've tried in ERB with the same results. |
From quick googling this Alternatively, you could use your plain Rails 7.1 app with the Since you have this issue when you use def my_action
raise I18n.method(:translate).source_location.inspect
end |
Ok, good advice. I'll try adding gems to the new app, but at this point, I think it has more gems than my old one. Will report back - Thank you for your help. |
Well, I have stripped my app down to the bone. My Gemfile: source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.2.2"
gem "i18n-active_record", require: "i18n/active_record"
gem "jsbundling-rails"
gem "mysql2"
gem "puma" # , '~> 3.7'
gem "rails", "7.1.3" I've also gone through and commented out every single initializer. And blanked out the I also reinstalled Ruby 3.2.2, removed and regenerated the And...it is still showing that hash instead of text when it's pulling the translation out of ActiveRecord. Any ideas on what I could try next? |
Actually, I pasted/copied Gemfile from the working new app to the old one, ran |
Adding
Reverting back to Rails 7.0, I get the same RuntimeError, referencing the same line. |
Another possible clue. It seems Rails 7.1 might be storing translation values a little differently? Notice how the
|
So, the method hasn't been overridden. That's good.
Ok, and what happens if you use this Gemfile with the plain app you mentioned earlier(the one that worked properly)? |
If I use that gemfile with the plain app, it still translates everything properly. |
Well, then it is clear that it is not gems that causing this issue. And how do you initialize the Regarding this one
This output is very unusual, because the value of the Translation.find(117998).update(value: "Customer's Company Name:") |
If I save directly in the console per your example, it seems to work fine. But for many records, the Regarding the initializing of i18n-active_record, I have the standard initializer from this project's readme, plus the following in my config.i18n.default_locale = :en
config.i18n.fallbacks = [:en] |
Ok, I think we're getting closer. I have a In Rails 7, if I run the following in my browser-based debugger, you can see this class recognized: >> Translation
=> Translation(id: integer, locale: string, key: string, value: text, interpolations: text, is_proc: boolean, created_at: datetime, updated_at: datetime) But if I do the same thing in 7.1, I wind up with something different: >> Translation
=> I18n::Backend::ActiveRecord::Translation(id: integer, locale: string, key: string, value: text, interpolations: text, is_proc: boolean, created_at: datetime, updated_at: datetime) This has not been an issue so far in my years of using this gem, but I'm wonder if it's now required for me to setup a custom translation model as described in the readme? If so, where do I put the following block (from the readme)? I18n::Backend::ActiveRecord.configure do |config|
config.translation_model = MyTranslation
end I tried in an initializer, the In any case, using a custom model still gives a
Here's the same results from Rails 7.0.8:
|
First of all, It looks like there are issues with auto-loading models from initialisers, but this is not the case here. I would do the following. module MyApp
class Application < Rails::Application
# ...
config.to_prepare do
I18n::Backend::ActiveRecord.configure do |config|
config.translation_model = Translation
end
end
end
end The idea here is to make the value of the |
Thanks, @timfjord - I'll give that a shot and see what I come up with. In the meantime, here's some more of what I've found. After doing a mysqlimport from my production database translations table:
This cannot be updated via Rails console, I get the
Now, because the
You can see the way the value is presented has changed. Not sure why - using same version of MySQL in dev and production. But from this point forward, everything with this record will work as expected before the upgrade to Rails 7.1. |
@timfjord - I have a Rails 7.1 test app that throws the errors I'm seeing at https://github.com/floydj/translated. You can see in that project that when seeding the database, or running integration tests, I'm using direct mysql statements to create the translations and then trying to use them. If I use ActiveRecord to create the translations, it works as it should. But the app is more setup to replicate what I'm dealing with, which is existing translations from a Rails 7 app. |
Thanks for sharing the app, it was very useful. So the good thing is that I've figured out what the problem was and sent a PR to your test app with a fix - floydj/translated#1 Basically, the problem here was that you were trying to insert values as they are, but, apparently, they weren't compatible with Rails 7.1 In terms of how to deal with this. If you really need to insert the values directly, you should probably just adapt them so they are compatible with the I am closing the issue for now, as I don't think there is something we could do with gem itself to prevent this. |
Awesome. Glad you found the point where it gave trouble with Rails 7.1. But it doesn't solve my issue. That example app I shared is not how I normally add translations, it was just to illustrate the error I saw. I normally add the translations using standard Active Record methods, not direct SQL statements. I still have a table full of translations that throw Psych errors, since they were inserted using previous versions of Rails. Is there no way to "upgrade" them without going through all of them manually? |
You could write a small script that processes all items and wraps them in |
Another option to discover could be changing the default coder. serialize :value, coder: ActiveRecord::Coders::YAMLColumn If that doesn't work, you could try to override this directly in the gem just to see if it is working or nor. |
Ok, thanks for possible solutions. My vote would be for some kind of note in the README, I can't be the only one that'll run into this use case. |
In case it helps someone else, here are a few bits that helped me convert things over to be compatible with Rails 7.1. Using MySQL here. # find Psych problems
Translation.all.each do |trans|
trans.value
rescue Psych::SyntaxError
puts "Serialization problem with #{trans.id} - #{trans.key}"
end
# convert everything over to newer serialization format
Translation.all.each do |translation|
sql = %{update translations set value = CONCAT('--- "', value, '"\n') where id = #{translation.id}}
ActiveRecord::Base.connection.execute(sql)
end After doing that, there will still be some odds and ends to look at. I had some HTML translations with links that I had to manually fix in the MySQL client:
|
You could have also used Translation.all.each do |translation|
sql = %{update translations set value = '#{YAML.dump(translation.value_before_type_cast)}' where id = #{translation.id}}
ActiveRecord::Base.connection.execute(sql)
end But in general, yeah, this is the right way to go. I will mention this issue in the README |
I'm trying to upgrade a Rails 7 app to 7.1, but running into issues with I18n translations.
Given the following translation:
And trying to use that in my view:
I'll always get a hash in the resulting HTML, rather than the String I expect:
{"Customer's Company Name"=>nil}
Translation occurs properly in any of the following conditions:
en.yml
file AND removing it from the translations tablei18n.-active_record
(not a long-term option for this project, but tried it for testing)About the app:
I have tried creating a brand-new Rails 7.1 app with i18n-active_record and...the translation works fine, even with the colon at the end of a value. So it seems there is something in my app causing this, but I'm stuck, unsure of how or what to debug further.
Any idea what's going on or how I can troubleshoot further? Appreciate the help!
The text was updated successfully, but these errors were encountered: