Chapter 18. Localization

This chapter covers

  • The need for localization
  • Strategies for localizing an application
  • Dynamic localization in Java
  • Obstacles to late localization

Android is a worldwide open platform gaining market share at a rapid pace. As Android reaches into new markets globally, the opportunity for mobile developers to distribute applications is reaching a level previously enjoyed by only the most successful of software products and projects. You can deploy an application across the globe, have the Google Marketplace handle the commercial transaction, and receive a royalty check. And you can accomplish all this without ever leaving your home office or dorm room!

To sell an application worldwide successfully, you must target it to a broad and diverse audience. English enjoys a broad acceptance and practice, and therefore you can expect that an English language application will sell well globally, but why give up on sales opportunities to the broader non-English-speaking Android market? In its simplest approach, this means translation into multiple languages. But there’s more! Beyond language translation, an application needs to properly handle dates and times, number and currency formats, and for some applications unit of measure. This chapter is an introduction to the localization capabilities of the Android platform.

In this chapter we cover the topics required for localizing an application. You’ll learn high-level strategies for localizing an application, and you’ll take a hands-on approach to converting an existing application to another language. Looking back to chapter 12’s Field Service application, you’ll refactor that code to be localization ready and then translate it to Spanish. We demonstrate the localized version of the application through screenshots throughout the chapter.

We conclude the chapter with a discussion of challenges of localizing an application as an afterthought rather than designing for localization from the start.

We think it’s only fair to note that the author of this chapter is a native English speaker and his knowledge of any languages beyond English involves computer programming: Java, C, C#, Objective-C, and so on. If you’re one of the talented and fortunate among us who can speak numerous languages, please bear with the rest of us as we broaden our horizons to the global scene.

18.1. The need for localization

For many programmers there’s only one language: Java. Of course the world is larger than one programming language, and it’s much larger than a single spoken and written language. The majority of computer users choose a language when they set up their computer and never think twice about the decision. In fact, after the initial setup many of the resources related to other languages may even be deleted from the computer or phone, to save storage space. If this describes your experience, you’re not alone! The aim of this chapter is to equip you to navigate the task of localizing an Android application and in the process reach a broader audience. As a side benefit, you’ll likely find that you look at application development differently, even if you never pursue localization of your own applications.

The reasons for localizing an application are manifold. For a commercial application, there are numerous markets to reach; there’s no need to limit your sales to a single marketplace. Your application may be bound for some cultural reasons to a specific region, but many applications such as games, utilities, and productivity tools are of universal interest and appeal. Games in particular are often relatively light in textual components, with the majority of the text constrained to settings screens and help files. It’s to the developer’s advantage to access additional markets to increase sales volume. Volume is important, considering the low price point of most mobile applications.

Even if your application isn’t designed to generate sales revenue directly, its purpose may be to help build your brand and expand your influence. If you’re part of an organization with a presence beyond your home country, localization is important to you as well.

Incredibly, the market reach of the mobile phone is greater worldwide than that of the personal computer. People even have cell phones ahead of running water in some parts of the globe. Many of these cell phones run a version of the Android OS, so as an Android developer, you can reach a large and diverse market. A small amount of revenue across numerous transactions can really add up!

Whether your purpose in localizing an application is to increase sales or to reach a new market for noncommercial reasons, you need a strategy and some practical skills, both of which you’ll learn in this chapter. Before jumping into the details of localizing an application, let’s examine the concept of a locale.

18.2. Exploring locales

A locale is generally referenced as a short character code including both the language and the geographic region. The origin and meaning of these values stem from political actions and boundaries, both of which change over time. Our discussion should be considered practical and hopefully useful rather than being a treatise on the history, meaning, and minutia of the “official” definition of locale, which is elusive.

As language and regional barriers are blurred thanks to technology, the concept of a locale has been employed imperfectly to aid electronic communication. The ISO format for a locale identifier is a short character code of the following syntax:

language_REGION

where the language is represented first as two lowercase characters and followed by the region, which is represented as two uppercase characters. For example, the locale setting most Android phones employ in the United Kingdom is en_GB for “English, Great Britain.” In Australia, the value is en_AU. en_US is the locale for English in the United States. Figure 18.1 shows an Android emulator instance indicating the various flavors of English locales in the Customize Locale application.

