From 118585a67219e5538f8ac44bfd194b7255b0d4be Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 17 May 2022 17:44:29 +0100 Subject: [PATCH] Update weblateToCounterpart to be more resilient (#8633) * Remove unused code for weblate->counterpart conversion Happens at build time instead now * Update `weblateToCounterpart` to be more resilient --- __mocks__/browser-request.js | 56 +++++++++++++++++++++++++++++++----- src/languageHandler.tsx | 28 +++++------------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/__mocks__/browser-request.js b/__mocks__/browser-request.js index aa9c710299..7029f1c190 100644 --- a/__mocks__/browser-request.js +++ b/__mocks__/browser-request.js @@ -1,3 +1,19 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + const en = require("../src/i18n/strings/en_EN"); const de = require("../src/i18n/strings/de_DE"); const lv = { @@ -5,6 +21,32 @@ const lv = { "Uploading %(filename)s and %(count)s others|one": "Качване на %(filename)s и %(count)s друг", }; +function weblateToCounterpart(inTrs) { + const outTrs = {}; + + for (const key of Object.keys(inTrs)) { + const keyParts = key.split('|', 2); + if (keyParts.length === 2) { + let obj = outTrs[keyParts[0]]; + if (obj === undefined) { + obj = outTrs[keyParts[0]] = {}; + } else if (typeof obj === "string") { + // This is a transitional edge case if a string went from singular to pluralised and both still remain + // in the translation json file. Use the singular translation as `other` and merge pluralisation atop. + obj = outTrs[keyParts[0]] = { + "other": inTrs[key], + }; + console.warn("Found entry in i18n file in both singular and pluralised form", keyParts[0]); + } + obj[keyParts[1]] = inTrs[key]; + } else { + outTrs[key] = inTrs[key]; + } + } + + return outTrs; +} + // Mock the browser-request for the languageHandler tests to return // Fake languages.json containing references to en_EN, de_DE and lv // en_EN.json @@ -13,7 +55,7 @@ const lv = { module.exports = jest.fn((opts, cb) => { const url = opts.url || opts.uri; if (url && url.endsWith("languages.json")) { - cb(undefined, {status: 200}, JSON.stringify({ + cb(undefined, { status: 200 }, JSON.stringify({ "en": { "fileName": "en_EN.json", "label": "English", @@ -24,16 +66,16 @@ module.exports = jest.fn((opts, cb) => { }, "lv": { "fileName": "lv.json", - "label": "Latvian" - } + "label": "Latvian", + }, })); } else if (url && url.endsWith("en_EN.json")) { - cb(undefined, {status: 200}, JSON.stringify(en)); + cb(undefined, { status: 200 }, JSON.stringify(weblateToCounterpart(en))); } else if (url && url.endsWith("de_DE.json")) { - cb(undefined, {status: 200}, JSON.stringify(de)); + cb(undefined, { status: 200 }, JSON.stringify(weblateToCounterpart(de))); } else if (url && url.endsWith("lv.json")) { - cb(undefined, {status: 200}, JSON.stringify(lv)); + cb(undefined, { status: 200 }, JSON.stringify(weblateToCounterpart(lv))); } else { - cb(true, {status: 404}, ""); + cb(true, { status: 404 }, ""); } }); diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index 0b33cd6a18..1d3fef1666 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -556,27 +556,13 @@ function getLangsJson(): Promise { }); } -function weblateToCounterpart(inTrs: object): object { - const outTrs = {}; - - for (const key of Object.keys(inTrs)) { - const keyParts = key.split('|', 2); - if (keyParts.length === 2) { - let obj = outTrs[keyParts[0]]; - if (obj === undefined) { - obj = {}; - outTrs[keyParts[0]] = obj; - } - obj[keyParts[1]] = inTrs[key]; - } else { - outTrs[key] = inTrs[key]; - } - } - - return outTrs; +interface ICounterpartTranslation { + [key: string]: string | { + [pluralisation: string]: string; + }; } -async function getLanguageRetry(langPath: string, num = 3): Promise { +async function getLanguageRetry(langPath: string, num = 3): Promise { return retry(() => getLanguage(langPath), num, e => { logger.log("Failed to load i18n", langPath); logger.error(e); @@ -584,7 +570,7 @@ async function getLanguageRetry(langPath: string, num = 3): Promise { }); } -function getLanguage(langPath: string): Promise { +function getLanguage(langPath: string): Promise { return new Promise((resolve, reject) => { request( { method: "GET", url: langPath }, @@ -597,7 +583,7 @@ function getLanguage(langPath: string): Promise { reject(new Error(`Failed to load ${langPath}, got ${response.status}`)); return; } - resolve(weblateToCounterpart(JSON.parse(body))); + resolve(JSON.parse(body)); }, ); });