I18n - language fallback behaviour

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 of the i18next framework).

Cheers,

Tobias

As I seem to be the only one interested in this topic :grimacing:
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

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