Figure 18.1. English locales on Android emulator

To access the available locales on an Android device, select Language & Keyboard from the Settings app, then tap on Select Language. This presents the installed locale options, as shown in figure 18.2.

Figure 18.2. On-device locale options

When you speak of a locale, you often think of language: English, Spanish, Chinese, Polish, and so forth. Locale is more about orthography, or the rules for the written language. But the topic of localization encompasses more than just words. For example, Great Britain and the United States share a common language: English. The differences extend beyond how the language is used and how certain words are spelled. Consider the formatting of dates, which differs on either side of the Atlantic Ocean. In the United States, it’s common to format a date with the month preceding the day: MM/DD/YYYY. In the UK, it’s more common to see the day of the month listed first: DD/MM/YYYY.

As an Android developer, you must keep not only written language in mind, but also the formatting of dates, times, and numbers that users can customize. These differences are more than trivia; they have a direct impact on how an application is coded, how it behaves, and importantly, how it’s tested prior to release. The Date & Time settings are shown in a separate preferences screen, as you can see in figure 18.3.

Figure 18.3. Date and time settings

As the use of speech technology improves and becomes more heavily adopted, the spoken word will also be germane to the topic of localization.

Localization in practice entails more than just picking a language, so let’s talk strategy on localizing an Android application.

18.3. Strategies for localizing an application

Ideally an application is built from the “top down” with localization[1] in mind from day one. If you always take this approach from the start, congratulations, this topic will be a breeze for you. But if you’ve ever written an application that has some hard-coded strings or perhaps some code that makes specific assumptions about status codes or date formatting, you have some work to do to make your applications play nicely across multiple locales.

1 Localization is the how to, and the why. Frank Ableson’s post on Linux Magazine scratches the surface: http://www.linux-mag.com/id/7794.

There are a number of perspectives on localization. We won’t cover all of them, but the discussion that follows should give you a good foundation for localizing your application. Throughout this chapter, most of the code examples we use are from a localized variant of the Field Service application you met in chapter 12. The code in chapter 12 is not localized. The chapter 20 code is both localized and is additionally translated into Spanish. Let’s get started!

18.3.1. Identifying target locales and data

In all likelihood, you’ll develop your Android application in your native language and your initial target deployment may be in that same language. Your application may be aimed at a specific people group and a specific language. Whether you’re targeting a broader audience or a specific single market, it’s a good idea to always keep your target market in mind.

For example, in the Field Service application, you may have users, customers, and dispatchers distributed anywhere in the world. This means that you need to keep the entire infrastructure in mind, not just the mobile application. You might congratulate yourself for making your application play nicely in the fr_FR locale settings, but if all the application data is still shown in English, you’re missing a vital element of the bigger objective. So not only does your mobile code need to be localized, but the entire infrastructure needs to keep locale in focus.

Data generated on the server may require on-the-fly translation. Perhaps a simpler approach is to filter query results based on the specified language. The device’s locale can be programmatically obtained at runtime using the toString() method of the Locale class. This is shown in the following listing and demonstrated in figure 18.4 and figure 18.5.

Figure 18.4. en_US locale

Figure 18.5. es_ES locale

Listing 18.1. Getting current locale at runtime
private void RefreshUserInfo() {
 final TextView emaillabel = (TextView) findViewById(R.id.emailaddresslabel);
            emaillabel.setText(this.getString(R.string.user) +": " +
this.myprefs.getEmail() + "
" + this.getString(R.string.server)+ ": " +
 this.myprefs.getServer() + "
" +
   this.getString(R.string.locale) + ":" + Locale.getDefault().toString()

            );
    }

You obtain a reference to a TextView widget for displaying textual information at runtime. The get-Default() static method returns the currently selected locale. The toString() method displays the ISO format of the locale.

When submitting a request to a server-side application, this locale value can be passed along as a query parameter:

http://<servername>/somepage.php?a=b&c=d&locale=en_US

How the server side handles the query is application-specific and beyond our discussion here. Keep in mind that localization is more than the translation of strings within your application itself. Speaking of strings, they’re up next in our discussion.

