Skip to content

Translating templates

wvengen edited this page Dec 14, 2013 · 14 revisions

When you're familiar with i18n, you may want to skip to foodsoft-specific notes.

Basic

Each locale has its own <lang>.yml file in config/locales (please see existing files). Starting with plain text in the templates, e.g. in the file app/views/home/_start_nav.haml

 %h3 Direkt zu ...

was changed to

 %h3= t '.title'

The = lets the remainder of the line be parsed as code. The t() function takes care of translation, and it argument '.title' is an identifier. Since it starts with a ., Ruby on Rails prepends view directory and simplified filename in addition to the locale, so that the full identifier becomes de.home.start_nav. This is put into config/locales/de.yml.

In a command

When there is a more complex command on the line, the function call needs to have brackets. E.g.

%li= link_to "Mitglieder", foodcoop_users_path

was changed to

%li= link_to t('.members'), foodcoop_users_path

The brackets are required so that the parser knows that foodcoop_users_path belongs to link_to() (and not to t()).

Arguments

Another issue is when code appears in the text. To separate code from text, it is better to put that in an argument than inside the translation. For example

%small (Letzte Aktualisierung ist #{distance_of_time_in_words(Time.now, current_user.ordergroup.account_updated)} her)

was changed to

%small= t '.my_ordergroup.last_update', when: distance_of_time_in_words(Time.now, current_user.ordergroup.account_updated)

The corresponding text in in the locale file was set to Letzte Aktualisiering ist %{when} her. Note the use of the percent sign to reference the variable given on the t() command.

Newlines in emails

Some templates are for email messages. By default, the YAML template system ignores empty lines (which makes sense for web pages), but for emails they are important. To keep those, start the text with a | sign. Now that we're using localeapp, this is no longer relevant - use two newlines when you mean one and qute the text (see existing example).

text: |
  Hallo!

  %{user} <%{mail}> hat dich in die Gruppe "%{group}" eingeladen.
  Um die Einladung anzunehmen und der Foodcoop beizutreten, gehe zu: %{link}
  Dieser Link kann nur einmal aufgerufen werden und ist nur bis %{expires} gültig.
    
  Grüße sendet die Foodsoft!

HTML Escaping

You can skip this section at first, and come back when you find yourself wanting to put HTML inside a translation.

The HAML template parser tries to be safe and escape text to HTML entities when needed. Sometimes this is not desired, however. If the strings from our locales files have no variables that may contain user input, they are safe anyway and we can print them raw by using != instead of =. An example can be found in passing a link to a translation in sessions/new.html.haml (translation), where

Achtung, Cookies und Javascript müssen aktiviert sein!
= link_to "NoScript", "http://noscript.net/"
bitte abschalten.

was changed to

!= t '.nojs', link: link_to(t('.noscript'), "http://noscript.net/")

Here two translation texts were used:

nojs: 'Achtung, Cookies und Javascript müssen aktiviert sein! %{link} bitte abschalten.'
noscript: 'NoScript'

Since link_to() returns html code, it should not be escaped. Still we want to include it in the``.nojs translation, since different languages may have a different word order. As all the inputs here (%{link}`) are completely fixed, it is safe to print it raw using `!=`.

A more beautiful way to do this is using html_safe. I'll demonstrate that with a translation consisting of multiple paragraphs of text in _modal_form.html.haml (translation):

%p
  Hier kannst du eine Person in die Gruppe
  %b=h @invite.group.name
  einladen, die noch nicht Mitglied der Foodcoop ist.
  %br/
  Die Person ist dann nach erstmaliger Anmeldung automatisch Mitglied dieser Gruppe.

was changed to just

= t('.body', group: @invite.group.name).html_safe

so that the translator can decide how to order the paragraphs. Here the translation was put into paragraphs, and the group name was made bold using html:

body:
  <p>Hier kannst du eine Person in die Gruppe <b>%{group}</b> einladen, die noch nicht Mitglied der Foodcoop ist.</p>
  <p>Die Person ist dann nach erstmaliger Anmeldung automatisch Mitglied dieser Gruppe.</p>

Sometimes you may come across raw t('.foo'), which is the same thing as t('.foo').html_safe. I hope this is enough to get you going! And please feel free to expand this.

Foodsoft-specific notes

So far, we've covered general Ruby on Rails i18n. Within foodsoft we're also using some things that are not part of the general practice.

heading_helper

Some tables are pretty crowded with information. That means that the table headings cannot be too wide. That's why heading_helper was introduced. Uses this in table headings and definition lists when you need a label for a model field.

heading_helper basically calls <modelclass>#human_attribute_name; only when short: true is passed it uses an abbreviated version with the full name as title attribute. This is used, for example, in articles/_articles.html.haml:

%th{:style => "width: 4em;"}= heading_helper Article, :unit_quantity, short: true

with corresponding attribute translations in config/locales/en.yml:

en:
  activerecord:
    attributes:
      article:
        unit_quantity: Unit quantity
        unit_quantity_short: U.Q.

resulting in the html code

<abbr title="Unit quantity">U.Q.</abbr>
Clone this wiki locally