More at Features | Support | Blog | Demo | Community | Download

Internationalization (i18n)

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:

1 How Spree i18n works

Spree uses the standard Rails approach to internationalization so we suggest take some time to review the official Rails i18n guide and the wiki to help you get started.

1.1 The spree-i18n project

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.

You will need to install the spree-i18n gem if you want to use any of the community supplied translations of Spree.

1.2 Translation Files

Each language is stored in a YAML file located in +config/locales*. 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:

--- pt-BR: 'no': "Não" 'yes': "Sim" 5_biggest_spenders: "Os 5 maiores compradores" abbreviation: Abreviação access_denied: "Acesso não autorizado" account: Conta account_updated: "Conta atualizada!" action: Ação actions: cancel: Cancelar create: Criar destroy: Remover list: Listar listing: Listando new: Novo update: Atualizar
1.2.1 Localization Files

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 config/ru-RU.yml.

Spree has over 25 locale files and counting. See the Github Repository for a complete list.

1.2.2 Required Files

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 spree_i18n gem. The Rails translation files should be added manually to your application’s config/locales directory.

So for example, if you wanted to provide a Russian translation, you would install the spree_i18n extension and then copy the ru-Ru.yml file from rails-i18n into #{Rails.root}/ config/locales.

If you do not need all of the localizations for your project you can skip installation of the spree_i18n gem and just copy the needed Spree translations to #{Rails.root}/ config/locales.

1.3 Translating Views

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) %>

1.4 The Default Locale

Since Spree is basically a Rails application it has the same default locale as any Rails application. The default locale is en which use the English language. We can verify this in the rails console

>> I18n.locale => :en

You can also see in the console how the default locale values are translated into English

>> I18n.t(:action) => Action

2 Deploying the Translations

2.1 Including the spree_i18n Gem

The spree_i18n gem is configured in the same manner as any Rubygem in a Rails application. Simply add it to the Gemfile.

#Gemfile.rb gem 'spree_i18n'

If you don’t want to limit yourself to a specific released version of spree_i18n gem then you can tell bundler to use the “edge” version and point it at the Github repository.

#Gemfile.rb gem 'spree_i18n', :git => 'git://'

2.2 Verifying the Gem Installation

You can verify that the locales have been installed properly by firing up your Rails console and running the following command:

>> I18n.available_locales.count => 28

The exact number will of course depend on the number of locales available in the spree_i18n project at the time you run this command.

2.3 Setting the Default Locale

The default locale for Spree is en. This can be changed by editing the :default_locale setting in the AppConfiguration model. This setting is ignored unless the relevant translation file are within #{Rails.root}/config/locales or the spree_i18n 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.

2.4 Setting the Default Currency

Spree makes use of the rails NumberHelper 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 _numbers.yml, within #{Rails.root}/config/locales following the format:

--- en-GB: number: currency: format: format: "%u%n" unit: "£" precision: 2 separator: '.' delimiter: ','

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.

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 :en locale will become £1 in en-GB. 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.

Multiple currency support and other pricing related improvements are being considered for future versions of Spree.

3 Creating and Modifying Locales

The spree_i18n gem contains several helpful Rake tasks for helping you create new localizations as well as maintaining existing ones.

These instructions pertain to the use of the spree_18n gem. They assume that you are working with your locale files within the context of the spree_i18n 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.

3.1 Refreshing the Default Locale

The default Spree locale is actually maintained as part of the Spree project (and not part of spree_i18n project.) A copy of the default locale information is, however, available in the spree_i18n source. Before you run any of the other rake tasks, its a good idea to “refresh” the localization information for en.yml.

$ rake spree_i18n:update_default

This updates the localization files in the default directory with the latest information from the Spree project.

3.2 Checking the Translation Progress

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.

$ rake spree_i18n:stats

This will list all of the available locales and give you the percentage of completion for each.

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”.

3.3 Syncing the Locales

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.

$ rake spree_i18n:sync

Remember to run rake spree_i18n:update_default first if you haven’t done so already.

3.4 Adding a New Locale

Its simple enought to add a new locale using the appropriate Rake task.

$ rake spree_i18n:new LOCALE=es-PE

This will generate a new localization with the file name es-PE.yml in the config/locales directory. Here’s a snippet of the file that is generated:

--- es-PE: 'no': #"No" 'yes': #"Yes" 5_biggest_spenders: #"5 Biggest Spenders" abbreviation: #Abbreviation access_denied: #"Access Denied" account: #Account account_updated: #"Account updated!" action: #Action actions: cancel: #Cancel create: #Create destroy: #Destroy list: #List listing: #Listing new: #New update: #Update

Remember that you will also need the corresponding Rails locale information in your applications Rails.root directory. So in order to get your locale to work with both Spree and Rials you will also need the correct locale file from rails_i18n.

3.5 Default Values

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" => "es-PE" >> I18n.t(:action) => "Acción

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 spree_i18n 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 es-PE locale, the es locale is consulted. If there were no value found in that locale it would have defaulted to the value specified in the default en locale.

4 Localizing Extensions

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 t() 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).

Since Spree extensions are equivalent to Rails Engines they can provide localization information automatically (just like a standalone Rails application.)

5 Disabling Internationalization

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.