Android Apps Localization

Hello everyone šŸ™‚

As you might have noticed, I’ve recently decided to take a longer break in DSP competition. Few things to do, Easter in the meantime… but of course I didn’t give up and today I’m back šŸ˜‰

In thisĀ post I’d like to show you how do we localize Android apps. Let’s see!

What is localization ?

Generally, localizationĀ is a process of adaptingĀ the product or application to specific markets by adjusting its language and cultural resourcesĀ accordingly.

People often think that localization is only a process of translating documentation and user interface into multiple languages, but in fact it may concern many other not less important topics, e.g. formats of numeric values or dates, currencies, numbers comparison/sorting methods, symbols, national flags or even country-specific law requirements.

Android supports app’s resources localization in pretty easy way. We can quite conveniently provide different versions of strings, images and layouts used in our application for different languages/regions. Let’s take a look atĀ the basics of Android app’s localization.

Android localization basics

InĀ every Android application, localization is based on the language userĀ has set on his/her device. The language can be changed in Settings -> Language & input. Changing the language in this place affects both user interface’s language and region-specific settings (e.g. dates formats).

To retrieve the current locale (constant/object representing selected language) in code the following statement can be used:

var currentLang = Resources.Configuration.Locale;

In case user has Polish language set on his/her phone, currentLang variable would contain “pl_PL” locale symbol. For the full list of locales symbols, see for example this list.

Basically, everything that is placed under Resources folder in Android solution can be localized. All of you probably haveĀ values folder in Resources, which contains Strings.xml file. We’ll see more details about this file in a while, but to present the ease of localization to you, it’s enough to create another folder underĀ Resources called e.g.Ā values-pl, which makes retrieving strings from Strings.xml file located in this folder on devices with language set to Polish. Simple as that. The same can be done with every type of resource. It means we can create totally different layouts of our Activities or use different images (e.g. countries’ flags) depending on user’s device’s language.

Strings localization

Strings.xml file

To-be-localized strings (BTW, I think that we should do it straightaway with all strings we use in our app) should be put in values/Strings.xml file, which has the following structure:


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ApplicationName">MoneyBack</string>
<string name="titleMenu">Menu:</string>
<string name="btnPeople">People management</string>
<string name="titleName">Name</string>
<string name="titleLastName">Last name</string>
<string name="titlePhoneNumber">Phone number</string>
<string name="btnSavePerson">Save person</string>
<string name="btnPeopleList">List of people</string>
<string name="peopleListTitle">List of people</string>
</resources>

view raw

Strings.xml

hosted with ❤ by GitHub

The file is built in accordance with standard XML rules. The name represents Android resource ID (cannot contain any spaces or dashes) to which we will refer from code and other places in order to retrieve the value of this resource, which is placed between “>” and “<” characters.

For instance, first resource from above-pastedĀ Strings.xml hasĀ nameĀ = “ApplicationName” and value = “MoneyBack”.

As mentioned in the previous paragraph, I also created Strings.xml file in values-pl folder, containing the same resources’ Polish translations. The contents of values-pl/Strings.xml file:


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ApplicationName">MoneyBack</string>
<string name="titleMenu">Menu:</string>
<string name="btnPeople">Zarządzaj osobami</string>
<string name="titleName">Imię</string>
<string name="titleLastName">Nazwisko</string>
<string name="titlePhoneNumber">Numer telefonu</string>
<string name="btnSavePerson">Zapisz osobę</string>
<string name="btnPeopleList">Lista osĆ³b</string>
<string name="peopleListTitle">Lista osĆ³b</string>
</resources>

view raw

Strings.xml

hosted with ❤ by GitHub

Usage in layout files

In our Activities’ layout files (AXML) we can retrieve resources’ values by using @string/id syntax. For example, TextView‘s text can be set in the following way:


<TextView
android:text="@string/titleMenu"
android:id="@+id/titleMenu" />

view raw

Main.axml

hosted with ❤ by GitHub

It can be used exactly the same way in the UI designer in Visual Studio.

Usage directly in code

In the code we can retrieve values of particular resources using Resources.GetTextĀ method giving it selected resource’s id asĀ Resource.String class’s property:

stringĀ titleMenuText = Resources.GetText(Resource.String.titleMenu);

With all strings translated, I can see UI ofĀ MoneyBack translated when my device’s language is set to Polish:

Quantity strings

Very interesting concept are so called quantity strings. It allows to define differently formatted strings depending on a number of some elements determined at runtime. For instance, on the list of people we could have the following strings displayed depending on the number of people:

“There is 1 person in your database.”

“There are 2 people in your database.”

To declare such kind of quantity string, we’d add to Strings.xml the following section:


<plurals name="numberOfPeople">
<item quantity="one">There is %d person in your database.</item>
<item quantity="other">There are %d people in your database..</item>
</plurals>

To illustrate: in order to retrieve and format appropriate string depending on value stored in numPeople variable, the following code might be used:

var text = Resources.GetQuantityString(Resource.Plurals.numberOfPeople, numPeople, numPeople);

Second parameter passed is used to determine which string (plural) to use, and third parameter is the actual value passed to the final string (in the place of %d in that case).

TheĀ quantity of each plural can contain one of the following values:

  • zero
  • one
  • two
  • few
  • many
  • other

More details can be found here.

Application’s/Activity’s name

We can also localize the name of our app, by using string resource in the ActivityAttributeĀ defined on MainActivity:

[Activity(Label = "@string/ApplicationName", MainLauncher = true, Icon = "@drawable/icon")]

The same can be done for any of our app’s activities. However, be careful here if you are referencing your main Android project from another one (e.g. from tests project) – I’ve experienced really annoying issue with that (more details below).

