I18n - locale file - use ruby - use translation() - ruby-on-rails

In a I18n locale file (eg el.yml):
can I use translation method in order to use an already defined translation?
can I use ruby code inside?
For example, in the locale yml file, in several places I want to use the word "Invalid". So one approach is to translate the word "Invalid" each time
Another approach is to translate it once, at the top, and then in each translation inside the locale yml which contains this word I could use something like t(:invalid)..
eg:
el:
# global translations - in order to be used later in the file
locked: 'kleidomeno'
invalid: 'mi egiro'
password: 'kodikos'
devise:
failure:
invalid: "#{Invalid} %{authentication_keys} or #{password}."
locked: "Your account is #{locked}."
last_attempt: "You have one more attempt before your account is #{locked}."
not_found_in_database: "#{invalid} %{authentication_keys} ή #{password}."

can I use translation method in order to use an already defined translation?
Yes, that's what I18n translation comes for, e.g.
t 'something'
can I use ruby code inside?
No, it's a .yml file, which does not accept Ruby or any other programming languages.
Another approach is to translate it once
To translate once, you can write a new Rake task to generate the target yml for you.
Or maybe, wrap the official translation function with a new method, which can recognize your custom string syntax:
# custom translate
def ct(msg)
msg.gsub(/#\{\s*([^\}]+)\s*\}/) {|_| t $1}
end
Call it like:
ct 'Your account is #{locked}.'
I think you'd better remove these failure strings out of your yml file if so.

Related

Rails language name using I18n locale

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.

Multi language with Rails app to prepare YML file

I am building a car rental app with Ruby on Rails and currently I have been coding with English. Basically I have an user and car model, where user can login, sign in, log out and list their car.
I would like to implement another language allowing the user to select English or Spanish from a dropdown. I have default error messages returns from the controller actions such as "can't be blank, already used" etc. And I also have custom JS messages, such as if user successfully adds a car, jQuery returns "your car has been published". Lastly, I also have Flash messages. But I do not know how should I handle errors, custom JS and Flash messages in the YML file according to user's language selection.
It actually really depends on the structure of your YAML file, for example, for ActiveRecord error messages:
it:
errors:
format: "%{attribute} %{message}"
messages: &errors_messages
empty: "non può essere vuoto"
blank: "non può essere lasciato in bianco"
If you want to access I18n (a.k.a Internationalization) outside of views, you can use I18n.t(your_key), which is in fact the helper you have access to in your views. So for example, if you wish to translate a notice in a controller you could be doing something like:
def your_action
redirect_to other_path, notice: I18n.t("notices.successful_action")
end
And then having in your YAML the correspondent structure:
en:
notices:
successful_action: "You did it!"
Hope this helps!
I do not know how should I handle error, custom js and flash messages in yml file according to user's language selection
For Rails app-related translations in general, including error messages, the Rails i18n gem has you covered. You can see what languages have been translated in the gem's locale file.
For specifically overriding error messages or creating new ones, see The Rails Guide sections on looking up translations and translations for ActiveRecord models to see what keys in your YAML files you should be putting your translations under.
For flash messages, have a look at this StackOverflow question to see how you can use lazy lookups (eg t('.notice')) in your controllers.
For the ability to use translations in Javascript files in the same way you do in Ruby (eg I18n.t("my_translation"), and be able to manage those translations in your YAML files with the rest of your Rails translations, have a look at the i18n-js gem. Setup instructions are in the README file.

RAILS I18n: How to use # in translation key?

Here is in our yml file:
Or make up unique one like login#a.com : 'test'
But here is the error on view page for I18n.t("Or make up unique one like login#a.com"):
translation missing: zh-CN.Or make up unique one like login#a.com
What causes the missing translation of t()?
UPDATE:
Just verified that the problem was caused by # sign. Now the question becomes how to use # in translation key.
I highly recommend the Rails i18n guide for beginners.
It will help you understand how to structure your files, how to setup routes to support a locale param, how to set the locale, and other useful tips.
The t helper is not intended to take a string of text to translate. It takes a yaml key and outputs the translated text from a locale file.
You want to structure your yaml file as such:
config/locales/en.yml
en:
some_key: hello world
config/locales/cn.yml
cn:
some_key: hello in Chinese
Then using it in your views
<%= t :some_key %>
Based on the I18n.locale setting, the t helper will look up :some_key in the corresponding locale file and output the translated text.

Unable to use I18n.t call in an initializer file in Rails 3.1.1

I would like to use I18n.t in an initializer file in Rails 3.1.1.
This question already exists for Rails 2 (http://stackoverflow.com/questions/3514536/unable-to-use-i18n-t-call-in-an-initializer-file). Supposedly, it was answered by a subsequent release. It appears to be an issue again in Rails 3.1.1.
The problem:
I have a custom time format called :dxl.
I would like to format my Email.sent_at datetime as :dxl.
The solution:
In can add the format to en.yml (time.formats.dxl) and use it with:
I18n.localize(email.sent_at, :format => :dxl)
I also want to show the utc time. I do not see a way to use I18n for this, so I am using:
email.sent_at.utc.to_s(:dxl)
The rub:
To support to_s(format), I believe I need to assign Time::DATE_FORMATS[:dxl] in an initializer (e.g. config/initializers/time_formats.rb).
I would rather not duplicate the strftime format string in both en.yml and the initializer.
Unfortunately, it looks like I18n is not usable within an initializer. When I add this to config/initializers/time_formats.rb:
Time::DATE_FORMATS[:dxl] = I18n.translate('time.formats.dxl')
I get:
> Time.now.utc.to_s(:dxl)
=> "translation missing: en.time.formats.dxl"
Is there a way to ensure I18n is ready (has read the en.yml file) in an initializer?
I did verify that the translation does work correctly if I copy/paste the strftime format into the initializer.
Thanks.

Internationalizing whole text with markup in Rails 3

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

Resources