Split translations between EW and shared components (#31441)

* Split translations between EW and shared components

Uses update module API with global TranslationKey type that can be
overridden.

WIP.

* Removed the wrong script (for now)

* Add the type files

* Add shared components i18n file

* More i18n strings

* Add i18n check for shared conmponents

* Needs a different name

* rerun i18n for merge from develop, fix test

* Move translated strings to shared components file

NB. there are lots of removed strings for a few languages where we
seem to have hit a localazy bug or something where the key/value
for plurals got switched, making the translations invalid. They've
been missing for a while so I'm removing them rather than trying to
restore them,

* Add shared components files to localazy

* Merge element web & shared component translations

for the built app

* Use right translations for shared component tests

and fix missign en_EN strings

* Pull shared components translations too

* Fix/disable warnings

* We can now remove the build:res call

...right? (right?)

* Remove webpack import for languages index

..and just load it using a relative path which we do for the individual
language files and also did anyway for the index because even in non-test
it was an object, not a string, so we always usesd the 'test' code path.

* Make the storybook language selector work

...without referring to the parent app's files

* Revert unnecessary yarn lock change

* Typo

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

* Add comment on why we use merge

* Fix localazy download config

to actually put the translations in the right place

* Better typescript syntax

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

* Watch both translations files

---------

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
David Baker
2026-01-07 11:49:01 +00:00
committed by GitHub
co-authored by Michael Telatynski
parent 4ee04d0661
commit 13696af194
131 changed files with 1783 additions and 1763 deletions
@@ -5,14 +5,13 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type TranslationKey } from "../i18nKeys";
import { I18nApi } from "./I18nApi";
describe("I18nApi", () => {
it("can register a translation and use it", () => {
const i18n = new I18nApi();
i18n.register({
"hello.world": {
["hello.world" as TranslationKey]: {
en: "Hello, World!",
},
});
@@ -9,7 +9,6 @@ import { type I18nApi as II18nApi, type Variables, type Translations } from "@el
import { humanizeTime } from "./humanize";
import { _t, getLocale, registerTranslations } from "./i18n";
import { type TranslationKey } from "../i18nKeys";
export class I18nApi implements II18nApi {
/**
@@ -24,10 +23,11 @@ export class I18nApi implements II18nApi {
*/
public register(translations: Partial<Translations>): void {
const langs: Record<string, Record<string, string>> = {};
for (const key in translations) {
for (const lang in translations[key]) {
for (const lang in translations[key as keyof Translations]) {
langs[lang] = langs[lang] || {};
langs[lang][key] = translations[key][lang];
langs[lang][key] = translations[key as keyof Translations]![lang];
}
}
+4 -12
View File
@@ -25,13 +25,11 @@ import React from "react";
import { KEY_SEPARATOR } from "matrix-web-i18n";
import counterpart from "counterpart";
import type { TranslationKey } from "../index";
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
import webpackLangJsonUrl from "$webapp/i18n/languages.json";
export { KEY_SEPARATOR, normalizeLanguageKey, getNormalizedLanguageKeys } from "matrix-web-i18n";
// Path where we load language files from (the index plus translations for each language)
// The filename is appended to this, so a relative path here will result in a fetch for
// a relative URL.
const i18nFolder = "i18n/";
// Control whether to also return original, untranslated strings
@@ -421,13 +419,7 @@ async function getLanguage(langPath: string): Promise<ICounterpartTranslation> {
}
export async function getLangsJson(): Promise<Languages> {
let url: string;
if (typeof webpackLangJsonUrl === "string") {
// in Jest this 'url' isn't a URL, so just fall through
url = webpackLangJsonUrl;
} else {
url = i18nFolder + "languages.json";
}
const url = i18nFolder + "languages.json";
const res = await fetch(url, { method: "GET" });