From 7e5e3786cf6f82b66b20dcb9a06a64be262ffdf0 Mon Sep 17 00:00:00 2001 From: icarus Date: Thu, 23 Oct 2025 23:08:47 +0800 Subject: [PATCH] feat(i18n): add language preference handling and improve initialization Initialize i18n with user's preferred language from preferences or fallback to default Standardize locale file imports naming convention and improve i18n initialization flow --- src/main/index.ts | 10 +++++ src/main/utils/language.ts | 77 +++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 4412c28af2..a4f8cb4676 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -35,6 +35,8 @@ import { dataRefactorMigrateService } from './data/migrate/dataRefactor/DataRefa import { dataApiService } from '@data/DataApiService' import { cacheService } from '@data/CacheService' import { initWebviewHotkeys } from './services/WebviewService' +import { i18n } from './utils/language' +import { defaultLanguage } from '@shared/config/constant' const logger = loggerService.withContext('MainEntry') @@ -168,6 +170,14 @@ if (!app.requestSingleInstanceLock()) { await preferenceService.initialize() + const userLanguage = preferenceService.get('app.language') + if (userLanguage) { + i18n.changeLanguage(userLanguage) + } else { + logger.warn('No user language preference found, falling back to default language') + i18n.changeLanguage(defaultLanguage) + } + // Initialize DataApiService await dataApiService.initialize() diff --git a/src/main/utils/language.ts b/src/main/utils/language.ts index ad4f743e02..acb39404d8 100644 --- a/src/main/utils/language.ts +++ b/src/main/utils/language.ts @@ -5,9 +5,9 @@ import type { LanguageVarious } from '@shared/data/preference/preferenceTypes' import { app } from 'electron' import i18n from 'i18next' -import EnUs from '../../renderer/src/i18n/locales/en-us.json' -import ZhCn from '../../renderer/src/i18n/locales/zh-cn.json' -import ZhTw from '../../renderer/src/i18n/locales/zh-tw.json' +import enUS from '../../renderer/src/i18n/locales/en-us.json' +import zhCN from '../../renderer/src/i18n/locales/zh-cn.json' +import zhTW from '../../renderer/src/i18n/locales/zh-tw.json' // import deDE from '../../renderer/src/i18n/locales/de-de.json' // import elGR from '../../renderer/src/i18n/locales/el-gr.json' // import esES from '../../renderer/src/i18n/locales/es-es.json' @@ -19,37 +19,37 @@ import deDE from '../../renderer/src/i18n/translate/de-de.json' import elGR from '../../renderer/src/i18n/translate/el-gr.json' import esES from '../../renderer/src/i18n/translate/es-es.json' import frFR from '../../renderer/src/i18n/translate/fr-fr.json' -import JaJP from '../../renderer/src/i18n/translate/ja-jp.json' +import jaJP from '../../renderer/src/i18n/translate/ja-jp.json' import ptPT from '../../renderer/src/i18n/translate/pt-pt.json' -import RuRu from '../../renderer/src/i18n/translate/ru-ru.json' +import ruRU from '../../renderer/src/i18n/translate/ru-ru.json' const logger = loggerService.withContext('main:i18n') // const resources = Object.fromEntries([ -// ['en-us', EnUs], -// ['zh-cn', ZhCn], -// ['zh-tw', ZhTw], -// ['ja-JP', JaJP], -// ['ru-RU', RuRu], +// ['en-US', enUS], +// ['zh-CN', zhCN], +// ['zh-TW', zhTW], // ['de-DE', deDE], // ['el-GR', elGR], // ['es-ES', esES], // ['fr-FR', frFR], -// ['pt-PT', ptPT] +// ['ja-JP', jaJP], +// ['pt-PT', ptPT], +// ['ru-RU', ruRU] // ] as const) const resources = Object.fromEntries( ( [ - ['en-us', EnUs], - ['zh-cn', ZhCn], - ['zh-tw', ZhTw], - ['ja-JP', JaJP], - ['ru-RU', RuRu], + ['en-US', enUS], + ['zh-CN', zhCN], + ['zh-TW', zhTW], ['de-DE', deDE], ['el-GR', elGR], ['es-ES', esES], ['fr-FR', frFR], - ['pt-PT', ptPT] + ['ja-JP', jaJP], + ['pt-PT', ptPT], + ['ru-RU', ruRU] ] as const ).map(([key, translation]) => [key, { translation }]) ) @@ -70,21 +70,36 @@ export const getI18n = (): Record => { return resources[language] } -i18n.init({ - resources, - lng: getAppLanguage(), - fallbackLng: defaultLanguage, - interpolation: { - escapeValue: false - }, - saveMissing: true, - missingKeyHandler: (_1, _2, key) => { - logger.error(`Missing key: ${key}`) - } -}) +let t: (key: string) => string = () => { + logger.error('i18n not inialized') + return '' +} -const t = i18n.t +let changeLang: (lang: LanguageVarious) => void = () => { + logger.error('i18n not inialized') +} -const changeLang: typeof i18n.changeLanguage = i18n.changeLanguage +i18n + .init({ + resources, + lng: getAppLanguage(), + fallbackLng: defaultLanguage, + ns: 'translation', + interpolation: { + escapeValue: false + }, + saveMissing: true, + missingKeyHandler: (_1, _2, key) => { + logger.error(`Missing key: ${key}`) + } + }) + .then((tfn) => { + changeLang = (lang: LanguageVarious) => { + i18n.changeLanguage(lang) + } + t = (key: string) => tfn(key) + const lng = getAppLanguage() + logger.debug('i18n context', { lng, resource: resources[lng] }) + }) export { changeLang, i18n, t }