Android Strings XML Tips & Tricks
This article shows a few tricks which can help you when developing string resources for Android applications.
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:
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:
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
Create a High-Quality Mobile App with Us
Together, we will get your project off the ground and achieve amazing results
Using XML entities for inclusions is a neat hack but probably not a good idea, since there’s probably no translation tool or service that will support it.
Good point. Glad you mentioned it, because I’ve already wanted to apply it.
I don’t know either any translation tool supporting entities but keep in mind that not all the apps require translations.
If not, then why use string resources at all.
Do you mean not using string resources but hardcoding everything in layouts, manifests and Java/Kotlin code?
Few reasons:
1. String resources are standard location of texts. Just like design patterns. If some text needs to be changed it can be easily found even by a new developer.
2. Plulars need to be placed into resources.
3. Lint checks like common misspellings or dots instead of ellipsis work in resources.
4. It is easier to review/audit string resource files instead of texts spread across bunch of XMLs and Java/Kotlin files.
Hey Karol and thanks for your knowledge contribution to the community.
I find the article’s header image unrelated and a little bit insulting, I’m pretty sure there are other images that relate more to the content.
I’m sure I am not the only person that would expect something different from a technical article.
Thanks for the feedback, I’ve just changed it.
Wow, that top image isn’t offensive it all, very professional… Ahhh, someone got to you already. Shame it was there in the first place. Maybe this was going to be on brazzers blog at first