Merge pull request #2776 from element-hq/quenting/locales-as-assets
Handle locales as Vite assets
This commit is contained in:
2
src/@types/i18next.d.ts
vendored
2
src/@types/i18next.d.ts
vendored
@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
import "i18next";
|
||||
// import all namespaces (for the default language, only)
|
||||
import app from "../../public/locales/en-GB/app.json";
|
||||
import app from "../../locales/en-GB/app.json";
|
||||
|
||||
declare module "i18next" {
|
||||
interface CustomTypeOptions {
|
||||
|
||||
@@ -5,10 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import i18n from "i18next";
|
||||
import i18n, {
|
||||
type BackendModule,
|
||||
type ReadCallback,
|
||||
type ResourceKey,
|
||||
} from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import Backend from "i18next-http-backend";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill";
|
||||
@@ -19,6 +22,68 @@ import { Config } from "./config/Config";
|
||||
import { ElementCallOpenTelemetry } from "./otel/otel";
|
||||
import { platform } from "./Platform";
|
||||
|
||||
// This generates a map of locale names to their URL (based on import.meta.url), which looks like this:
|
||||
// {
|
||||
// "../locales/en-GB/app.json": "/whatever/assets/root/locales/en-aabbcc.json",
|
||||
// ...
|
||||
// }
|
||||
const locales = import.meta.glob<string>("../locales/*/*.json", {
|
||||
query: "?url",
|
||||
import: "default",
|
||||
eager: true,
|
||||
});
|
||||
|
||||
const getLocaleUrl = (
|
||||
language: string,
|
||||
namespace: string,
|
||||
): string | undefined => locales[`../locales/${language}/${namespace}.json`];
|
||||
|
||||
const supportedLngs = [
|
||||
...new Set(
|
||||
Object.keys(locales).map((url) => {
|
||||
// The URLs are of the form ../locales/en-GB/app.json
|
||||
// This extracts the language code from the URL
|
||||
const lang = url.match(/\/([^/]+)\/[^/]+\.json$/)?.[1];
|
||||
if (!lang) {
|
||||
throw new Error(`Could not parse locale URL ${url}`);
|
||||
}
|
||||
return lang;
|
||||
}),
|
||||
),
|
||||
];
|
||||
|
||||
// A backend that fetches the locale files from the URLs generated by the glob above
|
||||
const Backend = {
|
||||
type: "backend",
|
||||
init(): void {},
|
||||
read(language: string, namespace: string, callback: ReadCallback): void {
|
||||
(async (): Promise<ResourceKey> => {
|
||||
const url = getLocaleUrl(language, namespace);
|
||||
if (!url) {
|
||||
throw new Error(
|
||||
`Namespace ${namespace} for locale ${language} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
credentials: "omit",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw Error(`Failed to fetch ${url}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
})().then(
|
||||
(data) => callback(null, data),
|
||||
(error) => callback(error, null),
|
||||
);
|
||||
},
|
||||
} satisfies BackendModule;
|
||||
|
||||
enum LoadState {
|
||||
None,
|
||||
Loading,
|
||||
@@ -74,6 +139,7 @@ export class Initializer {
|
||||
nsSeparator: false,
|
||||
pluralSeparator: "_",
|
||||
contextSeparator: "|",
|
||||
supportedLngs,
|
||||
interpolation: {
|
||||
escapeValue: false, // React has built-in XSS protections
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ import { cleanup } from "@testing-library/react";
|
||||
import "vitest-axe/extend-expect";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import EN_GB from "../public/locales/en-GB/app.json";
|
||||
import EN_GB from "../locales/en-GB/app.json";
|
||||
import { Config } from "./config/Config";
|
||||
|
||||
// Bare-minimum i18n config
|
||||
|
||||
Reference in New Issue
Block a user