# I18n - language fallback behaviour

**URL:** <https://discourse.nodered.org/t/i18n-language-fallback-behaviour/13039>\
**Category:** Feature Requests\
**Created:** [8 July 2019 12:32 UTC](https://discourse.nodered.org/t/i18n-language-fallback-behaviour/13039 "2019-07-08T12:32:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![tot92](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/tot92/32/10076_2.png) [@tot92](https://discourse.nodered.org/u/tot92)\
**Post date:** [8 July 2019 12:32 UTC](https://discourse.nodered.org/t/i18n-language-fallback-behaviour/13039/1 "2019-07-08T12:32:32Z")

</div>

Hi there,

I recently tried to add internationalisation to my nodes.

Beside the default "en-US" files I added corresponding "de" files.  
This works fine if I set my browser language to "de".  
But if I set it to "de-DE", it will not fall back to "de" but to "en-US".

It would be nice, if "de-DE" would fall back to "de" first (following the [fallback principles](https://www.i18next.com/principles/fallback) of the i18next framework).

Cheers,

Tobias

---

<div class="post-metadata">

**Author:** ![tot92](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/tot92/32/10076_2.png) [@tot92](https://discourse.nodered.org/u/tot92)\
**Post date:** [18 October 2019 13:47 UTC](https://discourse.nodered.org/t/i18n-language-fallback-behaviour/13039/2 "2019-10-18T13:47:18Z")

</div>

As I seem to be the only one interested in this topic 😬  
I fixed the issue in my local installation (tested with node-red@1.0.1 and Chrome, Firefox and IE11):

All changes (only) affect `@node-red/util/lib/i18n.js`.

First I added the following helper function:

`function readFile(lng, ns) { return new Promise((resolve, reject) => { if (resourceCache[ns] && resourceCache[ns][lng]) { resolve(resourceCache[ns][lng]); } else if (resourceMap[ns]) { const file = path.join(resourceMap[ns].basedir, lng, resourceMap[ns].file); fs.readFile(file, "utf8", function (err, content) { if (err) { reject(err); } else { try { resourceCache[ns] = resourceCache[ns] || {}; resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, '')); const baseLng = lng.split('-')[0]; if (baseLng !== lng && resourceCache[ns][baseLng]) { // merge in base language (e. g. "de" in "de-DE"/"de-CH"/etc.) mergeCatalog(resourceCache[ns][baseLng], resourceCache[ns][lng]); } if (lng !== defaultLang) { mergeCatalog(resourceCache[ns][defaultLang], resourceCache[ns][lng]); } resolve(resourceCache[ns][lng]); } catch (e) { reject(e); } } }); } else { reject(new Error("Unrecognised namespace")); } }); }`

Then I changed the `MessageFileLoader` object to

`var MessageFileLoader = { type: "backend", init: function (services, backendOptions, i18nextOptions) { }, read: function (lng, ns, callback) { const baseLng = lng.split('-')[0]; // read base language (e. g. 'de'), then actual language (e. g. 'de-DE') // return "data || baseData || Error" readFile(baseLng, ns).then( baseData => readFile(lng, ns).then(data => callback(null, data), () => callback(null, baseData)), () => readFile(lng, ns).then(data => callback(null, data), err => callback(err)) ); } }`

Cheers,

Tobias

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [18 October 2019 13:52 UTC](https://discourse.nodered.org/t/i18n-language-fallback-behaviour/13039/3 "2019-10-18T13:52:16Z")

</div>

Hi @tot92

I must have missed your previous post, my apologies.

If you wanted to raise a PR to propose this change we can review it properly there.

Thanks,  
Nick
