Best practices for creating translation files for multiple platforms
We are currently facing the problem to create and host translations for an app for multiple platforms (iOS, Android, HTML5, BlackBerry …). Are there any best practices for hosting the translations and creating the required translation files (en.lproj/Localizable.string, values-fr/strings.xml, …) on the fly?
I think about hosting the translations and their keys at a table at Google Docs (or other platforms) and exporting the data to csv and than using scripts to create the files.
I search the internet but found not good starting point so far.
6 Solutions collect form web for “Best practices for creating translation files for multiple platforms”
You can try Loco or Shuttle as cross-platform localization tool.
Do you know Transifex ?
Transifex is a modern, open-source localization platform. It’s a web system which automates the translation workflow for complex international projects.
We successfully used PhraseApp for multiple platforms. They have an API so we could provide shell scripts in the project tree to update translations with a quick command. You might even do that as a build step.
Mind you that there seem to be some hard-to-manage hurdles for these services since the different localized platforms have different feature sets. For example, Android supports pluralization which iOS does not IIRC.
There is http://www.getlocalization.com/
It’s free if you’re willing to post and share your individual strings and their translation publicly.
I make apps in both English and Japanese. What I do is store both translations in a file that I can access anywhere in the app, i.e. a global variable, instance, singleton, or what ever you feel comfortable with.
Make all the translations that you need in house because computer translators don’t say things just right.
Then where ever you use them pull it from the list based off a boolean value that says either English or Japanese.
An open-source online (deployable to your server of choice) translation tool that may fulfill your requirements is Pootle, that is built on top of Translate Toolkit. I have used Pootle as a translator for LibreCAD. You could browse LibreCAD’s Translation Server and see it in action. LibreCAD uses Qt as its base-framework and Pootle handles uploading and downloading TS files, which are used for translations in Qt. Having also used Transifex, I can tell you that Pootle is not that fancy (you may see that for yourself, although have in mind that LibreCAD’s Translation Server uses an older version of Pootle), but it is not bad at all to work with. You should just establish that the files your application will need for translations can be exported (and possibly imported) from (and possibly to) your Translation Server. You can translate using a web browser or you can translate offline and then proceed to upload your edited files and batch-apply all your changed translations. Another web-based translation tool that seems to provide a similar yet more modern approach than Pootle (looks better and has tight version control integration), while being based on Translate Toolkit as well, is Weblate. This is also open-source and can be deployed to your server of choice.
To provide some more insight, if you look at Translation Related File Formats, you will have a better idea of what Pootle and Translate Toolkit are capable of exporting/importing. From that list and from my translation experience, I can tell you that INI files are used for translations in Joomla! core and extensions, PHP translation arrays are used for translations in Yii applications, and Qt Linguist TS files are used, as mentioned before, for translations in Qt applications. I have also experimented with GNU gettext, which is the endorsed by the Free Software Foundation library for localization. GNU gettext uses PO files for translations, which can be handled by Translate Toolkit.
The core idea behind all localization approaches, no matter what the platform is, is more or less the same. You design your code having a specific main language in mind and use this language in your code. English would be the ideal choice but this is not necessary. You should choose a language that all developers can work with, a language that does not slow down developing (while looking for a couple of labels for buttons, you would not like to think over just one label for minutes), and a language that is used by your main target audience, only in the case that a main target audience exists and at the same time developing with another language in mind would possibly make the application feel unnatural for your main target audience, after it has been translated to your main target audience’s language. This is also the language that all your translators will receive the source language strings in (and, therefore, have as a point of reference), in order to translate into all other target languages. You may have to compromise, because we are talking about one and only one language for developing. Moving on, anytime during developing that you need to insert a language string in your code, you do not insert it directly, but you enclose it in a special function call that is specified by the localization platform you use. In a Qt application, for instance, instead of
QLabel *label = new QLabel("Password:"); you would write
QLabel *label = new QLabel(tr("Password:"));. During the execution of the application, the user language is determined inside the
tr function call, the appropriate language file for the user language is browsed, and the translated message corresponding to
"Password:" for the user language is retrieved and used as a label. Language determination/definition is a separate mechanism that essentially gets/sets a global/static variable, the one that is looked up when the
tr function is called in the example above. What may be handled specially by each platform is plural forms (conditional translation based on some parameter). In Yii, for instance, you could have
'n==1#one book|n>1#many books' as the translation string. In your application you would use
Yii::t('app', 'n==1#one book|n>1#many books', 1);, that is you would also supply the actual number as a parameter, so that the correct form can be used (the
'app' parameter used in the translation function refers to a specific translation category named
app, since, under every language, you could use different translation categories for parts of your application).
To add some final insight, using a generic common back-end for translations would allow you to re-use the vast majority of your translated strings, when migrating from one framework to another, or even if multiple different implementations exist for the same application at the same time, e.g. a browser-based application exists along with a native application. Plural forms would require special handling and separate translations for the same language string because of being really platform-specific (but, if needed, most of the plural forms can be eliminated by moving the condition from the translation string domain to the code domain). But the vast majority of the translations in an application are direct mappings of one string to another. Some frameworks, like Qt, have tools for scanning the source files and updating translation files based on new uses of the special translation function (
tr in Qt). If such a tool exists for the framework of your choice, you would not need to add a translation mapping manually to a translation file. After scanning the source files, the mapping would appear in the translation files, defaulting to the original string as its translation and waiting for the translated string to replace it. Investigate the possible workflows before committing to an approach.