From 2601283032abb7231257459ce92e4af165162814 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Wed, 28 Jan 2026 21:58:05 +0800 Subject: [PATCH] add about dialog i18n fixes #2711 closes #2721 --- locales/en/translation.json | 2 ++ src/main/aboutPanel.ts | 5 +++-- src/main/i18n.ts | 2 +- src/main/index.ts | 22 +++++++++++++++------- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/locales/en/translation.json b/locales/en/translation.json index 783be30b..253dc3ee 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -5,6 +5,7 @@ "\"ffmpeg\" experimental flag": "\"ffmpeg\" experimental flag", "(data tracks such as GoPro GPS, telemetry etc. are not copied over by default because ffmpeg cannot cut them, thus they will cause the media duration to stay the same after cutting video/audio)": "(data tracks such as GoPro GPS, telemetry etc. are not copied over by default because ffmpeg cannot cut them, thus they will cause the media duration to stay the same after cutting video/audio)", "(detected)": "(detected)", + "{{appStoreType}} edition, based on GitHub v{{appVersion}}": "{{appStoreType}} edition, based on GitHub v{{appVersion}}", "{{durationMsFormatted}} ms": "{{durationMsFormatted}} ms", "{{frameCount}} frames": "{{frameCount}} frames", "{{numFrames}} frames_one": "{{numFrames}} frames", @@ -143,6 +144,7 @@ "Copy selected segments times to clipboard": "Copy selected segments times to clipboard", "Copy to clipboard": "Copy to clipboard", "Copy to YouTube description/comment:": "Copy to YouTube description/comment:", + "Copyright": "Copyright", "Could not open media due to error {{errorCode}}": "Could not open media due to error {{errorCode}}", "Create byte sized segments": "Create byte sized segments", "Create chapters from merged segments? (slow)": "Create chapters from merged segments (slow)", diff --git a/src/main/aboutPanel.ts b/src/main/aboutPanel.ts index 7efed0c2..356809c1 100644 --- a/src/main/aboutPanel.ts +++ b/src/main/aboutPanel.ts @@ -1,6 +1,7 @@ import type { AboutPanelOptionsOptions } from 'electron'; // eslint-disable-next-line import/no-extraneous-dependencies import { app } from 'electron'; +import { t } from 'i18next'; import { appName, copyrightYear } from './common.js'; import { isLinux } from './util.js'; @@ -15,7 +16,7 @@ export function getAboutPanelOptions() { const aboutPanelLines = [ isStoreBuild ? homepageUrl : githubUrl, '', - `Copyright © 2016-${copyrightYear} Mikael Finstad ❤️ 🇳🇴`, + `${t('Copyright')} © 2016-${copyrightYear} Mikael Finstad ❤️ 🇳🇴`, ]; const aboutPanelOptions: AboutPanelOptionsOptions = { @@ -30,7 +31,7 @@ export function getAboutPanelOptions() { aboutPanelOptions.applicationVersion = appVersion; } else if (isStoreBuild) { // https://github.com/mifi/lossless-cut/issues/1882 - aboutPanelOptions.applicationVersion = `${process.windowsStore ? 'Microsoft Store' : 'App Store'} edition, based on GitHub v${appVersion}`; + aboutPanelOptions.applicationVersion = t('{{appStoreType}} edition, based on GitHub v{{appVersion}}', { appStoreType: process.windowsStore ? 'Microsoft Store' : 'App Store', appVersion }); } return aboutPanelOptions; diff --git a/src/main/i18n.ts b/src/main/i18n.ts index a6542256..d0023cd8 100644 --- a/src/main/i18n.ts +++ b/src/main/i18n.ts @@ -8,7 +8,7 @@ import { commonI18nOptions, loadPath, addPath } from './i18nCommon.js'; // See also renderer // https://github.com/i18next/i18next/issues/869 -export default i18n +export default await i18n .use(Backend) .use({ type: 'languageDetector', async: false, detect: () => app.getLocale() }) // See also i18next.config.base.ts diff --git a/src/main/index.ts b/src/main/index.ts index 91f88457..9144ddae 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -58,9 +58,6 @@ if (isWindows) { app.setAppUserModelId(app.name); } -// https://www.electronjs.org/docs/latest/api/app#appsetaboutpaneloptionsoptions -app.setAboutPanelOptions(getAboutPanelOptions()); - let filesToOpen: string[] = []; // Keep a global reference of the window object, if you don't, the window will @@ -197,6 +194,17 @@ function updateMenu() { menu({ app, mainWindow, newVersion, isStoreBuild }); } +async function changeLanguage(language: string | null) { + try { + await i18n.changeLanguage(language ?? undefined); + updateMenu(); + // https://www.electronjs.org/docs/latest/api/app#appsetaboutpaneloptionsoptions + app.setAboutPanelOptions(getAboutPanelOptions()); + } catch (err) { + logger.error('Failed to set language', err); + } +} + function openFilesEventually(paths: string[]) { if (rendererReady) openFiles(paths); else filesToOpen = paths; @@ -250,6 +258,7 @@ async function init() { logger.info('Initialized config store'); const allowMultipleInstances = configStore.get('allowMultipleInstances'); + const language = configStore.get('language'); if (!allowMultipleInstances && !safeRequestSingleInstanceLock({ argv: process.argv })) { logger.info('Found running instance, quitting'); @@ -307,9 +316,7 @@ async function init() { askBeforeClose = val; }); - ipcMain.on('setLanguage', (_e, language) => { - i18n.changeLanguage(language).then(() => updateMenu()).catch((err) => logger.error('Failed to set language', err)); - }); + ipcMain.on('setLanguage', (_e, newLanguage) => changeLanguage(newLanguage)); ipcMain.handle('tryTrashItem', async (_e, path) => { try { @@ -362,7 +369,8 @@ async function init() { } createWindow(); - updateMenu(); + // will also updateMenu and set about panel options + await changeLanguage(language); const enableUpdateCheck = configStore.get('enableUpdateCheck');