Add chinese translation

Based on https://github.com/dyxang/Fantasy-Map-Generator-Chinese
This commit is contained in:
Blipz 2026-03-28 04:59:26 +01:00
parent 7eeb1f76c3
commit c5f1577c4b
12 changed files with 3359 additions and 980 deletions

View file

@ -1,23 +1,49 @@
import i18next from "i18next";
import i18nextHTTPBackend from "i18next-http-backend";
import { isVowel } from "../utils";
import { TOptions } from "i18next";
function initTooltips() {
for (const tip of document.querySelectorAll("[data-tip]")) {
tip.setAttribute(
"data-original-tip",
tip.getAttribute("data-tip") as string,
);
}
}
function updateLabels() {
for (const label of document.querySelectorAll("[data-html]")) {
const translation = i18next.t(label.getAttribute("data-html") as string);
let vars: TOptions = {
interpolation: { escapeValue: false },
};
for (const attr of label.attributes) {
if (attr.name.startsWith("data-var-")) {
vars[attr.name.slice(9)] = attr.value;
}
}
const translation = i18next.t(
label.getAttribute("data-html") as string,
vars,
);
if (translation) label.innerHTML = translation;
}
for (const label of document.querySelectorAll("[data-text]")) {
const translation = i18next.t(label.getAttribute("data-text") as string);
if (translation) label.textContent = translation;
}
for (const tip of document.querySelectorAll("[data-tip]")) {
const translation = i18next.t(tip.getAttribute("data-tip") as string);
for (const tip of document.querySelectorAll("[data-original-tip]")) {
const translation = i18next.t(
tip.getAttribute("data-original-tip") as string,
);
if (translation) tip.setAttribute("data-tip", translation);
}
}
function addFormatters() {
i18next.services.formatter?.add("link", (value, _lng, options) => {
return `<a href="${value}" target="blank">${options.text}</a>`;
});
i18next.services.formatter?.add("gender", (value, lng, options) => {
if (lng !== "fr") return value;
else if (options.gender === "feminine") {
@ -43,13 +69,22 @@ window.initLocale = async () => {
await i18next.use(i18nextHTTPBackend).init(
{
lng: options.language,
fallbackLng: "en",
backend: {
loadPath: "locales/{{lng}}/lang.json",
},
keySeparator: "::",
nsSeparator: false,
returnEmptyString: false,
},
() => {
addFormatters();
initTooltips();
updateLabels();
},
);
};
window.changeLocale = () => {
i18next.changeLanguage(options.language, updateLabels);
};

View file

@ -144,7 +144,7 @@ class ProvinceModule {
form[formName] += 10;
const fullName = i18next.t("{{provinceName}} {{provinceForm}}", {
provinceName: name,
provinceForm: i18next.t(formName),
provinceForm: i18next.t(`provinceForm::${formName}`),
});
const color = getMixedColor(s.color!);
const kinship = nameByBurg ? 0.8 : 0.4;
@ -327,7 +327,7 @@ class ProvinceModule {
const fullName = i18next.t("{{provinceName}} {{provinceForm}}", {
provinceName: name,
provinceForm: i18next.t(formName),
provinceForm: i18next.t(`provinceForm::${formName}`),
});
const dominion = colony

View file

@ -64,6 +64,7 @@ gender.fr = {
Diarchy: "feminine",
Horde: "feminine",
League: "feminine",
Marches: "feminine",
Oligarchy: "feminine",
Tetrarchy: "feminine",
Theocracy: "feminine",
@ -834,7 +835,7 @@ class StatesModule {
const stateGender = gender[options.language as string]?.[state.formName];
if (!state.name && state.formName)
return i18next.t("The {{noun}}", {
noun: i18next.t(state.formName),
noun: i18next.t(`stateForm::${state.formName}`),
gender: stateGender,
});
const adjName =
@ -842,13 +843,14 @@ class StatesModule {
return adjName
? i18next.t("{{adjective}} {{noun}}", {
adjective: getAdjective(state.name),
noun: i18next.t(state.formName),
noun: i18next.t(`stateForm::${state.formName}`),
gender: stateGender,
})
: i18next.t("{{noun}} of {{complement}}", {
noun: i18next.t(state.formName),
noun: i18next.t(`stateForm::${state.formName}`),
complement: state.name,
gender: stateGender,
interpolation: { escapeValue: false },
});
}
}