GNU Gettext
Is GNU's implementation of the Gettext system and also the most common translation format for libre-software. It has support for plurals, contexts, and contains a vast ecosystem of tools designed for it.
The only caveat is that Gettext does not handle how fractional values can affect plural-forms.
Gettext usually comes in two containers:
- A human-readable
.po
file for translators - A binary
.mo
file for the program.
Lens provide support for both of these in the form of Gettext::POBackend
and Gettext::MOBackend
respectively.
Note
Lens does not currently offer any method to export .po
to .mo
. So an external tool would have to be used.
Using Gettext
As with all backends, the first step is to initialize it with the locale directory.
gettext_backend = Gettext::MOBackend.new("locales")
Locale files are searched with the **
glob, so feel free to nest in as many levels as you'd like.
Tip
There are no API/behavior differences between the po
and mo
varieties. Anything that is shown to apply to one would also apply to the other.
Now you'll just need to call the #create
method:
catalogue_hash = gettext_backend.create()
Which returns a mapping of the language code, as defined via the Language
header — or the file name when it isn't defined, to a Catalogue object.
Now, we can begin translating!
catalogue = catalogue_hash["en_US"]
The most basic syntax for translating strings is the #gettext
method. If a translation is not found, then the original ID would be returned.
catalogue.gettext("A message") # => "Translated message"
catalogue.gettext("I don't exist") # => "I don't exist"
Pluralization
Plurals are handled through the #ngettext
method. The given number is passed to the C expression from the Plural-Forms
header, to compute which plural-form to use.
catalogue.ngettext("I have %d apple", "I have %d apples", 0) # => "Translated I have %d apple"
catalogue.ngettext("I have %d apple", "I have %d apples", 1) # => "Translated I have %d apples"
Context
A translation can be constrained by a specific context, and can be accessed through the #pgettext
method. This is useful to avoid ambiguities with commonly seen strings.
catalogue.pgettext("CopyPasteMenu", "copy") # => "Translated copy"
catalogue.pgettext("CopyPasteMenu", "I don't exist") # => "I don't exist"
Context w/ pluralization
A context-constrained translation can also have plurals, which are accessed through the #npgettext
method
catalogue.npgettext("CopyPasteMenu", "Export %d file", "Export %d files", 0) # => "Translated message with plural-form 1"
catalogue.npgettext("CopyPasteMenu", "Export %d file", "Export %d files", 1) # => "Translated message with plural-form 0"