added locale for context-menu

This commit is contained in:
injurka 2024-11-06 16:19:36 +04:00 committed by 亢奋猫
parent ceca3408ff
commit 35efada37e
12 changed files with 55 additions and 12 deletions

View File

@ -29,6 +29,11 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle('app:reload', () => mainWindow.reload()) ipcMain.handle('app:reload', () => mainWindow.reload())
ipcMain.handle('open:website', (_, url: string) => shell.openExternal(url)) ipcMain.handle('open:website', (_, url: string) => shell.openExternal(url))
// language
ipcMain.handle('app:set-language', (_, language) => {
configManager.setLanguage(language)
})
// theme // theme
ipcMain.handle('app:set-theme', (_, theme: 'light' | 'dark') => { ipcMain.handle('app:set-theme', (_, theme: 'light' | 'dark') => {
configManager.setTheme(theme) configManager.setTheme(theme)

View File

@ -1,5 +1,9 @@
import { app } from 'electron'
import Store from 'electron-store' import Store from 'electron-store'
type ThemeVarious = 'light' | 'dark'
type LanguageVarious = 'zh-CN' | 'zh-TW' | 'en-US'
export class ConfigManager { export class ConfigManager {
private store: Store private store: Store
@ -7,11 +11,19 @@ export class ConfigManager {
this.store = new Store() this.store = new Store()
} }
getTheme(): 'light' | 'dark' { getLanguage(): LanguageVarious {
return this.store.get('theme', 'light') as 'light' | 'dark' return this.store.get('language', app.getLocale()) as LanguageVarious
} }
setTheme(theme: 'light' | 'dark') { setLanguage(theme: ThemeVarious) {
this.store.set('language', theme)
}
getTheme(): ThemeVarious {
return this.store.get('theme', 'light') as ThemeVarious
}
setTheme(theme: ThemeVarious) {
this.store.set('theme', theme) this.store.set('theme', theme)
} }
} }

11
src/main/utils/locales.ts Normal file
View File

@ -0,0 +1,11 @@
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'
const locales = {
'en-US': EnUs,
'zh-CN': ZhCn,
'zh-TW': ZhTw
}
export { locales }

View File

@ -6,6 +6,7 @@ import { join } from 'path'
import icon from '../../build/icon.png?asset' import icon from '../../build/icon.png?asset'
import { titleBarOverlayDark, titleBarOverlayLight } from './config' import { titleBarOverlayDark, titleBarOverlayLight } from './config'
import { configManager } from './services/ConfigManager' import { configManager } from './services/ConfigManager'
import { locales } from './utils/locales'
export function createMainWindow() { export function createMainWindow() {
// Load the previous state with fallback to defaults // Load the previous state with fallback to defaults
@ -48,10 +49,13 @@ export function createMainWindow() {
mainWindowState.manage(mainWindow) mainWindowState.manage(mainWindow)
mainWindow.webContents.on('context-menu', () => { mainWindow.webContents.on('context-menu', () => {
const locale = locales[configManager.getLanguage()]
const { common } = locale.translation
const menu = new Menu() const menu = new Menu()
menu.append(new MenuItem({ label: '复制', role: 'copy' })) menu.append(new MenuItem({ label: common.copy, role: 'copy' }))
menu.append(new MenuItem({ label: '粘贴', role: 'paste' })) menu.append(new MenuItem({ label: common.paste, role: 'paste' }))
menu.append(new MenuItem({ label: '剪切', role: 'cut' })) menu.append(new MenuItem({ label: common.cut, role: 'cut' }))
menu.popup() menu.popup()
}) })

View File

@ -1,6 +1,7 @@
import { ElectronAPI } from '@electron-toolkit/preload' import { ElectronAPI } from '@electron-toolkit/preload'
import { FileType } from '@renderer/types' import { FileType } from '@renderer/types'
import { WebDavConfig } from '@renderer/types' import { WebDavConfig } from '@renderer/types'
import { LanguageVarious } from '@renderer/types'
import type { OpenDialogOptions } from 'electron' import type { OpenDialogOptions } from 'electron'
import { Readable } from 'stream' import { Readable } from 'stream'
@ -17,6 +18,7 @@ declare global {
checkForUpdate: () => void checkForUpdate: () => void
openWebsite: (url: string) => void openWebsite: (url: string) => void
setProxy: (proxy: string | undefined) => void setProxy: (proxy: string | undefined) => void
setLanguage: (theme: LanguageVarious) => void
setTheme: (theme: 'light' | 'dark') => void setTheme: (theme: 'light' | 'dark') => void
minApp: (options: { url: string; windowOptions?: Electron.BrowserWindowConstructorOptions }) => void minApp: (options: { url: string; windowOptions?: Electron.BrowserWindowConstructorOptions }) => void
reload: () => void reload: () => void

View File

@ -8,6 +8,7 @@ const api = {
reload: () => ipcRenderer.invoke('app:reload'), reload: () => ipcRenderer.invoke('app:reload'),
setProxy: (proxy: string) => ipcRenderer.invoke('app:proxy', proxy), setProxy: (proxy: string) => ipcRenderer.invoke('app:proxy', proxy),
checkForUpdate: () => ipcRenderer.invoke('app:check-for-update'), checkForUpdate: () => ipcRenderer.invoke('app:check-for-update'),
setLanguage: (lang: string) => ipcRenderer.invoke('app:set-language', lang),
setTheme: (theme: 'light' | 'dark') => ipcRenderer.invoke('app:set-theme', theme), setTheme: (theme: 'light' | 'dark') => ipcRenderer.invoke('app:set-theme', theme),
openWebsite: (url: string) => ipcRenderer.invoke('open:website', url), openWebsite: (url: string) => ipcRenderer.invoke('open:website', url),
minApp: (url: string) => ipcRenderer.invoke('minapp', url), minApp: (url: string) => ipcRenderer.invoke('minapp', url),

View File

@ -17,6 +17,8 @@
"edit": "Edit", "edit": "Edit",
"duplicate": "Duplicate", "duplicate": "Duplicate",
"copy": "Copy", "copy": "Copy",
"paste": "Paste",
"cut": "Cut",
"regenerate": "Regenerate", "regenerate": "Regenerate",
"provider": "Provider", "provider": "Provider",
"you": "You", "you": "You",

View File

@ -17,6 +17,8 @@
"edit": "编辑", "edit": "编辑",
"duplicate": "复制", "duplicate": "复制",
"copy": "复制", "copy": "复制",
"paste": "粘贴",
"cut": "剪切",
"regenerate": "重新生成", "regenerate": "重新生成",
"provider": "提供商", "provider": "提供商",
"you": "用户", "you": "用户",

View File

@ -17,6 +17,8 @@
"edit": "編輯", "edit": "編輯",
"duplicate": "複製", "duplicate": "複製",
"copy": "複製", "copy": "複製",
"paste": "貼上",
"cut": "剪下",
"regenerate": "重新生成", "regenerate": "重新生成",
"provider": "提供商", "provider": "提供商",
"you": "您", "you": "您",

View File

@ -4,7 +4,7 @@ import i18n from '@renderer/i18n'
import { useAppDispatch } from '@renderer/store' import { useAppDispatch } from '@renderer/store'
import { setClickAssistantToShowTopic, setLanguage, setShowTopicTime } from '@renderer/store/settings' import { setClickAssistantToShowTopic, setLanguage, setShowTopicTime } from '@renderer/store/settings'
import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings' import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
import { ThemeMode } from '@renderer/types' import { LanguageVarious, ThemeMode } from '@renderer/types'
import { isValidProxyUrl } from '@renderer/utils' import { isValidProxyUrl } from '@renderer/utils'
import { Input, Select, Switch } from 'antd' import { Input, Select, Switch } from 'antd'
import { FC, useState } from 'react' import { FC, useState } from 'react'
@ -30,9 +30,10 @@ const GeneralSettings: FC = () => {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { t } = useTranslation() const { t } = useTranslation()
const onSelectLanguage = (value: string) => { const onSelectLanguage = (value: LanguageVarious) => {
dispatch(setLanguage(value)) dispatch(setLanguage(value))
localStorage.setItem('language', value) localStorage.setItem('language', value)
window.api.setLanguage(value)
i18n.changeLanguage(value) i18n.changeLanguage(value)
} }

View File

@ -1,5 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { ThemeMode } from '@renderer/types' import { LanguageVarious, ThemeMode } from '@renderer/types'
export type SendMessageShortcut = 'Enter' | 'Shift+Enter' export type SendMessageShortcut = 'Enter' | 'Shift+Enter'
@ -7,7 +7,7 @@ export interface SettingsState {
showAssistants: boolean showAssistants: boolean
showTopics: boolean showTopics: boolean
sendMessageShortcut: SendMessageShortcut sendMessageShortcut: SendMessageShortcut
language: string language: LanguageVarious
proxyUrl?: string proxyUrl?: string
userName: string userName: string
showMessageDivider: boolean showMessageDivider: boolean
@ -36,7 +36,7 @@ const initialState: SettingsState = {
showAssistants: true, showAssistants: true,
showTopics: true, showTopics: true,
sendMessageShortcut: 'Enter', sendMessageShortcut: 'Enter',
language: navigator.language, language: navigator.language as LanguageVarious,
proxyUrl: undefined, proxyUrl: undefined,
userName: '', userName: '',
showMessageDivider: false, showMessageDivider: false,
@ -79,7 +79,7 @@ const settingsSlice = createSlice({
setSendMessageShortcut: (state, action: PayloadAction<SendMessageShortcut>) => { setSendMessageShortcut: (state, action: PayloadAction<SendMessageShortcut>) => {
state.sendMessageShortcut = action.payload state.sendMessageShortcut = action.payload
}, },
setLanguage: (state, action: PayloadAction<string>) => { setLanguage: (state, action: PayloadAction<LanguageVarious>) => {
state.language = action.payload state.language = action.payload
}, },
setProxyUrl: (state, action: PayloadAction<string | undefined>) => { setProxyUrl: (state, action: PayloadAction<string | undefined>) => {

View File

@ -136,6 +136,7 @@ export enum ThemeMode {
dark = 'dark', dark = 'dark',
auto = 'auto' auto = 'auto'
} }
export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'en-US'
export type WebDavConfig = { export type WebDavConfig = {
webdavHost: string webdavHost: string