Documentation  |   Table of Contents   |  < Previous   |  Next >   |  Index

12    Localized Applications

Palm OS® Programmer's Companion

Volume I

     

When you write an application, or any other type of software, you need to take special care when working with characters, strings, numbers, and dates, as different countries represent these items in different ways. This chapter describes how to write code that works properly for any language that is supported by Palm OS®. The chapter covers:

In addition to this chapter, also see Chapter 8, "Text," which describes how to work with text and characters in a way that makes your application easily localizable.


NOTE: PalmOSGlue provides backward compatibility for many of the functions described in this chapter. When a function has a PalmOSGlue equivalent, that equivalent is shown in parentheses following the function name. See "Backward Compatibility with PalmOSGlue" for more information on PalmOSGlue.

This chapter does not cover how to actually perform localization of resources. For more information on this subject, see the Palm OS Programming Development Tools Guide.

Localization Guidelines ^TOP^

If there is a possibility that your application is going to be localized, you should follow these guidelines when you start planning the application. It's a good idea to follow these guidelines even if you don't think your application is going to be localized.

  • If you use the English language version of the software as a guide when designing the layout of the screen, try to allow:
    • extra space for strings
    • larger dialogs than the English version requires
  • Don't put language-dependent strings in code. If you have to display text directly on the screen, remember that a one-line warning or message in one language may need more than one line in another language. See the section "Strings" in Chapter 8, "Text," for further discussion.
  • Don't depend on the physical characteristics of a string, such as the number of characters, the fact that it contains a particular substring, or any other attribute that might disappear in translation.
  • Database names must use only 7-bit ASCII characters (0x20 through 0x7E). If an actual PDB name is displayed to the user, the application should have a way of associating a localizable name (resource based, if possible) with each database.
  • Use the functions described in this chapter when working with characters, strings, numbers, and dates.
  • Consider using string templates as described in the section "Dynamically Creating String Content" in Chapter 8. Use as many parameters as possible to give localizers greater flexibility. Avoid building sentences by concatenating substrings together, as this often causes translation problems.
  • Abbreviations may be the best way to accommodate the particularly scarce screen real estate on the Palm Powered handheld.
  • Remember that user interface elements such as lists, fields, and tips scroll if you need more space.

The book Palm OS User Interface Guidelines provides further user interface guidelines.

Using Overlays to Localize Resources ^TOP^

Palm OS version 3.5 adds support for localizing resource databases through overlays. Localization overlays provide a method for localizing a software module without requiring a recompile or modification of the software. Each overlay database is a separate resource database that provides an appropriately localized set of resources for a single software module (the PRC file, or base database) and a single target locale (language and country).

No requirements are placed on the base database, so for example, third parties can construct localization overlays for existing applications without forcing any modifications by the original application developer. In rare cases, you might want to disable the use of overlays to prevent third parties from creating overlays for your application. To do so, you should include an 'xprf'=0 resource (symbolically named sysResTExtPrefs) in the database and set its disableOverlays flag. This resource is defined in UIResources.r.

An overlay database has the same creator as the base database, but its type is 'ovly', and a suffix identifying the target locale is appended to its name. For example, Datebook.prc might be overlaid with a database named Datebook_jpJP, which indicates that this overlay is for Japan. Each overlay database has an 'ovly'=1000 resource specifying the base database's type, the target locale, and information necessary to identify the correct version of the base database for which it was designed.

The Palm OS SDK provides tools that you can use to create overlays. See the "PRC to Overlay Tool" chapter in the Palm OS Programming Development Tools Guide for more information on creating overlays.

When a PRC file is opened on a system that supports overlays, the Overlay Manager determines what the current locale is for this handheld, and it looks for an overlay matching the base database and the locale. The overlay database's name must match the base database's name, its suffix must match the locale's suffix, and it must have an 'ovly'=1000 resource that matches the base database. If the name, suffix, and overlay resource are all correct, the overlay is opened in addition to the PRC file. When the PRC file is closed, its overlay is closed as well.

