This commit is contained in:
Biki Kalita
2026-01-17 23:10:57 +05:30
parent 92e908aed8
commit 31d0e6d3dc
7 changed files with 94 additions and 7 deletions

View File

@@ -168,6 +168,13 @@ function SettingsContent({
// Save locale to localStorage for persistence across restarts // Save locale to localStorage for persistence across restarts
localStorage.setItem("next-ai-draw-io-locale", lang) localStorage.setItem("next-ai-draw-io-locale", lang)
// Notify Electron main process to update its menu language
if (window.electronAPI?.setUserLocale) {
window.electronAPI.setUserLocale(lang).catch((error) => {
console.error("Failed to sync locale with Electron:", error)
})
}
const parts = pathname.split("/") const parts = pathname.split("/")
if (parts.length > 1 && i18n.locales.includes(parts[1] as Locale)) { if (parts.length > 1 && i18n.locales.includes(parts[1] as Locale)) {
parts[1] = lang parts[1] = lang

View File

@@ -38,6 +38,12 @@ interface SetProxyResult {
devMode?: boolean devMode?: boolean
} }
/** Result of setting user locale */
interface SetUserLocaleResult {
success: boolean
error?: string
}
declare global { declare global {
interface Window { interface Window {
/** Main window Electron API */ /** Main window Electron API */
@@ -62,6 +68,10 @@ declare global {
getProxy: () => Promise<ProxyConfig> getProxy: () => Promise<ProxyConfig>
/** Set proxy configuration (saves and restarts server) */ /** Set proxy configuration (saves and restarts server) */
setProxy: (config: ProxyConfig) => Promise<SetProxyResult> setProxy: (config: ProxyConfig) => Promise<SetProxyResult>
/** Get user's preferred locale */
getUserLocale: () => Promise<"en" | "zh" | "ja" | undefined>
/** Set user's preferred locale */
setUserLocale: (locale: string) => Promise<SetUserLocaleResult>
} }
/** Settings window Electron API */ /** Settings window Electron API */
@@ -88,4 +98,10 @@ declare global {
} }
} }
export { ConfigPreset, ApplyPresetResult, ProxyConfig, SetProxyResult } export type {
ConfigPreset,
ApplyPresetResult,
ProxyConfig,
SetProxyResult,
SetUserLocaleResult,
}

View File

@@ -13,7 +13,7 @@ import {
getCurrentPresetId, getCurrentPresetId,
setCurrentPreset, setCurrentPreset,
} from "./config-manager" } from "./config-manager"
import { detectSystemLocale, getMenuTranslations } from "./menu-i18n" import { getMenuTranslations, getPreferredLocale } from "./menu-i18n"
import { restartNextServer } from "./next-server" import { restartNextServer } from "./next-server"
import { showSettingsWindow } from "./settings-window" import { showSettingsWindow } from "./settings-window"
@@ -39,8 +39,8 @@ export function rebuildAppMenu(): void {
function getMenuTemplate(): MenuItemConstructorOptions[] { function getMenuTemplate(): MenuItemConstructorOptions[] {
const isMac = process.platform === "darwin" const isMac = process.platform === "darwin"
// Get translations for current system locale // Get translations for preferred locale (saved preference or system default)
const locale = detectSystemLocale(app.getLocale()) const locale = getPreferredLocale(app.getLocale())
const t = getMenuTranslations(locale) const t = getMenuTranslations(locale)
const template: MenuItemConstructorOptions[] = [] const template: MenuItemConstructorOptions[] = []

View File

@@ -137,6 +137,7 @@ interface ConfigPresetsFile {
version: 1 version: 1
currentPresetId: string | null currentPresetId: string | null
presets: ConfigPreset[] presets: ConfigPreset[]
userLocale?: "en" | "zh" | "ja"
} }
const CONFIG_FILE_NAME = "config-presets.json" const CONFIG_FILE_NAME = "config-presets.json"
@@ -161,6 +162,7 @@ export function loadPresets(): ConfigPresetsFile {
version: 1, version: 1,
currentPresetId: null, currentPresetId: null,
presets: [], presets: [],
userLocale: undefined,
} }
} }
@@ -181,6 +183,7 @@ export function loadPresets(): ConfigPresetsFile {
version: 1, version: 1,
currentPresetId: null, currentPresetId: null,
presets: [], presets: [],
userLocale: undefined,
} }
} }
} }
@@ -462,3 +465,21 @@ export function getCurrentPresetEnv(): Record<string, string> {
} }
return env return env
} }
/**
* Get user's preferred locale from config
* Returns undefined if not set
*/
export function getUserLocale(): "en" | "zh" | "ja" | undefined {
const data = loadPresets()
return data.userLocale
}
/**
* Set user's preferred locale in config
*/
export function setUserLocale(locale: "en" | "zh" | "ja" | null): void {
const data = loadPresets()
data.userLocale = locale === null ? undefined : locale
savePresets(data)
}

