In this section, you will learn how you can seamlessly internationalize your Titanium apps. We'll look specifically how you can use external language files to display text in the user's preferred language.
Titanium.Locale namespace for use in localization. It also provides
String formatting functions to handle dates, times, currencies, and more. You can even internationalize the name of your app itself. We'll look at those features, as well as how to test your language settings in this section.
Rather than hard-coding strings into your project, you can use localized strings. Localized strings are replaced at runtime with values appropriate to the user's language. Titanium relies on resources files and string placeholders to accomplish this task.
At the top level of your Titanium project (the same level as
tiapp.xml and the
Resources directory), you will create a folder called
i18n. Inside this folder, you will have folders for each of the supported languages in your application, named according to the ISO 639-1 standard. For example,
en for English, is the default.
Resource file structure
The string resource file closely mirrors the format of Android localization files, which have an XML-based format. The name attribute represents the 'key' for the string, and the text inside the XML node represents the value. A typical
strings.xml file would look like the following:
Resource files are processed and included with your application at build time by our Titanium build scripts. This means that these strings won't be processed if you use Xcode or Eclipse to build your project natively.
String resource names (the "keys") must begin with a letter, and can contain digits, English characters, and the underscore. The contents (values) of each string resource must be UTF-8 compatible strings. While a given platform may not crash or throw an exception if you don't follow these rules, there's a good chance you will encounter some unexpected behavior.
Getting a localized string
Titanium provides two functions for obtaining a localized string from your resource files. Both take the key of the string requested as their first parameter. The
L() macro is a short form for Ti.Locale.getString():
To handle situations where no key exists in the
strings.xml file, the L() macro accepts a second argument to provide default
Additionally, you can use the
titleid property of Titanium UI objects, such as labels or buttons, to directly reference a string resource without using the
L() macro. For example:
Replacing values in a localized string
You probably noticed the %1 and %2 placeholders in the sample
strings.xml file above. The
String object in Titanium contains a
format function which formats strings according to the IEEE printf specification. If your localization string contains replacement keys, as
format_test does in our example file above, you can replace values into your localized string like so:
Using the other replacement values from the printf spec, you can also do ordered values:
Internationalizing the app's name
One thing that has been a little tricky for some developers, is changing the application name based on locale.
For example, say you had an application named "Cat", but you wanted it to be "Gato" in Spanish locales, "猫" in Japanese, and so on. Let 's see how you would prepare your application to display its name appropriately for both iOS and Android distributions.
Changing Locale for Testing
Before learning to configure your apps to use localized strings for application names, let's first see how we can change locales manually for testing. Below you can find short videos for both iOS and Android that show you exactly how to do that.
iOS App Name Localization
For iOS it's pretty simple. Use the standard method for creating localization paths, which means creating and using the
i18n directory like this (details here):
In each of your language directories under
i18n, you'll include an
app.xml file that includes the necessary XML structure for defining the localized name of your app. That structure will look like his for each file:
And that's it. The next time you build your application, these localized strings will be used for your application name. If everything was configured correctly, you'll see the app name has changed based on the selected locale.
Android App Name Localization
In its current state, Android app name localization is a little more involved. First, we need to create language-specific resource folders explicitly for Android. To do so, we will create the
platform/android/res/values-(language code) directory structure, like this:
You'll notice in this case we are creating the Android native
strings.xml files, rather than the
app.xml files used by iOS. While the file names are different, the contents will be identical to those in the iOS files seen above.
Aside from the
strings.xml files, there's one more thing we need to add. To make your app use these localized strings, you need to modify the existing
AndroidManifest.xml. In order to do that, we need to add that custom manifest file, seen in the picture above at
AndroidManifest.xml file placed here should be a copy of the generated
AndroidManifest.xml file found in your project's
build/android directory. For more details on custom
AndroidManifest.xml files, check out this wiki entry on the topic.
Now open up
platform/android/AndroidManifest.xml and change the
android:label attributes of the
<activity> elements from the defined value of your app name to the value
@string/app_name. Yeah, that was a lot of instructions all in one sentence, so here's a gist to show you what I mean:
With these changes in place, you can now rebuild your app (probably best to give it a clean first) and you'll have a successfully localized application name.
This is how your home screens might look on Android and iOS when Japanese is the selected language.
And just in case my description was clear as mud, check out a Titanium project with these localizations set up first hand. Just go to the AppNameLocalization project repository on Github. It contains the very basic project discussed here. With all this, you should be well-equipped to distribute your apps in as many languages as you wish to support.
- AppNameLocalization project on Github
- Appcelerator Wiki: Internationalization
- Appcelerator Wiki: Maintaining a Custom AndroidManifest.xml
Internationalizing image and file resources
Titanium does not provide built-in functions for internationalizing image and file resources. But you can easily accomplish this yourself. There are a couple of techniques you can employ:
- Put the path and file name of each resource in the
strings.xmlfile, then use that string in the
imageproperty, like this:
- Put your images into a set of folders that match the 2-letter ISO codes, and include that directory in the path with
Ti.Locale.currentCountry, like this:
This technique won't work for the splash screen graphic. You should ideally avoid text that would need translation in your splash screen.
Date and time formatting
Titanium provides string formatting functions that you can use to create formatted dates and times. These include
At the time of this writing, natively, Android does not format dates in accordance with the official DateFormat documentation. Consequently, this will affect the corresponding
long formats of Titanium String Formatting. Furthermore, when the device settings are set to certain languages, the translations can be wrong or fields in the incorrect order. For example, the following code is run on a device to demonstrate the issue:
This results in the following when the device is set to display in Polish:
maja is output for the month of May, whereas the Polish for May is actually Maj.
Similarly, when the device is set to English (United Kingdom), the month fields are incorrectly displayed before the dates:
This issue may well be fixed by the time you read this but, nevertheless, it gives us an opportunity to employ some of Titanium's tools to provide a workaround that gives you full control over the date format and translations.
We can use JavaScipt's Date object to return the date, which provides methods such as
getFullYear() to individually retrieve some of the information that we need. Although it does not specifically provide a method for returning the name of the month, we can derive it, in English, from the space-separated string output from
Date. To do so, we'll use the JavaScipt String.split() function. This will give us a key to lookup in the
Using string substitution placeholders, dynamic values can be passed to the
headingDate string. This enables each locale to display the fields in a different order. In the following
string.xml files, Polish and English translations will return the date in the default order, whereas Spanish will result in a modified order.
Using this code, the date in Polish is translated correctly:
In addition, the recognized date format for the UK is produced:
Lastly, the date in Spanish has been reordered:
Other formatting and locale functions
Titanium also provides string formatting functions that you can use to create formatted currency and decimal numbers. These functions are
String.formatDecimal(), respectively. The Ti.Locale module provides the
Ti.Locale.formatTelephoneNumber() method for getting a locale-formatted phone number. That module also includes functions for retrieving the correct currency symbol and currency code for the user's locale.
When building internationalized apps, you'll need to test each of the supported languages. You can do so either on-device or in the simulator/emulator. In each case, you configure the device's language settings to change locales.
To set the language on iOS:,
- Tap Settings, General, International.
- Tap Language
- Select the language to use. Tap Done (or OK).
- Optionally, in Settings, tap General, International, Region Format to specify your locale format for dates and times.
To set the language on Android:
- Open your Android Settings
- Tap Language and Keyboard.
- Tap Select language
- Tap the language to use
In this activity, you will create an internationalized app that outputs language-specific strings and test that in the simulator/emulator.
- Create a new Titanium Mobile project named "Language Test" with an app ID of your choice.
- Using your computer's file management tools, create an
i18ndirectory at the root of your project. In that directory, create two directories:
- Using Studio, within the
endirectory, create a
strings.xmlfile following the format shown above. Add three key/value pairs:
- language = Language
- test = Test
- tab = Tab
- In the
esdirectory, create a matching copy of
strings.xmlexcept that the values should be as follows:
- language = Lengua
- test = Prueba
- tab = Lengüeta
- In the
esdirectory, create an
app.xmlfile following the format shown above. Add the necessary key and value to specify "Lengua Prueba" as the translated version of the app's name. (This won't have any effect if you're building for Android.)
- In app.js, on tab 1, add the necessary code to output the internationalized "Language Test" string as the text of
- On tab 2, change the text of
label2to output today's date using the
- For both tab 1 and tab 2, update the text to use the internationalized "tab" key plus the tab's number.
- Build the app for the simulator/emulator. The label and tab text should output in English (unless your emulator is already set to output text in Spanish). Close the app.
- Change the simulator/emulator's settings to display text in Spanish. Open the app. Label and tab text should now be in Spanish. On iOS, the app's icon should be labeled in Spanish as well.
References and Further Reading
In this chapter, you learned how to internationalize your app, including using language strings, internationalizing the app name, and formatting strings, dates, and currency values.