The overlay is opened in read-only mode and is hidden from the programmer. When you open a database, you'll receive a reference to the base database, not the overlay. You can simply make Resource Manager calls like you normally would, and the Resource Manager accesses the overlay where appropriate.

When accessing a localizable resource, do not use functions that search for a resource only in the database you specify. For example:


// WRONG! searches only one database.  
DmOpenRef dbP = DmNextOpenResDatabase(NULL); 
UInt16 resIndex = DmFindResource(dpP, strRsc,  
strRscID); 
MemHandle resH = DmGetResourceIndex(dbP,  
resIndex); 

In the example above, dbP is a reference to the most recently opened database, which is typically the overlay version of the database. Passing this reference to DmFindDatabase means that you are searching only the overlay database for the resource. If you're searching for a non-localized resource, DmFindResource won't be able to locate it. Instead, you should use DmGet1Resource, which searches the most recently opened database and its overlay for a resource, or DmGetResource, which searches all open databases and their overlays.


// Right. DmGet1Resource searches both  
// databases.  
MemHandle resH = DmGet1Resource(strRsc,  
strRscID); 
// Or use DmGetResource to search all open  
// databases. 
MemHandle resH = DmGetResource(strRsc,  
strRscID); 

The Data Manager only opens an overlay if the resource database is opened in read-only mode. If you open a resource database in read-write mode, the associated overlay is not opened. What's more, if you modify an overlaid resource in the base database, the checksum in the overlay's 'ovly' resource becomes invalid, which prevents the overlay from being used at all. Thus if you change the resource database, you must also change the overlay database.

You typically don't work with the Overlay Manager directly although it does provide a few public functions. One potentially useful function is OmGetCurrentLocale (or OmGlueGetCurrentLocale), which returns a structure identifying the locale on this handheld.

Dates ^TOP^

If your application deals with dates and times, it should abide by the values the user has set in the system preference for date and time display. The default preferences at startup vary among locales, and the default values can be overridden by the user.

To check the system preferences call PrefGetPreference with one of the values listed in the second column of Table 12.1. The third column lists an enumerated type that helps you interpret the value.

Table 12.1  Date and time preferences

Preference

Name

Returns a value of type

Date formats (i.e., month first or day first)

prefDateFormat, prefLongDateFormat

DateFormatType

Time formats (i.e., use a 12-hour clock or use a 24-hour clock)

prefTimeFormat

TimeFormatType

Start day of week (i.e., Sunday or Monday)

prefWeekStartDay

0 (Sunday) or 1(Monday)

Local time zone

prefMinutesWestOfGMT

(before Palm OS 4.0),

prefTimeZone (Palm OS 4.0 and higher)

Minutes east1 of Greenwich Mean Time (GMT), also known as Universal Coordinated Time (UTC).

Daylight savings time adjustment

prefDaylightSavings (before Palm OS 4.0),

prefDaylightSavingAdjustment (Palm OS 4.0 and higher)

Before 4.0, the DaylightSavingsTypes described the daylight savings adjustment. In Palm OS 4.0 and higher, the preference is stored as the number of minutes by which to adjust the current time.

1. The previous name of this preference notwithstanding, a positive value indicates minutes east of GMT, while a negative value indicates minutes west of GMT.

IMPORTANT: The prefMinutesWestOfGMT preference mentioned above is not the same as the prefTimeZone preference. The prefMinutesWestOfGMT returns an unsigned value ranging from 0 to 1440. The prefTimeZone preference ranges from -720 to 720.

To work with dates in your code, use the Date and Time Manager API. It contains functions such as DateToAscii, DayOfMonth, DayOfWeek, DaysInMonth, and DateTemplateToAscii, which allow you to work with dates independent of the user's preference settings.

Numbers ^TOP^