View File

@@ -1,4 +1,5 @@
import { app, BrowserWindow, dialog, ipcMain } from "electron" import { app, BrowserWindow, dialog, ipcMain } from "electron"
import { rebuildAppMenu } from "./app-menu"
import { import {
applyPresetToEnv, applyPresetToEnv,
type ConfigPreset, type ConfigPreset,
@@ -7,7 +8,9 @@ import {
getAllPresets, getAllPresets,
getCurrentPreset, getCurrentPreset,
getCurrentPresetId, getCurrentPresetId,
getUserLocale,
setCurrentPreset, setCurrentPreset,
setUserLocale,
updatePreset, updatePreset,
} from "./config-manager" } from "./config-manager"
import { restartNextServer } from "./next-server" import { restartNextServer } from "./next-server"
@@ -251,4 +254,32 @@ export function registerIpcHandlers(): void {
} }
} }
}) })
// ==================== User Locale ====================
ipcMain.handle("get-user-locale", () => {
return getUserLocale()
})
ipcMain.handle("set-user-locale", (_event, locale: string) => {
// Validate locale is one of the supported values
if (!["en", "zh", "ja"].includes(locale)) {
return { success: false, error: "Invalid locale" }
}
try {
setUserLocale(locale as "en" | "zh" | "ja")
// Rebuild the menu to reflect the new locale
rebuildAppMenu()
return { success: true }
} catch (error) {
return {
success: false,
error:
error instanceof Error
? error.message
: "Failed to set locale",
}
}
})
} }

View File

@@ -3,6 +3,8 @@
* Translations for menu labels that don't use Electron's built-in roles * Translations for menu labels that don't use Electron's built-in roles
*/ */
import { getUserLocale } from "./config-manager"
export type MenuLocale = "en" | "zh" | "ja" export type MenuLocale = "en" | "zh" | "ja"
export interface MenuTranslations { export interface MenuTranslations {
@@ -169,10 +171,15 @@ export function detectSystemLocale(appLocale: string): MenuLocale {
/** /**
* Get locale from stored preference or system default * Get locale from stored preference or system default
* Checks localStorage for user's language preference first * Checks config file for user's language preference first
*/ */
export function getPreferredLocale(appLocale: string): MenuLocale { export function getPreferredLocale(appLocale: string): MenuLocale {
// In Electron, we don't have direct access to localStorage // Try to get from saved preference first
// This will be handled by reading from a config file if needed const savedLocale = getUserLocale()
if (savedLocale) {
return savedLocale
}
// Fall back to system locale
return detectSystemLocale(appLocale) return detectSystemLocale(appLocale)
} }

View File

@@ -26,4 +26,9 @@ contextBridge.exposeInMainWorld("electronAPI", {
getProxy: () => ipcRenderer.invoke("get-proxy"), getProxy: () => ipcRenderer.invoke("get-proxy"),
setProxy: (config: { httpProxy?: string; httpsProxy?: string }) => setProxy: (config: { httpProxy?: string; httpsProxy?: string }) =>
ipcRenderer.invoke("set-proxy", config), ipcRenderer.invoke("set-proxy", config),
// User locale settings
getUserLocale: () => ipcRenderer.invoke("get-user-locale"),
setUserLocale: (locale: string) =>
ipcRenderer.invoke("set-user-locale", locale),
}) })