/* * 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; /** * 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>((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 = {}; 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);