I've been interested in localization on Android recently. There's a few neat things I've been experimenting with I thought I'd share.

xliff:g

One common problem when sending strings for translation is that some parts of a string should not be localized. For example, suppose I've got this string:

<string name="hello">Hello, %s!</string>

I don't want %s to be touched by any translator - it might break my code! You can use xliff:g to indicate to translators not to translate a string:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="hello">Hello, <xliff:g id="name">%s</xliff:g>!</string> </resources

As an added bonus, you can specify an "example" parameter.

<string name="hello">Hello, <xliff:g id="name" example="Dan Lew">%s</xliff:g>!</string>

If you do that, your code in Android Studio will automatically fold:

R.string.hello --> "Hello, (Dan Lew)!"

Phrase

Phrase is a small library from Square that makes localization clearer. One problem with localization is that the formatting strings ( %1$s , %2$d , etc.) are difficult to interpret (as both a developer and a translator). Wouldn't it be easier to use plain English?

With Phrase, you can turn my previous example into something more readable:

<string name="hello">Hello, {name}!</string>

Then in code you format the string by keyword instead of by position:

Phrase.from(context, R.string.hello) .put("name", "Dan Lew") .format();

If you've ever dealt with strings with more than one positional parameter you'll quickly realize why this is helpful.

Another reason I like Phrase is because it handles HTML in strings well. Without it you have to escape your HTML and then later call Html.fromHtml() , which is ugly. With Phrase you can skip all of that, just using plain HTML in your strings:

<string name="hello">Hello, <b>{name}</b>!</string>

pseudolocalization

Edit April 6, 2015: The pseudolocalization information below is out-of-date. Please refer to this article for the latest information.

In Android 4.3, they added a new locale, "Accented English" (identifier zz_ZZ). The advantange of enabling this locale is finding potential problems with your app - either its inability to handle weird characters or simply finding unlocalized strings.

aapt supports generating a pseudolocalized version of your strings automatically. From the command-line, you can call aapt -c zz_ZZ and it'll generate accented English automatically. For gradle builds, you use resConfig :

defaultConfig { resConfig "zz_ZZ" }

If you're like me, you'll only want test translations generated on debug builds:

android.applicationVariants.all { variant -> if (variant.buildType.isDebuggable()) { variant.mergedFlavor.addResourceConfiguration("zz_ZZ") } }

Watch out - the pseudolocalizer doesn't know which parts of the string to localize and which not. Good thing we just learned about xliff:g! Just make sure to wrap your format parameters (or anything else you don't want changed, like URLs) with xliff:g tags and they won't be touched by the pseudolocalization tool.

Here's my final string, ready for translation, Phrase and pseudolocalization:

<string name="hello">Hello, <xliff:g id="name" example="Dan Lew">{name}</xliff:g>!</string>

It may seem like a lot, but trust me - when it comes to localization, you want to help your translators as much as possible so you can get a high-quality, accurate depiction of your app in other locales.