INTRODUCTION TO ANDROID LOCALIZATION

Lecture Two: Format Strings and Plurals



In the last article we ran through the basics of internationalization and localization for Android apps and localized one into French. In this lecture, we will share some common localization issues and their solutions.



String Types

Let’s first go through the three types of string resources, all of which you will likely encounter during your l10n process:

a) Strings: Most basic string

<string name="language">language</string>

b) String arrays: List of items organized into a string array

<string-array name="language_array">
  <item>English</item>
  <item>French</item>
</string-array>

c) Quantity strings: Strings that handle pluralization (more on this later)

<plurals name="languages">
  <item quantity="one">%d language</item>
  <item quantity="other">%d languages</item>
</plurals>


Format strings

Let’s say you have a dynamic string:

OneSky translated 1 out of 3 languages.

This can be achieved by the following:

values/strings.xml (default)

<!--%s{username} translated %3$d{num} out of %2$d{total} languages -->
<string name="sentence_test">%1$s translated %2$d out of %3$d languages.</string>

MainActivity.java

/*getString(R.string.sentence_test, “username”, num, total)*/
String sentence = getString(R.string.sentence_test, "OneSky", 1, 3);

Note: If you are unfamiliar with the above format, we recommend reading about Android string formatting.



The Problem

The first issue you would run into is string positioning. For example, if this string was in Chinese, here is what it would look like:

OneSky 翻譯了 3 個語言中的 1 個。

As you can see, the order of the arguments is different from the English version (even if you can’t read Chinese, you’ll notice 3 precedes 1).

So how do we achieve the above result with format strings?



The Answer: Positional Specifiers

One of the handy features of format strings is positional specifiers. You can tell the formatter the order of the arguments by inserting n$ into the format specifier, e.g. %1$s, %2$d, %3$d.

Therefore the format string for Traditional Chinese would look like this:

values-zh-Hant/strings.xml

<!--%s{username}  翻譯了 %3$d{total} 個語言中的 %2$d{num} 個。-->
<string name="sentence_test">%1$s 翻譯了 %3$d 個語言中的 %2$d 個。</string>


Plurals

If you are a detail-minded person you might have noticed another problem in the above example: what if there is only one language in total?

OneSky translated 1 out of 1 languages.  //grammatical mistake

Luckily, Android Studio has nifty string arrays that can handle your second l10n issue: pluralization. Enable pluralization support through these steps:

1) In the default values/strings.xml, insert the following quantity string:

<plurals name="languages">
  <item quantity="one">%d language</item>
  <item quantity="other">%d languages</item>
</plurals>

2) Test the plural form with the following code:

int numLang = 1;
Resources res = getResources();
String numLanguages = res.getQuantityString(R.plurals.languages, numLang, numLang);

3) The first numLang parameter in res.getQuantityString() will return the correct string form while the second numLang parameter replaces the %d placeholder, if present. (Otherwise we only need to call it once.)

4) The string numLanguages should have the value 1 language.



Gender Rules

While Android supports both plural and gender rules, the XML resources file format cannot handle gender rules as of Android Studio v2.2.3. We’ll keep you updated if this gets resolved in a future release.



Download sample file for Android Localization Lectures!

Android Localization Guide-sample file



<  Go to Lecture One: A Beginner’s Guide

    Go to Lecture Three: Best Practices  >

Learn localization and reach global markets like these do.

  • Tango
  • Viber
  • Day One
  • Hootsuite
  • 500px
  • Truecaller
  • Glide
  • Wish
  • Secret