Other resources

As we already said,Ā not only strings can be localized. You can localize any kind of resources placed within ResourcesĀ folder, for example images or data files.

The file ā€œobj\Debug\android\bin\packaged_resourcesā€ does not exist

Two weeks ago, when I finally decided to take a break in publishing DSP posts, I wanted to work onĀ MoneyBack a bit, however I encountered very frustrating issue, which I even described in this StackOverflow post. I’ve been fighting with that problem for few days and I still actually don’t know the real causeĀ of the issue.

Basically, when IĀ used resource string on my PeopleListActivity in order to translate its title:

[Activity(Label = "@string/peopleListTitle")]

I couldn’t build my MoneyBack.Android.TestsĀ (yes, different project!) project. I was getting the following build error message:

ResourceNotFound.JPG
Error during building Android tests project

I explored all existing forums threads on this topic and couldn’t resolve this issue. Finally,Ā by setting build output verbosity to Diagnostic in Tools -> Options -> Projects and Solutions -> Build and RunĀ I was able to see the detailed error my build process is giving. It was telling me thatĀ @string/peopleListTitleĀ doesn’t exist (or something similar). So when I changed theĀ Label‘s value inĀ ActivityAttribute to use a string directly (not taken as a resource), it worked fine and the build passed.

Today I tried once more to use resource string, obviously getting the same error message. Then I realized that my MoneyBack.Android.Tests project is referencing Ā MoneyBack project in which I define those somehow missing strings:

ResourceNotFound_Test_Reference.JPG
Tests project referencing the main one

so I removed that reference (commenting out my unit tests which use MoneyBack‘s logic) and the build worked fine. ApparentlyĀ when trying to build tests project, which references the main one, in which my strings are defined, it somehow needs those strings resources to be present in tests project’s output directory.Ā I have no idea why, because I’m not directly using those strings resources in my tests project.

Then I added the reference back and in MoneyBack.Android.Tests project I just created values folder and copy-pasted Strings.xml file to it from the MoneyBack project:

Resources_Strings_Copied.JPG
Strings.xml copied into test project

and it builds OK!

Does any of you have some idea why it may happen?Ā If you have a clue, you can answer here or even on SO.

For me it seems like a bug in the build process. I wanted to share it with you, because I wasted so much time because of this issue and maybe some of you will also find it useful.

BTW, I really recommend usingĀ Diagnostic verbosity of the build output for debugging such issues.

Summary

We’ve seen how Android application can be easily localized. I really recommend to put all strings visible for the end user from the beginning in Strings.xml file. Thanks to that, in case our application needs to be localized, we can even hire/ask some foreign languages’ interpreters to create country-specificĀ values folder and translate strings resources conveniently. This is even very common in mobile apps communities, that people who are non-technical can contribute to the project by translating the application into their own language.

I hope I won’t meet any other issues like the one I described today on my further DSP way šŸ™‚ It wouldĀ allow me to write more stuff here and hopefully implement some usable app finally! Keep your fingers crossed šŸ™‚

PS: If I already mentioned taking breaks in DSP competition, I will also take one more during the first week of May (1-5.05.2017). In case anyone cares šŸ˜‰

 

 

.NET full stack web developer & digital nomad
0 0 votes
Article Rating
Subscribe
Notify of
guest
12 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Cosi
Cosi
7 years ago

Hello Dawid,

To make Android app localization a more streamlined process, I warmly recommend you manage your projects with the localization platform https://poeditor.com
It’s a great collaborative tool with a clean interface and many possibilities to automate the l10n workflow (integrations with Github/Bitbucket/Gitlab, Translation Memory etc.)

Cheers,
Cosette

Youenn
Youenn
7 years ago

I’m glad I don’t have to care about localization in my current project ;)!

Did you manage to find the cause of the problem you describe at the end of your post?

Youenn
Youenn
7 years ago

It is weird indeed. It would understand if you were having issues at runtime, as those resources may be required when the assembly is being loaded. But why it is required at build-time is a mystery. Unless there is a VS service running underneath that needs it for whatever other reason?

Youenn
Youenn
6 years ago

I’m glad I don’t have to care about localization in my current project ;)!

Did you manage to find the cause of the problem you describe at the end of your post?

Dawid Sibiński
Dawid Sibiński
6 years ago
Reply to  Youenn

Hey,
no, I didn’t find the reason behind that error. I don’t get why I cannot build a project, because of missing resources from another project which is only referenced. I will try to explore build’s output once more and if I don’t find anything more, I’ll report a bug to Xamarin, as it seems abnormal.

Youenn
Youenn
6 years ago

It is weird indeed. It would understand if you were having issues at runtime, as those resources may be required when the assembly is being loaded. But why it is required at build-time is a mystery. Unless there is a VS service running underneath that needs it for whatever other reason?

Dawid Sibiński
Dawid Sibiński
6 years ago
Reply to  Youenn

Maybe, but I couldn’t check it anyhow. I think I will just report it in some spare time šŸ˜‰

Cosi
Cosi
6 years ago

Hello Dawid,

To make Android app localization a more streamlined process, I warmly recommend you manage your projects with the localization platform https://poeditor.com
It’s a great collaborative tool with a clean interface and many possibilities to automate the l10n workflow (integrations with Github/Bitbucket/Gitlab, Translation Memory etc.)

Cheers,
Cosette

Dawid Sibiński
Dawid Sibiński
6 years ago
Reply to  Cosi

Hey Cosette,
thank you for this recommendation šŸ™‚ Maybe if my app reaches enough popularity one day, I’ll think of making a use of it!
That only shows how important is localization and how community cares about it.