update dynamic strings on language change
This commit is contained in:
parent
efc3865bd6
commit
17afad3dcd
|
|
@ -1,5 +1,6 @@
|
||||||
import { StringLike } from './StringLike';
|
import { StringLike } from './StringLike';
|
||||||
import { Format } from './format';
|
import { Format } from './format';
|
||||||
|
import { Emitter, Unsubscribe, createNanoEvents } from 'nanoevents';
|
||||||
|
|
||||||
/// All string keys.
|
/// All string keys.
|
||||||
export enum I18nStringKey {
|
export enum I18nStringKey {
|
||||||
|
|
@ -100,6 +101,11 @@ export enum I18nStringKey {
|
||||||
kNotLoggedIn = 'kNotLoggedIn',
|
kNotLoggedIn = 'kNotLoggedIn',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface I18nEvents {
|
||||||
|
// Called when the language is changed
|
||||||
|
languageChanged: (lang: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
// This models the JSON structure.
|
// This models the JSON structure.
|
||||||
export type Language = {
|
export type Language = {
|
||||||
languageName: string;
|
languageName: string;
|
||||||
|
|
@ -141,6 +147,7 @@ export class I18n {
|
||||||
private langs : Map<string, Language> = new Map<string, Language>();
|
private langs : Map<string, Language> = new Map<string, Language>();
|
||||||
private lang: Language = fallbackLanguage;
|
private lang: Language = fallbackLanguage;
|
||||||
private languageDropdown: HTMLSpanElement = document.getElementById('languageDropdown') as HTMLSpanElement;
|
private languageDropdown: HTMLSpanElement = document.getElementById('languageDropdown') as HTMLSpanElement;
|
||||||
|
private emitter: Emitter<I18nEvents> = createNanoEvents();
|
||||||
|
|
||||||
CurrentLanguage = () => this.langId;
|
CurrentLanguage = () => this.langId;
|
||||||
|
|
||||||
|
|
@ -200,6 +207,8 @@ export class I18n {
|
||||||
if (this.langId !== fallbackId) {
|
if (this.langId !== fallbackId) {
|
||||||
window.localStorage.setItem('i18n-lang', this.langId);
|
window.localStorage.setItem('i18n-lang', this.langId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitter.emit('languageChanged', this.langId);
|
||||||
console.log('i18n initalized for', id, 'sucessfully!');
|
console.log('i18n initalized for', id, 'sucessfully!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,7 +219,6 @@ export class I18n {
|
||||||
homeBtnText: I18nStringKey.kSiteButtons_Home,
|
homeBtnText: I18nStringKey.kSiteButtons_Home,
|
||||||
faqBtnText: I18nStringKey.kSiteButtons_FAQ,
|
faqBtnText: I18nStringKey.kSiteButtons_FAQ,
|
||||||
rulesBtnText: I18nStringKey.kSiteButtons_Rules,
|
rulesBtnText: I18nStringKey.kSiteButtons_Rules,
|
||||||
accountDropdownUsername: I18nStringKey.kNotLoggedIn,
|
|
||||||
accountLoginButton: I18nStringKey.kGeneric_Login,
|
accountLoginButton: I18nStringKey.kGeneric_Login,
|
||||||
accountRegisterButton: I18nStringKey.kGeneric_Register,
|
accountRegisterButton: I18nStringKey.kGeneric_Register,
|
||||||
accountSettingsButton: I18nStringKey.kAccountModal_AccountSettings,
|
accountSettingsButton: I18nStringKey.kAccountModal_AccountSettings,
|
||||||
|
|
@ -339,6 +347,17 @@ export class I18n {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const kDomClassToStringMap: StringKeyMap = {
|
||||||
|
"mod-end-turn-btn": I18nStringKey.kVMButtons_EndTurn,
|
||||||
|
"mod-ban-btn": I18nStringKey.kAdminVMButtons_Ban,
|
||||||
|
"mod-kick-btn": I18nStringKey.kAdminVMButtons_Kick,
|
||||||
|
"mod-change-username-btn": I18nStringKey.kVMButtons_ChangeUsername,
|
||||||
|
"mod-temp-mute-btn": I18nStringKey.kAdminVMButtons_TempMute,
|
||||||
|
"mod-indef-mute-btn": I18nStringKey.kAdminVMButtons_IndefMute,
|
||||||
|
"mod-unmute-btn": I18nStringKey.kAdminVMButtons_Unmute,
|
||||||
|
"mod-get-ip-btn": I18nStringKey.kAdminVMButtons_GetIP,
|
||||||
|
}
|
||||||
|
|
||||||
for (let domId of Object.keys(kDomIdtoStringMap)) {
|
for (let domId of Object.keys(kDomIdtoStringMap)) {
|
||||||
let element = document.getElementById(domId);
|
let element = document.getElementById(domId);
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
|
|
@ -367,6 +386,13 @@ export class I18n {
|
||||||
element.setAttribute(attr, this.GetStringRaw(attributes[attr] as I18nStringKey));
|
element.setAttribute(attr, this.GetStringRaw(attributes[attr] as I18nStringKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let domClass of Object.keys(kDomClassToStringMap)) {
|
||||||
|
let elements = document.getElementsByClassName(domClass);
|
||||||
|
for (let element of elements) {
|
||||||
|
element.innerHTML = this.GetStringRaw(kDomClassToStringMap[domClass]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a (raw, unformatted) string. Currently only used if we don't need formatting.
|
// Returns a (raw, unformatted) string. Currently only used if we don't need formatting.
|
||||||
|
|
@ -389,6 +415,10 @@ export class I18n {
|
||||||
GetString(key: I18nStringKey, ...replacements: StringLike[]): string {
|
GetString(key: I18nStringKey, ...replacements: StringLike[]): string {
|
||||||
return Format(this.GetStringRaw(key), ...replacements);
|
return Format(this.GetStringRaw(key), ...replacements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on<e extends keyof I18nEvents>(event: e, cb: I18nEvents[e]): Unsubscribe {
|
||||||
|
return this.emitter.on(event, cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export let TheI18n = new I18n();
|
export let TheI18n = new I18n();
|
||||||
|
|
@ -826,33 +826,33 @@ function userModOptions(user: { user: User; element: HTMLTableRowElement }) {
|
||||||
td.setAttribute('aria-expanded', 'false');
|
td.setAttribute('aria-expanded', 'false');
|
||||||
let ul = document.createElement('ul');
|
let ul = document.createElement('ul');
|
||||||
ul.classList.add('dropdown-menu', 'dropdown-menu-dark', 'table-dark', 'text-light');
|
ul.classList.add('dropdown-menu', 'dropdown-menu-dark', 'table-dark', 'text-light');
|
||||||
if (perms.bypassturn) addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kVMButtons_EndTurn), () => VM!.endTurn(user.user.username));
|
if (perms.bypassturn) addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kVMButtons_EndTurn), () => VM!.endTurn(user.user.username), "mod-end-turn-btn");
|
||||||
if (perms.ban) addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_Ban), () => VM!.ban(user.user.username));
|
if (perms.ban) addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_Ban), () => VM!.ban(user.user.username), "mod-ban-btn");
|
||||||
if (perms.kick) addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_Kick), () => VM!.kick(user.user.username));
|
if (perms.kick) addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_Kick), () => VM!.kick(user.user.username), "mod-kick-btn");
|
||||||
if (perms.rename)
|
if (perms.rename)
|
||||||
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kVMButtons_ChangeUsername), () => {
|
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kVMButtons_ChangeUsername), () => {
|
||||||
let newname = prompt(TheI18n.GetString(I18nStringKey.kVMPrompts_AdminChangeUsernamePrompt, user.user.username));
|
let newname = prompt(TheI18n.GetString(I18nStringKey.kVMPrompts_AdminChangeUsernamePrompt, user.user.username));
|
||||||
if (!newname) return;
|
if (!newname) return;
|
||||||
VM!.renameUser(user.user.username, newname);
|
VM!.renameUser(user.user.username, newname);
|
||||||
});
|
}, "mod-rename-btn");
|
||||||
if (perms.mute) {
|
if (perms.mute) {
|
||||||
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_TempMute), () => VM!.mute(user.user.username, MuteState.Temp));
|
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_TempMute), () => VM!.mute(user.user.username, MuteState.Temp), "mod-temp-mute-btn");
|
||||||
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_IndefMute), () => VM!.mute(user.user.username, MuteState.Perma));
|
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_IndefMute), () => VM!.mute(user.user.username, MuteState.Perma), "mod-indef-mute-btn");
|
||||||
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_Unmute), () => VM!.mute(user.user.username, MuteState.Unmuted));
|
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_Unmute), () => VM!.mute(user.user.username, MuteState.Unmuted), "mod-unmute-btn");
|
||||||
}
|
}
|
||||||
if (perms.grabip)
|
if (perms.grabip)
|
||||||
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_GetIP), async () => {
|
addUserDropdownItem(ul, TheI18n.GetString(I18nStringKey.kAdminVMButtons_GetIP), async () => {
|
||||||
let ip = await VM!.getip(user.user.username);
|
let ip = await VM!.getip(user.user.username);
|
||||||
alert(ip);
|
alert(ip);
|
||||||
});
|
}, "mod-get-ip-btn");
|
||||||
tr.appendChild(ul);
|
tr.appendChild(ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addUserDropdownItem(ul: HTMLUListElement, text: string, func: () => void) {
|
function addUserDropdownItem(ul: HTMLUListElement, text: string, func: () => void, classname: string) {
|
||||||
let li = document.createElement('li');
|
let li = document.createElement('li');
|
||||||
let a = document.createElement('a');
|
let a = document.createElement('a');
|
||||||
a.href = '#';
|
a.href = '#';
|
||||||
a.classList.add('dropdown-item');
|
a.classList.add('dropdown-item', classname);
|
||||||
a.innerHTML = text;
|
a.innerHTML = text;
|
||||||
a.addEventListener('click', () => func());
|
a.addEventListener('click', () => func());
|
||||||
li.appendChild(a);
|
li.appendChild(a);
|
||||||
|
|
@ -1250,6 +1250,29 @@ w.VMName = null;
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
// Initalize the i18n system
|
// Initalize the i18n system
|
||||||
await TheI18n.Init();
|
await TheI18n.Init();
|
||||||
|
TheI18n.on('languageChanged', lang => {
|
||||||
|
// Update all dynamic text
|
||||||
|
if (VM) {
|
||||||
|
document.title = Format('{0} - {1}', VM.getNode()!, TheI18n.GetString(I18nStringKey.kGeneric_CollabVM));
|
||||||
|
if (turn !== -1) {
|
||||||
|
if (turn === 0) elements.turnstatus.innerText = TheI18n.GetString(I18nStringKey.kVM_TurnTimeTimer, turnTimer);
|
||||||
|
else elements.turnstatus.innerText = TheI18n.GetString(I18nStringKey.kVM_WaitingTurnTimer, turnTimer);
|
||||||
|
elements.turnBtnText.innerText = TheI18n.GetString(I18nStringKey.kVMButtons_EndTurn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
elements.turnBtnText.innerText = TheI18n.GetString(I18nStringKey.kVMButtons_TakeTurn);
|
||||||
|
if (VM!.getVoteStatus())
|
||||||
|
elements.voteTimeText.innerText = TheI18n.GetString(I18nStringKey.kVM_VoteForResetTimer, voteTimer);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
document.title = TheI18n.GetString(I18nStringKey.kGeneric_CollabVM);
|
||||||
|
}
|
||||||
|
if (!auth || !auth.account) elements.accountDropdownUsername.innerText = TheI18n.GetString(I18nStringKey.kNotLoggedIn);
|
||||||
|
if (darkTheme) elements.toggleThemeBtnText.innerHTML = TheI18n.GetString(I18nStringKey.kSiteButtons_LightMode);
|
||||||
|
else elements.toggleThemeBtnText.innerHTML = TheI18n.GetString(I18nStringKey.kSiteButtons_DarkMode);
|
||||||
|
|
||||||
|
});
|
||||||
// Load theme
|
// Load theme
|
||||||
var _darktheme : boolean;
|
var _darktheme : boolean;
|
||||||
if (localStorage.getItem("cvm-dark-theme") === "0")
|
if (localStorage.getItem("cvm-dark-theme") === "0")
|
||||||
|
|
|
||||||
|
|
@ -620,6 +620,10 @@ export default class CollabVMClient {
|
||||||
return this.auth;
|
return this.auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNode() {
|
||||||
|
return this.node;
|
||||||
|
}
|
||||||
|
|
||||||
private onInternal<E extends keyof CollabVMClientPrivateEvents>(event: E, callback: CollabVMClientPrivateEvents[E]): Unsubscribe {
|
private onInternal<E extends keyof CollabVMClientPrivateEvents>(event: E, callback: CollabVMClientPrivateEvents[E]): Unsubscribe {
|
||||||
return this.internalEmitter.on(event, callback);
|
return this.internalEmitter.on(event, callback);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user