From 3cadb9b58736c5f27e42c74f80f0850ba2067024 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 12 Jan 2018 16:21:30 +0000 Subject: [PATCH 1/3] Fall back for missing i18n plurals Counterpart doesn't do fallback if there is a translation for the base string in the preferred language but not the required pluralisation. This meant that if someone added some plurals to a language or a string, but not all, you'd get completely empty strings in the interface. Work around this in the wrapper function. --- src/languageHandler.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/languageHandler.js b/src/languageHandler.js index e732927a75..2d1fbc2f85 100644 --- a/src/languageHandler.js +++ b/src/languageHandler.js @@ -40,7 +40,7 @@ export function _td(s) { // Wrapper for counterpart's translation function so that it handles nulls and undefineds properly // Takes the same arguments as counterpart.translate() -function safeCounterpartTranslate(...args) { +function safeCounterpartTranslate(text, options) { // Horrible hack to avoid https://github.com/vector-im/riot-web/issues/4191 // The interpolation library that counterpart uses does not support undefined/null // values and instead will throw an error. This is a problem since everywhere else @@ -48,19 +48,29 @@ function safeCounterpartTranslate(...args) { // valid ES6 template strings to i18n strings it's extremely easy to pass undefined/null // if there are no existing null guards. To avoid this making the app completely inoperable, // we'll check all the values for undefined/null and stringify them here. - if (args[1] && typeof args[1] === 'object') { - Object.keys(args[1]).forEach((k) => { - if (args[1][k] === undefined) { + let count; + + if (options && typeof options === 'object') { + count = options['count']; + Object.keys(options).forEach((k) => { + if (options[k] === undefined) { console.warn("safeCounterpartTranslate called with undefined interpolation name: " + k); - args[1][k] = 'undefined'; + options[k] = 'undefined'; } - if (args[1][k] === null) { + if (options[k] === null) { console.warn("safeCounterpartTranslate called with null interpolation name: " + k); - args[1][k] = 'null'; + options[k] = 'null'; } }); } - return counterpart.translate(...args); + let translated = counterpart.translate(text, options); + if (translated === undefined && count !== undefined) { + // counterpart does not do fallback if no pluralisation exists + // in the preferred language, so do it here + options.locale = 'en'; + translated = counterpart.translate(text, options); + } + return translated; } /* From 0557737f8dcc4ea4e00e535cf3e0d30812b47305 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 Jan 2018 17:45:29 +0000 Subject: [PATCH 2/3] Don't modify original options arg --- src/languageHandler.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/languageHandler.js b/src/languageHandler.js index 2d1fbc2f85..4e24c04d36 100644 --- a/src/languageHandler.js +++ b/src/languageHandler.js @@ -67,8 +67,7 @@ function safeCounterpartTranslate(text, options) { if (translated === undefined && count !== undefined) { // counterpart does not do fallback if no pluralisation exists // in the preferred language, so do it here - options.locale = 'en'; - translated = counterpart.translate(text, options); + translated = counterpart.translate(text, Object.assign({}, options, {locale: 'en'})); } return translated; }