mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
Simplfiy LangSelector (#1226)
## Description: Simplify how translations work. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
This commit is contained in:
+50
-47
@@ -26,8 +26,8 @@ import uk from "../../resources/lang/uk.json";
|
||||
|
||||
@customElement("lang-selector")
|
||||
export class LangSelector extends LitElement {
|
||||
@state() public translations: any = {};
|
||||
@state() private defaultTranslations: any = {};
|
||||
@state() public translations: Record<string, string> | undefined;
|
||||
@state() private defaultTranslations: Record<string, string> | undefined;
|
||||
@state() private currentLang: string = "en";
|
||||
@state() private languageList: any[] = [];
|
||||
@state() private showModal: boolean = false;
|
||||
@@ -91,16 +91,18 @@ export class LangSelector extends LitElement {
|
||||
const savedLang = localStorage.getItem("lang");
|
||||
const userLang = this.getClosestSupportedLang(savedLang || browserLocale);
|
||||
|
||||
this.defaultTranslations = await this.loadLanguage("en");
|
||||
this.translations = await this.loadLanguage(userLang);
|
||||
this.defaultTranslations = this.loadLanguage("en");
|
||||
this.translations = this.loadLanguage(userLang);
|
||||
this.currentLang = userLang;
|
||||
|
||||
await this.loadLanguageList();
|
||||
this.applyTranslation(this.translations);
|
||||
this.applyTranslation();
|
||||
}
|
||||
|
||||
private async loadLanguage(lang: string): Promise<any> {
|
||||
return Promise.resolve(this.languageMap[lang] || {});
|
||||
private loadLanguage(lang: string): Record<string, string> {
|
||||
const language = this.languageMap[lang] || {};
|
||||
const flat = flattenTranslations(language);
|
||||
return flat;
|
||||
}
|
||||
|
||||
private async loadLanguageList() {
|
||||
@@ -166,15 +168,15 @@ export class LangSelector extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private async changeLanguage(lang: string) {
|
||||
private changeLanguage(lang: string) {
|
||||
localStorage.setItem("lang", lang);
|
||||
this.translations = await this.loadLanguage(lang);
|
||||
this.translations = this.loadLanguage(lang);
|
||||
this.currentLang = lang;
|
||||
this.applyTranslation(this.translations);
|
||||
this.applyTranslation();
|
||||
this.showModal = false;
|
||||
}
|
||||
|
||||
private applyTranslation(translations: any) {
|
||||
private applyTranslation() {
|
||||
const components = [
|
||||
"single-player-modal",
|
||||
"host-lobby-modal",
|
||||
@@ -195,32 +197,17 @@ export class LangSelector extends LitElement {
|
||||
"o-button",
|
||||
];
|
||||
|
||||
document.title = translations.main?.title || document.title;
|
||||
document.title = this.translateText("main.title") ?? document.title;
|
||||
|
||||
document.querySelectorAll("[data-i18n]").forEach((element) => {
|
||||
const key = element.getAttribute("data-i18n");
|
||||
const keys = key?.split(".") || [];
|
||||
let text = translations;
|
||||
|
||||
for (const k of keys) {
|
||||
text = text?.[k];
|
||||
if (!text) break;
|
||||
}
|
||||
|
||||
if (!text && this.defaultTranslations) {
|
||||
let fallback = this.defaultTranslations;
|
||||
for (const k of keys) {
|
||||
fallback = fallback?.[k];
|
||||
if (!fallback) break;
|
||||
}
|
||||
text = fallback;
|
||||
}
|
||||
|
||||
if (text) {
|
||||
element.innerHTML = text;
|
||||
} else {
|
||||
if (key === null) return;
|
||||
const text = this.translateText(key);
|
||||
if (text === null) {
|
||||
console.warn(`Translation key not found: ${key}`);
|
||||
return;
|
||||
}
|
||||
element.textContent = text;
|
||||
});
|
||||
|
||||
components.forEach((tag) => {
|
||||
@@ -236,23 +223,18 @@ export class LangSelector extends LitElement {
|
||||
key: string,
|
||||
params: Record<string, string | number> = {},
|
||||
): string {
|
||||
const keys = key.split(".");
|
||||
let text: any = this.translations;
|
||||
|
||||
for (const k of keys) {
|
||||
text = text?.[k];
|
||||
if (!text) break;
|
||||
let text: string | undefined;
|
||||
if (this.translations && key in this.translations) {
|
||||
text = this.translations[key];
|
||||
} else if (this.defaultTranslations && key in this.defaultTranslations) {
|
||||
text = this.defaultTranslations[key];
|
||||
} else {
|
||||
console.warn(`Translation key not found: ${key}`);
|
||||
return key;
|
||||
}
|
||||
|
||||
if (!text && this.defaultTranslations) {
|
||||
text = this.defaultTranslations;
|
||||
for (const k of keys) {
|
||||
text = text?.[k];
|
||||
if (!text) return key;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [param, value] of Object.entries(params)) {
|
||||
for (const param in params) {
|
||||
const value = params[param];
|
||||
text = text.replace(`{${param}}`, String(value));
|
||||
}
|
||||
|
||||
@@ -309,3 +291,24 @@ export class LangSelector extends LitElement {
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
function flattenTranslations(
|
||||
obj: Record<string, any>,
|
||||
parentKey = "",
|
||||
result: Record<string, string> = {},
|
||||
): Record<string, string> {
|
||||
for (const key in obj) {
|
||||
const value = obj[key];
|
||||
const fullKey = parentKey ? `${parentKey}.${key}` : key;
|
||||
|
||||
if (typeof value === "string") {
|
||||
result[fullKey] = value;
|
||||
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
||||
flattenTranslations(value, fullKey, result);
|
||||
} else {
|
||||
console.warn("Unknown type", typeof value, value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user