@awsless/i18n 0.0.17 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +30 -29
- package/dist/index.js +204 -280
- package/dist/svelte-5.svelte.d.ts +19 -18
- package/dist/svelte-5.svelte.js +39 -40
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { LanguageModel } from "ai";
|
|
2
|
+
import { Plugin } from "vite";
|
|
3
|
+
//#region src/vite.d.ts
|
|
4
4
|
type Translator = (defaultLocale: string, list: {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
source: string;
|
|
6
|
+
locale: string;
|
|
7
7
|
}[]) => TranslationResponse[] | Promise<TranslationResponse[]>;
|
|
8
8
|
type TranslationResponse = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
source: string;
|
|
10
|
+
locale: string;
|
|
11
|
+
translation: string;
|
|
12
12
|
};
|
|
13
13
|
type I18nPluginProps = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
/** The original language your source text is written in.
|
|
15
|
+
* @default "en"
|
|
16
|
+
*/
|
|
17
|
+
default?: string;
|
|
18
|
+
/** The list of target locales to translate your text into. */
|
|
19
|
+
locales: string[];
|
|
20
|
+
/** Function that performs the translation of a given text. */
|
|
21
|
+
translate: Translator;
|
|
22
22
|
};
|
|
23
23
|
declare const i18n: (props: I18nPluginProps) => Plugin;
|
|
24
|
-
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/translate/ai.d.ts
|
|
25
26
|
type AiTranslationProps = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
/** The maximum number of output tokens allowed in the AI's response. */
|
|
28
|
+
maxOutputTokens: number;
|
|
29
|
+
/** The language model to use for translations (e.g., gpt-4, gpt-3.5-turbo). */
|
|
30
|
+
model: LanguageModel;
|
|
31
|
+
/** Number of text entries to translate in a single batch.
|
|
32
|
+
* @default 1000
|
|
33
|
+
*/
|
|
34
|
+
batchSize?: number;
|
|
35
|
+
/** Custom translation guidelines for the AI. These are injected into the prompt. */
|
|
36
|
+
rules?: string[];
|
|
36
37
|
};
|
|
37
38
|
declare const ai: (props: AiTranslationProps) => Translator;
|
|
38
|
-
|
|
39
|
-
export { type AiTranslationProps, type I18nPluginProps, type Translator, ai, i18n };
|
|
39
|
+
//#endregion
|
|
40
|
+
export { type AiTranslationProps, type I18nPluginProps, type Translator, ai, i18n };
|
package/dist/index.js
CHANGED
|
@@ -1,299 +1,223 @@
|
|
|
1
|
-
// src/vite.ts
|
|
2
1
|
import MagicString from "magic-string";
|
|
3
|
-
|
|
4
|
-
// src/cache.ts
|
|
5
2
|
import { readFile, stat, writeFile } from "fs/promises";
|
|
6
3
|
import { join } from "path";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
4
|
+
import { glob } from "glob";
|
|
5
|
+
import { walk } from "estree-walker";
|
|
6
|
+
import lineColumn from "line-column";
|
|
7
|
+
import { parse } from "svelte/compiler";
|
|
8
|
+
import { parse as parse$1 } from "@swc/core";
|
|
9
|
+
import { simple } from "swc-walk";
|
|
10
|
+
import { BaseVisitor } from "swc-walk/baseVisitor";
|
|
11
|
+
import { generateObject } from "ai";
|
|
12
|
+
import chunk from "chunk";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
//#region src/cache.ts
|
|
15
|
+
const GENERATED_CACHE_FILE = "i18n.generated.json";
|
|
16
|
+
const OVERRIDE_CACHE_FILE = "i18n.json";
|
|
17
|
+
const loadFile = async (cwd, fileName) => {
|
|
18
|
+
const file = join(cwd, fileName);
|
|
19
|
+
try {
|
|
20
|
+
await stat(file);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return new Cache();
|
|
23
|
+
}
|
|
24
|
+
const data = await readFile(file, "utf8");
|
|
25
|
+
return new Cache(JSON.parse(data));
|
|
18
26
|
};
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
const loadGeneratedCache = async (cwd) => {
|
|
28
|
+
return loadFile(cwd, GENERATED_CACHE_FILE);
|
|
21
29
|
};
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
const loadOverrideCache = async (cwd) => {
|
|
31
|
+
return loadFile(cwd, OVERRIDE_CACHE_FILE);
|
|
24
32
|
};
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
const saveCache = async (cwd, cache) => {
|
|
34
|
+
await writeFile(join(cwd, GENERATED_CACHE_FILE), JSON.stringify(cache.toJSON(), void 0, " ") + "\n");
|
|
27
35
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
merged.replace(item.source, item.locale, item.translation);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return merged;
|
|
36
|
+
const mergeCaches = (...caches) => {
|
|
37
|
+
const merged = new Cache();
|
|
38
|
+
for (const cache of caches) for (const item of cache.entries()) merged.replace(item.source, item.locale, item.translation);
|
|
39
|
+
return merged;
|
|
36
40
|
};
|
|
37
41
|
var Cache = class {
|
|
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
|
-
for (const [locale, translation] of Object.entries(locales)) {
|
|
73
|
-
yield { source, locale, translation };
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
toJSON() {
|
|
78
|
-
return Object.fromEntries(
|
|
79
|
-
Object.entries(this.data).sort(([left], [right]) => left.localeCompare(right)).map(([source, locales]) => {
|
|
80
|
-
return [
|
|
81
|
-
source,
|
|
82
|
-
Object.fromEntries(
|
|
83
|
-
Object.entries(locales).sort(([left], [right]) => left.localeCompare(right))
|
|
84
|
-
)
|
|
85
|
-
];
|
|
86
|
-
})
|
|
87
|
-
);
|
|
88
|
-
}
|
|
42
|
+
data;
|
|
43
|
+
constructor(data = {}) {
|
|
44
|
+
this.data = data;
|
|
45
|
+
}
|
|
46
|
+
set(source, locale, translation) {
|
|
47
|
+
if (!this.data[source]) this.data[source] = {};
|
|
48
|
+
if (typeof this.data[source][locale] === "undefined") this.data[source][locale] = translation;
|
|
49
|
+
}
|
|
50
|
+
replace(source, locale, translation) {
|
|
51
|
+
if (!this.data[source]) this.data[source] = {};
|
|
52
|
+
this.data[source][locale] = translation;
|
|
53
|
+
}
|
|
54
|
+
get(source, locale) {
|
|
55
|
+
return this.data[source]?.[locale];
|
|
56
|
+
}
|
|
57
|
+
has(source, locale) {
|
|
58
|
+
return typeof this.get(source, locale) === "string";
|
|
59
|
+
}
|
|
60
|
+
delete(source, locale) {
|
|
61
|
+
if (typeof this.data[source]?.[locale] !== "undefined") delete this.data[source][locale];
|
|
62
|
+
if (this.data[source] && Object.keys(this.data[source]).length === 0) delete this.data[source];
|
|
63
|
+
}
|
|
64
|
+
*entries() {
|
|
65
|
+
for (const [source, locales] of Object.entries(this.data)) for (const [locale, translation] of Object.entries(locales)) yield {
|
|
66
|
+
source,
|
|
67
|
+
locale,
|
|
68
|
+
translation
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
toJSON() {
|
|
72
|
+
return Object.fromEntries(Object.entries(this.data).sort(([left], [right]) => left.localeCompare(right)).map(([source, locales]) => {
|
|
73
|
+
return [source, Object.fromEntries(Object.entries(locales).sort(([left], [right]) => left.localeCompare(right)))];
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
89
76
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return list;
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/diff.ts
|
|
79
|
+
const findNewTranslations = (cache, sources, locales) => {
|
|
80
|
+
const list = [];
|
|
81
|
+
for (const source of sources) for (const locale of locales) if (!cache.has(source, locale)) list.push({
|
|
82
|
+
source,
|
|
83
|
+
locale
|
|
84
|
+
});
|
|
85
|
+
return list;
|
|
102
86
|
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (!locales.includes(item.locale) || !sources.includes(item.source)) {
|
|
106
|
-
cache.delete(item.source, item.locale);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
87
|
+
const removeUnusedTranslations = (cache, sources, locales) => {
|
|
88
|
+
for (const item of cache.entries()) if (!locales.includes(item.locale) || !sources.includes(item.source)) cache.delete(item.source, item.locale);
|
|
109
89
|
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const start = node.quasi.loc.start;
|
|
129
|
-
const end = node.quasi.loc.end;
|
|
130
|
-
const content = code.substring(
|
|
131
|
-
origin.toIndex(start.line, start.column) + 2,
|
|
132
|
-
origin.toIndex(end.line, end.column)
|
|
133
|
-
);
|
|
134
|
-
found.push(content);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
walk(ast.html, { enter });
|
|
138
|
-
if (ast.instance) {
|
|
139
|
-
walk(ast.instance.content, { enter });
|
|
140
|
-
}
|
|
141
|
-
if (ast.module) {
|
|
142
|
-
walk(ast.module.content, { enter });
|
|
143
|
-
}
|
|
144
|
-
return found;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/find/svelte.ts
|
|
92
|
+
const findSvelteTranslatable = (code) => {
|
|
93
|
+
const found = [];
|
|
94
|
+
const origin = lineColumn(code);
|
|
95
|
+
const ast = parse(code);
|
|
96
|
+
const enter = (node) => {
|
|
97
|
+
if (node.type === "TaggedTemplateExpression" && node.tag.type === "MemberExpression" && node.tag.object.type === "Identifier" && node.tag.object.name === "lang" && node.tag.property.type === "Identifier" && node.tag.property.name === "t" && node.quasi.type === "TemplateLiteral" && node.quasi.loc) {
|
|
98
|
+
const start = node.quasi.loc.start;
|
|
99
|
+
const end = node.quasi.loc.end;
|
|
100
|
+
const content = code.substring(origin.toIndex(start.line, start.column) + 2, origin.toIndex(end.line, end.column));
|
|
101
|
+
found.push(content);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
walk(ast.html, { enter });
|
|
105
|
+
if (ast.instance) walk(ast.instance.content, { enter });
|
|
106
|
+
if (ast.module) walk(ast.module.content, { enter });
|
|
107
|
+
return found;
|
|
145
108
|
};
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
import { parse } from "@swc/core";
|
|
149
|
-
import { simple } from "swc-walk";
|
|
150
|
-
import { BaseVisitor } from "swc-walk/baseVisitor";
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/find/typescript.ts
|
|
151
111
|
var PatchedBaseVisitor = class extends BaseVisitor {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
}
|
|
112
|
+
FunctionBody(node, state, callback) {
|
|
113
|
+
for (const statement of node.stmts) callback(statement, state);
|
|
114
|
+
}
|
|
157
115
|
};
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
node.template.span.end - ast.span.start - 1
|
|
171
|
-
).toString("utf8");
|
|
172
|
-
found.push(content);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
baseVisitor
|
|
177
|
-
);
|
|
178
|
-
return found;
|
|
116
|
+
const baseVisitor = new PatchedBaseVisitor();
|
|
117
|
+
const findTypescriptTranslatable = async (code) => {
|
|
118
|
+
const found = [];
|
|
119
|
+
const ast = await parse$1(code, { syntax: "typescript" });
|
|
120
|
+
const bytes = Buffer.from(code, "utf8");
|
|
121
|
+
simple(ast, { TaggedTemplateExpression(node) {
|
|
122
|
+
if (node.tag.type === "MemberExpression" && node.tag.object.type === "Identifier" && node.tag.object.value === "lang" && node.tag.property.type === "Identifier" && node.tag.property.value === "t") {
|
|
123
|
+
const content = bytes.subarray(node.template.span.start - ast.span.start + 1, node.template.span.end - ast.span.start - 1).toString("utf8");
|
|
124
|
+
found.push(content);
|
|
125
|
+
}
|
|
126
|
+
} }, baseVisitor);
|
|
127
|
+
return found;
|
|
179
128
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
return found;
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/find.ts
|
|
131
|
+
const findTranslatable = async (cwd) => {
|
|
132
|
+
const files = await glob("**/*.{js,ts,svelte}", {
|
|
133
|
+
cwd,
|
|
134
|
+
ignore: [
|
|
135
|
+
"**/node_modules/**",
|
|
136
|
+
"**/.svelte-kit/**",
|
|
137
|
+
"**/.*/**"
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
const found = [];
|
|
141
|
+
for (const file of files) {
|
|
142
|
+
const code = await readFile(join(cwd, file), "utf8");
|
|
143
|
+
if (code.includes("lang.t`")) {
|
|
144
|
+
if (file.endsWith(".svelte")) found.push(...findSvelteTranslatable(code));
|
|
145
|
+
else {
|
|
146
|
+
const entries = await findTypescriptTranslatable(code);
|
|
147
|
+
found.push(...entries);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return found;
|
|
205
152
|
};
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
return {
|
|
251
|
-
code: transformedCode.toString(),
|
|
252
|
-
map: transformedCode.generateMap({
|
|
253
|
-
hires: true
|
|
254
|
-
})
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// src/translate/ai.ts
|
|
263
|
-
import { generateObject } from "ai";
|
|
264
|
-
import chunk from "chunk";
|
|
265
|
-
import { z } from "zod";
|
|
266
|
-
var ai = (props) => {
|
|
267
|
-
return async (originalLocale, texts) => {
|
|
268
|
-
const batches = chunk(texts, props.batchSize ?? 1e3);
|
|
269
|
-
const translations = await Promise.all(
|
|
270
|
-
batches.map(async (texts2) => {
|
|
271
|
-
const result = await generateObject({
|
|
272
|
-
model: props.model,
|
|
273
|
-
maxOutputTokens: props.maxOutputTokens,
|
|
274
|
-
schema: z.object({
|
|
275
|
-
translations: z.object({
|
|
276
|
-
source: z.string(),
|
|
277
|
-
locale: z.string(),
|
|
278
|
-
translation: z.string()
|
|
279
|
-
}).array()
|
|
280
|
-
}),
|
|
281
|
-
prompt: [
|
|
282
|
-
`You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.`,
|
|
283
|
-
...props?.rules ?? [],
|
|
284
|
-
"",
|
|
285
|
-
`JSON FILE:`,
|
|
286
|
-
JSON.stringify(texts2)
|
|
287
|
-
].join("\n"),
|
|
288
|
-
system: "You are a helpful translator."
|
|
289
|
-
});
|
|
290
|
-
return result.object.translations;
|
|
291
|
-
})
|
|
292
|
-
);
|
|
293
|
-
return translations.flat(3);
|
|
294
|
-
};
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/vite.ts
|
|
155
|
+
const i18n = (props) => {
|
|
156
|
+
let cache;
|
|
157
|
+
let generatedCache;
|
|
158
|
+
return {
|
|
159
|
+
name: "awsless/i18n",
|
|
160
|
+
enforce: "pre",
|
|
161
|
+
async buildStart() {
|
|
162
|
+
const cwd = process.cwd();
|
|
163
|
+
this.info("Finding all translatable text...");
|
|
164
|
+
const sourceTexts = await findTranslatable(cwd);
|
|
165
|
+
generatedCache = await loadGeneratedCache(cwd);
|
|
166
|
+
const overrideCache = await loadOverrideCache(cwd);
|
|
167
|
+
removeUnusedTranslations(generatedCache, sourceTexts, props.locales);
|
|
168
|
+
cache = mergeCaches(generatedCache, overrideCache);
|
|
169
|
+
const newSourceTexts = findNewTranslations(cache, sourceTexts, props.locales);
|
|
170
|
+
if (newSourceTexts.length > 0) {
|
|
171
|
+
this.info(`Translating ${newSourceTexts.length} new texts.`);
|
|
172
|
+
const translations = await props.translate(props.default ?? "en", newSourceTexts);
|
|
173
|
+
this.info(`Translated ${translations.length} texts.`);
|
|
174
|
+
for (const item of translations) generatedCache.set(item.source, item.locale, item.translation);
|
|
175
|
+
}
|
|
176
|
+
cache = mergeCaches(generatedCache, overrideCache);
|
|
177
|
+
await saveCache(cwd, generatedCache);
|
|
178
|
+
this.info(`Translating done.`);
|
|
179
|
+
},
|
|
180
|
+
transform(code) {
|
|
181
|
+
if (code.includes("lang.t`")) {
|
|
182
|
+
const transformedCode = new MagicString(code);
|
|
183
|
+
for (const item of cache.entries()) transformedCode.replaceAll(`lang.t\`${item.source}\``, `lang.t.get(\`${item.source}\`, {${props.locales.map((locale) => {
|
|
184
|
+
const translation = cache.get(item.source, locale);
|
|
185
|
+
if (translation === item.source) return;
|
|
186
|
+
return `"${locale}":\`${translation}\``;
|
|
187
|
+
}).filter((v) => !!v).join(",")}})`);
|
|
188
|
+
return {
|
|
189
|
+
code: transformedCode.toString(),
|
|
190
|
+
map: transformedCode.generateMap({ hires: true })
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
295
195
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/translate/ai.ts
|
|
198
|
+
const ai = (props) => {
|
|
199
|
+
return async (originalLocale, texts) => {
|
|
200
|
+
const batches = chunk(texts, props.batchSize ?? 1e3);
|
|
201
|
+
return (await Promise.all(batches.map(async (texts) => {
|
|
202
|
+
return (await generateObject({
|
|
203
|
+
model: props.model,
|
|
204
|
+
maxOutputTokens: props.maxOutputTokens,
|
|
205
|
+
schema: z.object({ translations: z.object({
|
|
206
|
+
source: z.string(),
|
|
207
|
+
locale: z.string(),
|
|
208
|
+
translation: z.string()
|
|
209
|
+
}).array() }),
|
|
210
|
+
prompt: [
|
|
211
|
+
`You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.`,
|
|
212
|
+
...props?.rules ?? [],
|
|
213
|
+
"",
|
|
214
|
+
`JSON FILE:`,
|
|
215
|
+
JSON.stringify(texts)
|
|
216
|
+
].join("\n"),
|
|
217
|
+
system: "You are a helpful translator."
|
|
218
|
+
})).object.translations;
|
|
219
|
+
}))).flat(3);
|
|
220
|
+
};
|
|
299
221
|
};
|
|
222
|
+
//#endregion
|
|
223
|
+
export { ai, i18n };
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
+
//#region src/framework/svelte-5.svelte.d.ts
|
|
1
2
|
type StringArgs = Array<string | number | {
|
|
2
|
-
|
|
3
|
+
toString(): string;
|
|
3
4
|
}>;
|
|
4
5
|
type Translate = {
|
|
5
|
-
|
|
6
|
+
(template: TemplateStringsArray, ...args: StringArgs): string;
|
|
6
7
|
};
|
|
7
8
|
declare const lang: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
/** Get the current locale.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* console.log(lang.locale)
|
|
13
|
+
*/
|
|
14
|
+
locale: string;
|
|
15
|
+
/** Translate helper for translating template strings.
|
|
16
|
+
* The i18n Vite plugin will find all instances where you want text
|
|
17
|
+
* to be translated and automatically translate your text during build time.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* lang.t`Hello world!`
|
|
21
|
+
*/
|
|
22
|
+
readonly t: Translate;
|
|
22
23
|
};
|
|
23
|
-
|
|
24
|
-
export { lang };
|
|
24
|
+
//#endregion
|
|
25
|
+
export { lang };
|
package/dist/svelte-5.svelte.js
CHANGED
|
@@ -1,42 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
//#region src/framework/svelte-5.svelte.ts
|
|
2
|
+
let locale = $state("en");
|
|
3
|
+
let t = $derived.by(() => {
|
|
4
|
+
const api = (template, ...args) => {
|
|
5
|
+
return String.raw({ raw: template.raw }, ...args);
|
|
6
|
+
};
|
|
7
|
+
api.get = (og, translations) => {
|
|
8
|
+
return translations[locale] ?? og;
|
|
9
|
+
};
|
|
10
|
+
return api;
|
|
11
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
|
-
export {
|
|
41
|
-
lang
|
|
12
|
+
const lang = {
|
|
13
|
+
/** Get the current locale.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* console.log(lang.locale)
|
|
17
|
+
*/
|
|
18
|
+
get locale() {
|
|
19
|
+
return locale;
|
|
20
|
+
},
|
|
21
|
+
/** To change the locale that is being rendered simply change this property.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* lang.locale = 'jp'
|
|
25
|
+
*/
|
|
26
|
+
set locale(v) {
|
|
27
|
+
locale = v;
|
|
28
|
+
},
|
|
29
|
+
/** Translate helper for translating template strings.
|
|
30
|
+
* The i18n Vite plugin will find all instances where you want text
|
|
31
|
+
* to be translated and automatically translate your text during build time.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* lang.t`Hello world!`
|
|
35
|
+
*/
|
|
36
|
+
get t() {
|
|
37
|
+
return t;
|
|
38
|
+
}
|
|
42
39
|
};
|
|
40
|
+
//#endregion
|
|
41
|
+
export { lang };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awsless/i18n",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"test": "pnpm code test",
|
|
68
|
-
"build": "pnpm
|
|
69
|
-
"build-svelte": "pnpm
|
|
68
|
+
"build": "pnpm tsdown --no-fixed-extension src/index.ts --format esm --dts --clean",
|
|
69
|
+
"build-svelte": "pnpm tsdown --no-fixed-extension --no-clean src/framework/svelte-5.svelte.ts --format esm --dts",
|
|
70
70
|
"prepublish": "if pnpm test; then pnpm build; pnpm build-svelte; else exit; fi"
|
|
71
71
|
}
|
|
72
72
|
}
|