Android Localization
This document introduces the localization features of the Android SDK and how to access them with Xamarin.
Android Platform Features
This section describes the main localization features of Android. Skip to the next section to see specific code and examples.
Locale
Users choose their language in Settings > Language & input. This selection controls both the language displayed and regional settings used (eg. for date and number formatting).
The current locale can be queried via the current context's Resources
:
var lang = Resources.Configuration.Locale; // eg. "es_ES"
This value will be a locale identifier that contains both a language code and a locale code, separated by an underscore. For reference, here is a list of Java locales and Android-supported locales via StackOverflow.
Common examples include:
en_US
for English (United States)es_ES
for Spanish (Spain)ja_JP
for Japanese (Japan)zh_CN
for Chinese (China)zh_TW
for Chinese (Taiwan)pt_PT
for Portuguese (Portugal)pt_BR
for Portuguese (Brazil)
LOCALE_CHANGED
Android generates android.intent.action.LOCALE_CHANGED
when the user
changes their language selection.
Activities can opt to handle this by setting the android:configChanges
attribute on the activity, like this:
[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",
ConfigurationChanges = ConfigChanges.Locale | ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
Internationalization Basics in Android
Android's localization strategy has the following key parts:
Resource folders to contain localized strings, images, and other resources.
GetText
method, which is used to retrieve localized strings in code@string/id
in AXML files, to automatically place localized strings in layouts.
Resource Folders
Android applications manage most content in resource folders, such as:
- layout - contains AXML layout files.
- drawable - contains images and other drawable resources.
- values - contains strings.
- raw - contains data files.
Most developers are already familiar with the use of dpi suffixes on the drawable directory to provide multiple versions of an image, letting Android choose the correct version for each device. The same mechanism is used to provide multiple language translations by suffixing resource directories with language and culture identifiers.
Note
When specifying a top-level language like es
only
two characters are required; however when specifying a full locale, the
directory name format requires a dash and lowercase r to separate
the two parts, for example pt-rBR or zh-rCN. Compare this to
the value returned in code, which has an underscore (eg. pt_BR
). Both
of these are different to the value .NET CultureInfo
class uses,
which has a dash only (eg. pt-BR
). Keep these differences in mind
when working across Xamarin platforms.
Strings.xml file format
A localized values directory (eg. values-es or values-pt-rBR) should contain a file called Strings.xml that will contain the translated text for that locale.
Each translatable string is an XML element with the resource ID specified
as the name
attribute and the translated string as the value:
<string name="app_name">TaskyL10n</string>
You need to escape according to normal XML rules, and the name
must be a valid Android resource ID (no spaces or dashes). Here is
an example of the default (English) strings file for the example:
values/Strings.xml
<resources>
<string name="app_name">TaskyL10n</string>
<string name="taskadd">Add Task</string>
<string name="taskname">Name</string>
<string name="tasknotes">Notes</string>
<string name="taskdone">Done</string>
<string name="taskcancel">Cancel</string>
</resources>
The Spanish directory values-es contains a file with the same name (Strings.xml) that contains the translations:
values-es/Strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">TaskyLeon</string>
<string name="taskadd">agregar tarea</string>
<string name="taskname">Nombre</string>
<string name="tasknotes">Notas</string>
<string name="taskdone">Completo</string>
<string name="taskcancel">Cancelar</string>
</resources>
With the strings files set-up, the translated values can be referenced in both layouts and code.
AXML Layout Files
To reference localized strings in layout files, use the @string/id
syntax. This
XML snippet from the sample shows text
properties being set with localized
resource IDs (some other attributes have been omitted):
<TextView
android:id="@+id/NameLabel"
android:text="@string/taskname"
... />
<CheckBox
android:id="@+id/chkDone"
android:text="@string/taskdone"
... />
GetText Method
To retrieve translated strings in code, use the GetText
method and
pass the resource ID:
var cancelText = Resources.GetText (Resource.String.taskcancel);
Quantity Strings
Android string resources also let you create quantity strings which allow translators to provide different translations for different quantities, such as:
- "There is 1 task left."
- "There are 2 tasks still to do."
(rather than a generic "There are n task(s) left").
In the Strings.xml
<plurals name="numberOfTasks">
<!--
As a developer, you should always supply "one" and "other"
strings. Your translators will know which strings are actually
needed for their language.
-->
<item quantity="one">There is %d task left.</item>
<item quantity="other">There are %d tasks still to do.</item>
</plurals>
To render the complete string use the GetQuantityString
method, passing the
resource ID and the value to be displayed (which is passed twice). The
second parameter is used by Android to determine which quantity
string to use,
the third parameter is the value actually substituted into the string (both
are required).
var translated = Resources.GetQuantityString (
Resource.Plurals.numberOfTasks, taskcount, taskcount);`
Valid quantity
switches are:
- zero
- one
- two
- few
- many
- other
They're described in more detail in the Android docs.
If a given language does not require 'special' handling, those quantity
strings
will be ignored (for example, English only uses one
and other
; specifying a zero
string will have no effect, it will not be used).
Images
Localized images follow the same rules as strings files: all images referenced in the application should be placed in drawable directories so there is a fallback.
Locale-specific images should then be placed in qualified drawable folders such as drawable-es or drawable-ja (dpi specifiers can also be added).
In this screenshot, four images are saved in the drawable directory, but only one, flag.png, has localized copies in other directories.
Other Resource Types
You can also provide other types of alternative, language-specific resources including layouts, animations, and raw files. This means you could provide a specific screen layout for one or more of your target languages, for example you could create a layout specifically for German that allows for very long text labels.
Android 4.2 introduced support for
right to left (RTL) languages
if you set the application setting android:supportsRtl="true"
. The
resource qualifier "ldrtl"
can be included in a directory name to
contain custom layouts that are designed for RTL display.
For more information on resource directory naming and fallback, refer to the Android docs for providing alternative resources.
App name
The application name is easy to localize by using a @string/id
in for the
MainLauncher
activity:
[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Locale)]
Right-to-Left (RTL) Languages
Android 4.2 and newer provides full support for RTL layouts, described in detail in the Native RTL Support blog.
When using Android 4.2 (API level 17) and newer, alignment values can be
specified with start
and end
instead of left
and right
(for
example android:paddingStart
). There are also new APIs like
LayoutDirection
, TextDirection
, and TextAlignment
to help build
screens that adapt for RTL readers.
The following screenshot shows the localized Tasky sample in Arabic:
The next screenshot shows the localized Tasky sample in Hebrew:
RTL text is localized using Strings.xml files in the same way as LTR text.
Testing
Make sure to thoroughly test the default locale. Your application will crash if the default resources cannot be loaded for some reason (i.e. they are missing).
Emulator Testing
Refer to Google's Testing on an Android Emulator section for instructions on how to set an emulator to a specific locale using the ADB shell.
adb shell setprop persist.sys.locale fr-CA;stop;sleep 5;start
Device Testing
To test on a device, change the language in the Settings app.
Tip
Make a note of the icons and location of the menu items so that you can revert the language to the original setting.
Summary
This article covers the basics of localizing Android applications using the built-in resource handling. You can learn more about i18n and L10n for iOS, Android and cross-platform (including Xamarin.Forms) apps in this cross-platform guide.