/
index.ts
123 lines (111 loc) · 3.67 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2024 Terwer, Inc. <https://terwer.space/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
import { II18nManager, ILocale, IPicGo, IStringKeyMap } from "../types"
import { ObjectAdapter, I18n } from "@picgo/i18n"
import { ZH_CN, ILocalesKey, ILocales } from "./zh-CN"
import { EN } from "./en"
import { ZH_TW } from "./zh-TW"
import yaml from "js-yaml"
import _ from "lodash-es"
import { hasNodeEnv, win } from "universal-picgo-store"
import { ensureFileSync, pathExistsSync } from "../utils/nodeUtils"
import { browserPathJoin } from "../utils/browserUtils"
const languageList: IStringKeyMap<IStringKeyMap<string>> = {
"zh-CN": ZH_CN,
"zh-TW": ZH_TW,
en: EN,
}
class I18nManager implements II18nManager {
private readonly i18n: I18n
private readonly objectAdapter: ObjectAdapter
private readonly ctx: IPicGo
constructor(ctx: IPicGo) {
this.ctx = ctx
this.objectAdapter = new ObjectAdapter(languageList)
let language = this.ctx.getConfig<string>("settings.language") || "zh-CN"
if (!languageList[language]) {
language = "zh-CN" // use default
}
this.i18n = new I18n({
adapter: this.objectAdapter,
defaultLanguage: language,
})
this.loadOutterI18n()
}
translate<T extends string>(key: ILocalesKey | T, args?: IStringKeyMap<string>): string {
return this.i18n.translate(key, args) || key
}
setLanguage(language: string): void {
this.i18n.setLanguage(language)
this.ctx.saveConfig({
"settings.language": language,
})
}
addLocale(language: string, locales: ILocale): boolean {
const originLocales = this.objectAdapter.getLocale(language)
if (!originLocales) {
return false
}
const newLocales = _.merge(originLocales, locales)
this.objectAdapter.setLocale(language, newLocales)
return true
}
addLanguage(language: string, locales: ILocale): boolean {
const originLocales = this.objectAdapter.getLocale(language)
if (originLocales) {
return false
}
this.objectAdapter.setLocale(language, locales)
languageList[language] = locales
return true
}
getLanguageList(): string[] {
return Object.keys(languageList)
}
// ===================================================================================================================
private getOutterI18nFolder(): string {
let i18nFolder: string
if (hasNodeEnv) {
const fs = win.fs
const path = win.require("path")
i18nFolder = path.join(this.ctx.baseDir, "i18n-cli")
if (!pathExistsSync(fs, path, i18nFolder)) {
ensureFileSync(fs, path, i18nFolder)
}
} else {
i18nFolder = browserPathJoin(this.ctx.baseDir, "i18n-cli")
}
return i18nFolder
}
private loadOutterI18n(): void {
const i18nFolder = this.getOutterI18nFolder()
if (hasNodeEnv) {
const fs = win.fs
const path = win.require("path")
const files = fs.readdirSync(i18nFolder, {
withFileTypes: true,
})
files.forEach((file: any) => {
if (file.isFile() && file.name.endsWith(".yml")) {
const i18nFilePath = path.join(i18nFolder, file.name)
const i18nFile = fs.readFileSync(i18nFilePath, "utf8")
try {
const i18nFileObj = yaml.load(i18nFile) as ILocales
languageList[file.name.replace(/\.yml$/, "")] = i18nFileObj
} catch (e) {
console.error(e)
}
}
})
} else {
throw new Error("load outer i18n is not support in browser")
}
}
}
export { I18nManager }