@amazon-devices/keplerscript-kepleri18n-lib
The Kepler Internationalization (i18n) API enables localization functionality in your apps.
Remarks
As a best practice store UI messages in a resource file that is not part of the source code. The Asset Resolver API enables apps to manage external string resources in Kepler. The API defines both the resource file format and the expected location of string resource files within an application's source directory. Aps can use this API to retrieve localized strings that match the device locale, ensuring users see UI messages in their preferred language.
Get started
Setup
Add the following library dependency to the dependencies
section of your package.json file.
"@amazon-devices/asset-resolver-lib": "~1.0.0", // or latest version
"@amazon-devices/keplerscript-kepleri18n-lib": "~1.0.0", // or latest major version
Usage
The following sections describe how to use the Asset Resolver and Internationalization APIs.
Define Resource Files
The first step is to create resource files in which you will store the string resources. The resource files that you create and own are for text in the source language. The string resource file format is PUFF-J. See PUFF-J page for more details and an extensive PUFF-J sample.
Some rules and best practices to keep in mind:
- The file extension for a resource file is .puff.json. A typical PUFF-J resource file name is strings.puff.json.
- The character set for resource IDs in PUFF-J is restricted to alphanumeric, underscore, hyphen, and colon. The rule is not currently enforced, but it will be in the near future.
- As a best practice, name resource IDs descriptively such that they identify where the resource is used and what the resource is used for. For example, for a string resource used as the Wi-Fi setup dialog title, the ID could be "wifi-setup-dialog-title".
- Include enough context for the resource in the
note
attribute. Especially for strings that have placeholders, provide context on what the placeholders are as well as sample values for the placeholders. - You can organize string resources into multiple PUFF-J files. Keep in mind that resource keys defined in PUFF-J files must be unique across the set of all PUFF-J files in the application. If you do create multiple PUFF-J files, consider prefixing resource keys with application name and file name so that it’s easier to ensure uniqueness of resource keys.
Example PUFF-J file:
{
"note": "Resources for App A",
"dir": "ltr",
"resources": {
"wifi-setup-dialog-title": "Connect to Wi-Fi",
"wifi-setup-network-connected-message": {
"note": "This message is displayed upon successful connection to a Wi-Fi network. The {ssid} placeholder is the SSID of the connected Wi-Fi network, such as 'Home Network'.",
"value": "Wi-Fi is successfully connected. Network: {ssid}"
}
}
}
The string "Wi-Fi is successfully connected. Network: {ssid}" in the example is a classic message format pattern. For string resources that contain placeholders that are replaced at runtime, do not concatenate strings to form the complete message. Translating string fragments out of context and then concatenating them leads to incorrect translation of the complete message. Kepler provides a message format solution that you can use to write the complete message as a classic message format pattern. Translators can then view and translate the complete message. See Message Format guide on using MessageFormatClassic
API and specifying patterns.
PUFF-J also supports number resources. Number resources are represented in double floating-point type.
Resource File Location in Source Repository
Place app source-language PUFF-J files directly in the assets/text/ subdirectory. These are the source files from which your localization provider takes the strings to translate. Localized PUFF-J files are placed in the corresponding assets/text/<BCP-47 language tag>/ subdirectories.
BCP-47 uses a hyphen as the subtag separator, for example en-US
, not an underscore which is used in locale IDs on POSIX platforms to separate between language and region fields.
en-US PUFF-J file symbolic links
If the root / source-language PUFF-J files are in American English and en
PUFF-J files are in British English, add a en-US
subfolder and add symbolic links under en-US
subfolder linking to corresponding root PUFF-J files (For example for the example subdirectory tree below: mkdir assets/text/en-US; cd assets/text/en-US; ln -s ../strings.puff.json strings.puff.json
). This is to make sure that for the en-US
locale, the root PUFF-J files in American English are retrieved before en
PUFF-J files in British English."
Example assets/text/ subdirectory tree:
assets
└── text
├── strings.puff.json
├── en-US
│ └── strings.puff.json --- symbolic link to root PUFF-J file ---> ../strings.puff.json
├── fr
│ └── strings.puff.json
├── fr-CA
│ └── strings.puff.json
└── ja
└── strings.puff.json
Make sure that the assets directory is included in or copied into the source directory from which VPT packaging tool creates the app package. For React Native for Kepler apps, the build tool takes care of that.
API to Retrieve Resources Defined In Resource Files
Use Asset Resolver API to retrieve resources defined in PUFF-J files.
The following example shows how to call AssetResolver
.
import { AssetResolver } from '@amazon-devices/asset-resolver-lib'
...
const strResource = AssetResolver.getString("desired-resource-id");
// strResource.value is the resource string.
// strResource.dir is the text base (written) direction of the resource string as specified in corresponding PUFF-J file.
const numberResource = AssetResolver.getNumber("another-resource-id");
// numberResource is the resource number.
Set the dir
attribute of a string resource to Text UI widget when the string resource might have a text base direction that is different from the Text UI widget's default text base direction. For example, if an Arabic string resource is displayed in an English UI, set the Text UI widget’s text base direction attribute to this dir
attribute value, which is rtl
(right to left) as set in the Arabic PUFF-J resource file.
For select and plural string resource types, AssetResolver.getString()
returns the resource as a classic message format pattern string. For more information about Resource Types, see Resource Types in the "PUFF-J File Format" topic.
For information about using the MessageFormatClassic
class with the returned pattern string to produce the formatted string, see Message Format guide.
String Formatting
Message Format
User-facing messages can have variables such as names, numbers, dates, and time to be filled in at runtime. Localized message translations often have different word ordering based on the target language's grammar. Thus, translators need to be able to move variables around in a message's translation. Translators can only do so when they have the complete message with placeholders for variables. Concatenating phrases based on source language grammar can render the message untranslatable. Kepler provides a message format solution which has placeholders for the variables in the message. Developers can use this message format pattern to write the complete message in a localization friendly manner.
The MessageFormatClassic
class adopts the classic ICU MessageFormat pattern. For pattern tutorial and reference, see classic ICU MessageFormat guide. Since the inception of classic ICU MessageFormat patterns, there have been several shifts in the best practices - the most important of them is the use of named arguments, rather than numbered / positional arguments. Please use the named arguments examples as reference. And use the MessageFormatClassic
class with the patterns rather than what's shown in code examples there.
NOTE: Unicode has a working group drafting a new message format standard. We will review it for inclusion in Kepler after the standard is released.
MessageFormatClassic
supports both named-argument style and numbered-argument style for placeholders in patterns. Named-argument style is recommended because with descriptively named placeholders, both developers and translators benefit from improved readability and can better infer what kind of values goes into a placeholder in a pattern.
Use Message Format in React Native for Kepler
The following procedure shows how to use the MessageFormatClassic
class.
-
Import
MessageFormatClassic
from the@amazon-devices/keplerscript-kepleri18n-lib
package.import { MessageFormatClassic } from '@amazon-devices/keplerscript-kepleri18n-lib';
-
To use named-argument style pattern in the
MessageFormatClassic
class, construct a JavaScript built-inMap
object populated with argument names and corresponding values. Then pass the populatedMap
instance as well as the pattern to theMessageFormatClassic.format()
method.Use the named-argument style pattern instead of the numbered-argument style pattern as shown in the following example.
import { MessageFormatClassic } from '@amazon-devices/keplerscript-kepleri18n-lib'; ... // Retrieve the pattern from the string resources. It's hardcoded here to simplify the example. const pattern: string = "Car number {carNumber} wins! Congratulations, {driverName}!"; const carNumber: number = 3; const driverName: string = "Alice"; const argMap = new Map<string, number | string | Date>(); argMap.set("carNumber", carNumber); argMap.set("driverName", driverName); const message: string | null = MessageFormatClassic.format(pattern, argMap); if (message === null) { // Error return; } // message is "Car number 3 wins! Congratulations, Alice!".
-
To use numbered-argument style pattern in the
MessageFormatClassic
class, callMessageFormatClassic.formatPositional()
method with the pattern and argument values in the numbered-argument order. For example, the value for argument zero{0}
is provided first after the pattern parameter. If there is more than one argument in the pattern, it is followed by the value for argument one{1}
, and so on.The following example shows how to use a numbered-argument style pattern:
import { MessageFormatClassic } from '@amazon-devices/keplerscript-kepleri18n-lib'; ... // Retrieve the pattern from the string resources. It's hardcoded here to simplify the example. const pattern: string = "Car number {0} wins! Congratulations, {1}!"; const carNumber: number = 11; const driverName: string = "Bob"; const message: string | null = MessageFormatClassic.formatPositional(pattern, carNumber, driverName); if (message === null) { // Error return; } // message is "Car number 11 wins! Congratulations, Bob!".
Measurement Units
For formatting measurement units such as for temperature, distance, speed, power, torque, and pressure, use Message Format described above with measurement unit skeletons in pattern:
- Specifying skeletons in classic ICU MessageFormat patterns
- Number skeletons, which include support for measurement unit formatting.
- Available measurement units from Unicode CLDR
The following are examples of classic ICU MessageFormat patterns with measurement unit skeletons.
"Current Temperature: {temperatureInFahrenheit, number, :: unit/fahrenheit}"
// Sample output: "Current Temperature: 70°F".
"{distanceInKilometers, number, :: unit/kilometer unit-width-full-name}"
// Sample outputs: "1 kilometer", "100 kilometers". Notice the plural is already taken care of in the format result.
"{speedInKilometersPerHour, number, :: unit/kilometer-per-hour}"
// Sample output: "50 km/h".
"{speedInMilesPerHour, number, :: unit/mile-per-hour}"
// Sample output: "25 mph".
"{pressureInPSI, number, :: unit/pound-force-per-square-inch}"
// Sample output: "36 psi"
Elapsed Time/Duration
In React Native for Kepler, the ECMAScript Intl.DurationFormat
object (Stage 3 Proposal) is available. API documentation and examples are available on Mozilla MDN Web Docs. The TC39 API proposal is on GitHub.
Sorting in Alphabetical And Natural Order / Collation
In React Native for Kepler, the ECMAScript Intl.Collator
object is available. API documentation and examples are available on Mozilla MDN Web Docs.
Application / System Locale And Time Zone Preferences
I18nManager
provides functions to retrieve, modify, and listen for changes to application locale and time zone preferences. For more information about the API, see the I18nManager section in the React Native for Kepler Internationalization and Localization API.
Modules
- ArgumentConverter
- MessageFormatClassic
- ProductNameFormat
- turbo-modules/NativeKeplerI18n
- types/KeplerI18nTypes
Last updated: Sep 30, 2025