diff --git a/front/.prettierignore b/front/.prettierignore
index 8d8c68de..bef7f3b6 100644
--- a/front/.prettierignore
+++ b/front/.prettierignore
@@ -1,5 +1,3 @@
src/Messages/generated
src/Messages/JsonMessages
-src/i18n/i18n-svelte.ts
-src/i18n/i18n-types.ts
-src/i18n/i18n-util.ts
+src/i18n/i18n-*.ts
diff --git a/front/.typesafe-i18n.json b/front/.typesafe-i18n.json
index 0cecbe32..2f7fe9a4 100644
--- a/front/.typesafe-i18n.json
+++ b/front/.typesafe-i18n.json
@@ -1,5 +1,5 @@
{
- "$schema": "https://unpkg.com/typesafe-i18n@2.59.0/schema/typesafe-i18n.json",
+ "$schema": "https://unpkg.com/typesafe-i18n@5.3.5/schema/typesafe-i18n.json",
"baseLocale": "en-US",
"adapter": "svelte"
}
\ No newline at end of file
diff --git a/front/package.json b/front/package.json
index 4ddae384..eba55d46 100644
--- a/front/package.json
+++ b/front/package.json
@@ -60,7 +60,7 @@
"standardized-audio-context": "^25.2.4",
"ts-deferred": "^1.0.4",
"ts-proto": "^1.96.0",
- "typesafe-i18n": "^2.59.0",
+ "typesafe-i18n": "^5.3.5",
"uuidv4": "^6.2.10",
"zod": "^3.14.3"
},
diff --git a/front/src/Components/Menu/Menu.svelte b/front/src/Components/Menu/Menu.svelte
index 2583c208..78419867 100644
--- a/front/src/Components/Menu/Menu.svelte
+++ b/front/src/Components/Menu/Menu.svelte
@@ -88,16 +88,11 @@
}
}
- function translateMenuName(menu: MenuItem) {
- if (menu.type === "scripting") {
- return menu.label;
- }
-
- // Bypass the proxy of typesafe for getting the menu name : https://github.com/ivanhofer/typesafe-i18n/issues/156
- const getMenuName = $LL.menu.sub[menu.key];
-
- return getMenuName();
- }
+ $: subMenuTranslations = $subMenusStore.map((subMenu) =>
+ subMenu.type === "scripting" ? subMenu.label : $LL.menu.sub[subMenu.key]()
+ );
+ $: activeSubMenuTranslation =
+ activeSubMenu.type === "scripting" ? activeSubMenu.label : $LL.menu.sub[activeSubMenu.key]();
@@ -106,20 +101,20 @@
diff --git a/front/src/Components/Menu/SettingsSubMenu.svelte b/front/src/Components/Menu/SettingsSubMenu.svelte
index 41fd425a..b08a645c 100644
--- a/front/src/Components/Menu/SettingsSubMenu.svelte
+++ b/front/src/Components/Menu/SettingsSubMenu.svelte
@@ -28,12 +28,12 @@
let previewCameraPrivacySettings = valueCameraPrivacySettings;
let previewMicrophonePrivacySettings = valueMicrophonePrivacySettings;
- function saveSetting() {
+ async function saveSetting() {
let change = false;
if (valueLocale !== previewValueLocale) {
previewValueLocale = valueLocale;
- setCurrentLocale(valueLocale as Locales);
+ await setCurrentLocale(valueLocale as Locales);
}
if (valueVideo !== previewValueVideo) {
@@ -174,7 +174,7 @@
diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts
index d01c39a6..bd305413 100644
--- a/front/src/Connexion/ConnectionManager.ts
+++ b/front/src/Connexion/ConnectionManager.ts
@@ -363,15 +363,13 @@ class ConnectionManager {
if (locale) {
try {
- if (locales.indexOf(locale) == -1) {
- locales.forEach((l) => {
- if (l.startsWith(locale.split("-")[0])) {
- setCurrentLocale(l);
- return;
- }
- });
+ if (locales.indexOf(locale) !== -1) {
+ await setCurrentLocale(locale as Locales);
} else {
- setCurrentLocale(locale as Locales);
+ const nonRegionSpecificLocale = locales.find((l) => l.startsWith(locale.split("-")[0]));
+ if (nonRegionSpecificLocale) {
+ await setCurrentLocale(nonRegionSpecificLocale);
+ }
}
} catch (err) {
console.warn("Could not set locale", err);
diff --git a/front/src/Phaser/Entity/RemotePlayer.ts b/front/src/Phaser/Entity/RemotePlayer.ts
index f820b578..ae0d1196 100644
--- a/front/src/Phaser/Entity/RemotePlayer.ts
+++ b/front/src/Phaser/Entity/RemotePlayer.ts
@@ -4,7 +4,7 @@ import { Character } from "../Entity/Character";
import type { GameScene } from "../Game/GameScene";
import type { PointInterface } from "../../Connexion/ConnexionModels";
import type { PlayerAnimationDirections } from "../Player/Animation";
-import type { Unsubscriber } from "svelte/store";
+import { get, Unsubscriber } from "svelte/store";
import type { ActivatableInterface } from "../Game/ActivatableInterface";
import type CancelablePromise from "cancelable-promise";
import LL from "../../i18n/i18n-svelte";
@@ -113,7 +113,7 @@ export class RemotePlayer extends Character implements ActivatableInterface {
const actions: ActionsMenuAction[] = [];
if (this.visitCardUrl) {
actions.push({
- actionName: LL.woka.menu.businessCard(),
+ actionName: get(LL).woka.menu.businessCard(),
protected: true,
priority: 1,
callback: () => {
@@ -125,8 +125,8 @@ export class RemotePlayer extends Character implements ActivatableInterface {
actions.push({
actionName: blackListManager.isBlackListed(this.userUuid)
- ? LL.report.block.unblock()
- : LL.report.block.block(),
+ ? get(LL).report.block.unblock()
+ : get(LL).report.block.block(),
protected: true,
priority: -1,
style: "is-error",
diff --git a/front/src/i18n/.gitignore b/front/src/i18n/.gitignore
index 19f1f0f5..e2c9bddb 100644
--- a/front/src/i18n/.gitignore
+++ b/front/src/i18n/.gitignore
@@ -1,3 +1 @@
-i18n-svelte.ts
-i18n-types.ts
-i18n-util.ts
\ No newline at end of file
+i18n-*.ts
diff --git a/front/src/i18n/de-DE/index.ts b/front/src/i18n/de-DE/index.ts
index a72ecc1f..7c0dfb5b 100644
--- a/front/src/i18n/de-DE/index.ts
+++ b/front/src/i18n/de-DE/index.ts
@@ -16,8 +16,6 @@ import trigger from "./trigger";
const de_DE: Translation = {
...(en_US as Translation),
- language: "Deutsch",
- country: "Deutschland",
audio,
camera,
chat,
diff --git a/front/src/i18n/en-US/index.ts b/front/src/i18n/en-US/index.ts
index b1a0e422..c0e018a2 100644
--- a/front/src/i18n/en-US/index.ts
+++ b/front/src/i18n/en-US/index.ts
@@ -14,8 +14,6 @@ import emoji from "./emoji";
import trigger from "./trigger";
const en_US: BaseTranslation = {
- language: "English",
- country: "United States",
audio,
camera,
chat,
diff --git a/front/src/i18n/formatters.ts b/front/src/i18n/formatters.ts
index 00695fd6..da775944 100644
--- a/front/src/i18n/formatters.ts
+++ b/front/src/i18n/formatters.ts
@@ -1,8 +1,8 @@
-import type { AsyncFormattersInitializer } from "typesafe-i18n";
+import type { FormattersInitializer } from "typesafe-i18n";
import type { Locales, Formatters } from "./i18n-types";
// eslint-disable-next-line @typescript-eslint/require-await
-export const initFormatters: AsyncFormattersInitializer = async () => {
+export const initFormatters: FormattersInitializer = async () => {
const formatters: Formatters = {
// add your formatter functions here
};
diff --git a/front/src/i18n/fr-FR/index.ts b/front/src/i18n/fr-FR/index.ts
index 77acbb4a..c378a3bb 100644
--- a/front/src/i18n/fr-FR/index.ts
+++ b/front/src/i18n/fr-FR/index.ts
@@ -16,8 +16,6 @@ import trigger from "./trigger";
const fr_FR: Translation = {
...(en_US as Translation),
- language: "Français",
- country: "France",
audio,
camera,
chat,
diff --git a/front/src/i18n/locales.ts b/front/src/i18n/locales.ts
index bff2f8e6..c18a1e5b 100644
--- a/front/src/i18n/locales.ts
+++ b/front/src/i18n/locales.ts
@@ -1,52 +1,44 @@
import { detectLocale, navigatorDetector, initLocalStorageDetector } from "typesafe-i18n/detectors";
import { FALLBACK_LOCALE } from "../Enum/EnvironmentVariable";
-import { initI18n, setLocale } from "./i18n-svelte";
+import { setLocale } from "./i18n-svelte";
import type { Locales } from "./i18n-types";
-import { baseLocale, getTranslationForLocale, locales } from "./i18n-util";
+import { baseLocale, locales } from "./i18n-util";
+import { loadLocaleAsync } from "./i18n-util.async";
-const fallbackLocale = FALLBACK_LOCALE || baseLocale;
+const fallbackLocale = (FALLBACK_LOCALE || baseLocale) as Locales;
const localStorageProperty = "language";
export const localeDetector = async () => {
const exist = localStorage.getItem(localStorageProperty);
- let detectedLocale: Locales = fallbackLocale as Locales;
+ let detectedLocale: Locales = fallbackLocale;
if (exist) {
const localStorageDetector = initLocalStorageDetector(localStorageProperty);
- detectedLocale = detectLocale(fallbackLocale, locales, localStorageDetector) as Locales;
+ detectedLocale = detectLocale(fallbackLocale, locales, localStorageDetector);
} else {
- detectedLocale = detectLocale(fallbackLocale, locales, navigatorDetector) as Locales;
+ detectedLocale = detectLocale(fallbackLocale, locales, navigatorDetector);
}
- await initI18n(detectedLocale);
+ await setCurrentLocale(detectedLocale);
};
-export const setCurrentLocale = (locale: Locales) => {
+export const setCurrentLocale = async (locale: Locales) => {
localStorage.setItem(localStorageProperty, locale);
- setLocale(locale).catch(() => {
- console.log("Cannot reload the locale!");
- });
+ await loadLocaleAsync(locale);
+ setLocale(locale);
};
-export type DisplayableLocale = { id: Locales; language: string; country: string };
+export const displayableLocales: { id: Locales; language: string; region: string }[] = locales.map((locale) => {
+ const [language, region] = locale.split("-");
-function getDisplayableLocales() {
- const localesObject: DisplayableLocale[] = [];
- locales.forEach((locale) => {
- getTranslationForLocale(locale)
- .then((translations) => {
- localesObject.push({
- id: locale,
- language: translations.language,
- country: translations.country,
- });
- })
- .catch((error) => {
- console.log(error);
- });
- });
+ // backwards compatibility
+ if (!Intl.DisplayNames) {
+ return { id: locale, language, region };
+ }
- return localesObject;
-}
-
-export const displayableLocales = getDisplayableLocales();
+ return {
+ id: locale,
+ language: new Intl.DisplayNames(locale, { type: "language" }).of(language),
+ region: new Intl.DisplayNames(locale, { type: "region" }).of(region),
+ };
+});
diff --git a/front/src/i18n/zh-CN/index.ts b/front/src/i18n/zh-CN/index.ts
index 23e2a24c..58816346 100644
--- a/front/src/i18n/zh-CN/index.ts
+++ b/front/src/i18n/zh-CN/index.ts
@@ -16,8 +16,6 @@ import trigger from "./trigger";
const zh_CN: Translation = {
...(en_US as Translation),
- language: "中文",
- country: "中国",
audio,
camera,
chat,
diff --git a/front/tsconfig.json b/front/tsconfig.json
index edb99eb5..e5ac9819 100644
--- a/front/tsconfig.json
+++ b/front/tsconfig.json
@@ -8,7 +8,7 @@
"moduleResolution": "node",
//"module": "CommonJS",
"module": "ESNext",
- "target": "ES2017",
+ "target": "ES2020",
"declaration": false,
"downlevelIteration": true,
"jsx": "react",
diff --git a/front/yarn.lock b/front/yarn.lock
index 142e6c2c..f2b5e14d 100644
--- a/front/yarn.lock
+++ b/front/yarn.lock
@@ -2991,10 +2991,10 @@ type-fest@^0.21.3:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
-typesafe-i18n@^2.59.0:
- version "2.59.0"
- resolved "https://registry.yarnpkg.com/typesafe-i18n/-/typesafe-i18n-2.59.0.tgz#09a9a32e61711418d927a389fa52e1c06a5fa5c4"
- integrity sha512-Qv3Mrwmb8b73VNzQDPHPECzwymdBRVyDiZ3w2qnp4c2iv/7TGuiJegNHT/l3MooEN7IPbSpc5tbXw2x3MbGtFg==
+typesafe-i18n@^5.3.5:
+ version "5.3.5"
+ resolved "https://registry.yarnpkg.com/typesafe-i18n/-/typesafe-i18n-5.3.5.tgz#8561648a2be0df660404aa087993f3eee584cb87"
+ integrity sha512-ZjCCQ2lCyyvUThtxJblXoxwpr62paOjMRi/Kia1PSEh3gRfwPvEorABS0zTdF6lZ75MQXoz0WqtobChVjkO5mQ==
typescript@*:
version "4.3.2"