Add language switcher on settings

This commit is contained in:
Nolway 2022-01-07 01:50:47 +01:00 committed by Alexis Faizeau
parent 6ff4d6d634
commit 54ae3bf215
7 changed files with 91 additions and 36 deletions

View file

@ -4,7 +4,7 @@
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
import { isMobile } from "../../Enum/EnvironmentVariable";
import { menuVisiblilityStore } from "../../Stores/MenuStore";
import { translator } from "../../Translator/Translator";
import { languages, translator } from "../../Translator/Translator";
let fullscreen: boolean = localUserStore.getFullscreen();
let notification: boolean = localUserStore.getNotification() === "granted";
@ -12,14 +12,18 @@ import { translator } from "../../Translator/Translator";
let ignoreFollowRequests: boolean = localUserStore.getIgnoreFollowRequests();
let valueGame: number = localUserStore.getGameQualityValue();
let valueVideo: number = localUserStore.getVideoQualityValue();
let valueLanguage: string = translator.getStringByLanguage(translator.getCurrentLanguage()) ?? "en-US";
let previewValueGame = valueGame;
let previewValueVideo = valueVideo;
let previewValueLanguage = valueLanguage;
function saveSetting() {
if (valueGame !== previewValueGame) {
previewValueGame = valueGame;
localUserStore.setGameQualityValue(valueGame);
window.location.reload();
let change = false;
if (valueLanguage !== previewValueLanguage) {
previewValueLanguage = valueLanguage;
translator.switchLanguage(previewValueLanguage);
change = true;
}
if (valueVideo !== previewValueVideo) {
@ -27,6 +31,16 @@ import { translator } from "../../Translator/Translator";
videoConstraintStore.setFrameRate(valueVideo);
}
if (valueGame !== previewValueGame) {
previewValueGame = valueGame;
localUserStore.setGameQualityValue(valueGame);
change = true;
}
if (change) {
window.location.reload();
}
closeMenu();
}
@ -127,6 +141,17 @@ import { translator } from "../../Translator/Translator";
</select>
</div>
</section>
<section>
<h3>{translator._("menu.settings.language.title")}</h3>
<div class="nes-select is-dark">
<select class="languages-switcher" bind:value={valueLanguage}>
<!-- svelte-ignore missing-declaration -->
{#each languages as language}
<option value={language.id}>{`${language.language} (${language.country})`}</option>
{/each}
</select>
</div>
</section>
<section class="settings-section-save">
<p>{translator._("menu.settings.save.warning")}</p>
<button type="button" class="nes-btn is-primary" on:click|preventDefault={saveSetting}
@ -205,6 +230,10 @@ import { translator } from "../../Translator/Translator";
margin: 0 0 15px;
}
}
.languages-switcher option {
text-transform: capitalize;
}
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {

View file

@ -3,11 +3,6 @@ import fs from "fs";
const translationsBasePath = "./translations";
const fallbackLanguage = process.env.FALLBACK_LANGUAGE || "en-US";
export type LanguageFound = {
id: string;
default: boolean;
};
const getAllLanguagesByFiles = (dirPath: string, languages: Array<LanguageFound> | undefined) => {
const files = fs.readdirSync(dirPath);
languages = languages || new Array<LanguageFound>();
@ -25,10 +20,18 @@ const getAllLanguagesByFiles = (dirPath: string, languages: Array<LanguageFound>
const rawData = fs.readFileSync(dirPath + "/" + file, "utf-8");
const languageObject = JSON.parse(rawData);
languages?.push({
id: parts[1],
default: languageObject.default !== undefined && languageObject.default,
});
if (
"language" in languageObject && typeof languageObject.language === "string" &&
"country" in languageObject && typeof languageObject.country === "string" &&
"default" in languageObject && typeof languageObject.default === "boolean"
) {
languages?.push({
id: parts[1],
language: languageObject.language,
country: languageObject.country,
default: languageObject.default
});
}
}
});
@ -57,16 +60,5 @@ const getFallbackLanguageObject = (dirPath: string, languageObject: Object | und
return languageObject;
};
const languagesToObject = () => {
const object: { [key: string]: boolean } = {};
languages.forEach((language) => {
object[language.id] = false;
});
return object;
};
export const languages = getAllLanguagesByFiles(translationsBasePath, undefined);
export const languagesObject = languagesToObject();
export const fallbackLanguageObject = getFallbackLanguageObject(translationsBasePath, undefined);