18.3.2. Identifying and managing strings

There’s perhaps no more emblematic localization topic than the concept of translating and managing an application’s “strings” into target languages. Textual strings are the most visible and obvious means to target an application for a particular locale.

The centerpiece of string management within an Android application is the strings.xml file stored in the /res/values folder. The values folder contains the default resources for the application. Values for additional locales are stored in folders with names identifying the attributes for a specific language or locale. For example, figure 18.6 shows string files for both the default locale and for Spanish translation of those strings.

Figure 18.6. Multiple strings.xml files

A strings.xml file contains a list of strings, as shown in the following listing, which shows some of the strings used in the Field Service application.

Listing 18.2. Default strings.xml file

The strings.xml files are standard XML files . To create one of these files, you can either create it “by hand” or you can select File > New: Android Xml File in Eclipse. Each string value has an attribute that uniquely identifies the string along with a value stored between the <string> and </string> tags.

When creating a strings.xml file for any target language beyond the default locale, you have the option of translating every string or just a subset of the strings. At runtime, your application will automatically load the correct string, looking first in the locale-specific file and working back to the default to find the required value. This cascading works in a manner similar to CSS. The most “precise” interpretation of the device locale is the first file to be searched. If the resource isn’t found in this location, the platform works its way up the tree toward the default. Let’s look at an example.

Let’s say your application is written in a default language of English with 20 unique strings stored in /res/values/strings.xml. You anticipate that your application will be deployed around the globe, but you’re specifically targeting English- and French-speaking users in the United States, France, and Canada.

To implement this strategy, your application contains four different strings.xml files, one in each of the directories listed in table 18.1.

Table 18.1. List of strings.xml files

Directory

Comment

/res/values/strings.xml Default strings.xml stores values in English for this example
/res/values-fr/strings.xml Complete translation of strings in French
/res/values-fr-rFR/strings.xml A subset of strings with France-specific translations, spellings, etc.
/res/values-fr-rCA/strings.xml A subset of strings with Canada-specific translations, spellings, etc.

When a string is looked up at runtime, Android uses the current locale as a filter to choose resources. Let’s say our device is set for the French Canadian locale: fr_CA. If the string we require is found in the /res/values-fr-rCA/strings.xml file, it’s used. If the string isn’t found there, the file /res/values-fr/strings.xml is searched next because it’s the general French strings file. If it’s still not found, the string will be taken from the default strings file /res/values/strings.xml.

Not every string needs to be provided in each file. If only a handful of strings differ in Canada versus the general French strings, just provide the Canada-specific values in the fr_rCA file. Following this practice of managing a minimum number of strings can be helpful, because it can be labor- and testing-intensive to manage multiple string tables.

So far, our discussion has included only strings, language, and region-specific files. Strings aren’t the only resources that may be localized. In the next section we take a brief look at other localized resources.

18.3.3. Drawables and layouts

Beyond strings, your application may need to provide locale-specific resources for drawables (images) and for user interface layouts. The process of managing drawables and layouts is identical to managing strings. If you require locale-specific versions of your images and layouts, they should be put in locale-specific folders in the /res folder.

Providing locale-specific images seems reasonable, because your application’s images may have textual contents, or perhaps your application has images of region-specific currency. It’d make sense to show an appropriate image of a greenback dollar in the US or a Euro in most of Europe. But what about layouts: why would you want to localize a layout?

Most UI elements such as TextView widgets and Buttons display textual values. If those textual values vary in length from one language to the next—which they can and often do—it may be prudent to provide a locale-specific layout file in some instances. The idea here is to be intentional about your application’s visual appearance rather than letting the user have a nondeterministic experience. Recall that many UI elements specify a width value wrap_content. This may not result in a visually appealing layout at runtime. If a particular string is going to distort the UI of your application, find out ahead of time and rearrange your widgets within a locale-specific layout as required.

In addition to your resources, you need to consider the data values your application uses, such as date and time, numbers, and currency. This is the topic of the next section.

18.3.4. Dates, times, numbers, and currencies

