feat: show call participants in room list (Discord-style)
Docker / Docker Buildx (push) Has been cancelled
Build Debian package / Build package (release) Has been cancelled
Build and Deploy / prepare (release) Has been cancelled
Deploy release / Deploy to Cloudflare Pages (release) Has been cancelled
Build and Deploy / Trigger Pro pipeline (release) Has been cancelled
Build and Deploy / Windows arm64 (release) Has been cancelled
Build and Deploy / Windows x64 (release) Has been cancelled
Build and Deploy / macOS (release) Has been cancelled
Build and Deploy / Linux amd64 (sqlcipher static) (release) Has been cancelled
Build and Deploy / Linux arm64 (sqlcipher static) (release) Has been cancelled
Build and Deploy / ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }} (release) Has been cancelled
Build and Deploy / Deploy builds to ESS (release) Has been cancelled

This commit is contained in:
sorB
2026-05-10 14:25:35 +02:00
parent b797925316
commit 3da363517f
4610 changed files with 827237 additions and 1 deletions
@@ -0,0 +1,85 @@
/*
* Copyright 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
/**
* Script to generate i18n files for Storybook build.
*/
import * as fs from "node:fs";
import { createHash } from "node:crypto";
// Base path for i18n strings
const I18N_BASE_PATH = "./src/i18n/strings/";
// Destination path for generated i18n files
const I18N_DEST = "storybook-static/i18n/";
// List of languages to include
const INCLUDE_LANGS = [...new Set([...fs.readdirSync(I18N_BASE_PATH)])]
.filter((fn) => fn.endsWith(".json"))
.map((f) => f.slice(0, -5));
// Check if dist exists
if (!fs.existsSync("dist")) {
fs.mkdirSync("dist");
}
// Check if i18n exists
if (!fs.existsSync(I18N_DEST)) {
fs.mkdirSync(I18N_DEST);
}
// Type mapping language codes to filenames
type LangFileMap = Record<string, string>;
/**
* Prepare language files by creating hashed filenames and writing them to the destination.
* @returns Mapping of language codes to filenames
*/
function prepareLangFiles(): LangFileMap {
return INCLUDE_LANGS.reduce<Record<string, string>>((fileMap, lang) => {
const [filename, json] = createHashFromFile(lang);
fs.writeFileSync(`${I18N_DEST}${filename}`, json);
fileMap[lang] = filename;
return fileMap;
}, {});
}
/**
* Create a hash from the contents of the language file.
* @param lang - Language code
* @returns Tuple of filename and JSON content
*/
function createHashFromFile(lang: string): [filename: string, json: string] {
const translationsPath = `${I18N_BASE_PATH}${lang}.json`;
const jsonStr = fs.readFileSync(translationsPath).toString();
const jsonBuffer = Buffer.from(jsonStr);
const digest = createHash("sha256").update(jsonBuffer).digest("hex").slice(0, 7);
const filename = `${lang}.${digest}.json`;
return [filename, jsonStr];
}
/**
* Generate the languages.json file mapping language codes to filenames.
* @param langFileMap
*/
function genLangList(langFileMap: LangFileMap): void {
const languages: Record<string, string> = {};
INCLUDE_LANGS.forEach(function (lang) {
const normalizedLanguage = lang.toLowerCase().replace("_", "-");
const languageParts = normalizedLanguage.split("-");
if (languageParts.length == 2 && languageParts[0] == languageParts[1]) {
languages[languageParts[0]] = langFileMap[lang];
} else {
languages[normalizedLanguage] = langFileMap[lang];
}
});
fs.writeFileSync(`${I18N_DEST}/languages.json`, JSON.stringify(languages, null, 4));
}
const langFileMap = prepareLangFiles();
genLangList(langFileMap);