So, you've developed your own package. Great!
You did everything possible to make it a thing that will change the world. And to let the whole world use it, you enabled localization by writing all those t('…')
that are described in the Internationalization and the t functions family how-to.
And now? How could your ready-to-be-translated package speak other languages?
Here it comes to help the gettext system. It can parse all your PHP files, and create the resources that translators can translate. Here's how you can obtain it:
- For *nix systems: it's enough to do a simple
apt-get install gettext
. - For Mac OS X: MacPorts maintains a port of it
- For Windows: I compiled the latest binaries: you can find them in GitHub.
Manual generation of translatable files
Generate the template file (.pot)
First of all, you need to extract translatable strings and create a so called Portable Object Template
, actually a text file with a .pot
extension.
This is done by the xgettext
command. For concrete5, you may want to use the following command line:
xgettext --default-domain=messages --output-dir=PotFolder --output=PotFileName --language=PHP --from-code=UTF-8 --add-comments=i18n --keyword --keyword=t:1 --keyword=t2:1,2 --keyword=tc:1c,2 --no-escape --add-location --no-wrap --files-from=FileList
Where:
PotFolder
is the folder where to save the .pot file to be generatedPotFileName
is the name of the .pot file (only its name, without folder specification)FileList
is the name of a file containing the list of all the .php files of your package
Once you have this .pot file, you have various options to translate it.
The simplest one is to use Transifex. It's an online collaborative tools, very powerful and it's free for open source projects.
Generate the translation files (.po)
If you don't want to use Transifex, you have to manually generate a Portable Object
file for each language you want to translate. These are simple text files with a .po
file extensions. They can be generated starting from the .pot file with the following command line:
msginit --input=PotFile --output=PoFile --locale=LocaleCode --no-wrap
Where:
PotFile
is the name of the source .pot file you generated with xgettextPoFile
is the name of the .po to be generatedLocaleCode
is the locale code (language code and country code, for instanceit_IT
for Italian - Italy)
Now that .po file can be translated, with for instance POEdit.
Update the translation files (.po)
What happens if you change your source files? Don't worry, your previous translations won't be lost. YOu simply re-create the .pot file with xgettext as mentioned above, and you only have to update your .po file with this command:
msgmerge --no-fuzzy-matching --previous --lang=LocaleCode --force-po --add-location --no-wrap
--output-file=NewPoFile OldPoFile PotFile
Where:
LocaleCode
is the locale code (language code and country code, for instanceit_IT
for Italian - Italy)NewPoFile
is the name of the new .po to be generatedOldPoFile
is the name of your old .po containing translationsPotFile
is the name of the source .pot file you generated with xgettext
Final step to use the translation files
Ok, now you have translated everything. How can you use it?
concrete5 needs the compiled version of those .po files, that is the so-called Machine Object
files (they have the .mo file extension). POEdit can compile the .po files into .mo files for you. If you want to do it yourself, you can use the following command line:
msgfmt --output-file=MoFile --check-format --check-header --check-domain PoFile
Where:
MoFile
is the name of the .mo to be generatedPoFile
iis the name of your .po containing translations
Now you can place this .mo file in the following location under your concrete5 installation folder:
/packages/PackageName/languages/LocaleCode/LC_MESSAGES/messages.mo
Where:
PackageName
is the folder where your package residesLocaleCode
is the locale code (language code and country code, for instanceit_IT
for Italian - Italy)
Automatic management of translation files
I've created a tool to help package developers to manage all the above manual process. You only need the gettext tools available in your path and the PHP interpreter installed.
With a great lack of creativity, I called my tool i18n
. You can grab it from GitHub. You need the whole repo content, so just download it as a zip file (or git-clone it).
Once you got it, simply call the following line:
php i18n.php --webroot=concrete5root --interactive
Where:
concrete5root
is the root folder of your local concrete5 installation
i18n
will guide you throug the creation of the .pot file, the creation/update of the .po file and the generation of the .mo file. All that within seconds.
Final notes
In order to activate and use a package-specific language, that language must also be defined at the site-level.
So, if for instance you have the file /packages/discussion/languages/it_IT/LC_MESSAGES/messages.mo
, to use it you need to have also the file /languages/it_IT/LC_MESSAGES/messages.mo
. You can download system-level language files from the developers > Translate concrete5 concrete5.org page.
The whole process from .php files to .mo files could be accomplished by POEdit. Anyway there are a few drawbacks with that. The bigger ones is that POEdit does not supports the t2()
and tc()
functions, and is not able to extract i18n comments.