If your application displays large numbers or floating-point numbers, you must check and make sure you are using the appropriate thousands separator and decimal separator for the handheld's country by doing the following (see Listing 12.1):

  1. Store numbers using US conventions, which means using a "," as the thousands separator and a decimal point (.) as the decimal separator.
  2. Use PrefGetPreference and LocGetNumberSeparators to retrieve information about how the number should be displayed.
  3. Use StrLocalizeNumber to perform the localization.
  4. If a user enters a number that you need to manipulate in some way, convert it to the US conventions using StrDelocalizeNumber.

Listing 12.1  Working with numbers


// store numbers using US conventions.  
Char *jackpot = "20,000,000.00"; 
Char thou; // thousand separator 
Char dp; // decimal separator 
 
// Retrieve user's preferred number format.  
LocGetNumberSeparators((NumberFormatType) 
PrefGetPreference(prefNumberFormat), &thou,  
&dp); 
// Localize jackpot number. Converts "," to thou  
// and "." to dp.  
StrLocalizeNumber(jackpot, thou, dp); 
// Display string.  
// Assume inputString is a number user entered,  
// convert it to US conventions this way. Converts  
// thou to "," and dp to "." 
StrDelocalizeNumber(inputNumber, thou, dp); 

Obtaining Locale Information ^TOP^

Some applications may require information about the current locale. For example, many applications need to know the format for displaying dates or numbers, which is determined in part by the current locale (and described in more detail in the section "Dates" and "Numbers" in this chapter). Other applications may need other information, such as the country name.

The information that most applications require is stored in the system preferences structure and can be obtained using PrefGetPreference. This is the recommended way of obtaining locale-specific settings because the user can override many of these settings. Applications should always honor the user's preferences rather than the locale defaults.

Other locale-specific settings can not be set by the user and are not stored in the system preferences. Instead, these settings are stored in a private resource that contains information about several possible locales, including the locale currently used by the system. For example, the user cannot change the symbol used for the local currency. If your application needs this information, it must use the Locale Manager function LmGetLocaleSetting to retrieve it. The Locale Manager is new in Palm OS 4.0, but for backwards compatibility you can use the corresponding PalmOSGlue function LmGlueGetLocaleSetting. Listing 12.2 shows how to use LmGlueGetLocaleSetting.

Listing 12.2  Retrieving a locale setting using Locale Manager


LmLocaleType locale; 
Char currencySymbol[kMaxCurrencySymbolLen+1]; 
UInt16 index; 
 
// Find out what the current locale is.  
OmGlueGetCurrentLocale(&locale); 
 
// Find out which index in the locale resource  
// contains info about that locale.  
LmGlueLocaleToIndex(&locale, &index); 
 
// Get the currency symbol stored in the locale at  
// that index.  
LmGlueGetLocaleSetting(index, lmChoiceCurrencySymbol,  
currencySymbol, sizeof(currencySymbol)); 

Table 12.2 shows which types of information about the current locale should be retrieved from the system preferences and which types should be retrieved from the locale resource. Of course, if you want to retrieve information about a different locale or if you want to look up the default used for the current locale, you would always use the Locale Manager instead of the Preferences Manager.

Table 12.2  Obtaining locale information

Value

Function used to retrieve value

Language code

PrefGetPreference(prefLanguage)

Locale description

PrefGetPreference(prefLocale)

Country code

PrefGetPreference(prefCountry)

Country name

LmGlueGetLocaleSetting(..., lmChoiceCountryName, ...)

Currency name

LmGlueGetLocaleSetting(..., lmChoiceCurrencyName, ...)

Currency symbol

LmGlueGetLocaleSetting(..., lmChoiceCurrencySymbol, ...)

Unique currency symbol

LmGlueGetLocaleSetting(..., lmChoiceUniqueCurrencySymbol, ...)

Measurement system (metric or English)

PrefGetPreference(prefMeasurementSystem)

Number formats

PrefGetPreference(prefNumberFormat)

