From a5383f4064f94a162870f1e50792a8741f7cba34 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 24 Mar 2025 17:38:21 +0000 Subject: [PATCH] Bump i18next to 24.x and auto-migrate message catalog format --- package.json | 2 +- .../@node-red/editor-client/src/js/i18n.js | 1 - .../node_modules/@node-red/util/lib/i18n.js | 22 ++++++++++++++++++- .../node_modules/@node-red/util/package.json | 2 +- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d2fb401b6..7891fd6e7 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "hash-sum": "2.0.0", "hpagent": "1.2.0", "https-proxy-agent": "5.0.1", - "i18next": "21.10.0", + "i18next": "24.2.3", "iconv-lite": "0.6.3", "is-utf8": "0.2.1", "js-yaml": "4.1.0", diff --git a/packages/node_modules/@node-red/editor-client/src/js/i18n.js b/packages/node_modules/@node-red/editor-client/src/js/i18n.js index b8c03b85b..e5b479ea5 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/i18n.js +++ b/packages/node_modules/@node-red/editor-client/src/js/i18n.js @@ -27,7 +27,6 @@ RED.i18n = (function() { apiRootUrl = options.apiRootUrl||""; var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage(); var opts = { - compatibilityJSON: 'v3', backend: { loadPath: apiRootUrl+'locales/__ns__?lng=__lng__', }, diff --git a/packages/node_modules/@node-red/util/lib/i18n.js b/packages/node_modules/@node-red/util/lib/i18n.js index 4f1cf110f..7207d4990 100644 --- a/packages/node_modules/@node-red/util/lib/i18n.js +++ b/packages/node_modules/@node-red/util/lib/i18n.js @@ -80,6 +80,21 @@ function mergeCatalog(fallback,catalog) { } } +function migrateMessageCatalogV3toV4(catalog) { + const keys = Object.keys(catalog) + keys.forEach(key => { + if (typeof catalog[key] === 'object') { + catalog[key] = migrateMessageCatalogV3toV4(catalog[key]) + } else if (key.endsWith('_plural')) { + const otherKey = key.replace('_plural', '_other') + if (!catalog[otherKey]) { + catalog[otherKey] = catalog[key] + } + delete catalog[key] + } + }) + return catalog +} async function readFile(lng, ns) { if (/[^a-z\-]/i.test(lng)) { @@ -92,6 +107,12 @@ async function readFile(lng, ns) { const content = await fs.promises.readFile(file, "utf8"); resourceCache[ns] = resourceCache[ns] || {}; resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, '')); + + // Message catalogues are in i18next v3 format. That is no longer supported + // by i18next so we need to migrate any catalog to the v4 format. + // This primarily means mapping `FOO_plural` to `FOO_other` + resourceCache[ns][lng] = migrateMessageCatalogV3toV4(resourceCache[ns][lng]) + var baseLng = lng.split('-')[0]; if (baseLng !== lng && resourceCache[ns][baseLng]) { mergeCatalog(resourceCache[ns][baseLng], resourceCache[ns][lng]); @@ -139,7 +160,6 @@ function init(settings) { initPromise = new Promise((resolve,reject) => { i18n.use(MessageFileLoader); var opt = { - compatibilityJSON: 'v3', // debug: true, defaultNS: "runtime", ns: [], diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json index 5bfeb6508..0d44513de 100644 --- a/packages/node_modules/@node-red/util/package.json +++ b/packages/node_modules/@node-red/util/package.json @@ -16,7 +16,7 @@ ], "dependencies": { "fs-extra": "11.2.0", - "i18next": "21.10.0", + "i18next": "24.2.3", "json-stringify-safe": "5.0.1", "jsonata": "2.0.5", "lodash.clonedeep": "^4.5.0",