Android Strings XML Tips & Tricks

Karol Wrótniak
AndroidPub
Published in
4 min readJan 17, 2018

--

This article shows a few tricks which can help you developing string resources for Android applications.

How can percents make code sick?

By default string resources are so-called formatted. It means that they can be potentially used for formatting. Here is a simple example:

Lint performs checks on formatted strings and will complain if it encounters string like this: %d of %d left. The error message in such case is Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?.

One may think that adding formatted="false" attribute is a proper solution (in fact there is no other direct suggestions how to repair that). If you add suggested attribute lint error will disappear. However, the correct fix in such cases is to make format positional. In this example it would be %1$d of %2$d left.

On the other hand formatted="false" is intended for strings where percent signs are not parts of format specifiers, e.g. Equation: a=50%b+20%c.

The secret ingredient

Assume that you are developing an app for local market only and there is no need for English texts. Default translation (located in values directory) will be in the most common language in given area e.g. Polish in Poland or German in Switzerland. Since there is no locale qualifier in a directory name, English is assumed. This leads to several problems. Firstly, Android Studio spellchecker will complain about most of the words.

Moreover, lint may detect some words as common misspellings and produce warnings as a result. For example word adres is correct in Polish but is a common misspelling for English address. Here are the Quick fixes suggested by Android Studio:

False typo

Unfortunately the best one is not on the list. Note that adding tools:ignore="Typos" attribute to each tag works but is quite cumbersome thus not the best solution.

tools:locale attribute is what can really help. It tells the tools what language is used inside a file. You can add it to the resources tag like this:

Keep in mind that it is used only by Android Studio spellchecker and lint. It won’t affect any behaviour at runtime! Especially it won’t change plural rules. What does it mean in practice?

Let’s consider the same plural resource with the number of songs from the linked official documentation, but with Polish used as a default translation (located in values directory) and without English at all. Note that the current version of lint will complain about missing many quantity, we'll come back to this in the next chapter. Here is the snippet:

For example, if the language of the device is set to Polish and actual number of songs is 5, the resulting text is Znaleziono 5 piosenek. because 5 in Polish belongs to the many quantity. However, in other languages, the same number may be mapped to different quantities. Take a look at the table below:

Android Strings XML Tips & Tricks

CLDR cardinal integer chart fragment. Full version can be found on unicode.org

For example, if the language is set to Lithuanian we’ll get Znaleziono 5 piosenki. which is incorrect in Polish. However, if a device is running Android 7 or newer (API 24+) and you specify resConfigs 'pl' (see DSL documentation for more information). Then other quantity will be used in case of locales unsupported by app. Here is modified sample plural including that quantity:

Why inserts are sexy?

Let’s say that you have to repeat some text in a few places, e.g. some screen name is used as a label on a list and as a title on that screen itself. Of course, you can just copy and paste them but it is quite inconvenient. In case of text change, you have to remember to update it in several places. However, there is a better solution. You can just reference already existing strings, like that:

Entities to the rescue

What about case when only part of the text is repeated? For example application name is used inside several texts. Well, we can create custom internal XML entity for that. Then, it can used just like standard character entities (& etc.). Look at the following example:

To translate or not to translate?

Some texts are not meant to be translated. For example author’s or application name and other proper names. If you just provide only default translations for some strings, omitting them in language-specific files, lint will complain about missing translations. Of course you can suppress this error but fortunately, there is a cleaner solution.

translatable="false" attribute marks given string as untranslatable. Such resources not only don't require translations but even must not have any. Translation of untranslatable text will cause appropriate lint error. That feature is also supported by Android Studio's Translation Editor. Here is an example of untranslatable string:

Translatable attribute works only on single string level. If you have a lot of them you can group them into one file called donottranslate.xml. Lint will treat all of them as untranslatable.

--

--

Karol Wrótniak
AndroidPub

Android Developer @ Droids On Roids, Lead @ GDG Wrocław, Author @ Kodeco