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:
PotFolderis the folder where to save the .pot file to be generatedPotFileNameis the name of the .pot file (only its name, without folder specification)FileListis 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:
PotFileis the name of the source .pot file you generated with xgettextPoFileis the name of the .po to be generatedLocaleCodeis the locale code (language code and country code, for instanceit_ITfor 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:
LocaleCodeis the locale code (language code and country code, for instanceit_ITfor Italian - Italy)NewPoFileis the name of the new .po to be generatedOldPoFileis the name of your old .po containing translationsPotFileis 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:
MoFileis the name of the .mo to be generatedPoFileiis 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:
PackageNameis the folder where your package residesLocaleCodeis the locale code (language code and country code, for instanceit_ITfor 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:
concrete5rootis 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.
