A good translation should read naturally and respect the conventions of the target language. One factor which plays a significant role in creating a natural end result is context-aware string translation. Providing context in the form of developer comments is not too difficult for normal strings, however, consider context for placeholders: how and where can you add context to these?
“One Developer, two Developers, three Developers…..”
<key>%d month(s)</key> <string>%d month(s)</string>
How should this be translated to give a great end result? Are we ok with ‘0 month’ or ‘1 months’? The fact is that although this is quite common and has almost become acceptable, it does not read naturally nor is it correct. Furthermore, things get considerably worse in other languages that have more intricate pluralization rules.
In English two language rules will cover all cardinal numbers: one rule for the singular ‘one month’ and another to cover more than one month. This is different in Polish, in which, for example, there are four basic cases required to cover the cardinal numbers: one, few, many and other. See the full list of language plural rules at unicode.org. It is not possible to translate the above key-value pair into Polish as there are a number of different translations for ‘month’ which depend on the value passed into %d.
<key>%d months(s)</key> <string>%d miesiąc</string> / _1 month_ /
<string>%d miesiące</string> / _3 months_ /
<string>%d miesięcy</string> / _5 months_ /
<string>%d miesiąca</string> / _1.5 months_ /
So how does the app developer deal with this? Are there any solutions?
Enter ‘stringsdict’, an intermediary translation file format that was created to deal with this very issue.
What are stringsdict files?
Starting with iOS 7, Apple provided native support for pluralization and gender rules in the form of the .stringsdict file. It is an extension of the .strings format that allows translators to provide different forms of plurals depending on the magnitude of the number being used.
With a .stringsdict file you can supply a format string for each category of numbers a given language defines and get language-specific versions of each. Apple has made provision for 6 number categories and defined a key for each. See ‘Handling Noun Plurals and Units of Measurement’ in Apple’s guide to localizing your app.
How do they work?
The .stringsdict file is a plist file that consists of key-value pairs. Similarly to a regular .strings file, the key is the portion that is passed to the NSLocalizedString macro and gets replaced by localized text.
Instead of being localized text, the value in a .stringdict file defines a plural rule for the key.
A plural rule is a set of key-value pairs where the special key ‘NSStringLocalizedFormatKey’ defines a string with placeholder variables in it and the other keys define sets of key-values pairs that will replace the variables in that string with localized text from the relevant category.
The file enables the developer to better manage numbers/quantities by replacing the common one-to-one mapping with a more accurate and flexible one-to-six mapping. Now English plurals can be represented correctly and we can get ‘0 months’ and ‘1 month’:
<key>one</key> <string>%d month</string>
<key>other</key> <string>%d months</string>
Furthermore, it is now possible to provide correct localizations into languages that have a more complicated set of rules for dealing with plurals, like Polish.
<key>one</key> <string>%d miesiąc</string> / _1 month_ /
<key>few</key> <string>%d miesiące</string> / _2 months_ /
<key>many</key> <string>%d miesięcy</string> / _5 months_ /
<key>other</key> <string>%d miesiąca</string> / _1.5 months_ /
Each key-value pair provides a plural rule for a specific string and the means to provide unique, natural, and accurate translations for each. Some languages (for example, Arabic) use the full set of six keys that the .stringsdict format supports.
A full example of an entry in a .stringsdict file for the above case would be:
This would be used in the exact same way as you would use a .strings file:
textField.monthsAgo = NSLocalizedString(@"%d month(s)", @"Number of months since app installation.");