9.6 KiB
title | description | guide_group | order |
---|---|---|---|
Internationalization | How to localize an app to multiple languages. | tools-and-resources | 5 |
When distributing an app in the Pebble appstore, it can be downloaded by Pebble users all over the world. Depending on the app, this means that developers may want to internationalize their apps for a varierty of different locales. The locale is the region in the world in which the user may be using an app. The strings used in the app to convey information should be available as translations in locales where the app is used by speakers of a different language. This is the process of localization. For example, users in France may prefer to see an app in French, if the translation is available.
Internationalization on Pebble
The Pebble SDK allows an app to be localized with the Internationalization
API. Developers can use this to adjust how their app displays and behaves to
cater for users in non-English speaking countries. By default all apps are
assumed to be in English. Choose the user selected locale using
i18n_get_system_locale()
or to force one using setlocale()
.
Note: The app's locale also affects
strftime()
, which will output different strings for different languages. Bear in mind that these strings may be different lengths and use different character sets, so the app's layout should scale accordingly.
Locales Supported By Pebble
This is the set of locales that are currently supported:
Language | Region | Value returned by i18n_get_system_locale() |
---|---|---|
English | United States | "en_US" |
French | France | "fr_FR" |
German | Germany | "de_DE" |
Spanish | Spain | "es_ES" |
Italian | Italy | "it_IT" |
Portuguese | Portugal | "pt_PT" |
Chinese | China | "en_CN" |
Chinese | Taiwan | "en_TW" |
When the user's preferred language is set using the Pebble Time mobile app, the required characters will be loaded onto Pebble and will be used by the compatible system fonts. This means that any custom fonts used should include the necessary locale-specific characters in order to display correctly.
Translating an App
By calling setlocale(LC_ALL, "")
, the app can tell the system that it supports
internationalization. Use the value returned by setlocale()
to translate any
app strings. The implementation follows the
libc convention.
Users may expect text strings, images, time display formats, and numbers to
change if they use an app in a certain language.
Below is a simple approach to providing a translation:
// Use selocale() to obtain the system locale for translation
char *sys_locale = setlocale(LC_ALL, "");
// Set the TextLayer's contents depending on locale
if (strcmp("fr_FR", sys_locale) == 0) {
text_layer_set_text(s_output_layer, "Bonjour tout le monde!");
} else if ( /* Next locale string comparison */ ) {
/* other language cases... */
} else {
// Fall back to English
text_layer_set_text(s_output_layer, "Hello, world!");
}
The above method is most suitable for a few strings in a small number of languages, but may become unwieldly if an app uses many strings. A more streamlined approach for these situations is given below in Using Locale Dictionaries.
Using the Locale in JavaScript
Determine the language used by the user's phone in PebbleKit JS using the
standard
navigator
property:
console.log('Phone language is ' + navigator.language);
[INFO ] js-i18n-example__1.0/index.js:19 Phone language is en-US
This will reflect the user's choice of 'Language & Input' -> 'Language' on Android and 'General' -> 'Language & Region' -> 'i[Pod or Phone] Language' on iOS.
Note: Changing the language on these platforms will require a force close of the Pebble app or device restart before changes take effect.
Choosing the App's Locale
It is also possible to explicitly set an app's locale using setlocale()
.
This is useful for providing a language selection option for users who wish to
do so. This function takes two arguments; the category
and the locale
string. To set localization only for the current time, use LC_TIME
as the
category
, else use LC_ALL
. The locale
argument accepts the ISO locale
code, such as "fr_FR"
. Alternatively, set locale
to NULL
to query the
current locale or ""
(an empty string) to set the app's locale to the system
default.
// Force the app's locale to French
setlocale(LC_ALL, "fr_FR");
To adapt the way an application displays time, call setlocale(LC_TIME, "")
.
This will change the locale used to display time and dates in strftime()
without translating any strings.
Effect of Setting a Locale
Besides returning the value of the current system locale, calling
setlocale()
will have a few other effects:
-
Translate month and day names returned by
strftime()
%a
,%A
,%b
, and%B
. -
Translate the date and time representation returned by
strftime()
%c
. -
Translate the date representation returned by
strftime()
%x
.
Note that currently the SDK will not change the decimal separator added by the
printf()
family of functions when the locale changes; it will always be a .
regardless of the currently selected locale.
Using Locale Dictionaries
A more advanced method to include multiple translations of strings in an app
(without needing a large number of if
, else
statements) is to use the
Locale Framework. This
framework works by wrapping every string in the project's src
directory in
the _()
and replacing it with with a hashed value, which is then used with
the current locale to look up the translated string from a binary resource file
for that language.
Instructions for using this framework are as follows:
-
Add
hash.h
,localize.h
andlocalize.c
to the project. This will be thesrc
directory in the native SDK. -
Include
localize.h
in any file to be localized:
#include "localize.h"
- Initalize the framework at the start of the app's execution:
int main(void) {
// Init locale framework
locale_init();
/** Other app setup code **/
}
- For every string in each source file to be translated, wrap it in
_()
:
text_layer_set_text(some_layer, _("Meal application"));
- Save all source files (this will require downloading and extracting the
project from 'Settings' on CloudPebble), then run
get_dict.py
from the project root directory to get a JSON file containing the hashed strings to be translated. This file will look like the one below:
{
"1204784839": "Breakfast Time",
"1383429240": "Meal application",
"1426781285": "A fine meal with family",
"1674248270": "Lunch Time",
"1753964326": "Healthy in a hurry",
"1879903262": "Start your day right",
"2100983732": "Dinner Time"
}
-
Create a copy of the JSON file and perform translation of each string, keeping the equivalent hash values the same. Name the file according to the language, such as
locale_french.json
. -
Convert both JSON files into app binary resource files:
$ python dict2bin.py locale_english.json
$ python dict2bin.py locale_french.json
- Add the output binary files as project resources as described in {% guide_link app-resources/raw-data-files %}.
When the app is compiled and run, the _()
macro will be replaced with calls
to locale_str()
, which will use the app's locale to load the translated string
out of the binary resource files.
Note: If the translation lookup fails, the framework will fall back to the English binary resource file.
Publishing Localized Apps
The appstore does not yet support localizing an app's resources (such as name, description, images etc), so use this guide to prepare the app itself. To cater for users viewing appstore listings in a different locale, include a list of supported languages in the listing description, which itself can be written in multiple languages.
The format for a multi-lingual appstore description should display the supported languages at the top and a include a copy in each language, as shown in the example below:
Now supports - French, German and Spanish.
This compass app allows you to navigate in any directions from your wrist! Simply open the app and tilt to show the layout you prefer.
Français
Cette application de la boussole vous permet de naviguer dans toutes les directions à partir de votre poignet! Il suffit d'ouvrir l'application et de l'inclinaison pour montrer la disposition que vous préférez.
Deutsch
Dieser Kompass App ermöglicht es Ihnen, in jeder Richtung vom Handgelenk zu navigieren! Öffnen Sie einfach die App und kippen, um das Layout Sie bevorzugen zu zeigen.
Español
Esta aplicación brújula le permite navegar en cualquier dirección de la muñeca ! Basta con abrir la aplicación y la inclinación para mostrar el diseño que prefiera.