Localizing Resources

Language settings are part of the device’s configuration. (See the section called Device Configuration Changes and the Activity Lifecycle in Chapter 3 for an overview of device configuration.) Android provides qualifiers for different languages, just as it does for screen orientation, screen size, and other configuration factors. This makes localization straightforward: You create resource subdirectories with the desired language configuration qualifier and put the alternative resources in them. The Android resource system does the rest.

In your CriminalIntent project, create a new values resource file: In the project tool window, right-click res/values/ and select NewValues resource file. Enter strings for the File name. Leave the Source set option set to main and make sure Directory name is set to values.

Select Locale in the Available qualifiers list and click the >> button to move Locale to the Chosen qualifiers section. Select es: Spanish in the Language list. Any Region will be automatically selected in the Specific Region Only list – which is just what you want, so leave that selection be.

The resulting New Resource File window should look similar to Figure 17.2.

Figure 17.2  Adding a qualified strings resource file

Adding a qualified strings resource file

Note that Android Studio automatically changes the Directory name field to values-es. The language configuration qualifiers are taken from ISO 639-1 codes, and each consists of two characters. For Spanish, the qualifier is -es.

Click OK. The new strings.xml file will be listed under res/values, with (es) after its name. The strings files are grouped together in the project tool window’s Android view (Figure 17.3).

Figure 17.3  Viewing new strings.xml in Android view

Viewing new strings.xml in Android view

However, if you explore the directory structure, you will see that your project now contains an additional values directory: res/values-es. The newly generated strings.xml is located inside of this new directory (Figure 17.4).

Figure 17.4  Viewing new strings.xml in Project view

Viewing new strings.xml in Project view

Now it is time to make the magic happen. Add Spanish versions of all your strings to res/values-es/strings.xml. (If you do not wish to type these strings in, copy the contents from the solutions file at www.bignerdranch.com/​solutions/​AndroidProgramming4e.zip.)

Listing 17.1  Adding Spanish alternatives for string resources (res/values-es/strings.xml)

<resources>
    <string name="app_name">IntentoCriminal</string>
    <string name="crime_title_hint">Introduzca un título para el crimen.</string>
    <string name="crime_title_label">Título</string>
    <string name="crime_details_label">Detalles</string>
    <string name="crime_solved_label">Solucionado</string>
    <string name="new_crime">Crimen Nuevo</string>
    <string name="crime_suspect_text">Elegir Sospechoso</string>
    <string name="crime_report_text">Enviar el Informe del Crimen</string>
    <string name="crime_report">%1$s!
        El crimen fue descubierto el %2$s. %3$s, y %4$s
    </string>
    <string name="crime_report_solved">El caso está resuelto</string>
    <string name="crime_report_unsolved">El caso no está resuelto</string>
    <string name="crime_report_no_suspect">no hay sospechoso.</string>
    <string name="crime_report_suspect">el/la sospechoso/a es %s.</string>
    <string name="crime_report_subject">IntentoCriminal Informe del Crimen</string>
    <string name="send_report">Enviar el informe del crimen a través de</string>
</resources>

That is all you have to do to provide localized string resources for your app. To confirm, change your device’s settings to Spanish by opening Settings and finding the language settings. Depending on your version of Android, these settings will be labeled Language and input, Language and Keyboard, or something similar.

When you get to a list of language options, choose a setting for Español. The region (España or Estados Unidos) will not matter, because the qualification -es matches both. (Note that on newer versions of Android, users can select multiple languages and assign a priority order. If you are on a newer device, make sure Español appears first in your language settings list.)

Now run CriminalIntent and bask in the glory of your newly localized app. When you are done basking, return your device’s language setting to English. Look for Ajustes or Configuración (Settings) in the launcher and find the setting that includes Idioma (Language).

Default resources

The configuration qualifier for English is -en. In a fit of localization, you might think to rename your existing values directory to values-en. This is not a good idea, but pretend for a moment you did just that: Your hypothetical update means your app now has an English strings.xml in values-en and a Spanish strings.xml in values-es.

Your newly updated app will build just fine. It will also run just fine on devices with the language set to Spanish or English. But what happens if the user’s device language is set to Italian? Bad things. Very bad things. If the app is allowed to run, Android will not find string resources that match the current configuration. This will cause your app to crash with a Resources.NotFoundException.

Android Studio takes steps to save you from this fate. The Android Asset Packaging Tool (AAPT) does many checks while packaging up your resources. If AAPT finds that you are using resources that are not included in the default resource files, it will throw an error at compile time:

    Android resource linking failed

    warn: removing resource
    com.bignerdranch.android.criminalintent:string/crime_title_label
    without required default value.

    AAPT: error: resource string/crime_title_label
    (aka com.bignerdranch.android.criminalintent:string/crime_title_label)
    not found.

    error: failed linking file resources.

