How to Manage Resource Files for Effective i18n & L10n

Introduction

One important aspect of internationalization is to move user-facing hard-coded strings out of the code and into resource files. User-facing strings are typically found in user interfaces: menu items, labels, descriptions, and text elements that are rendered in the application. 

For example, the simple widget below renders many user-facing strings, from “search over 201,000 hotels” to “search now!”

If the strings are hard-coded in the code, this interface will show the same English strings for a Chinese, Japanese, or French user. When coding for a global application, the strings need to be moved from the pure code files into files that can be translated. 

If the code was written this way for instance:

Widget.addLabel(“city or airport”); // pseudo-code showing a hard-code user facing string
Widget.addLabel(“city or airport”); // pseudo-code showing a hard-code user facing string

It would have to be refactored as follows:

Widget.addLabel(I18nUtil.getString(“CITY_ID”)); // pseudo-code showing a user facing string is retrieved from a resource file.

Where CITY_ID is a key in a resource file that the I18nUtil.getString knows how to retrieve based on the locale. (A locale is a combination of a language, a region, and a variant).

In the U.S. English resource file, CITY_ID is mapped to “city or airport”. In the French resource file, CITY_ID is mapped to “ville ou aéroport” for instance.  As a .properties resource file, a snippet could look like:

SearchWidgetResources.properties (for U.S. English)

…
SEARCH_ID=search over {0} hotels
CITY _ID=city or airport
CHECK_IN_ID=check-in
…

SearchWidgetResources_fr.properties (for French)

…
SEARCH_ID=rechercher parmi {0} hôtels
CITY _ID=ville ou aéroport
CHECK_IN _ID=enregistrement
CHECK_OUT_ID=départ
…

Each programming language and framework tends to have its own way to handle resource files, how to denote locales, how to pass locales in the application execution path, and how to fall back on the default locale when a given locale resource is not found. 

For instance:

  • Android standard resource files end in xml (e.g. strings.xml) and are located under directories named “res/values” for the source locale, and “values-fr” for the French version of the files under that directory.
  • Java standard resource files end in properties and are named based on the target locales, such as “resources.properties” for the source locale and “resources_fr.properties” for the French file.

Non-Standard Systems

As opposed to consuming files in a standard way, some applications go to some lengths to find ‘creative alternatives. 

Here are a couple of real-life examples:

  • JSON files are named with the locales, as in a standard, but in the file itself the locale is the root of the file
{
  "en": {
     "testKey": "testValue",
     "UcsTagEditor.add": "Add",
     "UcsTagEditor.key": "Key"
   }
}

Instead of:

{
    "testKey": "testValue",
    "UcsTagEditor.add": "Add",
    "UcsTagEditor.key": "Key"
 }
  • One YAML file with all locales inside:  at build time the file is sliced into n YAML files, transformed into a CSV, sent for translation, returned as a CSV, pushed into a database
  • Developers create YAML files, they get all collated at build time into a read-only JSON file containing all the locales
  • Instead of being located in a directory directly under the locale code, i.e. 
en/resources.json 

the files are located “somewhere below”, i.e. 

en/my/deep/path/to/the/resources.json
  • YAML file format with an XML type structure instead of a YAML type structure, for instance:
- key: server_not_valid
  translation:
    msg: "The server does not exist"
- key: distributable_not_valid
  translation:
    msg: "The distributable does not exist"

Instead of

server_not_valid: "The server does not exist"
distributable_not_valid: "The distributable does not exist"

  translation:

    msg: “The distributable does not exist”

  • All resource files are named the same, like 200 files all named “en.json” instead of each file named differently.

Many more ‘creative’ non-standard resource files exist. For each non-standard type, this means more work, scripts, and development for L10n management and Localization engineers, but also more work, scripts, and development for software developers who are not leveraging the programming framework facilities and need to create their own. 

The processes downstream, typically gathering files, validating the files, sending to translation, tracking the files, on-boarding the files in the translation system, returning the files, verifying the files, re-organizing as per the non-standard format or naming convention or directory structure, pushing them to their respective repository/directory, etc. 

Following standard practices makes everyone’s life easier, including developers’. 

Best Practices Tips

Here are some simple tips that can help set the stage properly for development and localization.

  1. Use the file format for the programming framework: resx for .NET, JSON for JavaScript, properties for Java, etc.
  2. One file per locale: This allows a much more flexible and forward-looking structure to add or remove a target locale. The source file (e.g. the U.S. English file) can be modified independently of its translation into n locales. 
  3. Follow a locale-aware naming convention for either the file or the directory using ISO convention (e.g. ISO 639: fr_FR for France French or fr for French). The framework most likely already requires some standards. For instance:
    1. /path/to/file/resources_fr.json or
    2. /path/to/directory/fr/resources.json
  4. Keep it simple! If the developer writes the source strings in a YAML file, use YAML files for translations, and don’t create a special process. If YAML files are not the end result, if it’s JSON files, for instance, don’t use YAML files at development time, use JSON files right off the bat. 
  5. Name each file uniquely.
  6. Keep the locales consistent: In the same repository, don’t use the country as the locale for some files and the language for others, follow the simple language/country/variant (country and variant being optional).

L10n and i18n don’t have to be difficult, and Lingoport can help. Contact us here for a demo or to discuss your L10n and i18n needs. We can help you go global at the speed of development.

Author

Picture of Lingoport
Lingoport
Hand with mobile phone

Talk to Our Experts

Get you tailored consultation on i18n & L10n products and services.

Related Posts

Receive Latest News and Webinar Dates

Get the latest internationalization news delivered to your inbox.