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
This commit is contained in:
icarus 2025-10-23 23:08:47 +08:00
parent 57206dd3b1
commit 7e5e3786cf
2 changed files with 56 additions and 31 deletions

View File

@ -35,6 +35,8 @@ import { dataRefactorMigrateService } from './data/migrate/dataRefactor/DataRefa
import { dataApiService } from '@data/DataApiService' import { dataApiService } from '@data/DataApiService'
import { cacheService } from '@data/CacheService' import { cacheService } from '@data/CacheService'
import { initWebviewHotkeys } from './services/WebviewService' import { initWebviewHotkeys } from './services/WebviewService'
import { i18n } from './utils/language'
import { defaultLanguage } from '@shared/config/constant'
const logger = loggerService.withContext('MainEntry') const logger = loggerService.withContext('MainEntry')
@ -168,6 +170,14 @@ if (!app.requestSingleInstanceLock()) {
await preferenceService.initialize() 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 // Initialize DataApiService
await dataApiService.initialize() await dataApiService.initialize()

View File

@ -5,9 +5,9 @@ import type { LanguageVarious } from '@shared/data/preference/preferenceTypes'
import { app } from 'electron' import { app } from 'electron'
import i18n from 'i18next' import i18n from 'i18next'
import EnUs from '../../renderer/src/i18n/locales/en-us.json' import enUS from '../../renderer/src/i18n/locales/en-us.json'
import ZhCn from '../../renderer/src/i18n/locales/zh-cn.json' import zhCN from '../../renderer/src/i18n/locales/zh-cn.json'
import ZhTw from '../../renderer/src/i18n/locales/zh-tw.json' import zhTW from '../../renderer/src/i18n/locales/zh-tw.json'
// import deDE from '../../renderer/src/i18n/locales/de-de.json' // import deDE from '../../renderer/src/i18n/locales/de-de.json'
// import elGR from '../../renderer/src/i18n/locales/el-gr.json' // import elGR from '../../renderer/src/i18n/locales/el-gr.json'
// import esES from '../../renderer/src/i18n/locales/es-es.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 elGR from '../../renderer/src/i18n/translate/el-gr.json'
import esES from '../../renderer/src/i18n/translate/es-es.json' import esES from '../../renderer/src/i18n/translate/es-es.json'
import frFR from '../../renderer/src/i18n/translate/fr-fr.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 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 logger = loggerService.withContext('main:i18n')
// const resources = Object.fromEntries([ // const resources = Object.fromEntries([
// ['en-us', EnUs], // ['en-US', enUS],
// ['zh-cn', ZhCn], // ['zh-CN', zhCN],
// ['zh-tw', ZhTw], // ['zh-TW', zhTW],
// ['ja-JP', JaJP],
// ['ru-RU', RuRu],
// ['de-DE', deDE], // ['de-DE', deDE],
// ['el-GR', elGR], // ['el-GR', elGR],
// ['es-ES', esES], // ['es-ES', esES],
// ['fr-FR', frFR], // ['fr-FR', frFR],
// ['pt-PT', ptPT] // ['ja-JP', jaJP],
// ['pt-PT', ptPT],
// ['ru-RU', ruRU]
// ] as const) // ] as const)
const resources = Object.fromEntries( const resources = Object.fromEntries(
( (
[ [
['en-us', EnUs], ['en-US', enUS],
['zh-cn', ZhCn], ['zh-CN', zhCN],
['zh-tw', ZhTw], ['zh-TW', zhTW],
['ja-JP', JaJP],
['ru-RU', RuRu],
['de-DE', deDE], ['de-DE', deDE],
['el-GR', elGR], ['el-GR', elGR],
['es-ES', esES], ['es-ES', esES],
['fr-FR', frFR], ['fr-FR', frFR],
['pt-PT', ptPT] ['ja-JP', jaJP],
['pt-PT', ptPT],
['ru-RU', ruRU]
] as const ] as const
).map(([key, translation]) => [key, { translation }]) ).map(([key, translation]) => [key, { translation }])
) )
@ -70,21 +70,36 @@ export const getI18n = (): Record<string, any> => {
return resources[language] return resources[language]
} }
i18n.init({ let t: (key: string) => string = () => {
resources, logger.error('i18n not inialized')
lng: getAppLanguage(), return ''
fallbackLng: defaultLanguage, }
interpolation: {
escapeValue: false
},
saveMissing: true,
missingKeyHandler: (_1, _2, key) => {
logger.error(`Missing key: ${key}`)
}
})
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 } export { changeLang, i18n, t }