CH-J Toolsspráva serverů přes SSH
Menu
Vydané zdroje

CH-J Tools

Procházejte adresáře a soubory konkrétního vydání aplikace.

Stáhnout zdroje ZIP
CH-J / Server Manager 872 souborů
core-20261030T220507Z-61e4558d889f Přidáno: · Sestaveno:
i18n.js Přidáno: Datum není evidováno 4,8 KB · 91 řádků
Kód Stáhnout soubor
1"use strict";
3// Core UI translations. The texts live in data files (i18n/core/<language>.json) and the
4// list of languages in i18n/languages.json, so a language is added without code changes.
5// The Rust Core injects both into the window before this script runs; Node tests read the files.
6(function exposeI18n(root, factory) {
7 const api = factory();
8 if (typeof module === "object" && module.exports) module.exports = api;
9 else {
10 root.CHJ_I18N = api;
11 root.chjI18n = api.createI18n(api.defaultLanguage);
12 }
13})(typeof globalThis !== "undefined" ? globalThis : this, () => {
14 function loadData() {
15 const injected = globalThis.__CHJ_I18N__;
16 if (injected && injected.catalogs && injected.catalogs.core) return { manifest: injected.manifest, catalogs: injected.catalogs.core };
17 if (typeof require === "function" && typeof __dirname === "string") {
18 const fs = require("fs"), path = require("path"), dir = path.join(__dirname, "i18n");
19 const manifest = JSON.parse(fs.readFileSync(path.join(dir, "languages.json"), "utf8"));
20 const catalogs = {};
21 for (const language of manifest.languages) {
22 const file = path.join(dir, "core", `${language.code}.json`);
23 if (fs.existsSync(file)) catalogs[language.code] = JSON.parse(fs.readFileSync(file, "utf8"));
24 }
25 return { manifest, catalogs };
26 }
27 return { manifest: { defaultLanguage: "cs", fallbackLanguage: "en", languages: [] }, catalogs: {} };
28 }
30 const { manifest, catalogs } = loadData();
31 const languages = Object.freeze((manifest.languages || []).filter((entry) => catalogs[entry.code]).map((entry) => Object.freeze({ ...entry })));
32 const defaultLanguage = catalogs[manifest.defaultLanguage] ? manifest.defaultLanguage : (languages[0]?.code || "cs");
33 const sourceLanguage = catalogs.cs ? "cs" : defaultLanguage;
34 const localeByLanguage = Object.freeze(Object.fromEntries(languages.map((entry) => [entry.code, entry.locale || entry.code])));
35 const supportedLanguages = Object.freeze(languages.map((entry) => entry.code));
37 const entryByLanguage = Object.freeze(Object.fromEntries(languages.map((entry) => [entry.code, entry])));
39 // Exact code first (zh-tw, de-at), then the base language (fr-CA → fr).
40 function normalizeLanguage(value) {
41 const language = String(value || "").toLowerCase().replace(/_/g, "-");
42 if (supportedLanguages.includes(language)) return language;
43 const base = language.split("-")[0];
44 return supportedLanguages.includes(base) ? base : defaultLanguage;
45 }
47 // Lookup order: the language, its parent (regional variants), the fallback language, Czech.
48 function lookupChain(language) {
49 const parent = entryByLanguage[language]?.parent || (language.includes("-") ? language.split("-")[0] : null);
50 return [...new Set([language, parent, manifest.fallbackLanguage, sourceLanguage].filter(Boolean))];
51 }
53 function direction(language) {
54 return entryByLanguage[language]?.dir === "rtl" ? "rtl" : "ltr";
55 }
57 function interpolate(template, values = {}) {
58 return String(template).replace(/\{([A-Za-z0-9_]+)\}/g, (match, key) => (
59 Object.prototype.hasOwnProperty.call(values, key) ? String(values[key]) : match
60 ));
61 }
63 function createI18n(initialLanguage = defaultLanguage) {
64 let language = normalizeLanguage(initialLanguage);
65 const staticText = new WeakMap();
66 return Object.freeze({
67 apply(rootNode = document) {
68 // Text the application has set itself is not the static translation; its renderers refresh it.
69 rootNode.querySelectorAll("[data-i18n]").forEach((element) => {
70 if (staticText.has(element) && element.textContent !== staticText.get(element)) return;
71 const text = this.t(element.dataset.i18n);
72 element.textContent = text;
73 staticText.set(element, text);
74 });
75 rootNode.querySelectorAll("[data-i18n-placeholder]").forEach((element) => { element.placeholder = this.t(element.dataset.i18nPlaceholder); });
76 rootNode.querySelectorAll("[data-i18n-aria-label]").forEach((element) => { element.setAttribute("aria-label", this.t(element.dataset.i18nAriaLabel)); });
77 },
78 formatNumber(value, options) { return Number(value).toLocaleString(localeByLanguage[language], options); },
79 getLanguage() { return language; },
80 getDirection() { return direction(language); },
81 getLocale() { return localeByLanguage[language]; },
82 setLanguage(value) { language = normalizeLanguage(value); return language; },
83 t(key, values) {
84 const template = lookupChain(language).map((code) => catalogs[code]?.[key]).find((value) => value !== undefined) ?? key;
85 return interpolate(template, values);
86 }
87 });
88 }
90 return Object.freeze({ catalogs, createI18n, interpolate, normalizeLanguage, direction, supportedLanguages, languages, defaultLanguage });
91});
SHA-25612b7c32c09497f45ed2e5afe7df6e6fb86e8bf15d268840d818ca70ffa620fd5

CH-J Proprietary Software License 1.14 · Zdroje jsou zveřejněny pod CH-J Proprietary Software License 1.14. Jejich dostupnost nemění licenční podmínky ani neposkytuje další oprávnění.

SHA-256 archivu77380d4805485ffa4027fbe7858b5836f197a4aa9d52358a43e2d12d018744df
Soubory