View file

@ -77,6 +77,15 @@ class Translator {
});
}
/**
* TypeGuard to check if is a LanguageObject
* @param {unknown} object Presume LanguageObject
* @returns {boolean} Is a LanguageObject or not
*/
private isLanguageObject(object: unknown): object is LanguageObject {
return typeof object === "object";
}
/**
* Get from the Phase cache the current language object and promise to load it
* @param {Phaser.Cache.CacheManager} cacheManager Phaser CacheManager
@ -92,7 +101,11 @@ class Translator {
return reject(new Error("Language not found in cache"));
}
this.currentLanguageObject = languageObject as LanguageObject;
if (!this.isLanguageObject(languageObject)) {
throw new Error("Cannot load a bad language object");
}
this.currentLanguageObject = languageObject;
return resolve();
});
}
@ -109,11 +122,9 @@ class Translator {
let languageFound = undefined;
const languages: { [key: string]: boolean } = LANGUAGES as { [key: string]: boolean };
for (const language in languages) {
if (language.startsWith(languageString) && languages[language]) {
languageFound = this.getLanguageByString(language);
for (const language of LANGUAGES) {
if (language.id.startsWith(languageString) && language.default) {
languageFound = this.getLanguageByString(language.id);
break;
}
}
@ -129,6 +140,12 @@ class Translator {
return this.currentLanguage;
}
public switchLanguage(languageString: string) {
if (this.getLanguageByString(languageString)) {
localStorage.setItem("language", languageString);
}
}
/**
* Define the current language by the navigator or a cookie
*/
@ -232,4 +249,5 @@ class Translator {
}
}
export const languages: LanguageFound[] = LANGUAGES;
export const translator = new Translator();

View file

@ -1,2 +1,13 @@
declare const FALLBACK_LANGUAGE_OBJECT: Object;
declare const LANGUAGES: Object;
type LanguageObject = {
[key: string]: string | LanguageObject;
};
type LanguageFound = {
id: string;
language: string;
country: string;
default: boolean;
};
declare const FALLBACK_LANGUAGE_OBJECT: LanguageObject;
declare const LANGUAGES: LanguageFound[];

View file

@ -53,6 +53,9 @@
"small": "Small video quality (5 fps)"
}
},
"language": {
"title": "Language"
},
"save": {
"warning": "(Saving these settings will restart the game)",
"button": "Save"

View file

@ -53,6 +53,9 @@
"small": "Reduite (5 fps)"
}
},
"language": {
"title": "Langage"
},
"save": {
"warning": "(La sauvegarde de ces paramètres redémarre le jeu)",
"button": "Sauvegarder"

View file

@ -7,8 +7,7 @@ import sveltePreprocess from "svelte-preprocess";
import type { Configuration } from "webpack";
import webpack from "webpack";
import type WebpackDevServer from "webpack-dev-server";
import type { LanguageFound } from "./src/Translator/TranslationCompiler";
import { fallbackLanguageObject, languages, languagesObject } from "./src/Translator/TranslationCompiler";
import { fallbackLanguageObject, languages } from "./src/Translator/TranslationCompiler";
const MergeJsonWebpackPlugin = require("merge-jsons-webpack-plugin");
@ -223,7 +222,7 @@ module.exports = {
}),
new webpack.DefinePlugin({
FALLBACK_LANGUAGE_OBJECT: JSON.stringify(fallbackLanguageObject),
LANGUAGES: JSON.stringify(languagesObject),
LANGUAGES: JSON.stringify(languages),
}),
new MergeJsonWebpackPlugin({
output: {