Hello all,
With Jozef's tremendous effort we now have all UI strings in a dictionary.
Here's a couple of points that you may find relevant about keeping it
that way forward. Please do at least skim it all -- it's quite possible
there are some tricks in the I18n API that you're not aware of.
String Placement
----------------
From now on, strings that are visible in the UI should not be put
directly into the Conductor code.
They go to the dictionary located at:
conductor/src/config/locales/en.yml
It's a YAML file which for the most part follows the structure of our views.
For example, a "Pool Name" text that would find on the New Pool page
goes here:
pools:
new:
pool_name: Pool Name
Note that there is no need to put quotes around the string.
In the Code
-----------
To use a localized string in the code, you use the `I18n::t` (shorthand
for `translate`) function that comes in the I18n module with Rails.
The function takes the dictionary key and produces the appropriate string:
> t('pools.new.pool_name')
=> "Pool
Name"
You can drop the path in the views:
%p= t('.pool_name')
Rails will know that you're in the pools/new.haml.html view and it will
guess the location in the dictionary correctly.
Models don't have the I18n module included by default so you'll have to
specify it manually:
raise I18n::t('pools.errors.fatal_error')
Note that in models and controllers you *have* to specify the full path
in the dictionary. In views you can use the relative path.
Using Parameters
----------------
When it comes to localization, you can't rely on using code to modify
the strings.
For instance:
t('pool') + pools.count > 1 ? 's' : ''
Will work in English (it'll return "pool" for a single pool and
"pools"
for multiples) but it will not work in a lot of other languages.
Different languages have quite different pluralization rules. Some of
them differ based on counts other than (count == 1) and (count > 1).
You have to specify these in the dictionary like so:
deleted:
one: The pool was deleted.
other: All the pools were deleted.
Now you can call:
> t('deleted', :count => 1)
=> "The
pool was deleted."
> t('deleted', :count => 20)
=> "All
the pools were deleted"
Now the translators can put all the different versions into the
dictionary and we won't have to pollute our code with pluralization logic.
Similarly, it's not safe to just combine strings and variables together.
This is bad:
%p= t('confirm_deletion') + @pool.name + t('pool_question')'
It may work in English ("Are you sure you want to delete the Default
pool?") but not in other languages that have a different word order.
I18n allows you to put parameters into the dictionary:
pools:
index:
confirm_deletion: Are you sure you want to delete %{name} pool?
You can then pass the parameters to the `t` function:
%p= t('.confirm_deletion', :name => @pool.name)
And you'll get the desired result with a much cleaner code which also
happens to be more friendly to all the other languages.
Reviewers
---------
As we're nearing the release, we'll have the UI translated to a lot of
different languages.
We must make sure that we don't regress to putting strings back into the
code or building the strings in some weird untranslatable way.
I would like to ask all reviewers to look out for this stuff from now on
as well.
All new or modified code must follow proper internationalization
practices. If you see a patch that doesn't, please point it out and
don't let it go in without being fixed first.
For more details, you can look at the Rails Guides document that covers
the I18n API we're using:
http://guides.rubyonrails.org/i18n.html
I've also put this document on our wiki. Do share and update it as needed:
https://www.aeolusproject.org/redmine/projects/aeolus/wiki/Internationali...
Cheers,
Thomas
--
No trees were killed to send this message, but a large number of
electrons were terribly inconvenienced.