--- layout: page title: Internationalisation (for devs) --- # Internationalisation in the code
This page describes some technical aspects of internationalising the Alaveteli code. It's mostly aimed at devs who are working on the codebase — if you just want to translate Alaveteli into your own language, see translating Alaveteli instead.
## Deployment notes Deployed translations for the project live in ``locale/``. Translations live in the project page at [Transifex](https://www.transifex.net/projects/p/alaveteli/) and should be submitted there. For example, to deploy English and Spanish translations at once: * Ensure their PO files are at ```locale/en/app.po``` and ```locale/es/app.po``` (for example, by downloading them from Transifex) * SetAVAILABLE_LOCALES
to en es
To update the `.pot` and `.po` files for each language, run:
bundle exec rake gettext:store_model_attributes
followed by:
bundle exec rake gettext:find
If `gettext:find` only creates the file `locale/im-config.pot` then you need to
unset the `TEXTDOMAIN` environment variable and try again.
For more details about the translations, see the page about
[translating Alaveteli]({{ site.baseurl }}docs/customising/translation/).
## Technical implementation details
### Getting the current locale
This is complicated by the fact that there are two competing ways to define a
locale+territory combination. The POSIX (and gettext and Transifex) way is
like `en_GB`; the Rails way is like `en-US`. Because we are using gettext and
Transifex for translations, we must deal with both. Wherever you need to know
the Rails version of the currently selected locale, use `I18n.locale`; wherever
you want to know the POSIX version of the locale, use `FastGettext.locale`.
## I18n in templates
Before you add i18n strings to the source, you should read
[internationalisation guidelines](http://mysociety.github.io/internationalization.html)
that apply to all our projects.
Some hints for adding the strings into the Alaveteli code:
* Simple strings: ```<% = _("String to translate") %>```
* Strings that include variables: give the translator a hand by inserting
strings that can be interpolated, so the variable has meaning. For example,
```<%= "Nothing found for '" + h(@query) + "'" %>``` might become ```<%=
_("Nothing found for '{{search_terms}}'", :search_terms => h(@query)) %>```
* Strings containing numbers: ```<%= n_('%d request', '%d requests', @quantity) % @quantity %>```
* We allow some inline HTML where it helps with meaningful context, for example:
```
_('Browse all or ask us to add it.',
:browse_url => @browse_url, :add_url => @add_url)
```
Similar rules can apply to strings in the Ruby source code.
## Programmatic access of translated PublicBodies
Apart from the templates, the only other area of i18n currently implemented is
in the PublicBodies.
The implementation allows for getting different locales of a PublicBody like so:
```ruby
PublicBody.with_locale("es") do
puts PublicBody.find(230).name
end
```
Usually, that's all the code you need to know about. There's a method
```self.locale_from_params()``` available on all models which returns a locale
specified as ```locale=xx``` in the query string, and which falls back to the
default locale, that you can use in conjunction with the ```with_locale```
method above. All the joining on internal translation tables should usually be
handled automagically -- but there are some exceptions, that follow below.
### Overriding model field setters
Internally, we use the [Globalize plugin](https://github.com/globalize/globalize)
to localize model fields. Where column "foo" has been marked in the model as
```:translates```, globalize overrides ```foo.baz = 12``` to actually set the
value in column ```baz``` of table ```foo_translations```.
A side effect of the way it does this is that if you wish to override a
specific attribute setter, you will need to explicitly call the Globalize
machinery; something like:
```ruby
def name=(name)
globalize.write(self.class.locale || I18n.locale, "name", name)
self["name"] = short_name
# your other stuff here
end
```
### Searching
The ```find_first_by_