From d31622d98c0d1221b755f625c45ac8db76167500 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 21 Oct 2022 16:45:34 +0100
Subject: [PATCH] Fix i18n interpolation (#432)

---
 src/language-helper.ts | 36 ++++++++++++++++--------------------
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/src/language-helper.ts b/src/language-helper.ts
index 29189fe..46e8534 100644
--- a/src/language-helper.ts
+++ b/src/language-helper.ts
@@ -18,7 +18,7 @@ import counterpart from "counterpart";
 
 import type Store from 'electron-store';
 
-const DEFAULT_LOCALE = "en";
+const FALLBACK_LOCALE = 'en';
 
 export function _td(text: string): string {
     return text;
@@ -32,9 +32,7 @@ interface IVariables {
 }
 
 export function _t(text: string, variables: IVariables = {}): string {
-    const args = Object.assign({ interpolate: false }, variables);
-
-    const { count } = args;
+    const { count } = variables;
 
     // Horrible hack to avoid https://github.com/vector-im/element-web/issues/4191
     // The interpolation library that counterpart uses does not support undefined/null
@@ -43,21 +41,20 @@ export function _t(text: string, variables: IVariables = {}): string {
     // 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.
-    Object.keys(args).forEach((key) => {
-        if (args[key] === undefined) {
+    Object.keys(variables).forEach((key) => {
+        if (variables[key] === undefined) {
             console.warn("safeCounterpartTranslate called with undefined interpolation name: " + key);
-            args[key] = 'undefined';
+            variables[key] = 'undefined';
         }
-        if (args[key] === null) {
+        if (variables[key] === null) {
             console.warn("safeCounterpartTranslate called with null interpolation name: " + key);
-            args[key] = 'null';
+            variables[key] = 'null';
         }
     });
-    let translated = counterpart.translate(text, args);
-    if (translated === undefined && count !== undefined) {
-        // counterpart does not do fallback if no pluralisation exists
-        // in the preferred language, so do it here
-        translated = counterpart.translate(text, Object.assign({}, args, { locale: DEFAULT_LOCALE }));
+    let translated = counterpart.translate(text, variables);
+    if (!translated && count !== undefined) {
+        // counterpart does not do fallback if no pluralisation exists in the preferred language, so do it here
+        translated = counterpart.translate(text, { ...variables, locale: FALLBACK_LOCALE });
     }
 
     // The translation returns text so there's no XSS vector here (no unsafe HTML, no code execution)
@@ -75,8 +72,8 @@ export class AppLocalization {
     private readonly localizedComponents?: Set<Component>;
 
     constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) {
-        counterpart.registerTranslations("en", this.fetchTranslationJson("en_EN"));
-        counterpart.setFallbackLocale('en');
+        counterpart.registerTranslations(FALLBACK_LOCALE, this.fetchTranslationJson("en_EN"));
+        counterpart.setFallbackLocale(FALLBACK_LOCALE);
         counterpart.setSeparator('|');
 
         if (Array.isArray(components)) {
@@ -122,16 +119,15 @@ export class AppLocalization {
             locales = [locales];
         }
 
-        locales.forEach(locale => {
+        const loadedLocales = locales.filter(locale => {
             const translations = this.fetchTranslationJson(locale);
             if (translations !== null) {
                 counterpart.registerTranslations(locale, translations);
             }
+            return !!translations;
         });
 
-        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-        // @ts-ignore - this looks like a bug but is out of scope for this conversion
-        counterpart.setLocale(locales);
+        counterpart.setLocale(loadedLocales[0]);
         this.store.set(AppLocalization.STORE_KEY, locales);
 
         this.resetLocalizedUI();