The moral of the story is this: Provide a default resource for each of your resources. Resources in unqualified resource directories are your default resources. Default resources will be used if no match for the current device configuration is found. Your app will misbehave if Android looks for a resource and cannot find either one that matches the device configuration or a default.

Screen density works differently

The exception to providing default resources is for screen density. A project’s drawable directories are typically qualified for screen density with -mdpi, -xxhdpi, etc., as you have seen. However, Android’s decision about which drawable resource to use is not a simple matter of matching the device’s screen density or defaulting to an unqualified directory if there is no match.

The choice is based on a combination of screen size and density, and Android may choose a drawable from a directory that is qualified with a lower or higher density than the device and then scale the drawable. There are more details in the docs at developer.android.com/​guide/​practices/​screens_support.html, but the important point is that putting default drawable resources in res/drawable/ is not necessary.

Checking string coverage using the Translations Editor

As the number of languages you support grows, making sure you provide a version of each string for each language becomes more difficult. Luckily, Android Studio provides a handy Translations Editor to see all of your translations in one place. Before starting, open your default strings.xml and comment out crime_title_label and crime_details_label (Listing 17.2).

Listing 17.2  Commenting out strings (res/values/strings.xml)

<resources>
    <string name="app_name">CriminalIntent</string>
    <string name="crime_title_hint">Enter a title for the crime.</string>
    <!--<string name="crime_title_label">Title</string>-->
    <!--<string name="crime_details_label">Details</string>-->
    <string name="crime_solved_label">Solved</string>
    ...
</resources>

To launch the Translations Editor, right-click one of the strings.xml files in the project tool window and select Open Translations Editor. The Translations Editor displays all of the app’s strings and the translation status for each of the languages your app currently provides any qualified string values for. Since crime_title_label and crime_details_label are commented out, you will see those field names in red (Figure 17.5).

Figure 17.5  Using the Translations Editor to check your string coverage

Using the Translations Editor to check your string coverage

This provides an easy list of resources to add to your project. Find missing resources in any locale configuration and add them to the related strings file.

Although you can add strings right in the Translations Editor, in your case you only need to uncomment crime_title_label and crime_details_label. Do that before moving on.

Targeting a region

You can qualify a resource directory with a language-plus-region qualifier that targets resources even more specifically. For instance, the qualifier for Spanish spoken in Spain is -es-rES, where the r denotes a region qualifier and ES is the ISO 3166-1-alpha-2 code for Spain. Configuration qualifiers are not case sensitive, but it is good to follow Android’s convention here: Use a lowercase language code and an uppercase region code prefixed with a lowercase r.

Note that a language-region qualifier, such as -es-rES, may look like two distinct configuration qualifiers that have been combined, but it is just one. The region is not a valid qualifier on its own.

A resource qualified with both a locale and region has two opportunities for matching a user’s locale. An exact match occurs when both the language and region qualifiers match the user’s locale. If no exact match is found, the system will strip off the region qualifier and look for an exact match for the language only.

The selection of resources when there is not an exact match can vary depending on the device’s Android version. Figure 17.6 shows the locale resource resolution strategy before and after Android Nougat.

Figure 17.6  Locale resolution (pre- and post-Nougat)

Locale resolution (pre- and post-Nougat)

On devices running pre-Nougat versions of Android, if no language match is found, the default (unqualified resource) is used – period.

Nougat and later versions have enhanced locale support, with more locales and the ability to select more than one locale in the device’s settings. The system also uses a more intelligent resource resolution strategy for locale with the aim of showing the correct language as often as possible, even if the app does not provide an exact region match or a nonqualified language match. If no exact match is found on a device running Nougat, and no language-only match is found, the system will look for a resource qualified with the same language but a different region and will use the best match of resources that meet those criteria.

Consider an example. Suppose you set the language on your device to Spanish and your region to Chile (Figure 17.7). An app on your device contains Spanish strings.xml files tailored for Spain and Mexico (in values-es-rES and values-es-rMX). The default values directory contains an English strings.xml.

If your device is running pre-Nougat Android, you will see the English contents of the default values directory. But if your device is running Nougat or later, you will have a better experience: You will see the contents of values-es-rMX/strings.xml – which means you will see Spanish, though not tailored to Chile.

Figure 17.7  Locale resolution example (pre- and post-Nougat)

Locale resolution example (pre- and post-Nougat)

This example is a bit contrived. But it brings up an important point: Provide strings in as general a context as possible, using language-only qualified directories as much as possible and region-qualified directories only when necessary. Rather than maintaining all Spanish user-facing strings in region-qualified directories, this example app would be better off storing most of the Spanish strings in a language-only qualified values-es directory and providing region-qualified strings only for words and phrases that are different in the different regional dialects.

This not only makes maintaining the strings files easier for the programmer but also helps the system resolve the resources on both pre-Nougat devices and Nougat or later devices (by providing a language-only match). Note that this advice goes for all types of alternative resources in the values directories: Provide shared resources in more general directories and include only the resources that need to be tailored in more specifically qualified directories.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
54.225.35.224