How to create a basic translation (I18n) function

Here is one approach you might take to creating a translate function.

This function accepts three parameters:

  • translations - an object which might look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"english": {
"buttons": {
"ok": "OK",
"cancel": "Cancel",
"create_account": "Create Account"
},
"headings": {
"account": "My Account",
"home": "Home",
"my_page": "{{ name }}'s Page"
}
},
"french": {
...
},
"spanish": {
...
}
}
  • key - a string representing a potential entry in the translations object. Nesting is represented with a .. For example, if a user wanted to get the create account text for our english buttons then they would use a key like english.buttons.create_account.

  • substitutions - an optional flat object which tells translate how to handle interpolation. A replacement occurs when there is a match with the key and the interpolated argument is found in substitutions

translateTry in REPL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function translate(translations = {}, key = '', substitutions = {}) {
const phraseBook = {};
populatePhraseBook(translations);
if (phraseBook[key] && typeof phraseBook[key] === 'string') return handleSubstitutions(phraseBook[key], substitutions);
console.warn(`Missing translation for key: ${key}`);
function populatePhraseBook(morePhrases, prefix = '') {
for (const [key, phrase] of Object.entries(morePhrases)) {
const prefixedKey = prefix ? `${prefix}.${key}` : key;
if (typeof phrase === 'object') {
populatePhraseBook(phrase, prefixedKey);
} else {
phraseBook[prefixedKey] = phrase;
}
}
}
function handleSubstitutions(string, substitutions = {}) {
const interpolationRegex = /\{\{(.*?)\}\}/g;
return string.replace(interpolationRegex, (expression, match) => {
match = match.trim();
return substitutions.hasOwnProperty(match) ? substitutions[match] : expression
});
}
}