-
Notifications
You must be signed in to change notification settings - Fork 0
Internationalization
Conductor uses the Rails I18n API: http://guides.rubyonrails.org/i18n.html
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.
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 must specify the full path in the dictionary. In views you can use the relative path.
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"
when there’s more of them) 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 different word order.
I18n allows you to specify parameters in 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.
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.
We are using Zanata project
https://translate.zanata.org/zanata/
.
Here you can find information about starting to contribute in
translations.
Our dictionaries contributors can find here: https://translate.zanata.org/zanata/project/view/aeolus-conductor
Export/Import dictionaries to/from Zanata project
Zanata accepts PO file format, so we convert YML files to PO.(it will change in future, when we’d like to use gettext instead of the default rails i18n backend)
Prerequisites
* has an account in FAS (Fedora Accounts System)
* be a maintainer of
https://translate.zanata.org/zanata/project/view/aeolus-
conductor (to become a maintainer please write to some recent
maintainer, who
are possible to add new maintainer)
* when you’re a maintainer need to set USERNAME and KEY zanata.ini in
your
~/.config/zanata.ini (more details in Zanata documentation)
* installed i18-translator-tools gem
(http://rubygems.org/gems/i18n-
translators-tools) - used to convert YML file to PO file and vice
versa.
* installed zanata-python-client - command line tool for working with
Zanata
Export
# Create a new version of aeolus-conductor (if you’d like to start
translation for new version)\
$ zanata version create VERSION_#
</pre>
# Set languages that EN.YML will be translated to, then download ZANATA.XML
(AFAIK It can be downloaded only through UI)
# convert YML file to PO file:
<pre>
$ i18n-translator path_to/foo.yml path_to/foo.po
</pre>
# Rename PO file to 'aeolus-conductor.pot' and load ZANATA.XML file to the
same directory
# Push to Zanata(from dir where you have ZANATA.XML file stored)
<pre>
$ zanata push --project-type podir --srcdir path_to_directory_with_po_files
Import
# Pull from Zanata (from dir where you have ZANATA.XML file stored)\
$ zanata pull ~~~~project-type podir\\ \# Convert PO file to YML\
\ $ i18n-translator foo.po foo.yml\\ \# From this point is up to you how to clean up YML file.\ Things that need to be clean:\ ~~ it contains default and translation strings for every key i.e. for key \ ‘edit’:\ edit: \ default: Edit\ translation: 編集\ ~~ some of keys has “po-header” value with empty strings - appears after \ conversion with i18n-translator Note: Imported PO files, converted to YML format by this gem, are not ready to use. YML files need a revision. Only admin of Zanata project can upload the dictionaries for translation, for more questions please ask on IRC \#aeolus.