Number of decimal places for monetary values

LmGlueGetLocaleSetting(..., lmChoiceCurrencyDecimalPlaces, ...)

Starting day of the week

PrefGetPreference(prefWeekStartDay)

Date formats

PrefGetPreference(prefDateFormat)

PrefGetPreference(prefLongDateFormat)

Time format

PrefGetPreference(prefTimeFormat)

Time zone

PrefGetPreference(prefMinutesWestOfGMT) (pre 4.0)

PrefGetPreference(prefTimeZone) (4.0 and higher)

Daylight savings time

PrefGetPreference(prefDaylightSavings) (pre 4.0)

PrefGetPreference(prefDaylightSavingAdjustment) (4.0 and higher)

Notes on the Japanese Implementation ^TOP^

This section describes programming practices for applications that are to be localized for Japanese use. It covers:

Japanese Character Encoding ^TOP^

The character encoding used on Japanese systems is based on Microsoft code page 932. The complete 932 character set (JIS level 1 and 2) is supported in both the standard and large font sizes. The bold versions of these two fonts contain bolded versions of the glyphs found in the 7-bit ASCII range, but on some handhelds, the single-byte Katakana characters and the multi-byte characters are not bolded.

Japanese Character Input ^TOP^

On current Japanese handhelds, users enter Japanese text using Latin (ASCII) characters, and special software called a front-end processor (FEP) transliterates this text into Hiragana or Katakana characters. The user can then ask the FEP to phonetically convert Hiragana characters into a mixture of Hiragana and Kanji (Kana-Kanji conversion).

Figure 12.1  Input area on a Japanese handheld

Japanese handhelds have four additional buttons that control the FEP transliteration and conversion process. These four FEP buttons are arranged vertically between the left-most icons and the handwriting recognition area. The top-most FEP button tells the FEP to attempt Kana-Kanji conversion on the inline text. The next button confirms the inline text and terminates the inline conversion session. The third button toggles the transliteration mode between Hiragana and Katakana. The last button toggles the FEP on and off.

Japanese text entry is always inline, which means that transliteration and conversion happen directly inside of a field. The field code passes events to the FEP, which then returns information about the appropriate text to display.

During inline conversion, the Graffiti® or Graffiti® 2 space stroke acts as a shortcut for the conversion FEP button and the return stroke acts as a shortcut for the confirm FEP button.

The Calculator Button ^TOP^

On current Japanese handhelds, the Calculator silkscreen button doesn't generate a calcChr. Instead, it generates a keyDown event with the event's data.keyDown.chr field set to keyboardChr and it's data.keyDown.modifiers field set to commandKeyMask.

Displaying Japanese Strings on UI Objects ^TOP^

To conserve screen space, you should use half-width Katakana characters on user interface elements (such as buttons, menu items, labels, and pop-up lists) whenever the string contains only Katakana characters. If the string contains a mix of Katakana and either Hiragana, Kanji, or Romaji, then use the full-width Katakana characters instead.

Displaying Error Messages ^TOP^

You may have code that uses the macros ErrFatalDisplayIf and ErrNonFatalDisplayIf to determine error conditions. If the error condition occurs, the system displays the file name and line number at which the error occurred along with the message that you passed to the macro. Often these messages are hard-coded strings. On Japanese systems, the Palm OS traps the messages passed to these two macros and displays a generic message explaining that an error has occurred.

You should only use ErrFatalDisplayIf and ErrNonFatalDisplayIf for totally unexpected errors. Do not use them for errors that you believe your end users will see. If you wish to inform your users of an error, use a localizable resource to display the error message instead of ErrFatalDisplayIf or ErrNonFatalDisplayIf.

Chinese Fonts ^TOP^

Some Chinese fonts—especially 9 point on a standard display—use all of the available vertical space. Because of this the layout of form elements might need to be tweaked for proper vertical spacing.

Summary of Localization ^TOP^