When working with data, keep in mind that users in various parts of the world manipulate dates and numbers differently. If you doubt that, just try to enter the thirteenth day of December 2010 into an application expecting input in the form of DD/MM/YYYY. If you enter 12/13/2010, the application will choke because there’s no thirteenth month!

Manipulating these values isn’t so much of an Android topic as it is a Java topic. As such, our discussion here is limited to a quick survey of commonly used Java classes for the purpose of handling data in a locale-specific fashion. Demonstrating each of these classes is beyond the scope of this chapter, and we encourage you to view the exhaustive Javadocs available for these classes. Table 18.2 enumerates some of the classes you’re likely to employ when working with a localized application.

Table 18.2. Helpful classes for localized applications

Class name

Comment

java.util.GregorianCalendar Subclass of the Calendar class, allowing for date and time manipulation specific to a locale.
java.text.SimpleDateFormat Useful for formatting date and time according to custom developer-supplied formats.
java.text.DecimalFormat Formats a decimal value according to a specific locale and string format.
java.text.DecimalFormatSymbols Helper class to DecimalFormat. Use this class to retrieve currency symbols, grouping, and decimal symbols. Some locales use commas for grouping and period for decimal separation; others do the opposite. This class helps navigate those formatting distinctions.
java.util.Locale Most of the previous classes rely on this class in one way or another.

Before examining the localized version of our Field Service application in more detail, there’s one more topic to discuss that has less to do with code than it does with coding.

Most developers we know won’t translate their applications to multiple languages and locales on their own—they’ll employ a teammate or an outside service. Regardless of whom you work with, it’s helpful to keep them in mind from the start of your project. The next section discusses things you can do to work successfully with your translation team.

18.3.5. Working with the translation team

Managing the strings within an application is straightforward on the surface, but it’s not without some challenges, in part because you’re working with others. The translation professionals may be part of your organization or they may be an outside service. If you have the good fortune of working closely with a teammate for translation, things may go easier for you, as you can rely on them for not only term translation but also context. An outside party can provide those services as well, but the cost in terms of dollars and time may be much greater.

Some of the challenges relate to the translation task itself, but there’s another challenge with building a localized application: discipline. Unless you’re working in a structured environment, some aspects of software creation are fluid. You may have an idea for an enhancement to a section of your code. You’re excited about this feature, so you code the enhancement and add a menu item to enable this new aspect of your application. Terrific, your application is now more functional and your users love you! Hold on a moment. Did you use any string literals when you coded the new feature, including the menu? If so, did you get translations yet? A localized application may suffer from some latency and added expense when you factor in the translation and testing steps. When you send data out to your translation team, it’s important not only to provide an exhaustive list of strings or terms that need to be translated, but also to provide as much context as possible. For example, when we had the Field Service application’s terms translated to Spanish, we sent the list to our outside translation vendor. Included in that list was a brief description of each term and its use in the application. A further helpful step would be to storyboard the application with screenshots (or screencasts), thereby equipping the translation team with as much context as possible.

It’s also a good idea to keep cultural references in mind. Remember: your objective is to translate user experience, not just textual terms!

At this point, you have enough information on why localization is important and some feel for what needs to be done to make it happen. The next section digs deeper into the capabilities built within the Android resource subsystem to aid in localization.

18.4. Leveraging Android resource capabilities

With the rapid pace of innovation bringing new and varied capabilities to the mobile market in general, and Android-powered devices in particular, the topic of localization for the Android platform extends beyond mere language- and number-formatting requirements. Because Android devices can vary in terms of their graphical capabilities and physical attributes, some applications will require multiple layout files and drawables targeted for a particular orientation and collection of display characteristics. In short, the mechanics of multiple resource files for supporting multiple locales can also provide Android applications with a flexibility previously unavailable in the mobile landscape.

18.4.1. More than locale

Locale is but one of a handful of attributes that can be specified within your resources. In addition to language and region (locale), the following attributes may be used as qualifiers for organizing and specifying resources to be employed at runtime:

  • Mobile carrier country (mmc)
  • Mobile network code (mnc)
  • Orientation: portrait, landscape
  • Screen size: small, normal, large
  • Screen aspect: long (WQVGA, WVGA, FWVGA), notlong (QVGA, HVGA, VGA)
  • Dock Mode: car, desk
  • Screen pixel density: ldpi, mdpi, hdpi, nodpi (non scalable bitmaps)
  • Screen type: no touch, stylus, finger
  • Input method: qwerty keyboard, no keyboard
  • Navigation: wheel, trackball, dpad, none (touchscreen only)
  • API revision

