mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-06-08 17:20:00 +08:00
✨ Feature: finish i18n system
This commit is contained in:
@@ -17,7 +17,8 @@ import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||
import pkg from 'root/package.json'
|
||||
import { handleCopyUrl } from '~/main/utils/common'
|
||||
import { privacyManager } from '~/main/utils/privacyManager'
|
||||
import { T } from '#/i18n'
|
||||
// import { T } from '#/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
|
||||
let contextMenu: Menu | null
|
||||
let menu: Menu | null
|
||||
|
||||
@@ -9,7 +9,7 @@ import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
||||
import { handleCopyUrl } from '~/main/utils/common'
|
||||
import { handleUrlEncode } from '#/utils/common'
|
||||
import { T } from '#/i18n/index'
|
||||
import { T } from '~/main/i18n/index'
|
||||
// import dayjs from 'dayjs'
|
||||
|
||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { IPicGo } from 'picgo'
|
||||
import { showNotification, calcDurationRange } from '~/main/utils/common'
|
||||
import { RENAME_FILE_NAME, TALKING_DATA_EVENT } from '~/universal/events/constants'
|
||||
import logger from '@core/picgo/logger'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
import fse from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { privacyManager } from '~/main/utils/privacyManager'
|
||||
|
||||
@@ -10,17 +10,18 @@ import { CREATE_APP_MENU } from '@core/bus/constants'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
||||
import { app } from 'electron'
|
||||
import { i18n } from '~/universal/i18n'
|
||||
import { URLSearchParams } from 'url'
|
||||
// import { i18n } from '~/main/i18n'
|
||||
// import { URLSearchParams } from 'url'
|
||||
|
||||
const windowList = new Map<IWindowList, IWindowListItem>()
|
||||
|
||||
const handleWindowParams = (windowURL: string) => {
|
||||
const [baseURL, hash = ''] = windowURL.split('#')
|
||||
const search = new URLSearchParams()
|
||||
const lang = i18n.getLanguage()
|
||||
search.append('lang', lang)
|
||||
return `${baseURL}?${search.toString()}#${hash}`
|
||||
// const [baseURL, hash = ''] = windowURL.split('#')
|
||||
// const search = new URLSearchParams()
|
||||
// const lang = i18n.getLanguage()
|
||||
// search.append('lang', lang)
|
||||
// return `${baseURL}?${search.toString()}#${hash}`
|
||||
return windowURL
|
||||
}
|
||||
|
||||
windowList.set(IWindowList.TRAY_WINDOW, {
|
||||
|
||||
@@ -4,7 +4,7 @@ import path from 'path'
|
||||
import { app as APP } from 'electron'
|
||||
import { getLogger } from '@core/utils/localLogger'
|
||||
import dayjs from 'dayjs'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
const STORE_PATH = APP.getPath('userData')
|
||||
const configFilePath = path.join(STORE_PATH, 'data.json')
|
||||
const configFileBackupPath = path.join(STORE_PATH, 'data.bak.json')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs-extra'
|
||||
import { dbPathChecker, dbPathDir, getGalleryDBPath } from './dbChecker'
|
||||
import { DBStore, JSONStore } from '@picgo/store'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
const STORE_PATH = dbPathDir()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
SHOW_INPUT_BOX
|
||||
} from '~/universal/events/constants'
|
||||
import { DBStore } from '@picgo/store'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
// Cross-process support may be required in the future
|
||||
class GuiApi implements IGuiApi {
|
||||
|
||||
@@ -27,8 +27,7 @@ import {
|
||||
OPEN_URL,
|
||||
RELOAD_APP,
|
||||
SHOW_PLUGIN_PAGE_MENU,
|
||||
SET_MINI_WINDOW_POS,
|
||||
CHANGE_LANGUAGE
|
||||
SET_MINI_WINDOW_POS
|
||||
} from '#/events/constants'
|
||||
import {
|
||||
uploadClipboardFiles,
|
||||
@@ -38,7 +37,7 @@ import picgoCoreIPC from './picgoCoreIPC'
|
||||
import { handleCopyUrl } from '~/main/utils/common'
|
||||
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildUploadPageMenu } from './remotes/menu'
|
||||
import path from 'path'
|
||||
import { i18n, T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
|
||||
@@ -224,10 +223,6 @@ export default {
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
window?.setBounds(pos)
|
||||
})
|
||||
ipcMain.on(CHANGE_LANGUAGE, (evt: IpcMainEvent, lang: string) => {
|
||||
lang = lang || 'zh-CN'
|
||||
i18n.setLanguage(lang)
|
||||
})
|
||||
},
|
||||
dispose () {}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,16 @@ import {
|
||||
PICGO_OPEN_FILE,
|
||||
PASTE_TEXT,
|
||||
OPEN_WINDOW,
|
||||
DEFAULT_LOGO
|
||||
DEFAULT_LOGO,
|
||||
GET_LANGUAGE_LIST,
|
||||
SET_CURRENT_LANGUAGE,
|
||||
GET_CURRENT_LANGUAGE
|
||||
} from '#/events/constants'
|
||||
|
||||
import { GalleryDB } from 'apis/core/datastore'
|
||||
import { IObject, IFilter } from '@picgo/store/dist/types'
|
||||
import pasteTemplate from '../utils/pasteTemplate'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { i18nManager, T } from '~/main/i18n'
|
||||
|
||||
// eslint-disable-next-line
|
||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||
@@ -373,6 +376,31 @@ const handleDefaultLogo = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleI18n = () => {
|
||||
ipcMain.on(GET_LANGUAGE_LIST, (event: IpcMainEvent) => {
|
||||
event.sender.send(GET_LANGUAGE_LIST, i18nManager.languageList)
|
||||
})
|
||||
ipcMain.on(SET_CURRENT_LANGUAGE, (event: IpcMainEvent, language: string) => {
|
||||
i18nManager.setCurrentLanguage(language)
|
||||
const { lang, locales } = i18nManager.getCurrentLocales()
|
||||
if (process.platform === 'darwin') {
|
||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||
trayWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||
}
|
||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
||||
settingWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)
|
||||
miniWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||
}
|
||||
// event.sender.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||
})
|
||||
ipcMain.on(GET_CURRENT_LANGUAGE, (event: IpcMainEvent) => {
|
||||
const { lang, locales } = i18nManager.getCurrentLocales()
|
||||
event.sender.send(GET_CURRENT_LANGUAGE, lang, locales)
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
listen () {
|
||||
handleGetPluginList()
|
||||
@@ -387,6 +415,7 @@ export default {
|
||||
handleOpenFile()
|
||||
handleOpenWindow()
|
||||
handleDefaultLogo()
|
||||
handleI18n()
|
||||
},
|
||||
// TODO: separate to single file
|
||||
handlePluginUninstall,
|
||||
|
||||
@@ -12,7 +12,7 @@ import GuiApi from 'apis/gui'
|
||||
import { PICGO_CONFIG_PLUGIN, PICGO_HANDLE_PLUGIN_ING, PICGO_TOGGLE_PLUGIN, SHOW_MAIN_PAGE_DONATION, SHOW_MAIN_PAGE_QRCODE } from '~/universal/events/constants'
|
||||
import picgoCoreIPC from '~/main/events/picgoCoreIPC'
|
||||
import { PicGo as PicGoCore } from 'picgo'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
interface GuiMenuItem {
|
||||
label: string
|
||||
|
||||
95
src/main/i18n/index.ts
Normal file
95
src/main/i18n/index.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import yaml from 'js-yaml'
|
||||
import { ObjectAdapter, I18n } from '@picgo/i18n'
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
class I18nManager {
|
||||
private i18n: I18n | null = null
|
||||
private builtinI18nFolder = path.join(__static, 'i18n')
|
||||
private outterI18nFolder = ''
|
||||
private localesMap: Map<string, ILocales> = new Map()
|
||||
private currentLanguage: string = 'zh-CN'
|
||||
readonly defaultLanguage: string = 'zh-CN'
|
||||
private i18nFileList: II18nItem[] = [{
|
||||
label: '简体中文',
|
||||
value: 'zh-CN'
|
||||
}, {
|
||||
label: 'English',
|
||||
value: 'en'
|
||||
}]
|
||||
|
||||
setOutterI18nFolder (folder: string) {
|
||||
this.outterI18nFolder = folder
|
||||
}
|
||||
|
||||
addI18nFile (file: string, label: string) {
|
||||
this.i18nFileList.push({
|
||||
label,
|
||||
value: file
|
||||
})
|
||||
}
|
||||
|
||||
private getLocales (lang: string): ILocales {
|
||||
if (this.localesMap.has(lang)) {
|
||||
return this.localesMap.get(lang)!
|
||||
}
|
||||
let localesPath = path.join(this.builtinI18nFolder, `${lang}.yml`)
|
||||
if (!fs.existsSync(localesPath)) {
|
||||
localesPath = path.join(this.outterI18nFolder, `${lang}.yml`)
|
||||
if (!fs.existsSync(localesPath)) {
|
||||
localesPath = path.join(this.builtinI18nFolder, `${this.defaultLanguage}.yml`)
|
||||
}
|
||||
}
|
||||
try {
|
||||
const localesString = fs.readFileSync(localesPath, 'utf8')
|
||||
const locales = yaml.load(localesString) as unknown as ILocales
|
||||
this.localesMap.set(lang, locales)
|
||||
return locales
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
// if error, use default language
|
||||
localesPath = path.join(this.builtinI18nFolder, `${this.defaultLanguage}.yml`)
|
||||
const localesString = fs.readFileSync(localesPath, 'utf8')
|
||||
const locales = yaml.load(localesString) as unknown as ILocales
|
||||
this.localesMap.set(lang, locales)
|
||||
return locales
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentLanguage (lang: string) {
|
||||
const locales = this.getLocales(lang)
|
||||
this.currentLanguage = lang
|
||||
this.initI18n(lang, locales)
|
||||
}
|
||||
|
||||
private initI18n (lang: string = this.defaultLanguage, locales: ILocales) {
|
||||
const objectAdapter = new ObjectAdapter({
|
||||
[lang]: locales
|
||||
})
|
||||
this.i18n = new I18n({
|
||||
adapter: objectAdapter,
|
||||
defaultLanguage: lang
|
||||
})
|
||||
}
|
||||
|
||||
T (key: ILocalesKey, args: IStringKeyMap = {}): string {
|
||||
return this.i18n?.translate(key, args) || key
|
||||
}
|
||||
|
||||
get languageList () {
|
||||
return this.i18nFileList
|
||||
}
|
||||
|
||||
getCurrentLocales () {
|
||||
return {
|
||||
lang: this.currentLanguage,
|
||||
locales: this.getLocales(this.currentLanguage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const T = (key: ILocalesKey, args: IStringKeyMap = {}): string => {
|
||||
return i18nManager.T(key, args)
|
||||
}
|
||||
|
||||
export const i18nManager = new I18nManager()
|
||||
@@ -3,7 +3,7 @@ import ConfigStore from '~/main/apis/core/datastore'
|
||||
import path from 'path'
|
||||
import fse from 'fs-extra'
|
||||
import { PicGo as PicGoCore } from 'picgo'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
// from v2.1.2
|
||||
const updateShortKeyFromVersion212 = (db: typeof ConfigStore, shortKeyConfig: IShortKeyConfigs | IOldShortKeyConfigs) => {
|
||||
// #557 极端情况可能会出现配置不存在,需要重新写入
|
||||
|
||||
@@ -2,6 +2,9 @@ import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
import { dbPathChecker } from 'apis/core/datastore/dbChecker'
|
||||
import yaml from 'js-yaml'
|
||||
import { i18nManager } from '~/main/i18n'
|
||||
// import { ILocales } from '~/universal/types/i18n'
|
||||
|
||||
const configPath = dbPathChecker()
|
||||
const CONFIG_DIR = path.dirname(configPath)
|
||||
@@ -11,13 +14,14 @@ function beforeOpen () {
|
||||
resolveMacWorkFlow()
|
||||
}
|
||||
resolveClipboardImageGenerator()
|
||||
resolveOtherI18nFiles()
|
||||
}
|
||||
|
||||
/**
|
||||
* macOS 右键菜单
|
||||
*/
|
||||
function resolveMacWorkFlow () {
|
||||
const dest = `${os.homedir}/Library/Services/Upload pictures with PicGo.workflow`
|
||||
const dest = `${os.homedir()}/Library/Services/Upload pictures with PicGo.workflow`
|
||||
if (fs.existsSync(dest)) {
|
||||
return true
|
||||
} else {
|
||||
@@ -29,6 +33,20 @@ function resolveMacWorkFlow () {
|
||||
}
|
||||
}
|
||||
|
||||
function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
||||
try {
|
||||
const file1 = fs.existsSync(filePath1) && fs.readFileSync(filePath1)
|
||||
const file2 = fs.existsSync(filePath1) && fs.readFileSync(filePath2)
|
||||
|
||||
if (!file1 || !file2 || !file1.equals(file2)) {
|
||||
fs.copyFileSync(filePath1, filePath2)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
fs.copyFileSync(filePath1, filePath2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化剪贴板生成图片的脚本
|
||||
*/
|
||||
@@ -44,20 +62,6 @@ function resolveClipboardImageGenerator () {
|
||||
})
|
||||
}
|
||||
|
||||
function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
||||
try {
|
||||
const file1 = fs.existsSync(filePath1) && fs.readFileSync(filePath1)
|
||||
const file2 = fs.existsSync(filePath1) && fs.readFileSync(filePath2)
|
||||
|
||||
if (!file1 || !file2 || !file1.equals(file2)) {
|
||||
fs.copyFileSync(filePath1, filePath2)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
fs.copyFileSync(filePath1, filePath2)
|
||||
}
|
||||
}
|
||||
|
||||
function getClipboardFiles () {
|
||||
const files = [
|
||||
'/linux.sh',
|
||||
@@ -76,4 +80,34 @@ function resolveClipboardImageGenerator () {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化其他语言文件
|
||||
*/
|
||||
function resolveOtherI18nFiles () {
|
||||
const i18nFolder = path.join(CONFIG_DIR, 'i18n')
|
||||
if (!fs.pathExistsSync(i18nFolder)) {
|
||||
fs.mkdirSync(i18nFolder)
|
||||
}
|
||||
i18nManager.setOutterI18nFolder(i18nFolder)
|
||||
const i18nFiles = fs.readdirSync(path.join(CONFIG_DIR, 'i18n'), {
|
||||
withFileTypes: true
|
||||
})
|
||||
i18nFiles.forEach(item => {
|
||||
if (item.isFile()) {
|
||||
if (item.name.endsWith('.yml')) {
|
||||
const i18nFilePath = path.join(i18nFolder, item.name)
|
||||
const i18nFile = fs.readFileSync(i18nFilePath, 'utf8')
|
||||
try {
|
||||
const i18nFileObj = yaml.load(i18nFile) as unknown as ILocales
|
||||
if (i18nFileObj?.LANG_DISPLAY_LABEL) {
|
||||
i18nManager.addI18nFile(item.name.replace('.yml', ''), i18nFileObj.LANG_DISPLAY_LABEL)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default beforeOpen
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { i18n } from '#/i18n'
|
||||
import { i18nManager } from '~/main/i18n'
|
||||
export const initI18n = () => {
|
||||
const currentLanguage = db.get('settings.language') || 'zh-CN'
|
||||
i18n.setLanguage(currentLanguage)
|
||||
i18nManager.setCurrentLanguage(currentLanguage)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { showMessageBox } from '~/main/utils/common'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
class PrivacyManager {
|
||||
async check () {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { dialog, shell } from 'electron'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import pkg from 'root/package.json'
|
||||
import { lt } from 'semver'
|
||||
import { T } from '~/universal/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
import { getLatestVersion } from '#/utils/getLatestVersion'
|
||||
const version = pkg.version
|
||||
// const releaseUrl = 'https://api.github.com/repos/Molunerfinn/PicGo/releases'
|
||||
|
||||
Reference in New Issue
Block a user