Gettext_for_developers

Michal Čihař edited this page May 16, 2016 · 4 revisions
Clone this wiki locally

Translatable messages

When writing a message, always keep in mind that it will be translated to different languages, which might have completely different rules than English.

There are some widely spread mistakes which you should avoid:

  • Message concatenation - it might sound good to split out common prefix, but many languages won't share this prefix with English. For example Turn on/Turn off translates to Vypnout/Zapnout in Czech.
  • Value concatenation - avoid constructions like $num . __(' minutes'), always use format string because some languages will want to have number behind the word.
  • Format string order - do not assume other language will keep order of printf parameters, in many case it won't. Use position based format strings (eg. %2$s) when there are more than one parameters.
  • Use plurals - whenever you need to print something based on number, it is always good idea to use _ngettext. Many languages have more plural forms than English.
  • Untranslated parts - you might want to use some value directly as received from MySQL (eg. ON/OFF), but in most case it will look oddly in translated version. In some cases it might be useful to show original values though.
  • Include colon - is some languages, the string with trailing colon would translate differently, so avoid things like __('Table') . ':', use __('Table:') instead

Gettext in phpMyAdmin

Because of problems with native gettext implementation (see below) phpMyAdmin uses an embedded copy of the php-gettext library.

In contrast to standard gettext, all calls have an extra underscore at the beginning. So the most important function for you is __() (yes, two underscores), which returns the translated version of a string (this is same as function gettext in PHP). For example:

echo __('This is a message');
printf(__('Welcome to phpMyAdmin %s'), VERSION);

Plural forms

Gettext also allows to get proper plurals in all languages. To use this, you need to use the _ngettext() function:

printf(_ngettext('%d row', '%d rows', $rows), $rows);

Which will return a properly localized string based on the value of $rows (different languages have different and sometimes quite complex rules for plurals). See ngettext documentation for more details.

Comments for translators

If you want to add some comment to translators, you can add a PHP comment with l10n: prefix, which will be incorporated into the .po file and shown while editing the message:

/* l10n: Please note that this means day of week and not the sun */
echo __('Sun');

Different contexts

In some cases it can happen that single word in English would be translated differently to other languages. This can happen for short words such as "None", where the translation to some languages depend on gender of replaced word. To differentiate these, you can use context in gettext:

echo _pgettext('None table', 'None');

The first parameter describes in which context the translation should be made, while the second one is the actual English word.

Guidelines on adding/updating messages in the different branches

master

(current development)

Adding and updating messages is allowed.

when preparing a future stable

(f.e. 4.0-alpha/rc)

Once the preparation starts to make current development branch ready for stable, the window for adding new and changing existing messages closes. This to allow the translators to get all translations ready for the next major/minor (stable) release :

  • no new translatable strings
  • no updates that changes the content/meaning of a translatable string (but exceptions allowed after discussion on mailing list)
  • updates fixing typos and grammar are allowed

current stable

(f.e. QA_4_0)

  • no new translatable strings
  • no updates that changes the content/meaning of a translatable string
  • updates fixing typos and grammar are allowed

old releases

  • no maintance on translatable strings (no new strings, no fixes on existing strings)

Fixing typo

In case you want to fix typo in English (which won't affect translations), it is recommended to fix the typo in po files as well to avoid marking string as fuzzy (and forcing translators to review it). You can do it for example using sed:

sed -i 's/this is typo/this is a typo/' po/*.po

Adding a new message

To add a new message, you simply need to put it into the code (see above section for examples). For making the message appear in the .po files, you need to refresh them as described below.

Adding new messages is only allowed in the development branch (master) (see above)

Messages from JavaScript

For use in JavaScript, export your message in js/messages.php and use PMA_messages array to get message strings.

For String formatting you may want to include jquery.sprintf.js and use the $.sprintf() it supplies.

Updating .po files

When you add a new string, you need to regenerate the .po file so that translators can pick up new strings. This can be done by using:

./scripts/update-po

You need to have gettext installed to use this script.

You better avoid this when you are working on private branch because it will probably cause problems on merges.

When fixing typos

When you fix a typo or grammar in a message (not changing the meaning/content of the string), you should change this string in the *.po files before running the update-po script. This to avoid that the string is marked as fuzzy and thus requiring attention from a translator.

This can be done with this command :

sed -i 's/this is typo/this is a typo/' po/*.po ./scripts/update-po

Merging different branches

See Git#Merging_translations.

Why not to use native Gettext in PHP

Major reasons:

  • We would need to use only system supported locales and figure out their names (eg. use cs_CZ.UTF-8 instead of cs only)
  • Changes is the .mo file lead to PHP crash (last tested with PHP 7.0.3)

Gettext does not deal with file changes while it is running. As it was designed for standalone applications, it is not that big deal, because when you update the application, you will want to start using the new version. You'll have to restart it and translation files are loaded as well. But, in case of web applications this is a big issue because the webserver is usually running all the time and you don't want to restart it on every web application change.

Also changing the translation files causes PHP to crash, what is something we don't want to cause.

Category:Devel Category:Translating