Category: Blog, Android, Development

Android Strings XML Tips & Tricks

Android Strings XML Tips & Tricks

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

Post also published on Medium. Click and Follow us.

How can percents make code sick?

By default, string resources are so-called formatted. This 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 a 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 the formatted="false" attribute is the proper solution (in fact, there is no other direct suggestions on how to repair this issue). If you add the suggested attribute, the lint error will disappear. However, the correct fix in such cases is to make the 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 any 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. The default translation (located in values directory) will be in the most common language in the 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 it is quite cumbersome and, 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 this is used only by Android Studio spellchecker and lint. It won’t affect any behaviour at runtime! This is especially true in some areas – it won’t change plural rules, for instance. What does this 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, but 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 the 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 the other quantity will be used in case of locales unsupported by the app. Here is a modified sample plural including this quantity:

Why are inserts 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 this is quite inconvenient. In the case of text changes, you have to remember to update it in several places. However, there is a better solution. You can just reference already existing strings, like this:

Entities to the rescue

What about cases where only part of the text is repeated? For example, the application name is used inside several texts. Well, we can create a 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, the author’s or application name and other proper names. If you only provide 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 the given string as untranslatable. Such resources not only don’t require translations, but must not even have any. Translations of untranslatable text will cause the appropriate lint error. This feature is also supported by Android Studio’s Translation Editor. Here is an example of an untranslatable string:

The translatable attribute only works on a 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.

About the author

Karol Wrótniak

Karol Wrótniak

Mobile Developer

Flutter & Android Developer with 12 years of experience. A warhorse with impressive experience and skills in native and Flutter app development. Karol is probably the most active contributor to open source libraries you've ever met. He develops Gradle plugins and Bitrise steps, and he is engaged in many projects, in particular those related to testing.

Karol has been engaged as a speaker in many events and meetups like DevFest, 4Developers Wrocław, JDD Conference, Linux Academy, and more. He is an active member of Google Developers Group Wrocław, Flutter Wrocław, and Bitrise User Group.