Localization

The system is localized for the languages and locales offered as options in the Language picker in any given release of Palm webOS. You can localize your application to any of the available locales and the correct localization will be selected when the application is launched. If your application doesn’t support the selected locale, it will try to match just the language. If there is no match for the language, the base version will be selected.

To localize your application, create locale-named directories within your application to hold the localized files. The framework will look for a directory that matches the current locale and will automatically substitute the localized content for the content in the base version.

You can localize any of the following:

Application name and icon

Each locale can have a separate version of the application’s appinfo.json, which can be modified for that locale to customize any of the properties defined there.

JavaScript strings

Any string appearing in JavaScript executed by the application can be extracted and localized by encapsulating the string with the $L() function.

HTML scene or template

Each locale has a views directory, which is structured like the base version views directory and can contain any of the base version HTML files that you wish to modify for that locale.

HTML strings

Any string appearing in an HTML file or template can be localized by creating a copy of the file and modifying the strings.

Typically, you will develop your application with a base version and once you reach UI freeze or the UI is complete, you will do a test localization with a pseudolocale to confirm that you have identified all the strings and that your application structure is correct.

You can localize to multiple languages in parallel, but once you’ve done your localization, you will need to manage code or UI changes. This may be difficult under the current structure, as the tools don’t address change management, forcing you to manually migrate all changes.

It’s good to do a pseudolanguage localization early to test localization readiness, but wait on actual localization until your UI is final or very close to it.

Localized Application Structure

Localized applications have an additional directory, resources, at the application’s root directory, and within it are directories for each locale. Within resources are locale directories that include a localized version of appinfo.json and localization files for JavaScript string translation (strings.json), and localized versions of the application’s view files. Figure 11-2 shows an example of an exploded resources directory for the News application, which has a single localization for United States Spanish.

An example resources directory

Figure 11-2. An example resources directory

You’ll see that the first level of directories within resources is for locales. If the locale is set to es_US, the framework will look for content in the resources/es_us directory first. If that directory or the content (e.g., appinfo.json, specific strings in strings.json, HTML files in /views) is not there, it will then default to the app directory contents.

You can create this structure manually by creating and naming the directories with the valid language and region codes. Table 11-1 defines the initially supported languages and regions, but check the SDK documentation for the current set of supported names. All of the language names are encoded as a two-letter ISO 639 language code and all of the region names are based on a two-letter ISO 3166 country code.

At the time of this writing, there are no tools provided in the SDK to assist with creating or maintaining localization content, but tools are planned. Check the SDK site for any new information on localization tools.

appinfo.json

Each locale directory will include a copy of the main appinfo.json file, modified for localization and for file path changes. For the News application, the title is changed to “Noticias” and the main and icon property values are modified to adjust the relative path for the location of this version of appinfo.json. The file path must reflect that this version of appinfo.json is located at com.palm.app.news/resources/es_us/appinfo.json and the target files are located at com.palm.app.news:

{
  "title": "Noticias",
  "type": "web",
  "main": "../../index.html",
  "icon": "../../icon.png",
  "id": "com.palm.app.news",
  "version": "1.0",
  "vendor": "Palm",
  "theme": "light",
  "noWindow": "true"
}

We only localized the application name here, but you could also do the following:

  • Change the icon by pointing to a different icon image file. The appinfo.json file is encoded in UTF-8.

  • Use a localized index.html, which might be useful for including different stylesheets for a given localization or for changing page layout based on writing direction or cultural reasons.

JavaScript Text Strings

The Mojo framework will dynamically substitute localized strings based on the current locale. Any JavaScript string can be localized; you should localize all text strings that are displayed and are visible to the user, but not those that never appear. Examples of strings that should not be localized include logging information or information used strictly as internal data or arguments. Nor should you localize strings that don’t include text, such as HTML templates that contain only variable definitions.

Identifying strings

You prepare for string extraction and translation by encapsulating any target string with the $L() function, as in this example from app-assistant.js in News, where the default application menu attributes and model are set up:

// Setup App Menu for all scenes; all menu actions handled in
//  AppAssistant.handleCommand()
News.MenuAttr = {omitDefaultItems: true};

News.MenuModel = {
    visible: true,
    items: [
        {label: $L("About News..."), command: "do-aboutNews"},
        Mojo.Menu.editItem,
        {label: $L("Update All Feeds"), checkEnabled: true, command: "do-feedUpdate"},
        {label: $L("Preferences..."), command: "do-newsPrefs"},
        Mojo.Menu.helpItem
    ]
};

Or in this case, from preferences-assistant.js, where the list selector widget is set up:

// Setup list selector for UPDATE INTERVAL
    this.controller.setupWidget("feedCheckIntervalList",
        {
            label: $L("Interval"),
            choices: [
                {label: $L("Manual Updates"),   value: "00:00:00"},
                {label: $L("5 Minutes"),        value: "00:05:00"},
                {label: $L("15 Minutes"),       value: "00:15:00"},
                {label: $L("1 Hour"),           value: "01:00:00"},
                {label: $L("4 Hours"),          value: "04:00:00"},
                {label: $L("1 Day"),            value: "23:59:59"}
            ]
        },
        this.feedIntervalModel = {
            value : News.feedUpdateInterval
        });

