This repository has been archived by the owner on Mar 19, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
104 lines (82 loc) · 3.35 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
import { FluentBundle, FluentResource } from "@fluent/bundle";
interface L10nArgs {
availableLocales: string[],
defaultLocale: string,
localesDirectory?: string,
filter: (...args: any[]) => string
}
export class L10n {
public languages: { [key: string]: FluentBundle } = {};
public defaultLocale: string = "";
public filter: (...args: any[]) => string;
public format(id: string, ctx?: Record<string, any>) {
const language = this.filter();
let bundle = this.languages[language];
// Check if the bundle exists first, if it doesn't just fallback to the default language.
if(!bundle) bundle = this.languages[this.defaultLocale];
// Last resort, just return the ID of the string.
if(!bundle) return id;
const raw = bundle.getMessage(id);
if(raw && raw.value) {
const formatted = bundle.formatPattern(
raw.value,
ctx
);
return formatted;
} else {
throw new Error(`L10n string with id ${id} not found in ${language}.`)
}
}
private async load(args: L10nArgs) {
return new Promise(async (res) => {
if((this as any).loader) {
const data = await (this as any).loader({
locales: args.availableLocales,
defaultLocale: args.defaultLocale,
localesDirectory: args.localesDirectory
})
res(data);
} else {
const { existsSync, readFileSync } = await import("fs");
const { resolve } = await import("path");
let data: any = {};
for await (const locale of args.availableLocales) {
const path = resolve(args.localesDirectory || __dirname, `${locale}.ftl`);
if(existsSync(path)) {
const ftl = readFileSync(
path,
{ encoding: "utf-8" }
);
data[locale] = ftl;
}
}
res(data);
}
})
}
constructor(args: L10nArgs) {
if(!args.availableLocales || !args.availableLocales.length) throw new Error(`You need some locales in availableLocales.`);
if(!args.availableLocales.includes(args.defaultLocale)) throw new Error("Default locale isn't in available locales.");
if(!args.filter) throw new Error(`No filter was set.`);
this.filter = args.filter;
this.defaultLocale = args.defaultLocale;
this.load({ ...args }).then((data: any) => {
for(const [key, value] of Object.entries(data)) {
try {
const resource = new FluentResource(`${value}`);
const bundle = new FluentBundle(key);
const errors = bundle.addResource(resource);
if(errors.length) {
errors.forEach(error => {
throw error;
})
}
this.languages[key] = bundle;
} catch(e: any) {
throw new Error(`Failed to load ${key}: ${e.message}`)
}
}
})
}
}
export default L10n;