-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathi18n.ts
More file actions
99 lines (83 loc) · 2.52 KB
/
Copy pathi18n.ts
File metadata and controls
99 lines (83 loc) · 2.52 KB
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
import { getLanguage } from "obsidian";
import {
BaseMessage,
SupportedLocales,
TranslationKeys,
TranslationParams,
} from "./types";
export class I18n {
private static instance: I18n;
protected currentLocale: string = "en";
protected translations: Record<string, BaseMessage> = SupportedLocales;
protected flatTranslations: Record<string, Record<string, string>> = {};
private constructor() {
const lang = getLanguage();
this.currentLocale = this.translations[lang] ? lang : "en";
this.flattenTranslations();
}
public static getInstance(): I18n {
if (!I18n.instance) {
I18n.instance = new I18n();
}
return I18n.instance;
}
private flattenTranslations() {
for (const [locale, messages] of Object.entries(this.translations)) {
this.flatTranslations[locale] = this.flattenObject(messages);
}
}
private flattenObject(obj: any, prefix = ""): Record<string, string> {
return Object.keys(obj).reduce(
(acc: Record<string, string>, k: string) => {
const pre = prefix.length ? prefix + "." : "";
if (typeof obj[k] === "object") {
Object.assign(acc, this.flattenObject(obj[k], pre + k));
} else {
acc[pre + k] = obj[k];
}
return acc;
},
{}
);
}
public t(key: TranslationKeys, params?: TranslationParams): string {
const translation = this.flatTranslations[this.currentLocale][key];
if (!translation) {
console.warn(`Translation key not found: ${key}`);
return key;
}
if (!params) {
return translation;
}
// 只处理命名变量参数
return translation.replace(/\{\{([^}]+)\}\}/g, (match, name) => {
return params[name] !== undefined ? String(params[name]) : match;
});
}
public setLocale(locale: string): void {
if (this.translations[locale]) {
this.currentLocale = locale;
window.localStorage.setItem("language", locale);
} else {
console.warn(`Locale not found: ${locale}, falling back to 'en'`);
this.currentLocale = "en";
window.localStorage.setItem("language", "en");
}
}
public getLocale(): string {
return this.currentLocale;
}
public hasTranslation(key: TranslationKeys): boolean {
return !!this.flatTranslations[this.currentLocale][key];
}
public isChineseLocale(): boolean {
return this.currentLocale.toLowerCase().startsWith("zh");
}
}
// 导出默认实例
export const i18n = I18n.getInstance();
// 导出便捷的翻译函数
export const t = (key: TranslationKeys, params?: TranslationParams): string => {
return i18n.t(key, params);
};
export const isChineseLocale = (): boolean => i18n.isChineseLocale();