From 22dc4ef997ef97e17fe2a2899d85053573b15ab9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 11 Aug 2024 08:12:01 +0300 Subject: [PATCH] client: Apply locale selection --- src/public/app/components/app_context.js | 17 ++++++++++------ src/public/app/desktop.js | 8 ++++++-- src/public/app/mobile.js | 5 +++-- src/public/app/services/i18n.js | 25 ++++++++++++++---------- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/public/app/components/app_context.js b/src/public/app/components/app_context.js index 2e06493dc..3981c46c1 100644 --- a/src/public/app/components/app_context.js +++ b/src/public/app/components/app_context.js @@ -13,6 +13,7 @@ import MobileScreenSwitcherExecutor from "./mobile_screen_switcher.js"; import MainTreeExecutors from "./main_tree_executors.js"; import toast from "../services/toast.js"; import ShortcutComponent from "./shortcut_component.js"; +import { initLocale } from "../services/i18n.js"; class AppContext extends Component { constructor(isMainWindow) { @@ -24,16 +25,20 @@ class AppContext extends Component { this.beforeUnloadListeners = []; } - setLayout(layout) { + /** + * Must be called as soon as possible, before the creation of any components since this method is in charge of initializing the locale. Any attempts to read translation before this method is called will result in `undefined`. + */ + async earlyInit() { + await options.initializedPromise; + initLocale(); + } + + setLayout(layout) { this.layout = layout; } - async start() { + async start() { this.initComponents(); - - // options are often needed for isEnabled() - await options.initializedPromise; - this.renderWidgets(); await froca.initializedPromise; diff --git a/src/public/app/desktop.js b/src/public/app/desktop.js index 669f9d355..235502f31 100644 --- a/src/public/app/desktop.js +++ b/src/public/app/desktop.js @@ -6,11 +6,15 @@ import toastService from "./services/toast.js"; import noteAutocompleteService from './services/note_autocomplete.js'; import macInit from './services/mac_init.js'; import electronContextMenu from "./menus/electron_context_menu.js"; -import DesktopLayout from "./layouts/desktop_layout.js"; import glob from "./services/glob.js"; import { t } from "./services/i18n.js"; -bundleService.getWidgetBundlesByParent().then(widgetBundles => { +bundleService.getWidgetBundlesByParent().then(async widgetBundles => { + appContext.earlyInit(); + + // A dynamic import is required for layouts since they initialize components which require translations. + const DesktopLayout = (await import("./layouts/desktop_layout.js")).default; + appContext.setLayout(new DesktopLayout(widgetBundles)); appContext.start() .catch((e) => { diff --git a/src/public/app/mobile.js b/src/public/app/mobile.js index 1e2a366fa..484974ea3 100644 --- a/src/public/app/mobile.js +++ b/src/public/app/mobile.js @@ -1,8 +1,9 @@ import appContext from "./components/app_context.js"; -import MobileLayout from "./layouts/mobile_layout.js"; import glob from "./services/glob.js"; -glob.setupGlobs(); +glob.setupGlobs() +appContext.earlyInit(); +const MobileLayout = (await import("./layouts/mobile_layout.js")).default; appContext.setLayout(new MobileLayout()); appContext.start(); diff --git a/src/public/app/services/i18n.js b/src/public/app/services/i18n.js index a777db038..8b841c7de 100644 --- a/src/public/app/services/i18n.js +++ b/src/public/app/services/i18n.js @@ -1,16 +1,21 @@ import library_loader from "./library_loader.js"; +import options from "./options.js"; await library_loader.requireLibrary(library_loader.I18NEXT); -await i18next - .use(i18nextHttpBackend) - .init({ - lng: "en", - fallbackLng: "en", - debug: true, - backend: { - loadPath: `/${window.glob.assetPath}/translations/{{lng}}/{{ns}}.json` - } - }); +export async function initLocale() { + const locale = options.get("locale") || "en"; + + await i18next + .use(i18nextHttpBackend) + .init({ + lng: locale, + fallbackLng: "en", + debug: true, + backend: { + loadPath: `/${window.glob.assetPath}/translations/{{lng}}/{{ns}}.json` + } + }); +} export const t = i18next.t;