@awsless/i18n 0.0.5 → 0.0.7
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/README.MD +4 -0
- package/dist/index.cjs +82 -104
- package/dist/index.d.cts +11 -12
- package/dist/index.d.ts +11 -12
- package/dist/index.js +78 -100
- package/dist/{svelte.cjs → svelte.svelte.cjs} +20 -12
- package/dist/svelte.svelte.d.cts +8 -0
- package/dist/svelte.svelte.d.ts +8 -0
- package/dist/svelte.svelte.js +25 -0
- package/package.json +9 -6
- package/dist/svelte.d.cts +0 -9
- package/dist/svelte.d.ts +0 -9
- package/dist/svelte.js +0 -16
package/README.MD
CHANGED
|
@@ -9,6 +9,10 @@ The `@awsless/i18n` package is a Vite plugin that automatically translates your
|
|
|
9
9
|
- Extremely lightweight (373 bytes uncompressed 🔥)
|
|
10
10
|
- Svelte support
|
|
11
11
|
|
|
12
|
+
## Todo's
|
|
13
|
+
|
|
14
|
+
- Create a CLI command to find the text that needs to be translated & translate it, so that we can remove that part from the vite plugin.
|
|
15
|
+
|
|
12
16
|
## Setup
|
|
13
17
|
|
|
14
18
|
Install with (NPM):
|
package/dist/index.cjs
CHANGED
|
@@ -28,13 +28,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
33
|
-
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
ai: () => ai,
|
|
34
34
|
i18n: () => createI18nPlugin,
|
|
35
35
|
mock: () => mock
|
|
36
36
|
});
|
|
37
|
-
module.exports = __toCommonJS(
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
|
|
39
39
|
// src/cache.ts
|
|
40
40
|
var import_promises = require("fs/promises");
|
|
@@ -128,7 +128,7 @@ var findSvelteTranslatable = (code) => {
|
|
|
128
128
|
const enter = (node) => {
|
|
129
129
|
if (
|
|
130
130
|
//
|
|
131
|
-
node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && node.tag.name === "
|
|
131
|
+
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
|
|
132
132
|
) {
|
|
133
133
|
const start = node.quasi.loc.start;
|
|
134
134
|
const end = node.quasi.loc.end;
|
|
@@ -159,7 +159,7 @@ var findTypescriptTranslatable = async (code) => {
|
|
|
159
159
|
});
|
|
160
160
|
(0, import_swc_walk.simple)(ast, {
|
|
161
161
|
TaggedTemplateExpression(node) {
|
|
162
|
-
if (node.tag.type === "
|
|
162
|
+
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") {
|
|
163
163
|
const content = code.substring(
|
|
164
164
|
node.template.span.start - ast.span.start + 1,
|
|
165
165
|
node.template.span.end - ast.span.start - 1
|
|
@@ -185,14 +185,13 @@ var findTranslatable = async (cwd) => {
|
|
|
185
185
|
const found = [];
|
|
186
186
|
for (const file of files) {
|
|
187
187
|
const code = await (0, import_promises2.readFile)((0, import_path2.join)(cwd, file), "utf8");
|
|
188
|
-
if (code.includes("
|
|
189
|
-
if (
|
|
188
|
+
if (code.includes("lang.t`")) {
|
|
189
|
+
if (file.endsWith(".svelte")) {
|
|
190
190
|
found.push(...findSvelteTranslatable(code));
|
|
191
|
+
} else {
|
|
192
|
+
found.push(...await findTypescriptTranslatable(code));
|
|
191
193
|
}
|
|
192
194
|
}
|
|
193
|
-
if (code.includes("get(t)`")) {
|
|
194
|
-
found.push(...await findTypescriptTranslatable(code));
|
|
195
|
-
}
|
|
196
195
|
}
|
|
197
196
|
return found;
|
|
198
197
|
};
|
|
@@ -200,117 +199,96 @@ var findTranslatable = async (cwd) => {
|
|
|
200
199
|
// src/vite.ts
|
|
201
200
|
var createI18nPlugin = (props) => {
|
|
202
201
|
let cache;
|
|
203
|
-
return
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
await saveCache(cwd, cache);
|
|
220
|
-
},
|
|
221
|
-
transform(code) {
|
|
222
|
-
let replaced = false;
|
|
223
|
-
if (code.includes(`$t\``)) {
|
|
224
|
-
for (const item of cache.entries()) {
|
|
225
|
-
code = code.replaceAll(`$t\`${item.original}\``, () => {
|
|
226
|
-
replaced = true;
|
|
227
|
-
return `$t.get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
228
|
-
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
229
|
-
}).join(",")}})`;
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (code.includes(`get(t)\``)) {
|
|
234
|
-
for (const item of cache.entries()) {
|
|
235
|
-
code = code.replaceAll(`get(t)\`${item.original}\``, () => {
|
|
236
|
-
replaced = true;
|
|
237
|
-
return `get(t).get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
238
|
-
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
239
|
-
}).join(",")}})`;
|
|
240
|
-
});
|
|
241
|
-
}
|
|
202
|
+
return {
|
|
203
|
+
name: "awsless/i18n",
|
|
204
|
+
enforce: "pre",
|
|
205
|
+
async buildStart() {
|
|
206
|
+
const cwd = process.cwd();
|
|
207
|
+
this.info("Finding all translatable text...");
|
|
208
|
+
const originals = await findTranslatable(cwd);
|
|
209
|
+
cache = await loadCache(cwd);
|
|
210
|
+
removeUnusedTranslations(cache, originals, props.locales);
|
|
211
|
+
const newOriginals = findNewTranslations(cache, originals, props.locales);
|
|
212
|
+
if (newOriginals.length > 0) {
|
|
213
|
+
this.info(`Translating ${newOriginals.length} new texts.`);
|
|
214
|
+
const translations = await props.translate(props.default ?? "en", newOriginals);
|
|
215
|
+
for (const item of translations) {
|
|
216
|
+
cache.set(item.original, item.locale, item.translation);
|
|
242
217
|
}
|
|
243
|
-
|
|
244
|
-
|
|
218
|
+
}
|
|
219
|
+
await saveCache(cwd, cache);
|
|
220
|
+
this.info(`Translating done.`);
|
|
221
|
+
},
|
|
222
|
+
transform(code) {
|
|
223
|
+
let replaced = false;
|
|
224
|
+
if (code.includes("lang.t`")) {
|
|
225
|
+
for (const item of cache.entries()) {
|
|
226
|
+
code = code.replaceAll(`lang.t\`${item.original}\``, () => {
|
|
227
|
+
replaced = true;
|
|
228
|
+
return `lang.t.get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
229
|
+
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
230
|
+
}).join(",")}})`;
|
|
231
|
+
});
|
|
245
232
|
}
|
|
246
|
-
return {
|
|
247
|
-
code
|
|
248
|
-
};
|
|
249
233
|
}
|
|
234
|
+
if (!replaced) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
code
|
|
239
|
+
};
|
|
250
240
|
}
|
|
251
|
-
];
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
// src/translate/chat-gpt.ts
|
|
255
|
-
var import_openai = __toESM(require("openai"), 1);
|
|
256
|
-
var import_zod = require("openai/helpers/zod");
|
|
257
|
-
var import_zod2 = require("zod");
|
|
258
|
-
var chatgpt = (props) => {
|
|
259
|
-
const format = (0, import_zod.zodResponseFormat)(
|
|
260
|
-
import_zod2.z.object({
|
|
261
|
-
translations: import_zod2.z.object({
|
|
262
|
-
original: import_zod2.z.string(),
|
|
263
|
-
locale: import_zod2.z.string(),
|
|
264
|
-
translation: import_zod2.z.string()
|
|
265
|
-
}).array()
|
|
266
|
-
}),
|
|
267
|
-
"final_schema"
|
|
268
|
-
);
|
|
269
|
-
return async (originalLocale, list) => {
|
|
270
|
-
const client = new import_openai.default(props);
|
|
271
|
-
const response = await client.chat.completions.create({
|
|
272
|
-
model: props?.model ?? "gpt-4o-2024-08-06",
|
|
273
|
-
max_tokens: props?.maxTokens ?? 4095,
|
|
274
|
-
response_format: format,
|
|
275
|
-
messages: [
|
|
276
|
-
{ role: "system", content: "You are a helpful translator." },
|
|
277
|
-
{ role: "user", content: prompt(originalLocale, list, props?.rules) }
|
|
278
|
-
]
|
|
279
|
-
});
|
|
280
|
-
const json = response.choices[0]?.message.content;
|
|
281
|
-
if (typeof json !== "string") {
|
|
282
|
-
throw new Error("Invalid chat gpt response");
|
|
283
|
-
}
|
|
284
|
-
let data;
|
|
285
|
-
try {
|
|
286
|
-
data = JSON.parse(json);
|
|
287
|
-
} catch (error) {
|
|
288
|
-
throw new Error(`Invalid chat gpt json response: ${json}`);
|
|
289
|
-
}
|
|
290
|
-
return data.translations;
|
|
291
241
|
};
|
|
292
242
|
};
|
|
293
|
-
var prompt = (originalLocale, list, rules) => {
|
|
294
|
-
return `You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.
|
|
295
|
-
${rules?.join("\n") ?? ""}
|
|
296
243
|
|
|
297
|
-
|
|
298
|
-
|
|
244
|
+
// src/translate/ai.ts
|
|
245
|
+
var import_ai = require("ai");
|
|
246
|
+
var import_chunk = __toESM(require("chunk"), 1);
|
|
247
|
+
var import_zod = require("zod");
|
|
248
|
+
var ai = (props) => {
|
|
249
|
+
return async (originalLocale, texts) => {
|
|
250
|
+
const batches = (0, import_chunk.default)(texts, props.batchSize ?? 1e3);
|
|
251
|
+
const translations = await Promise.all(
|
|
252
|
+
batches.map(async (texts2) => {
|
|
253
|
+
const result = await (0, import_ai.generateObject)({
|
|
254
|
+
model: props.model,
|
|
255
|
+
maxTokens: props.maxTokens,
|
|
256
|
+
schema: import_zod.z.object({
|
|
257
|
+
translations: import_zod.z.object({
|
|
258
|
+
original: import_zod.z.string(),
|
|
259
|
+
locale: import_zod.z.string(),
|
|
260
|
+
translation: import_zod.z.string()
|
|
261
|
+
}).array()
|
|
262
|
+
}),
|
|
263
|
+
prompt: [
|
|
264
|
+
`You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.`,
|
|
265
|
+
...props?.rules ?? [],
|
|
266
|
+
"",
|
|
267
|
+
`JSON FILE:`,
|
|
268
|
+
JSON.stringify(texts2)
|
|
269
|
+
].join("\n"),
|
|
270
|
+
system: "You are a helpful translator."
|
|
271
|
+
});
|
|
272
|
+
return result.object.translations;
|
|
273
|
+
})
|
|
274
|
+
);
|
|
275
|
+
return translations.flat(3);
|
|
276
|
+
};
|
|
299
277
|
};
|
|
300
278
|
|
|
301
279
|
// src/translate/mock.ts
|
|
302
280
|
var mock = (translation = "REPLACED") => {
|
|
303
|
-
return (_,
|
|
281
|
+
return (_, originals) => {
|
|
304
282
|
const response = [];
|
|
305
|
-
for (const
|
|
306
|
-
response.push({ ...
|
|
283
|
+
for (const original of originals) {
|
|
284
|
+
response.push({ ...original, translation });
|
|
307
285
|
}
|
|
308
286
|
return response;
|
|
309
287
|
};
|
|
310
288
|
};
|
|
311
289
|
// Annotate the CommonJS export names for ESM import in node:
|
|
312
290
|
0 && (module.exports = {
|
|
313
|
-
|
|
291
|
+
ai,
|
|
314
292
|
i18n,
|
|
315
293
|
mock
|
|
316
294
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
-
import {
|
|
2
|
+
import { LanguageModel } from 'ai';
|
|
3
3
|
|
|
4
4
|
type Translator = (defaultLocale: string, list: {
|
|
5
5
|
original: string;
|
|
@@ -16,23 +16,22 @@ type I18nPluginProps = {
|
|
|
16
16
|
/** A list of locales that you want your text translated too. */
|
|
17
17
|
locales: string[];
|
|
18
18
|
/** The callback that is responsible for translating the text. */
|
|
19
|
-
translate:
|
|
20
|
-
original: string;
|
|
21
|
-
locale: string;
|
|
22
|
-
}[]) => TranslationResponse[] | Promise<TranslationResponse[]>;
|
|
19
|
+
translate: Translator;
|
|
23
20
|
};
|
|
24
|
-
declare const createI18nPlugin: (props: I18nPluginProps) => Plugin
|
|
21
|
+
declare const createI18nPlugin: (props: I18nPluginProps) => Plugin;
|
|
25
22
|
|
|
26
|
-
type
|
|
23
|
+
type AiTranslationProps = {
|
|
27
24
|
/** The maximum number of tokens that can be generated in the chat completion. */
|
|
28
|
-
maxTokens
|
|
25
|
+
maxTokens: number;
|
|
29
26
|
/** ID of the model to use. */
|
|
30
|
-
model
|
|
31
|
-
/**
|
|
27
|
+
model: LanguageModel;
|
|
28
|
+
/** */
|
|
29
|
+
batchSize?: number;
|
|
30
|
+
/** The rules that the ai should follow. It will be added to the prompt. */
|
|
32
31
|
rules?: string[];
|
|
33
32
|
};
|
|
34
|
-
declare const
|
|
33
|
+
declare const ai: (props: AiTranslationProps) => Translator;
|
|
35
34
|
|
|
36
35
|
declare const mock: (translation?: string) => Translator;
|
|
37
36
|
|
|
38
|
-
export {
|
|
37
|
+
export { ai, createI18nPlugin as i18n, mock };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
-
import {
|
|
2
|
+
import { LanguageModel } from 'ai';
|
|
3
3
|
|
|
4
4
|
type Translator = (defaultLocale: string, list: {
|
|
5
5
|
original: string;
|
|
@@ -16,23 +16,22 @@ type I18nPluginProps = {
|
|
|
16
16
|
/** A list of locales that you want your text translated too. */
|
|
17
17
|
locales: string[];
|
|
18
18
|
/** The callback that is responsible for translating the text. */
|
|
19
|
-
translate:
|
|
20
|
-
original: string;
|
|
21
|
-
locale: string;
|
|
22
|
-
}[]) => TranslationResponse[] | Promise<TranslationResponse[]>;
|
|
19
|
+
translate: Translator;
|
|
23
20
|
};
|
|
24
|
-
declare const createI18nPlugin: (props: I18nPluginProps) => Plugin
|
|
21
|
+
declare const createI18nPlugin: (props: I18nPluginProps) => Plugin;
|
|
25
22
|
|
|
26
|
-
type
|
|
23
|
+
type AiTranslationProps = {
|
|
27
24
|
/** The maximum number of tokens that can be generated in the chat completion. */
|
|
28
|
-
maxTokens
|
|
25
|
+
maxTokens: number;
|
|
29
26
|
/** ID of the model to use. */
|
|
30
|
-
model
|
|
31
|
-
/**
|
|
27
|
+
model: LanguageModel;
|
|
28
|
+
/** */
|
|
29
|
+
batchSize?: number;
|
|
30
|
+
/** The rules that the ai should follow. It will be added to the prompt. */
|
|
32
31
|
rules?: string[];
|
|
33
32
|
};
|
|
34
|
-
declare const
|
|
33
|
+
declare const ai: (props: AiTranslationProps) => Translator;
|
|
35
34
|
|
|
36
35
|
declare const mock: (translation?: string) => Translator;
|
|
37
36
|
|
|
38
|
-
export {
|
|
37
|
+
export { ai, createI18nPlugin as i18n, mock };
|
package/dist/index.js
CHANGED
|
@@ -75,7 +75,7 @@ var removeUnusedTranslations = (cache, originals, locales) => {
|
|
|
75
75
|
// src/find.ts
|
|
76
76
|
import { readFile as readFile2 } from "fs/promises";
|
|
77
77
|
import { glob } from "glob";
|
|
78
|
-
import {
|
|
78
|
+
import { join as join2 } from "path";
|
|
79
79
|
|
|
80
80
|
// src/find/svelte.ts
|
|
81
81
|
import { walk } from "estree-walker";
|
|
@@ -90,7 +90,7 @@ var findSvelteTranslatable = (code) => {
|
|
|
90
90
|
const enter = (node) => {
|
|
91
91
|
if (
|
|
92
92
|
//
|
|
93
|
-
node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && node.tag.name === "
|
|
93
|
+
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
|
|
94
94
|
) {
|
|
95
95
|
const start = node.quasi.loc.start;
|
|
96
96
|
const end = node.quasi.loc.end;
|
|
@@ -121,7 +121,7 @@ var findTypescriptTranslatable = async (code) => {
|
|
|
121
121
|
});
|
|
122
122
|
simple(ast, {
|
|
123
123
|
TaggedTemplateExpression(node) {
|
|
124
|
-
if (node.tag.type === "
|
|
124
|
+
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") {
|
|
125
125
|
const content = code.substring(
|
|
126
126
|
node.template.span.start - ast.span.start + 1,
|
|
127
127
|
node.template.span.end - ast.span.start - 1
|
|
@@ -147,14 +147,13 @@ var findTranslatable = async (cwd) => {
|
|
|
147
147
|
const found = [];
|
|
148
148
|
for (const file of files) {
|
|
149
149
|
const code = await readFile2(join2(cwd, file), "utf8");
|
|
150
|
-
if (code.includes("
|
|
151
|
-
if (
|
|
150
|
+
if (code.includes("lang.t`")) {
|
|
151
|
+
if (file.endsWith(".svelte")) {
|
|
152
152
|
found.push(...findSvelteTranslatable(code));
|
|
153
|
+
} else {
|
|
154
|
+
found.push(...await findTypescriptTranslatable(code));
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
|
-
if (code.includes("get(t)`")) {
|
|
156
|
-
found.push(...await findTypescriptTranslatable(code));
|
|
157
|
-
}
|
|
158
157
|
}
|
|
159
158
|
return found;
|
|
160
159
|
};
|
|
@@ -162,116 +161,95 @@ var findTranslatable = async (cwd) => {
|
|
|
162
161
|
// src/vite.ts
|
|
163
162
|
var createI18nPlugin = (props) => {
|
|
164
163
|
let cache;
|
|
165
|
-
return
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
await saveCache(cwd, cache);
|
|
182
|
-
},
|
|
183
|
-
transform(code) {
|
|
184
|
-
let replaced = false;
|
|
185
|
-
if (code.includes(`$t\``)) {
|
|
186
|
-
for (const item of cache.entries()) {
|
|
187
|
-
code = code.replaceAll(`$t\`${item.original}\``, () => {
|
|
188
|
-
replaced = true;
|
|
189
|
-
return `$t.get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
190
|
-
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
191
|
-
}).join(",")}})`;
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (code.includes(`get(t)\``)) {
|
|
196
|
-
for (const item of cache.entries()) {
|
|
197
|
-
code = code.replaceAll(`get(t)\`${item.original}\``, () => {
|
|
198
|
-
replaced = true;
|
|
199
|
-
return `get(t).get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
200
|
-
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
201
|
-
}).join(",")}})`;
|
|
202
|
-
});
|
|
203
|
-
}
|
|
164
|
+
return {
|
|
165
|
+
name: "awsless/i18n",
|
|
166
|
+
enforce: "pre",
|
|
167
|
+
async buildStart() {
|
|
168
|
+
const cwd = process.cwd();
|
|
169
|
+
this.info("Finding all translatable text...");
|
|
170
|
+
const originals = await findTranslatable(cwd);
|
|
171
|
+
cache = await loadCache(cwd);
|
|
172
|
+
removeUnusedTranslations(cache, originals, props.locales);
|
|
173
|
+
const newOriginals = findNewTranslations(cache, originals, props.locales);
|
|
174
|
+
if (newOriginals.length > 0) {
|
|
175
|
+
this.info(`Translating ${newOriginals.length} new texts.`);
|
|
176
|
+
const translations = await props.translate(props.default ?? "en", newOriginals);
|
|
177
|
+
for (const item of translations) {
|
|
178
|
+
cache.set(item.original, item.locale, item.translation);
|
|
204
179
|
}
|
|
205
|
-
|
|
206
|
-
|
|
180
|
+
}
|
|
181
|
+
await saveCache(cwd, cache);
|
|
182
|
+
this.info(`Translating done.`);
|
|
183
|
+
},
|
|
184
|
+
transform(code) {
|
|
185
|
+
let replaced = false;
|
|
186
|
+
if (code.includes("lang.t`")) {
|
|
187
|
+
for (const item of cache.entries()) {
|
|
188
|
+
code = code.replaceAll(`lang.t\`${item.original}\``, () => {
|
|
189
|
+
replaced = true;
|
|
190
|
+
return `lang.t.get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
191
|
+
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
192
|
+
}).join(",")}})`;
|
|
193
|
+
});
|
|
207
194
|
}
|
|
208
|
-
return {
|
|
209
|
-
code
|
|
210
|
-
};
|
|
211
195
|
}
|
|
196
|
+
if (!replaced) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
code
|
|
201
|
+
};
|
|
212
202
|
}
|
|
213
|
-
|
|
203
|
+
};
|
|
214
204
|
};
|
|
215
205
|
|
|
216
|
-
// src/translate/
|
|
217
|
-
import
|
|
218
|
-
import
|
|
206
|
+
// src/translate/ai.ts
|
|
207
|
+
import { generateObject } from "ai";
|
|
208
|
+
import chunk from "chunk";
|
|
219
209
|
import { z } from "zod";
|
|
220
|
-
var
|
|
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
|
-
data = JSON.parse(json);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
throw new Error(`Invalid chat gpt json response: ${json}`);
|
|
251
|
-
}
|
|
252
|
-
return data.translations;
|
|
210
|
+
var ai = (props) => {
|
|
211
|
+
return async (originalLocale, texts) => {
|
|
212
|
+
const batches = chunk(texts, props.batchSize ?? 1e3);
|
|
213
|
+
const translations = await Promise.all(
|
|
214
|
+
batches.map(async (texts2) => {
|
|
215
|
+
const result = await generateObject({
|
|
216
|
+
model: props.model,
|
|
217
|
+
maxTokens: props.maxTokens,
|
|
218
|
+
schema: z.object({
|
|
219
|
+
translations: z.object({
|
|
220
|
+
original: z.string(),
|
|
221
|
+
locale: z.string(),
|
|
222
|
+
translation: z.string()
|
|
223
|
+
}).array()
|
|
224
|
+
}),
|
|
225
|
+
prompt: [
|
|
226
|
+
`You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.`,
|
|
227
|
+
...props?.rules ?? [],
|
|
228
|
+
"",
|
|
229
|
+
`JSON FILE:`,
|
|
230
|
+
JSON.stringify(texts2)
|
|
231
|
+
].join("\n"),
|
|
232
|
+
system: "You are a helpful translator."
|
|
233
|
+
});
|
|
234
|
+
return result.object.translations;
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
return translations.flat(3);
|
|
253
238
|
};
|
|
254
239
|
};
|
|
255
|
-
var prompt = (originalLocale, list, rules) => {
|
|
256
|
-
return `You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.
|
|
257
|
-
${rules?.join("\n") ?? ""}
|
|
258
|
-
|
|
259
|
-
JSON FILE:
|
|
260
|
-
${JSON.stringify(list)}`;
|
|
261
|
-
};
|
|
262
240
|
|
|
263
241
|
// src/translate/mock.ts
|
|
264
242
|
var mock = (translation = "REPLACED") => {
|
|
265
|
-
return (_,
|
|
243
|
+
return (_, originals) => {
|
|
266
244
|
const response = [];
|
|
267
|
-
for (const
|
|
268
|
-
response.push({ ...
|
|
245
|
+
for (const original of originals) {
|
|
246
|
+
response.push({ ...original, translation });
|
|
269
247
|
}
|
|
270
248
|
return response;
|
|
271
249
|
};
|
|
272
250
|
};
|
|
273
251
|
export {
|
|
274
|
-
|
|
252
|
+
ai,
|
|
275
253
|
createI18nPlugin as i18n,
|
|
276
254
|
mock
|
|
277
255
|
};
|
|
@@ -17,26 +17,34 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
};
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
|
|
20
|
-
// src/framework/svelte.ts
|
|
21
|
-
var
|
|
22
|
-
__export(
|
|
23
|
-
|
|
24
|
-
t: () => t
|
|
20
|
+
// src/framework/svelte.svelte.ts
|
|
21
|
+
var svelte_svelte_exports = {};
|
|
22
|
+
__export(svelte_svelte_exports, {
|
|
23
|
+
lang: () => lang
|
|
25
24
|
});
|
|
26
|
-
module.exports = __toCommonJS(
|
|
27
|
-
var
|
|
28
|
-
var
|
|
29
|
-
var t = (0, import_store.derived)([locale], ([locale2]) => {
|
|
25
|
+
module.exports = __toCommonJS(svelte_svelte_exports);
|
|
26
|
+
var locale = $state("en");
|
|
27
|
+
var t = $derived.by(() => {
|
|
30
28
|
const api = (template, ...args) => {
|
|
31
29
|
return String.raw({ raw: template.raw }, ...args);
|
|
32
30
|
};
|
|
33
31
|
api.get = (og, translations) => {
|
|
34
|
-
return translations[
|
|
32
|
+
return translations[locale] ?? og;
|
|
35
33
|
};
|
|
36
34
|
return api;
|
|
37
35
|
});
|
|
36
|
+
var lang = {
|
|
37
|
+
set locale(v) {
|
|
38
|
+
locale = v;
|
|
39
|
+
},
|
|
40
|
+
get locale() {
|
|
41
|
+
return locale;
|
|
42
|
+
},
|
|
43
|
+
get t() {
|
|
44
|
+
return t;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
38
47
|
// Annotate the CommonJS export names for ESM import in node:
|
|
39
48
|
0 && (module.exports = {
|
|
40
|
-
|
|
41
|
-
t
|
|
49
|
+
lang
|
|
42
50
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/framework/svelte.svelte.ts
|
|
2
|
+
var locale = $state("en");
|
|
3
|
+
var 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
|
+
});
|
|
12
|
+
var lang = {
|
|
13
|
+
set locale(v) {
|
|
14
|
+
locale = v;
|
|
15
|
+
},
|
|
16
|
+
get locale() {
|
|
17
|
+
return locale;
|
|
18
|
+
},
|
|
19
|
+
get t() {
|
|
20
|
+
return t;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export {
|
|
24
|
+
lang
|
|
25
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awsless/i18n",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"types": "./dist/index.d.ts"
|
|
32
32
|
},
|
|
33
33
|
"./svelte": {
|
|
34
|
-
"require": "./dist/svelte.cjs",
|
|
35
|
-
"import": "./dist/svelte.js",
|
|
36
|
-
"types": "./dist/svelte.d.ts"
|
|
34
|
+
"require": "./dist/svelte.svelte.cjs",
|
|
35
|
+
"import": "./dist/svelte.svelte.js",
|
|
36
|
+
"types": "./dist/svelte.svelte.d.ts"
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"vitest": {
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
]
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
+
"@ai-sdk/openai": "^1.3.23",
|
|
45
46
|
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
|
46
47
|
"svelte": "^4.2.19",
|
|
47
48
|
"svelte-preprocess": "^6.0.2",
|
|
@@ -53,18 +54,20 @@
|
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"@swc/core": "^1.3.70",
|
|
57
|
+
"@types/chunk": "^0.0.0",
|
|
56
58
|
"@types/line-column": "^1.0.2",
|
|
59
|
+
"ai": "^4.3.19",
|
|
60
|
+
"chunk": "^0.0.3",
|
|
57
61
|
"estree-walker": "^3.0.3",
|
|
58
62
|
"glob": "^10.3.9",
|
|
59
63
|
"line-column": "^1.0.2",
|
|
60
|
-
"openai": "^4.57.0",
|
|
61
64
|
"swc-walk": "1.0.0-rc.2",
|
|
62
65
|
"zod": "^3.21.4"
|
|
63
66
|
},
|
|
64
67
|
"scripts": {
|
|
65
68
|
"test": "pnpm code test",
|
|
66
69
|
"build": "pnpm tsup src/index.ts --format cjs,esm --dts --clean",
|
|
67
|
-
"build-svelte": "pnpm tsup src/framework/svelte.ts --format cjs,esm --dts",
|
|
70
|
+
"build-svelte": "pnpm tsup src/framework/svelte.svelte.ts --format cjs,esm --dts",
|
|
68
71
|
"prepublish": "if pnpm test; then pnpm build; pnpm build-svelte; else exit; fi"
|
|
69
72
|
}
|
|
70
73
|
}
|
package/dist/svelte.d.cts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as svelte_store from 'svelte/store';
|
|
2
|
-
|
|
3
|
-
declare const locale: svelte_store.Writable<string>;
|
|
4
|
-
declare const t: svelte_store.Readable<{
|
|
5
|
-
(template: TemplateStringsArray, ...args: Array<string | number>): string;
|
|
6
|
-
get(og: string, translations: Record<string, string>): string;
|
|
7
|
-
}>;
|
|
8
|
-
|
|
9
|
-
export { locale, t };
|
package/dist/svelte.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as svelte_store from 'svelte/store';
|
|
2
|
-
|
|
3
|
-
declare const locale: svelte_store.Writable<string>;
|
|
4
|
-
declare const t: svelte_store.Readable<{
|
|
5
|
-
(template: TemplateStringsArray, ...args: Array<string | number>): string;
|
|
6
|
-
get(og: string, translations: Record<string, string>): string;
|
|
7
|
-
}>;
|
|
8
|
-
|
|
9
|
-
export { locale, t };
|
package/dist/svelte.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// src/framework/svelte.ts
|
|
2
|
-
import { derived, writable } from "svelte/store";
|
|
3
|
-
var locale = writable("en");
|
|
4
|
-
var t = derived([locale], ([locale2]) => {
|
|
5
|
-
const api = (template, ...args) => {
|
|
6
|
-
return String.raw({ raw: template.raw }, ...args);
|
|
7
|
-
};
|
|
8
|
-
api.get = (og, translations) => {
|
|
9
|
-
return translations[locale2] ?? og;
|
|
10
|
-
};
|
|
11
|
-
return api;
|
|
12
|
-
});
|
|
13
|
-
export {
|
|
14
|
-
locale,
|
|
15
|
-
t
|
|
16
|
-
};
|