Android is a moving target as it matures with new capabilities, so this list is regularly expanding and improving along with each Android release. For the most up-to-date version of this list, including the specific qualifiers for the resource folder definition, visit http://developer.android.com/guide/topics/resources/providing-resources.html.

At this point, you know how to make your applications provide locale- and device-specific resource files. The next section demonstrates how those resources relate to one another.

18.4.2. Assigning strings in resources

To effectively manage a localized application throughout its lifespan, you must leverage the strings.xml file to manage every string. The place where most (but not all) those strings are employed is within layout files. For example, this listing demonstrates a simple layout resource file that references string values.

Listing 18.3. Showsettings.xml, which references string constants

When defining a typical UI for an Android application, you define a layout containing multiple widgets. Regardless of the kind of layout you use, there will be widgets. Some of these widgets (namely TextView instances) will contain textual elements. In this case the android:text attribute is assigned a string value. For a properly localized application, this attribute will always refer to a string resource of the format @string/<identifier>. Likewise, the Button widget often displays textual strings and should also refer to a string constant.

Figure 18.7 shows a localized version of the configuration screen.

Figure 18.7. Localized screen referencing strings directly in layout

Of course, not every string in an application is defined as an attribute of a layout resource. Some strings are provided at runtime within Java code. Fortunately, this approach too is straightforward and is presented in the next section.

18.5. Localizing in Java code

Many of the strings your application uses can be referenced in the application’s layout files, but there’s often a need for building a string dynamically at runtime to display to the user. These strings embedded into your code must be localized as well! In fact, our experience shows that it’s these strings that flesh out the application and test your discipline as a developer committed to localization. These are also the strings that send you back to the translation team with further requests for translation services!

The first and fundamental use of localized strings in code is the simple string retrieved from the string table and directly displayed without further formatting. We’ll start by looking at a snippet of the Field Service application’s code prior to localization. The following listing shows the onCreateOptionsMenu method, which handles the creation of the presented menu options.

Listing 18.4. Menu creation code prior to localization

A literal string is used to add a menu option to the application in this pre-localization version of the code taken from chapter 12.

Let’s now see how this code is converted to a localized form. The first step (see the following listing) is to ensure that we have these strings present in the string table, as shown in listing 18.2.

Listing 18.5. Subset of the string table
<string name="sign_and_close">Sign and Close</string>
<string name="cancel">Cancel</string>

With the strings defined in the string table, you can reference them from code. When using localized strings in Java code, your best friend is the Context class’s getString method. This method takes a single integer argument representing the desired string, as defined by the R class. Recall that the R class is automatically generated by the Android Developer Tools whenever a resource is modified and saved within Eclipse. Consider the following code, which demonstrates using the getString method to retrieve localized strings.

Listing 18.6. Retrieving localized strings from the string table
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    menu.add(0, 0, 0, this.getString(R.string.sign_and_close));
    menu.add(0, 1, 1, this.getString(R.string.cancel));
    return true;
}

Retrieving a string is accomplished with a call to the getString method, passing in a reference to the string. The R.string.<identifier> value comes directly from the name attribute in the string table. Recall that the application-level R class is generated in the project as R.java. Never modify that file on your own, because it’s regularly updated by the ADT and all your manual changes are lost!

This localized menu is shown in figure 18.8.

Figure 18.8. Localized menu

Static strings are fine, but what about strings that have some formatting involved? What about when an application requires dynamic content to be localized? Let’s look at using the Formatter class next.

18.6. Formatting localized strings

One of the screens used in the Field Service application lists all the jobs assigned to this user. Figure 18.9 shows this in the en_US locale.

Figure 18.9. A job list in English

Note that the number of jobs phrase at the top of the screen is defined in the default string table as

<string name="there_are_count_jobs">Number of jobs: %d</string>

