Main menu

Working with locales across platforms

Loco expresses locales with standard codes, or language tags as you might know them. This page explains how developers interact with these codes when using the API. General information about managing custom project locales is available here.

Standard language tags

To open with an example, here are the two most common ways "Greek" might be represented:

  • "el" (language code only)
  • "el-GR" (+region code, indicates the country of Greece)

In accordance with RFC 5646, the following variations are also supported by Loco:

  • "el-Latn" (script code indicates transliteration to the Latin alphabet)
  • "el-polyton" (variant code indicates Polytonic Greek)
  • "el-x-custom" (private use extension for whatever else you need)

All Loco project locales follow this syntax, but if your platform uses something different (such as "gre" instead of "el") we have ways to ensure compatibility.

Custom language tags

If you need to use different codes from those Loco provides, you can specify a custom language tag for each of your project locales.

This is useful in a number of cases:

  • to use an underscore instead of a hyphen, such as "el_GR";
  • to use grandfathered tags, such as "zh-yue" for Cantonese;
  • to use alternative ISO standards, such "iw" for Hebrew, or "ger" for German;
  • to use completely non-standard references, like "en-rGB" or simply "english".

Once a custom language tag is defined it will be used across your project whenever Loco would normally use the standard form. This doesn't affect the functionality of Loco at all. A custom tag is just a label for your own purposes.

Platform aliases

The custom language tag is effectively an alias for the tag that Loco would normally use. In addition to this alias, Loco lets you define multiple aliases for targeting different platforms. For example: You could export Simplified Chinese as "zh-Hans" for iOS, but "zh-rCN" for Android.

img

Platform aliases are used by the Export API in two situations:

  1. When file paths are generated for Zip archives;
  2. When the file itself contains language tag references.

Language tags in file paths

For generating Zip archives, Loco defines a default path for each exportable file format. For example:

  • el-GR.lproj/Localizable.strings (for iOS);
  • res/values-el-rGR/strings.xml (for Android).

The language tag that appears in these paths can be customized by setting a platform alias. The following aliases are available for their respective export formats:

"android", "chrome", "codeigniter", "gettext", "ios", "java", "qt", "rails", "symfony".

The Export API also provides a custom file path parameter. This means you don't have to stick to the formats above, you can define any named alias you like and pass it to the Zip exporter. See documentation on custom file paths.

Language tags in file contents

Not all file formats contain language tag references. For those that do, the following aliases affect how they will be written to the relevant export:

  • "gettext" (defines the contents of the Language header in PO files)
  • "symfony" (defines the language attributes exported into Symfony XLIFF files)
  • "rails" (defines the hash keys used in Ruby on Rails YAML files)
  • "ios" (defines the language attributes exported into Xcode XLIFF files)
  • "icu" (defines the table key used in ICU resource bundle source files)
  • "ng" (defines the hash keys used in Angular JavaScript files)
  • "qt" (defines the language attributes exported into Qt Framework TS files)

Note that Loco does not validate your custom language tags against the file format's syntax. For example: always use a valid xml:lang attribute when exporting XML files.

Built-in platform formatting

Loco performs some platform-specific formatting automatically unless you override it with your own platform alias. This is limited to platforms that tend to use underscores instead of hyphens, plus "android" (which places the letter "r" before the region). All other platforms use the standard form by default.

For example, if you have locale "el-GR" and export to Android, the language tag "el-rGR" will be used unless you've overridden this with an alias called "android". Similarly this would be exported as "el_GR" into PO files unless you specified your own "gettext" alias.

Note that this formatting is also applied if you've specified a custom language tag but not a platform alias. For example, if you have locale "zh-Hans" but set your custom tag to "zh_CN" your Android export will use "zh-rCN". This is your custom tag, but in the Android style to avoid errors in your application.

If your custom tag is a non-standard format, it will just be used as it is. For example the tag "english" would not be parsed as a language tag so it would be exported without any formatting.

Language tag matching

In many cases it won't matter if your own codes don't exactly match the ones in Loco. However, if you're doing any of the following things it's recommended you keep them the same, or as close as possible:

  • presenting language tags to the Loco API.
  • exporting files that reference language tags.
  • exporting archives containing multiple files.
  • extracting specific languages from multi-language files.

Referencing project locales

When using the API you will often need to specify a language, such as when you export a file.

In these cases Loco has to match the parameter you specify to no more than one of your project locales. Care should be taken to avoid ambiguous or incorrect matches, so it's always a good idea to use the exact code and not an alias.

  • Example 1: (loose match)
    "en" matches "en-GB" (effectively as a wildcard) so if your project contained ["en-GB","fr-FR","de"] you would get a match.

  • Example 2: (ambiguous)
    "en" matches "en-GB" and "en-US" equally. So if your project contained both of these, you would get a 404 error - no match.

  • Example 3: (reverse match)
    "en-GB" does not technically match "en" (it's more specific), but amongst ["en","fr","de"] it will be matched in reverse as no other tag contradicts.

Matching on aliases

Custom languages tags as described above are only consulted if there is no match for the standard language tag. We don't recommend you rely on this, but it is supported if you find you have to.

For example: "english" matches nothing in ["en","fr","de"] but if you assigned the custom language tag "english" to "en" it would be matched as a final fallback. Alias matching is case-insensitive and your custom tag is NOT parsed; Hence "English" would be matched by "english", but NOT "eng" or "english-uk".

Platform aliases are only consulted during certain platform-specific import processes and shouldn't generally be used to present a locale parameter to the API.

Extracting locales from files

Most file formats have a single target language which can't be mistaken, but when importing from multi-language files there exists a case where the locale you specify means two things:

  1. The project locale you're importing into;
  2. The locale in the file you're extracting out.

If the locale you specify in this situation is not an exact match for both of these things, then knowing the priority order can be critical. For examples of matching languages in files, see importing XLIFF files.

If you're using custom language tags beware of ambiguity when specifying the language you want to extract. The locale parameter you present to the import API will always be consulted first. If there is no match in the file, then the canonical tag of the matching project locale will be used. Only when these both fail will aliases be consulted.

Notes on the standards

BCP47 and RFC 5646

If you're familiar with these standards, please note a few of Loco's storage limitations:

  • Only one variant subtag up to 8 characters is supported per locale.
  • Only one extension OR private use subtag up to 12 characters is supported per locale.
  • All project locales must have a language. If no language applies, you can specify "zxx" instead.
  • Loco only uses one code per language (e.g. Greek is "el", and not "gre" or "ell").
  • Loco doesn't recognize extended language or grandfathered subtags.

These restrictions only affect how Loco stores locales internally. You can always specify an alias if you need to use unsupported codes.

RFC 4647

Regarding the matching of language tags: Loco only very loosely follows some of the principles in RFC 4647.

For example: Loco allows "el" to match "el-Latn" as a wildcard, but this is technically wrong. "el" expands to "el-Grek" by default and so "Latn" is a mismatch on the script subtag. We hope you'll forgive our pragmatic approach!

Legacy projects

When Loco first launched it only supported the "xx_YY" style of locale codes. This legacy style became optional on November 8th 2015. If your project is old you can upgrade it to use standard language tags in your project settings.