I want to match the locale code to the specific language name. Is there any build in function in I18n/rails which would return the language name to the corresponding locales. Is installing a gem is the only way?
It seems there is no method for this in I18n.
If you just need current language name, you can easily include it in corresponding locale file:
# config/locales/en.yml
en:
language_name: "English"
And get it as usual: I18n.t('language_name') or I18n.t('language_name', locale: :en).
For general purposes you could use: https://github.com/hexorx/countries or initialize your own mapping as a ruby hash: { en: 'English', ... }.
Without installing an additional gem, you could make your own key/value pairs (either store it in a json file or store it to DB) and then lookup key eg "de" and read the value (in this case, "German"). It requires a bit of manual work (or setup a rake task or something to build it for you in appropriate format from some info source) but you aren't dependent on an additional gem in that case (which, without going thoroughly through the code, might have a far greater impact on your app performance/memory wise than your custom implementation for your specific need for all you know).
I am not aware of any rails built in functions that would return the entire language name, though. You can return the language abbreviation (eg for use in html lang attribute), but I think it stops there as far as the built in functions are concerned).
Have a look the following post in google groups (Gist). I hope there is no default support for the required conversion in rails.
Related
I am introducing a new locale to my application, and copy all existing files in config/locales/.locale1.yml to config/locales/.locale2.yml.
At first I expect that I18n.backend.send(:translations)['locale1'] would equal I18n.backend.send(:translations)['locale2'], but when I diff both hashes I realise that my new new 'locale2' is missing a bunch of translations.
I figure that for locale1 additional translations have been loaded from gems like for instance the popular rails-i18n gem.
As there is no (easy) way to find out in which .yml file a translation was defined, I want to get a list of all locale-files loaded from any gems.
Any suggestions how to get that information?
Even more interesting would be if I could actually implement a way to figure out from which file a translation was loaded, but I guess that would require writing a custom i18n backend that somehow stores where each key was loaded from.
After phrasing the question, it became quite clear what I need to search for: 'rails i18n load paths'.
By using:
Rails.configuration.i18n.load_path.select { |path| path.match('bundle/gems') }
I get close to what I need. Still not a list of what files are actually loaded or containing translations for the locale of interest, but at least a list of all gems that are considered by i18n.
For example :
en:
foobar-does-not-work: 'This is my value'
Then if I do :
t(foobar-does-not-work) # => returns nil
This will not parse in Ruby's yml. Is there some way to make it work though? My keys are based on URL's which have dashes ( - ) in them.
Which version of ruby are you using? Can you show us your code and the error?
It works for me:
> require 'yaml'
> YAML.load_file('foo.yml')
{"en"=>{"foobar-does-not-work"=>"This is my value"}}
And it works when I add it to my en.yml:
> I18n.t('foobar-does-not-work')
=> "This is my value"
Have you checked the value of I18n.locale?
Clearly there is an underlying problem that needs to be ferreted out. There is very good tool which analyzes your i18n YAML as the Rails app, which I have found extremely helpful in debug.
Install and run this gem i18n-tasks: https://github.com/glebm/i18n-tasks.
To create a comprehensive report of the your i18n components:
$ i18n-tasks health
From their spec:
This gem analyses code statically for key usages, such as I18n.t('some.key'), in order to:
Report keys that are missing or unused.
Pre-fill missing keys, optionally from Google Translate.
Remove unused keys.
Thus addressing the two main problems of i18n gem design:
Missing keys only blow up at runtime.
Keys no longer in use may accumulate and introduce overhead, without you knowing it.
I'm not sure the gem was intended to be used as an i18n debug tool, but I have found it to be useful for debugging hard to find problems in i18n.
I think you are just using the wrong key when calling the t method. Remove 'en' from the key. It should be:
t('foobar-does-not-work')
What's the best practice for internationalizing, say, a Terms of Service document in Rails 3? I can think of two options:
Creating a partial for each locale and choosing which one to load according to the current user's locale.
<li><%= I18n.t :tos_paragraph_1 %></li><li><%= I18n.t :tos_paragraph_2 %></li>
None of these seems like a good solution. Any ideas?
There are a few solutions, but if I were doing this for a production project, I would probably do something like the following:
Create files for your translated Terms of Services in config/locales/terms/, naming them terms.en.html, replacing en with the locale for each translation and html with the format of the file (e.g. you could use Haml, Markdown, etc.).
Create the following helper methods (put them in app/helpers/application_helper.rb to use them everywhere, but you can put them in whatever helper file you need/want):
def localized_document_for(document, locale)
raise ArgumentError.new('nil is not a valid document') if document.nil?
raise I18n::InvalidLocale.new('nil is not a valid locale') if locale.nil?
localized_document = path_for_localized_document(document, locale)
raise MissingTranslationData unless File.exists?(localized_document)
# If you're using Markdown, etc. replace with code to parse/format your document
File.open(localized_document).readlines.join
end
def path_for_localized_document(document, locale)
"#{Rails.root}/config/locales/#{document}/#{document}.#{locale.to_s}.html"
end
Now, in your views, you can use localized_document_for('terms', I18n.locale) any time you need to get the contents of the Terms of Service in the user's language. Now the code you're using to fetch the document is DRY (you can easily fetch other documents by creating another directory in config/locales and changing the value of the document argument), and your translated documents are stored in their own directory and can easily be edited (and don't depend on YAML, which brings no value to storing a single document in a file).
Note that if you wanted to do it the "Rails 3 Way," you could use the I18n::Backend::Chain (see https://github.com/svenfuchs/i18n/blob/master/lib/i18n/backend/chain.rb), and pass in I18n::Backend::Simple.new along with a custom backend that reads the files as necessary, but for a one-off deal I believe the helpers work sufficiently.
Creating a partial for each language is definitly undry.
The Rails way is the second option you suggest with a .yml for each language.
The doc provides great examples to let you organize the yml according to each page. Thus you have shortcuts for all your variables.
See http://guides.rubyonrails.org/i18n.html
I'm using the standard Rails I18n API to localise some of our views. This is working really well, but we now have a few use cases for regional changes to the en locale.
The API guide mentions that this isn't supported directly, and other plugins should be used. However, I'm wondering whether there's a simpler way to do this.
I already have en.yml, so in theory I could just create en-AU.yml and en-US.yml which are effectively clones of en.yml but with a few regional changes applied. I could then add additional English - American and English - Australian options to our configuration which would map to the new region-specific locales and allow users to use a region-specific locale.
The only problem I can think of with this is that it isn't DRY -- I would have duplicate translations for all common English words. I can't see a way around this.
Are there any other disadvantages to this approach, or should I just bite the bullet and dive into one of the plug-ins such as Globalize2 instead?
The rails-i18n-translation-inheritance-helper is getting a bit old now, so here's my approach for a Rails 3.2 project.
If you keep both en-US and en-AU in the same en.yml file you can use the yml repeated node to have a super en section:
For example:
en: &en
errors:
messages:
expired: "has expired, please request a new one"
not_found: "not found"
en-US:
<<: *en
en-AU:
<<: *en
errors:
messages:
not_found: "tis not found"
I'm using translation inheritance helper plugin for this.
In newer versions of Rails/i18n, they've added a fallback feature. Works similar to the outdated translation inheritance helper gem
see this answer for more info: Fall back to default language if translation missing
Hoping some learned Rails developers here can recommend an existing Ruby on Rails plugin or gem that allows you to continue using the Simple I18n backend whilst allowing you to optionally specify translations in the database.
Here's why:
I have one Rails app used for many websites. For the example I'll just use 2 websites:
Website 1: Leprechauns R Us
Website 2: Unicorns R Us
Most translations are the same for both websites, but occassionally I want to override a translation. For example, in my en-US.yml file I have the following translation:
view_all: View all
And for most websites this translation is fine, including for website 1 (Leprechauns) where I'm happy to use "View all".
However, for website 2, I'd like to use "View all Unicorns" as the view_all translation and I'd like to specify this in the database. For maintenance reasons I don't want to specify this override in a YAML file.
Many thanks,
Eliot
In the end I opted to take advantage of Rails' I18n::Backend::Simple's ability to process both .yml files and .rb files as locale dictionaries.
Artifacts created:
DB migration to create a translations table with columns: locale, key, text
Translation model to map to the translations table
Class method to_locale_hash on Translation model that returns a locale keyed hash as required by I18n::Backend::Simple.load_rb
A single-line file located at config/translations.rb with the line 'Translation.to_locale_hash'
For the source code see the Spree extension (sorry not in a Rails plugin structure, it will be easy to move over to a plugin should you require it) here:
http://github.com/eliotsykes/spree-i18n-db/tree/master