The framework will use any string that is encapsulated with $L() as a key in the appropriate strings.json file (based on the current locale) and substitute the resulting value (the localized string) in the original string’s place.

In this next example, the string arguments to Mojo.Log.warn() are not encapsulated, but the arguments to Mojo.Controller.errorDialog() are:

Mojo.Log.warn("Can't open feed database: ", result);
Mojo.Controller.errorDialog($L("Can't open feed database : ")+ result);

Sometimes translations can change the position of variables within the strings. If a variable is inserted within a string, use templates to allow for changes in position. For example:

Mojo.Log.warn("Can't open feed database (#", result, "). All feeds will be reloaded.");

// ** These next two lines are wrapped for book formatting only **
var message = new Template($L("Can't open database (#{message}).
   Feeds will be reloaded."));
Mojo.Controller.errorDialog(message.evaluate({message: result}));

This is even more critical if you have strings where there are multiple variables. Localization can change not only the location, but also the order of variables within strings. For example:

"Not enough memory to #{action} the file #{fname}."

becomes (in Finnish):

"Liian vähän muistia tiedoston #{fname} #{action}."

Also, be careful about reusing keys where the same original string might have multiple translations in another language. For example, “save” can be translated in one context to “speichern” in German. In another, it could be translated as “retten.” Likewise, the English word “add” can mean “append” in one context, and “sum” in another context. When using keys in different contexts, consider using different identifiers in your source documents, even if they both have the same localization into English.

Extracting strings

Once the strings are identified, you will extract them to a strings.json file, located in the root level of the locale directory.

You can manually extract the strings by scanning the file for $L() encapsulation and copying the strings into the key position in strings.json. If they aren’t encapsulated by the $L() function, the framework will not perform the substitutions.

Palm recognizes that this is a very tedious process and intends to provide tool support to facilitate string extraction, but at the time of this writing, those tools are not yet available. Refer to the Palm developer site for more information about localization tools.

Localizing strings

The strings.json file is a conventional JSON file, encoded in UTF-8, with the base version of the string used as a key and the localized version of the string as the value:

"Original String" : "Localized String",

The News resources/es/strings.json is shown here:

{
   "#{status}" : "#{status}",
   // ** These next four lines are wrapped for book formatting only **
   "0##{title} : No New Items|1##{title} : 1 New Item|1>##{title} :
     #{count} New Items" :
     "0##{title} : No hay elementos nuevos|1##{title} : 1 elemento nuevo|1>##{title} :
     #{count} elementos nuevos",
   "1 Day" : "1 día",
   "1 Hour" : "1 hora",
   "15 Minutes" : "15 minutos",
   "4 Hours" : "4 horas",
   "5 Minutes" : "5 minutos",
   "About News..." : "Acerca de noticias...",
   // ** These next three lines are wrapped for book formatting only **
   "Add Feed DB save error : #{message}; can't save feed list." :
     "Error de base de datos al intentar agregar nueva fuente web :
     #{message}; no se puede guardar la lista de 
       fuentes web.",
   "Add News Feed Source" : "Añadir fuente web de noticias",
   "Add..." : "Añadir...",
   "Adding a Feed" : "Añadiendo una fuente web",
   "All Read" : "Todas leídas",
   "All Unread" : "Todas las no leídas",
   "Can't open feed database: " : "No se puede abrir la base de datos de fuentes web: ",
   "Cancel" : "Cancelar",
   "Cancel search" : "Cancelar búsqueda",
   "Check out this News story..." : "Leer esta noticia...",
   "Check this out: " : "Mira esto: ",
   "Copyright 2009, Palm Inc." : "Copyright 2009, Palm Inc.",
   "Database save error: " : "Error al guardar en la base de datos: ",
   "Edit a Feed" : "Editar una fuente web",
   "Edit Feed" : "Editar fuente web",
   "Edit News Feed" : "Editar una fuente web de noticias",
   "Feature Feed" : "Fuente web destacada",
   "Featured Feed" : "Fuente web destacada",
   "Feature Rotation" : "Rotación de fuente web destacada",
   "Feed Request Success:" : "Solicitud de fuente web lograda:",
   "Feed Updates" : "Actualización de fuentes web",
   "Help..." : "Ayuda...",
   "Interval" : "Intervalo",
   // ** These next two lines are wrapped for book formatting only **
   "Invalid Feed - not a supported feed type" :
     "Fuente web no válida: no es un tipo de fuente web admitido",
   "Latest News" : "Últimas noticias",
   "Manual Updates" : "Actualizaciones manuales",
   "Mark Read or Unread" : "Marcar leída o no leída",
   "New Card" : "Tarjeta nueva",
   "New features" : "Nuevas características",
   "New Items" : "Elementos nuevos",
   "News Help" : "Ayuda para noticias",
   "News Preferences" : "Preferencias para noticias",
   // ** These next two lines are wrapped for book formatting only **
   "newsfeed.status" :
     "Estado #{status} devuelto desde solicitud de fuente web de noticias",
   "OK" : "OK",
   "Optional" : "Opcional",
   "Preferences..." : "Preferencias...",
   "Reload" : "Cargar nuevamente",
   "Rotate Every" : "Girar cada",
   "Rotation (in seconds)" : "Rotación (en segundos)",
   "RSS or ATOM feed URL" : "Fuente web RSS o ATOM URL",
   "Search for:  #{filter}" : "Buscar:  #{filter}",
   "Show Notification" :"Mostrar aviso",
   "SMS/IM" : "SMS/IM",
   // ** These next two lines are wrapped for book formatting only **
   "Status #{status} returned from newsfeed request." :
     "La solicitud de fuente web de noticias indicó el estado #{status}.",
   "Stop" : "Detener",
   "Title" : "Título",
   "Title (Optional)" : "Título (Opcional)",
   "Update All Feeds" : "Actualizar todas las fuentes web",
   "Wake Device" : "Activar dispositivo",
   // ** These next two lines are wrapped for book formatting only **
   "Will need to reload on next use." :
     "Se tendrá que cargar de nuevo la próxima vez que se use."

}

If the original string is not appropriate as a key, the $L() function can be called with an explicit key:

$L("value":"Original String", "key": "string_key")

In this case, string_key is the key in strings.json and the translation of Original String is the value:

{
"string_key" : "Localized String"
}

Here’s an example, again in News. The results template is defined with a key inside the $L() function:

AppAssistant.prototype.feedRequestSuccess = function(transport) {

  var t = new Template($L({key: "newsfeed.status",
    value: "Status #{status} returned from newsfeed request."}));
  Mojo.Log.info("com.palm.app.news - Feed Request Success: ",
    t.evaluate(transport));

And if you look back at the strings.json, you’ll see this entry, where the key is used instead of the original string:

// ** These next two lines are wrapped for book formatting only **
  "newsfeed.status" :
    "Estado #{status} devuelto desde solicitud de fuente web de noticias",

Localizable HTML

The framework does not dynamically substitute localized text strings for HTML text strings. Instead you will create a copy of the HTML scenes and templates, manually substituting the localized strings. You do get some help identifying strings and extracting them to strings.json to facilitate translation, but you’ll need to manually copy the translated strings to your localized HTML files.

You don’t have to limit the changes in the localized HTML files to localized text substitution. You may also make layout changes by locale; in some cases the translations may need some adjustments. And you can also include locale-specific CSS, which you can use in combination with your HTML to modify the presentation, either to accommodate text translations (for example, adjusting for significant changes in text length) or simply to address unique formatting requirements within a specific locale.

Identifying and extracting strings

You don’t need to extract the strings from the HTML files, but instead you will copy any HTML file that includes a localized string into the views directory for each locale. The structure of the views folder will mirror the base version, but only the files with localized content will be included. For example, News will have only three localized HTML files:

views/feedList/addFeed-scene.html
views/feedList/feedList-assistant.html
views/preferences/preferences-assistant.html

As part of your localization workflow, you may want to extract the strings, and it doesn’t hurt to include those strings in strings.json.

Note

Localizers are very familiar with translating whole HTML files. You may want to just hand over your file to the localizers to get translated to various languages and not take time to extract the strings.

Localizing strings

After translation, the localized strings must be copied into the localized version of the HTML file. Using the previous example of preferences-assistant.html, the strings are translated to es_US:

<div class="palm-page-header">
    <div class="palm-page-header-wrapper">
        <div class="icon news-mini-icon"></div>
        <div class="title">Preferencias para noticias</div>
    </div>
</div>

<div class="palm-group">
    <div class="palm-group-title"><span>Fuente web destacada</span></div>
        <div class="palm-list">
            <div x-mojo-element="IntegerPicker" id="featureFeedDelay"></div>
        </div>
    </div>
</div>

<div class="palm-group">
    <div class="palm-group-title"><span>Actualización de fuentes web</span></div>
           <div class="palm-list">
            <div class="palm-row first">
                <div class="palm-row-wrapper">
                    <div x-mojo-element="ListSelector" id="feedCheckIntervalList">
                    </div>
                </div>
            </div>
            <div class="palm-row">
                <div class="palm-row-wrapper">
                    <div x-mojo-element="ToggleButton" id="notificationToggle">
                    </div>
                    <div class="title left">Mostrar aviso</div>
                </div>
            </div>
            <div class="palm-row last">
                <div class="palm-row-wrapper">
                    <div x-mojo-element="ToggleButton" id="bgUpdateToggle"></div>
                    <div class="title left">Activar dispositivo</div>
                </div>
            </div>
        </div>
    </div>
</div>

You can see the other HTML files along with all the localization changes made for News to support the es_US locale. When you launch News with that locale selected, you’ll see something similar to Figure 11-3.

News localized to the es_US locale

Figure 11-3. News localized to the es_US locale

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

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