In the Spanish version of the string table, this is defined as

<string name="there_are_count_jobs">Hay %d trabajo(s)</string>

The %d placeholder is used to specify where the integer should be placed within the string. At runtime, this string is extracted and subsequently formatted with the help of the java.util.Formatter class, as shown here.

Listing 18.7. Formatting localized strings
if (this._joblist.getJobCount() == 0) {
    tv.setText(this.getString(R.string.there_are_no_jobs_available));
} else {
    Formatter f = new Formatter();
    tv.setText(f.format(this.getString(R.string.there_are_count_jobs),
    this._joblist.getJobCount()).toString());
}

In this dynamic formatting code, the first step is to determine whether there are any jobs to display to the user. If not, a static string is retrieved and assigned to the TextView. In the case where there are jobs available for display, an instance of the Formatter class is created. The format method of the Formatter object is invoked, passing in the localized string pulled from the string table associated with the identifier of R.string.there_are_count_jobs, along with the integer value representing the number of jobs.

The benefit of using the Formatter class is that you have the option of presenting strings in different manners in different languages. Figure 18.10 shows the job listings screen in English.

Figure 18.10. Job listings screen in en_US locale

Figure 18.11 shows the same screen but in Spanish. Note the different placement of the numeric value.

Figure 18.11. Job listings screen in es_ES locale

You’ve now seen examples of both statically and dynamically localized strings. There’s no end to the combinations you might employ in your applications.

We conclude this chapter with a brief discussion of obstacles you should avoid when building a localized application.

18.7. Obstacles to localization

Localizing an application shouldn’t be an afterthought. Too much effort is required to properly rework your application when you consider all the supporting cast around your application. The Field Service application has a server-side component, and with it a whole set of other users and use cases to consider. In this final section, we examine a couple of these considerations.

Anything that’s shown to the user should ideally be put into a form that’s readily consumed and is relevant to them. This means that certain elements of your coding approach might need to change—and this is often not easy to accomplish.

For example, one aspect of the Field Service application that should be treated differently is the use of the status code. The application uses the values OPEN and CLOSED transparently but without translation, as shown in figure 18.12.

Figure 18.12. Speedbumps in localization: OPEN status

This is a case where the same piece of text (OPEN, CLOSED) is used for not only display but also control of the application. In hindsight, this approach is something to avoid. The status code should be internal to the application and hidden from the user in its “raw” form. Instead, a locale-specific version should be rendered based on the underlying value. The status code ripples throughout the application, both on the device and on the server side, so modifying it involves a more comprehensive and costly effort than just translating some strings in the application.

Additionally, we discussed earlier in the chapter the idea of filtering out results that are potentially not usable for a particular user. Refer again to figure 18.12. Note that this screen is shown in Spanish but contains a “job” with English comments. Some elements of a job may be unable to be translated—for example, proper names of products or a physical address—but the comments themselves should be carefully distributed to only users who can be productive with the information.

The point in demonstrating some of the shortcomings of this (partially) localized application is to emphasize that localizing an application after it has been released is much more work than starting with localization in mind. Consequently, localizing an application down the road adds more cost than if you’d designed the application for localization from the start. In addition, the user experience may be compromised based on some of the steps required to make a localized application “fit” into an infrastructure that didn’t contemplate the possibility beforehand.

18.8. Summary

In this chapter we explored the topic of localizing an Android application. We reviewed high-level concepts, including motivation, strategy, and technique. The code used a variant of chapter 12’s Field Service application as an example to illustrate both the techniques and challenges of localizing an application.

We looked at the resource structure and the services performed for you automatically by the Android platform. Beyond the definition and organization of the resources, we examined the various means of working with localized strings.

Although you may not have learned much Spanish in this chapter, we trust that you’re now ready to add localization to your list of capabilities and in the process make your applications available to a much broader audience.

In addition to the basic mechanics of localizing an application, a key idea to take from this chapter is that localization isn’t a casual exercise to be undertaken at some point in the future, but rather it should be designed into the DNA of your application from the start.

In the next and final chapter, you get to go under the hood of Android as we look at the Android Native Development Kit (NDK) and write C code for Android.

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

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