i18n
Any string internationalization or localization must happen inside your extension code. As a convenience, the extension SDK provides access to a full-featured i18n library. This section describes how to use this library, but you are welcome to use any i18n mechanism that works well for you.
Providing and using i18n strings
There is an i18n
object in the global namespace that provides a few methods you'll commonly use:
i18n.getLanguage | Returns the language code currently selected by the user in Lucid, e.g. "en" or "es-LA" |
i18n.setData | Adds new strings to the currently active i18n dictionary, and updates the active language |
i18n.get | Gets a string from the currently active i18n dictionary and performs interpolations as necessary |
Here is a minimal example of using the library:
const language = i18n.getLanguage();
// Set the English strings as fallbacks, in case other languages
// don't have all the strings translated yet
i18n.setData({
"a": "ay",
"b": "bee",
}, language);
// If the language is set to a language that
// have a dictionary for, set those strings as replacements
if(language == "es-LA") {
i18n.setData({
"a": "ah",
"b": "bay",
}, language);
}
// Later...
const client = new EditorClient();
client.alert(i18n.get("a"));
Use JSON files for string dictionaries
Inlining your i18n strings into your source code isn't a scalable solution. Instead, you can put your dictionaries into .json
files under your resources
directory. For example, if you add the files resources/i18n/en.json
, resources/i18n/es-LA.json
, etc., your code could look like this instead:
import en from '../resources/i18n/en.json';
import de from '../resources/i18n/de.json';
import esLa from '../resources/i18n/es-LA.json';
const language = i18n.getLanguage();
i18n.setData(en, language);
if (language == 'de') {
i18n.setData(de, language);
} else if (language == 'es-LA') {
i18n.setData(esLa, language);
}
In order to import JSON files like this, you'll need to make sure your resources/resource.d.ts
file specifies their type:
declare module '*.json' {
const content: Record<string, string>;
export default content;
}
You must also have exclude: /\.json$/
in the raw-loader
rule for the resources directory in webpack.config.js
.
String interpolation
You can mark sections of your string to be replaced with curly braces:
i18n.setData(
{
'title': 'Send an email to {name}',
},
i18n.getLanguage(),
);
// "Send an email to Ben"
console.log(i18n.get('title', {'name': 'Ben'}));
Pluralization
count
is a reserved string interpolation ID, to be used only for pluralization.
You can provide entries in your i18n dictionary that support pluralization by appending (in most languages) .one
or .other
to the key:
i18n.setData(
{
'title.one': 'Send an email to {count} person',
'title.other': 'Send an email to {count} people',
},
i18n.getLanguage(),
);
// "Send an email to 1 person"
console.log(i18n.get('title', {'count': 1}));
// "Send an email to 4 people"
console.log(i18n.get('title', {'count': 4}));
You can learn more about pluralization rules on this site from the Unicode CLDR Project. You can see a full list of which pluralization rules you should specify for every possible language here.
For convenience, here is the list of pluralization suffixes you should provide (only for strings interpolating a count
) for each language supported by Lucid:
Language | Suffixes |
---|---|
Chinese | other |
Dutch | one, other |
English | one, other |
French | one, other |
German | one, other |
Italian | one, other |
Japanese | other |
Korean | one, other |
Polish | one, other |
Portuguese | one, other |
Russian | one, few, many |
Spanish | one, other |
Swedish | one, other |
List of strings
You can provide a list of strings for expansion into a comma-separated list.
i18n.setData(
{
'shopping-list': 'Purchase {shoplist} today',
},
i18n.getLanguage(),
);
// "Purchase bread today"
const shoppingList1 = ['bread'];
console.log(i18n.get('shopping-list', {'shoplist': shoppingList}));
// "Purchase bread, apples, fish, and butter today"
const shoppingList2 = ['bread', 'apples', 'fish', 'butter'];
console.log(i18n.get('shopping-list', {'shoplist': shoppingList2}));
By default, the list expansion will add commas and will default to and
. You can change the list options by specifying formatOptions
. Available options include ListStyles
as
List Style | Example |
---|---|
LONG | a, b, and c |
SHORT | a, b, & c |
NARROW | a, b, c |
List Type | Example |
---|---|
AND | a, b, and c |
OR | a, b, or c |
UNIT_LIST | a b c |
If the text will change based on the length of the list, it can be combined with the Pluralization rules by also providing a count
field.
i18n.setData(
{
'invite-list.one': 'You might invite your friend {friendlist} to the party',
'invite-list.many': 'You might invite your friends, {friendlist}, to the party',
},
i18n.getLanguate(),
);
// "You might invite your friend Anna to the party"
const friendList1 = ['Anna'];
console.log(i18n.get('invite-list', {'count': friendList1.length, 'friendlist': i18n.formatList(friendList2, {style: ListStyles.LONG, type: ListTypes.OR})}));
// "You might invite your friends, Anna, Betty, Carl, or Dave, to the party"
const friendList2 = ['Anna', 'Betty', 'Carl', 'Dave'];
console.log(i18n.get('invite-list', {'count': friendList2.length, 'friendlist': i18n.formatList(friendList2, {style: ListStyles.LONG, type: ListTypes.OR})}));
Wrapped strings
You can "wrap" sections of your i18n strings in markup, often used for producing HTML links and other simple markup:
i18n.setData(
{
'message': 'Send an email to <w0>{name}</w0>',
},
i18n.getLanguage(),
);
// Send an email to <a href="mailto:[email protected]">Ben</a>
console.log(i18n.get(
'message',
{'name': 'Ben'},
['<a href="mailto:[email protected]">{}</a>']
));
Here, you're replacing the first wrapping tag w0
with the email link, with the content of w0
being placed where the {}
is in the replacement text. If you need to do multiple wrapping tags in the same i18n string, number them w0
, w1
, w2
, etc.
Supported languages
i18n.getLanguage()
will tell you the user's currently-selected language in Lucid. This will be one of the following values:
Language | Code |
---|---|
Chinese (simplified) | zh-CN |
Chinese (traditional) | zh-TW |
Dutch | nl |
English | en |
French | fr-FR |
German | de |
Italian | it-IT |
Japanese | ja |
Korean | ko |
Polish | pl-PL |
Portuguese | pt-BR |
Russian | ru |
Spanish | es-LA |
Swedish | sv-SE |
Updated 8 months ago