This guide covers how Spree uses Rails’ internationalization features, and how you can leverage and extend these features in your Spree contributions and extensions. After reading it, you should be familiar with:
- How Spree is internationalized
- How to add translations
- Internationalizing extensions
- Disabling internationalization
Spree now stores all of the translation information in a separate Github project known as spree_i18n. This is a stand alone project with a large number of volunteer committers who maintain the locale files. This is basically the same approach
followed by the Rails project which keeps their localizations in rails-i18n.
The project is actually a Spree extension. This extension contains translations only. The rest of code needed to support the i18n features is part of the Spree core.
WARNING: You will need to install the spree_i18n gem if you want to use any of the community supplied translations of Spree.
Each language is stored in a YAML file located in . Each YAML file contains one top level key which is the language code for the translations contained within that file. The following is a snippet showing the basic layout of a locale file:
5_biggest_spenders: “Os 5 maiores compradores”
access_denied: “Acesso não autorizado”
account_updated: “Conta atualizada!”
Spree maintains its localization information in a YAML file using a naming convention similar to that of the Rails project. Each of the localization filenames contains a prefix representing the language code of the locale. For example, the Russian translation is contained in .
INFO: Spree has over 25 locale files and counting. See the Github Repository for a complete list.
Each locale that you wish to support will require both a Rails and Spree translation. The required Spree translation files are available automatically when you install the gem. The Rails translation files should be added manually to your application’s directory.
So for example, if you wanted to provide a Russian translation, you would install the spree_i18n extension and then copy the file from rails-i18n into .
When reviewing the source of any view in Spree you’ll notice that all text is rendered by passing a string to a helper method similar to:<%= t(‘price’) %>
The t() helper method looks up the currently configured locale and retrieves the translated value from the relevant locale yaml file.
Alternatively, you can use symbol notation as follows:
<%= t(:price) %>
Since Spree is basically a Rails application it has the same default locale as any Rails application. The default locale is which use the English language. We can verify this in the rails console
You can also see in the console how the default locale values are translated into English
The gem is configured in the same manner as any Rubygem in a Rails application. Simply add it to the using the git url.
gem ‘spree_i18n’, :git => ‘git://github.com/spree/spree_i18n.git’
You can verify that the locales have been installed properly by firing up your Rails console and running the following command:
The exact number will of course depend on the number of locales available in the project at the time you run this command.
The default locale for Spree is . This can be changed by editing the :default_locale setting in the . This setting is ignored unless the relevant translation file are within or the gem. In the future we hope to add a localization settings page that will allow you to set the default locale from the admin screen.
Spree makes use of the rails module to format numbers into the form of currency, otherwise prices within spree are simply regarded as numbers with no special properties. Currency formatting is therefore dictated by the current user locale (if locale is allowed to change) or the default locale (as above) if locale is fixed. To specify a currency format therefore you should do the following:
For each locale you support (just the default if you don’t allow locale switching) you must make a file, in the style , within following the format:
To ensure that currency stays consistent when a user changes their locale the same currency details should be provided for each of the supported locales.
INFO: By default Spree stores prices in only a single currency.
The single currency limitation means that if you do not change the default Rails currency settings for your locales the prices will be incorrect. For instance, $1 in locale will become £1 in . In this case it makes sense to pick a single currency and then to override the Rails defaults for the other locales so that the prices are in a consistent currency.
INFO: Multiple currency support and other pricing related improvements are being considered for future versions of Spree.
The gem contains several helpful Rake tasks for helping you create new localizations as well as maintaining existing ones.
WARNING: These instructions pertain to the use of the gem. They assume that you are working with your locale files within the context of the source code. It is certainly possible to work with locale files directly within your Rails application but the Rake tasks would need to be adjusted slightly if you intended to use them.
The default Spree locale is actually maintained as part of the Spree project (and not part of project.) A copy of the default locale information is, however, available in the source. Before you run any of the other rake tasks, its a good idea to “refresh” the localization information for .
$ bundle exec rake spree_i18n:update_default
This updates the localization files in the directory with the latest information from the Spree project.
The Spree localization files are essentially a continual work in progress. Over time new localization entries are added to the default locale and the translation files need to be updated. You can get a sense for how much translation work is needed using the rake task designed for this purpose.
$ bundle exec rake spree_i18n:stats
This will list all of the available locales and give you the percentage of completion for each.
NOTE: Some of the older translation files may overstate their completion percentage. Until recently it wasn’t possible to have default locales and so we used English translation values (with no comments) instead. In these cases the English values are counted as “translated”.
As new translation strings are added to Spree you will want to resync the locale files so that they provide “stub” entries for these strings which will help to identify them as needing translation. There is a special Rake task that will resync all of the locale files with the latest values from the Spree project. The Rake task will also reorder the translations alphabetically.
$ bundle exec rake spree_i18n:sync
NOTE: Remember to run first if you haven’t done so already.
Its simple enought to add a new locale using the appropriate Rake task.
$ bundle exec rake spree_i18n:new LOCALE=es-PE
This will generate a new localization with the file name in the directory. Here’s a snippet of the file that is generated:
5_biggest_spenders: #“5 Biggest Spenders”
access_denied: #“Access Denied”
account_updated: #“Account updated!”
WARNING: Remember that you will also need the corresponding Rails locale information in your applications directory. So in order to get your locale to work with both Spree and Rails you will also need the correct locale file from .
You will notice in some of the locales (especially newly created ones), that there are default values in English that are commented out. These commented values are provided as a guide to help people performing the translations since the translation key does not always give you the best idea of the complete English phrase in question.
Lets fire up the Rails console and test our new locale.
>> I18n.locale = “es-PE”
You’ll notice that there’s actually a translated value even though we did not set one explicitly in our locale. This is because the gem has instructed Rails to use fallback locales in an attempt to provide a value where translations are otherwise missing. So in the case of the locale, the locale is consulted. If there were no value found in that locale it would have defaulted to the value specified in the default locale.
Spree extensions can contain their own +config/locales* directory where developers can include yaml files for each language they wish to support.
We strongly urge all extension developers to ensure all customer facing text is rendered via the helper method even if they only include a single default language locale file (as other users can simply include the required yaml file and translations in their site extension).
INFO: Since Spree extensions are equivalent to Rails Engines they can provide localization information automatically (just like a standalone Rails application.)
If you don’t want to allow users to change the language / locale you can disable locale switching by changing the :allow_locale_switching setting to false in the AppConfiguration model.