Rails 4: I18n::InvalidLocaleData - ruby-on-rails

I installed the Kaminari gem and followed the instructions. I customized my theme to the foundations but when trying to further customize the pagination style using the en.yml file, I run into this error:
I18n::InvalidLocaleData in Campaigns#index
can not load translations from /myapp/config/locales/en.yml: #<Psych::SyntaxError: (/myapp/config/locales/en.yml): did not find expected key while parsing a block mapping at line 23 column 3>
Extracted source (around line #2):
1 <li>
2 <%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote %>
3 </li>
I simply copied and pasted what was in the docs..
en:
hello: "Hello world"
pagination:
first: "« First"
last: "Last »"
previous: "‹ Prev"
next: "Next ›"
truncate: "…"
If I delete everything other than pagination: line, the error still remains. I'm not super familiar with the locale file in Rails as well as YAML files so any help is highly appreciated.

According to the results from YAML Lint, it appears that the hello: "Hello world" line is invalid.
Also, it looks like the views.pagination.first line in your code is looking for a path like: views -> pagination -> first in your YAML file (and because this pattern can't be found, there's another error).
Therefore, it might be better to use this kind of YAML example:
en:
views:
pagination:
first: "« First"
last: "Last »"
previous: "‹ Prev"
next: "Next ›"
truncate: "…"

Related

Rails 6 internationalization - what has changed?

I started a fresh new Rails 6 project and got stuck to figure out why what obviously just worked (it's not the first app I start), fails...
So I created a dummy simply rails app with no additional gems and a home#index page:
<h1>Home#index</h1>
<p>
<%= t('hello.world') %>
</p>
Then I added a translation for the above key to config/locales/en.yml:
en:
hello: "Hello !"
world: "Hello World!"
and respected 1 tab indentation.
When navigating to localhost:3000/home/index I got the weird error:
/Users/serguei/.rvm/gems/ruby-2.7.0/gems/i18n-1.8.2/lib/i18n.rb:195: warning: The called method `translate' is defined here
Rendered home/index.html.erb within layouts/application (Duration: 6.2ms | Allocations: 3150)
Completed 500 Internal Server Error in 16ms (ActiveRecord: 0.0ms | Allocations: 5045)
ActionView::Template::Error (can not load translations from /Users/serguei/projects/rails/draft-app/config/locales/en.yml: #<Psych::SyntaxError: (<unknown>): did not find expected key while parsing a block mapping at line 2 column 3>):
1: <h1>Home#index</h1>
2: <p>
3: <%= t('hello.world') %>
4: </p>
app/views/home/index.html.erb:3
When changed the called translation to just hello:
<h1>Home#index</h1>
<p>
<%= t('hello') %>
</p>
and removing the last line from the en.yml file:
en:
hello: "Hello !"
it works.
Why so? What has changed since Rails 5 there? Can't we use nested translations anymore in locales files? Rails guides have nothing special about that. Or am I missing something?
Adding rails-i18n gem to the Gemfile didn't solve the problem.
Rails version: 6.0.2.1
Ruby version: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]
If you want to nest it, then you can't assign a string value to the parent, do this instead
en:
hello:
world: "Hello World!"
Then, in erb, this will work
<%= t('hello.world') %>
Give it a try.

Strange error while translating the word "admin" in Rails

Observe the following console output:
$ grep -IirF admin config/locales/
config/locales/static.el.yml: Administered: Χορηγήθηκε
config/locales/el.yml: admin: διαχειριστής
config/locales/system.el.yml: administered: Χορηγήθηκε
$ rails c
Running via Spring preloader in process 8176
Loading development environment (Rails 6.0.2.1)
irb(main):001:0> helper.t('admin1', locale: :el)
=> "admin1"
irb(main):002:0> helper.t('admin', locale: :el)
=> "διαχειριστής"
irb(main):003:0> helper.t('admin1', locale: :en)
=> "admin1"
irb(main):004:0> helper.t('admin', locale: :en)
=> {:js=>{true=>true, false=>false, :is_present=>"Is present", :is_blank=>"Is blank", :date=>"Date ...", :between_and_=>"Between ... and ...", :today=>"Today", :yesterday=>"Yesterday", :this_week=>"This week", :last_week=>"Last week", :number=>"Number ...", :contains=>"Contains", :is_exactly=>"Is exactly", :starts_with=>"Starts with", :ends_with=>"Ends with", :too_many_objects=>"Too many objects, use search box above", :no_objects=>"No objects found"}, :loading=>"Loading...", :toggle_navigation=>"Toggle navigation", :home=>{:name=>"Home"}, :pagination=>{:previous=>"« Prev", :next=>"Next »", :truncate=>"…"}, :misc=>{:search=>"Search", :filter=>"Filter", :refresh=>"Refresh", :show_all=>"Show all", :add_filter=>"Add filter", :bulk_menu_title=>"Selected items", :remove=>"Remove", :add_new=>"Add new", :chosen=>"Chosen %{name}", :chose_all=>"Choose all", :clear_all=>"Clear all", :up=>"Up", :down=>"Down", :navigation=>"Navigation", :root_navigation=>"Actions", :navigation_static_label=>"Links", :log_out=>"Log out", :time_ago=>"%{time} ago", :ago=>"ago", :more=>"Plus %{count} more %{models_name}"}, :flash=>{:successful=>"%{name} successfully %{action}", :error=>"%{name} failed to be %{action}", :noaction=>"No actions were taken", :model_not_found=>"Model '%{model}' could not be found", :object_not_found=>"%{model} with id '%{id}' could not be found"}, :table_headers=>{:model_name=>"Model name", :last_created=>"Last created", :records=>"Records", :username=>"User", :changes=>"Changes", :created_at=>"Date/Time", :item=>"Item", :message=>"Message"}, :actions=>{:dashboard=>{:title=>"Site Administration", :menu=>"Dashboard", :breadcrumb=>"Dashboard"}, :index=>{:title=>"List of %{model_label_plural}", :menu=>"List", :breadcrumb=>"%{model_label_plural}"}, :show=>{:title=>"Details for %{model_label} '%{object_label}'", :menu=>"Show", :breadcrumb=>"%{object_label}"}, :show_in_app=>{:menu=>"Show in app"}, :new=>{:title=>"New %{model_label}", :menu=>"Add new", :breadcrumb=>"New", :link=>"Add a new %{model_label}", :done=>"created"}, :edit=>{:title=>"Edit %{model_label} '%{object_label}'", :menu=>"Edit", :breadcrumb=>"Edit", :link=>"Edit this %{model_label}", :done=>"updated"}, :delete=>{:title=>"Delete %{model_label} '%{object_label}'", :menu=>"Delete", :breadcrumb=>"Delete", :link=>"Delete '%{object_label}'", :done=>"deleted"}, :bulk_delete=>{:title=>"Delete %{model_label_plural}", :menu=>"Multiple delete", :breadcrumb=>"Multiple delete", :bulk_link=>"Delete selected %{model_label_plural}"}, :export=>{:title=>"Export %{model_label_plural}", :menu=>"Export", :breadcrumb=>"Export", :link=>"Export found %{model_label_plural}", :bulk_link=>"Export selected %{model_label_plural}", :done=>"exported"}, :history_index=>{:title=>"History for %{model_label_plural}", :menu=>"History", :breadcrumb=>"History"}, :history_show=>{:title=>"History for %{model_label} '%{object_label}'", :menu=>"History", :breadcrumb=>"History"}}, :form=>{:cancel=>"Cancel", :basic_info=>"Basic info", :required=>"Required", :optional=>"Optional", :one_char=>"character", :char_length_up_to=>"length up to", :char_length_of=>"length of", :save=>"Save", :save_and_add_another=>"Save and add another", :save_and_edit=>"Save and edit", :all_of_the_following_related_items_will_be_deleted=>"? The following related items may be deleted or orphaned:", :are_you_sure_you_want_to_delete_the_object=>"Are you sure you want to delete this %{model_name}", :confirmation=>"Yes, I'm sure", :bulk_delete=>"The following objects will be deleted, which may delete or orphan some of their related dependencies:", :new_model=>"%{name} (new)"}, :export=>{:confirmation=>"Export to %{name}", :select=>"Select fields to export", :select_all_fields=>"Select All Fields", :fields_from=>"Fields from %{name}", :fields_from_associated=>"Fields from associated %{name}", :display=>"Display %{name}: %{type}", :options_for=>"Options for %{name}", :empty_value_for_associated_objects=>"<empty>", :click_to_reverse_selection=>"Click to reverse selection", :csv=>{:header_for_root_methods=>"%{name}", :header_for_association_methods=>"%{name} [%{association}]", :encoding_to=>"Encode to", :encoding_to_help=>"Choose output encoding. Leave empty to let current input encoding untouched: (%{name})", :skip_header=>"No header", :skip_header_help=>"Do not output a header (no fields description)", :default_col_sep=>",", :col_sep=>"Column separator", :col_sep_help=>"Leave blank for default ('%{value}')"}}, :history_rollback=>{:cancel=>"Cancel", :confirm=>"Are you sure?", :table_headers=>{:changes=>"Changes", :field=>"Field", :rollback=>"Rollback", :view_changes=>"View changes"}, :rollback_destroy=>"Rolled back newly-created record by destroying it.", :rollback_success=>"Rolled back changes to this record.", :rollback_impossible=>"Couldn't rollback. Sorry.", :version_not_found=>"Version does not exist.", :rollback_violates_foreign_key=>"Couldn't rollback: this model links to another model, which doesn't exists."}}
Translation seems to work correctly, except for a single word: 'admin'
Can someone explain this error, and how to overcome it?
This most likely has to do with a conflict with some other gem that adds an admin namespace, like maybe ActiveAdmin or rails_admin, or maybe a role authorization plugin. That's why it's returning a hash instead of a single string value.
Some other code or gem has loaded the admin key to look something like this:
en:
admin:
js:
'true': true
'false': false
is_present: Is present
....etc....
I would suggest nesting your key to avoid the conflict with something like:
en:
user_type:
admin: Administrator
helper.t('user_type.admin')
I would also suggest setting up the i18n-tasks gem, which can find and correct issues with translation files, as part of your CI or test suite, which I believe would have detected this conflict with the command i18n-tasks health and shown that admin is a dupilcate key, so when your yaml files and the gem's get combined, only the last one to write to the translations hash will be preserved.

Why don't my locale settings in number_to_currency work?

Per the Rails 3.2 API Docs, to use different locales for number_to_currency, I need to do the following:
<%= number_to_currency(1234567890.506, :locale => :fr) %>
I was expecting the following output:
# => 1 234 567 890,51 €
Even though I literally use that exact thing within my app and it keeps outputting the following:
$1,234,567,890.51
When I check for the available_locales within my app I get the following:
> I18n.available_locales
=> [:en, :de, :es, :fr, :ja, :pl, :"pt-BR", :ru, :sv, :"zh-CN"]
So it SHOULD work, but it doesn't.
What am I missing?
Update 1
Per #s3tjan's comment, I did some digging in that linked Rails issue and that led me to my application.rb where I discovered I18n.enforce_available_locales = false. I changed that to true and restarted the server.
When I tried the above again, I am now getting this error:
ActionView::Template::Error (:fr is not a valid locale):
Not sure how to fix this.
Update 2
So I just realize that I never had a locale file in my config/locales. What I really want is to use the GBP Pounds for currency, so I added an en-GB.yml file in my config/locales, then I restarted my server and console.
In my application.rb, I have the following:
I18n.enforce_available_locales = true
Then I checked my console and got this:
[1] pry(main)> I18n.available_locales
=> [:en, :de, :es, :fr, :ja, :pl, :"pt-BR", :ru, :sv, :"zh-CN", :"en-GB"]
[2] pry(main)>
So the :"en-GB" was added successfully to my app's load path.
But when I do this in my view:
<%= number_to_currency(1234567890.506, :locale => :"en-GB") %>
This is the error I get:
:"en-GB" is not a valid locale excluded from capture due to environment or should_capture callback
ActionView::Template::Error (:"en-GB" is not a valid locale):
So still not working.
Update 3
My en-GB.yml file was taken directly from https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en-GB.yml
So it looks exactly like that. Yet I am still getting the same error:
ActionView::Template::Error (:"en-GB" is not a valid locale):
Synopsis:
Remove custom language ymls and add the correct version of the i18n-rails gem. This resolved this special issue.
Original answer:
Ok my guess is that your en-GB.yml is empty. So it actually finds the file and adds the locale in I18n.available_locales BUT this does not include that all translations are available.
When you look at the format of such a yml file you will recognize they all start with
---
language-code
some_keys: ...
This is what actually is loaded into memory and therefore provides all the available translations. Available locale is just defined by found files in config/locales.
When you check the source of number_to_currency It takes the locale from the options and passes it along the key it looks for to I18n.
I18n.translate(:'number.format', :locale => options[:locale], :default => {})
Since you just say that en-GB is available but don't have the actual keys along the locale in memory you get the missing translation issue.
What I suggest is you either use the content of the linked yml file and paste it into your en-GB.yml or you remove your en-GB.yml and find a 3.2 working i18n-rails version and use it. i18n-rails provides plenty of default translations which are utilized all over default rails.
Addition:
Before you added the en-GB.yml file it actually worked like expected.
When no locale is found it defaults to dollar in here since the currency variable will be just and empty {}.
Somehow, I found the solution that worked for me.
First of all, you need to have a locale file with your requirements in it.
Here is the example of fr.yml file
For an instance, copy and paste this file in app/config/locales/
then restart your console,
then try, number_to_currency(1000.51, locale: :fr)
for sure, you will get '1 000,51 €'
Here is the full list of all supported countries' locale file.
Until and unless you don't have locale file with your format required in it, you won't get the desired result.
my rails version is 3.2.22.5, ruby is 2.4.2(I didnt install below 2.x.x)
I use locale yml from
https://github.com/svenfuchs/rails-i18n/blob/rails-3-x/rails/locale/en-GB.yml
This is work well
<%= number_to_currency(1234567890.506, :locale => :"en-GB") %>
<%= number_to_currency(1234567890.506, :locale => "en-GB") %>
to result
£1,234,567,890.51
and I add fr.yml too like
fr:
...
number:
currency:
format:
...
unit: €
And then this is work too
<%= number_to_currency(1234567890.506, :locale => :fr) %>
to result
€1,234,567,890.51
I didn't change or add configuration. I add only controller, view and locale file. And test it.
You could translate directly like, so test this
I18n.translate(:'number.currency.format', :locale => "en-GB", :default => {})
if it occur a same error, then check out you file's name, extension, path.
and you must restart server

Translation of "will_paginate" doesn't work. What am I doing wrong?

The basic scheme:
= will_paginate #products, :previous_label => t("previous_label"), :next_label => t("next_label")
de.yml
will_paginate:
page_gap: "…"
previous_label: "word for back"
next_label: "word for next"
en.yml
en:
will_paginate:
page_gap: "…"
previous_label: "previous"
next_label: "next"
But in the output are still the labels called Previous Label and Next Label.
What is still wrong? Also, I thought I didn't restart the server... but after restart still the same labels, not my translations
You can grab YAML files translated in various languages for will_paginate here : https://github.com/tigrish/will-paginate-i18n.
In your example, you're overriding the :previous_label and the :next_label, but you're not scoping it to 'will_paginate'.
Either remove the overrides completely and customise the labels in your translation file :
will_paginate #products
or scope the .t calls correctly :
will_paginate #products,
:previous_label => t("will_paginate.previous_label"),
:next_label => t("will_paginate.next_label")
you can then change the text of the pagination links by adding the following to config/locales/will_paginate.en.yml:
en:
will_paginate:
page_gap: "…"
previous_label: "previous"
next_label: "next"
And add following in application.rb
config.i18n.default_locale = :en

Change the text will_paginate renders

How can change the text that will_paginate shows?
Right now, it renders Previous ... Next. I need to put that in french Précédent ... Suivant. I checked on google and got this link : http://thewebfellas.com/blog/2010/8/22/revisited-roll-your-own-pagination-links-with-will_paginate-and-rails-3
However, I was wondering if there was an easier way.
You can override the default of Previous and Next this way:
<%= will_paginate #posts, :previous_label => 'Précédent', :next_label => 'Suivant' %>
Note: :previous_label was called :prev_label in versions 2.3.2 and older
So you have to ensure that the following is in place:
Your locale is set to french. This normally depends on the browser your are using. Chrome e.g. uses the locale of the operating system. I have set in application.rb the default locale (german for me): config.i18n.default_locale = :de
The directory config/locales contains a file fr.yml with the following content (there could be more customization):
views:
pagination:
first: "F"
previous: "« Prev"
next: "Next »"
last: "L"
truncate: "..."
This works for me in the current version of Rails 3.2.2 with gem 'will_paginate', '>= 3.0'.

Resources