@awsless/i18n 0.0.5 → 0.0.6
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 +83 -104
- package/dist/index.d.cts +11 -12
- package/dist/index.d.ts +11 -12
- package/dist/index.js +79 -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 -5
- 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");
|
|
@@ -126,9 +126,10 @@ var findSvelteTranslatable = (code) => {
|
|
|
126
126
|
css: false
|
|
127
127
|
});
|
|
128
128
|
const enter = (node) => {
|
|
129
|
+
console.log(node);
|
|
129
130
|
if (
|
|
130
131
|
//
|
|
131
|
-
node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && node.tag.name === "
|
|
132
|
+
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
133
|
) {
|
|
133
134
|
const start = node.quasi.loc.start;
|
|
134
135
|
const end = node.quasi.loc.end;
|
|
@@ -159,7 +160,7 @@ var findTypescriptTranslatable = async (code) => {
|
|
|
159
160
|
});
|
|
160
161
|
(0, import_swc_walk.simple)(ast, {
|
|
161
162
|
TaggedTemplateExpression(node) {
|
|
162
|
-
if (node.tag.type === "
|
|
163
|
+
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
164
|
const content = code.substring(
|
|
164
165
|
node.template.span.start - ast.span.start + 1,
|
|
165
166
|
node.template.span.end - ast.span.start - 1
|
|
@@ -185,14 +186,13 @@ var findTranslatable = async (cwd) => {
|
|
|
185
186
|
const found = [];
|
|
186
187
|
for (const file of files) {
|
|
187
188
|
const code = await (0, import_promises2.readFile)((0, import_path2.join)(cwd, file), "utf8");
|
|
188
|
-
if (code.includes("
|
|
189
|
-
if (
|
|
189
|
+
if (code.includes("lang.t`")) {
|
|
190
|
+
if (file.endsWith(".svelte")) {
|
|
190
191
|
found.push(...findSvelteTranslatable(code));
|
|
192
|
+
} else {
|
|
193
|
+
found.push(...await findTypescriptTranslatable(code));
|
|
191
194
|
}
|
|
192
195
|
}
|
|
193
|
-
if (code.includes("get(t)`")) {
|
|
194
|
-
found.push(...await findTypescriptTranslatable(code));
|
|
195
|
-
}
|
|
196
196
|
}
|
|
197
197
|
return found;
|
|
198
198
|
};
|
|
@@ -200,117 +200,96 @@ var findTranslatable = async (cwd) => {
|
|
|
200
200
|
// src/vite.ts
|
|
201
201
|
var createI18nPlugin = (props) => {
|
|
202
202
|
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
|
-
}
|
|
203
|
+
return {
|
|
204
|
+
name: "awsless/i18n",
|
|
205
|
+
enforce: "pre",
|
|
206
|
+
async buildStart() {
|
|
207
|
+
const cwd = process.cwd();
|
|
208
|
+
this.info("Finding all translatable text...");
|
|
209
|
+
const originals = await findTranslatable(cwd);
|
|
210
|
+
cache = await loadCache(cwd);
|
|
211
|
+
removeUnusedTranslations(cache, originals, props.locales);
|
|
212
|
+
const newOriginals = findNewTranslations(cache, originals, props.locales);
|
|
213
|
+
if (newOriginals.length > 0) {
|
|
214
|
+
this.info(`Translating ${newOriginals.length} new texts.`);
|
|
215
|
+
const translations = await props.translate(props.default ?? "en", newOriginals);
|
|
216
|
+
for (const item of translations) {
|
|
217
|
+
cache.set(item.original, item.locale, item.translation);
|
|
242
218
|
}
|
|
243
|
-
|
|
244
|
-
|
|
219
|
+
}
|
|
220
|
+
await saveCache(cwd, cache);
|
|
221
|
+
this.info(`Translating done.`);
|
|
222
|
+
},
|
|
223
|
+
transform(code) {
|
|
224
|
+
let replaced = false;
|
|
225
|
+
if (code.includes("lang.t`")) {
|
|
226
|
+
for (const item of cache.entries()) {
|
|
227
|
+
code = code.replaceAll(`lang.t\`${item.original}\``, () => {
|
|
228
|
+
replaced = true;
|
|
229
|
+
return `lang.t.get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
230
|
+
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
231
|
+
}).join(",")}})`;
|
|
232
|
+
});
|
|
245
233
|
}
|
|
246
|
-
return {
|
|
247
|
-
code
|
|
248
|
-
};
|
|
249
234
|
}
|
|
235
|
+
if (!replaced) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
code
|
|
240
|
+
};
|
|
250
241
|
}
|
|
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
242
|
};
|
|
292
243
|
};
|
|
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
244
|
|
|
297
|
-
|
|
298
|
-
|
|
245
|
+
// src/translate/ai.ts
|
|
246
|
+
var import_ai = require("ai");
|
|
247
|
+
var import_chunk = __toESM(require("chunk"), 1);
|
|
248
|
+
var import_zod = require("zod");
|
|
249
|
+
var ai = (props) => {
|
|
250
|
+
return async (originalLocale, texts) => {
|
|
251
|
+
const batches = (0, import_chunk.default)(texts, props.batchSize ?? 1e3);
|
|
252
|
+
const translations = await Promise.all(
|
|
253
|
+
batches.map(async (texts2) => {
|
|
254
|
+
const result = await (0, import_ai.generateObject)({
|
|
255
|
+
model: props.model,
|
|
256
|
+
maxTokens: props.maxTokens,
|
|
257
|
+
schema: import_zod.z.object({
|
|
258
|
+
translations: import_zod.z.object({
|
|
259
|
+
original: import_zod.z.string(),
|
|
260
|
+
locale: import_zod.z.string(),
|
|
261
|
+
translation: import_zod.z.string()
|
|
262
|
+
}).array()
|
|
263
|
+
}),
|
|
264
|
+
prompt: [
|
|
265
|
+
`You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.`,
|
|
266
|
+
...props?.rules ?? [],
|
|
267
|
+
"",
|
|
268
|
+
`JSON FILE:`,
|
|
269
|
+
JSON.stringify(texts2)
|
|
270
|
+
].join("\n"),
|
|
271
|
+
system: "You are a helpful translator."
|
|
272
|
+
});
|
|
273
|
+
return result.object.translations;
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
return translations.flat(3);
|
|
277
|
+
};
|
|
299
278
|
};
|
|
300
279
|
|
|
301
280
|
// src/translate/mock.ts
|
|
302
281
|
var mock = (translation = "REPLACED") => {
|
|
303
|
-
return (_,
|
|
282
|
+
return (_, originals) => {
|
|
304
283
|
const response = [];
|
|
305
|
-
for (const
|
|
306
|
-
response.push({ ...
|
|
284
|
+
for (const original of originals) {
|
|
285
|
+
response.push({ ...original, translation });
|
|
307
286
|
}
|
|
308
287
|
return response;
|
|
309
288
|
};
|
|
310
289
|
};
|
|
311
290
|
// Annotate the CommonJS export names for ESM import in node:
|
|
312
291
|
0 && (module.exports = {
|
|
313
|
-
|
|
292
|
+
ai,
|
|
314
293
|
i18n,
|
|
315
294
|
mock
|
|
316
295
|
});
|
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";
|
|
@@ -88,9 +88,10 @@ var findSvelteTranslatable = (code) => {
|
|
|
88
88
|
css: false
|
|
89
89
|
});
|
|
90
90
|
const enter = (node) => {
|
|
91
|
+
console.log(node);
|
|
91
92
|
if (
|
|
92
93
|
//
|
|
93
|
-
node.type === "TaggedTemplateExpression" && node.tag.type === "Identifier" && node.tag.name === "
|
|
94
|
+
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
95
|
) {
|
|
95
96
|
const start = node.quasi.loc.start;
|
|
96
97
|
const end = node.quasi.loc.end;
|
|
@@ -121,7 +122,7 @@ var findTypescriptTranslatable = async (code) => {
|
|
|
121
122
|
});
|
|
122
123
|
simple(ast, {
|
|
123
124
|
TaggedTemplateExpression(node) {
|
|
124
|
-
if (node.tag.type === "
|
|
125
|
+
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
126
|
const content = code.substring(
|
|
126
127
|
node.template.span.start - ast.span.start + 1,
|
|
127
128
|
node.template.span.end - ast.span.start - 1
|
|
@@ -147,14 +148,13 @@ var findTranslatable = async (cwd) => {
|
|
|
147
148
|
const found = [];
|
|
148
149
|
for (const file of files) {
|
|
149
150
|
const code = await readFile2(join2(cwd, file), "utf8");
|
|
150
|
-
if (code.includes("
|
|
151
|
-
if (
|
|
151
|
+
if (code.includes("lang.t`")) {
|
|
152
|
+
if (file.endsWith(".svelte")) {
|
|
152
153
|
found.push(...findSvelteTranslatable(code));
|
|
154
|
+
} else {
|
|
155
|
+
found.push(...await findTypescriptTranslatable(code));
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
|
-
if (code.includes("get(t)`")) {
|
|
156
|
-
found.push(...await findTypescriptTranslatable(code));
|
|
157
|
-
}
|
|
158
158
|
}
|
|
159
159
|
return found;
|
|
160
160
|
};
|
|
@@ -162,116 +162,95 @@ var findTranslatable = async (cwd) => {
|
|
|
162
162
|
// src/vite.ts
|
|
163
163
|
var createI18nPlugin = (props) => {
|
|
164
164
|
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
|
-
}
|
|
165
|
+
return {
|
|
166
|
+
name: "awsless/i18n",
|
|
167
|
+
enforce: "pre",
|
|
168
|
+
async buildStart() {
|
|
169
|
+
const cwd = process.cwd();
|
|
170
|
+
this.info("Finding all translatable text...");
|
|
171
|
+
const originals = await findTranslatable(cwd);
|
|
172
|
+
cache = await loadCache(cwd);
|
|
173
|
+
removeUnusedTranslations(cache, originals, props.locales);
|
|
174
|
+
const newOriginals = findNewTranslations(cache, originals, props.locales);
|
|
175
|
+
if (newOriginals.length > 0) {
|
|
176
|
+
this.info(`Translating ${newOriginals.length} new texts.`);
|
|
177
|
+
const translations = await props.translate(props.default ?? "en", newOriginals);
|
|
178
|
+
for (const item of translations) {
|
|
179
|
+
cache.set(item.original, item.locale, item.translation);
|
|
204
180
|
}
|
|
205
|
-
|
|
206
|
-
|
|
181
|
+
}
|
|
182
|
+
await saveCache(cwd, cache);
|
|
183
|
+
this.info(`Translating done.`);
|
|
184
|
+
},
|
|
185
|
+
transform(code) {
|
|
186
|
+
let replaced = false;
|
|
187
|
+
if (code.includes("lang.t`")) {
|
|
188
|
+
for (const item of cache.entries()) {
|
|
189
|
+
code = code.replaceAll(`lang.t\`${item.original}\``, () => {
|
|
190
|
+
replaced = true;
|
|
191
|
+
return `lang.t.get(\`${item.original}\`, {${props.locales.map((locale) => {
|
|
192
|
+
return `"${locale}":\`${cache.get(item.original, locale)}\``;
|
|
193
|
+
}).join(",")}})`;
|
|
194
|
+
});
|
|
207
195
|
}
|
|
208
|
-
return {
|
|
209
|
-
code
|
|
210
|
-
};
|
|
211
196
|
}
|
|
197
|
+
if (!replaced) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
code
|
|
202
|
+
};
|
|
212
203
|
}
|
|
213
|
-
|
|
204
|
+
};
|
|
214
205
|
};
|
|
215
206
|
|
|
216
|
-
// src/translate/
|
|
217
|
-
import
|
|
218
|
-
import
|
|
207
|
+
// src/translate/ai.ts
|
|
208
|
+
import { generateObject } from "ai";
|
|
209
|
+
import chunk from "chunk";
|
|
219
210
|
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;
|
|
211
|
+
var ai = (props) => {
|
|
212
|
+
return async (originalLocale, texts) => {
|
|
213
|
+
const batches = chunk(texts, props.batchSize ?? 1e3);
|
|
214
|
+
const translations = await Promise.all(
|
|
215
|
+
batches.map(async (texts2) => {
|
|
216
|
+
const result = await generateObject({
|
|
217
|
+
model: props.model,
|
|
218
|
+
maxTokens: props.maxTokens,
|
|
219
|
+
schema: z.object({
|
|
220
|
+
translations: z.object({
|
|
221
|
+
original: z.string(),
|
|
222
|
+
locale: z.string(),
|
|
223
|
+
translation: z.string()
|
|
224
|
+
}).array()
|
|
225
|
+
}),
|
|
226
|
+
prompt: [
|
|
227
|
+
`You have to translate the text inside the JSON file below from "${originalLocale}" to the provided locale.`,
|
|
228
|
+
...props?.rules ?? [],
|
|
229
|
+
"",
|
|
230
|
+
`JSON FILE:`,
|
|
231
|
+
JSON.stringify(texts2)
|
|
232
|
+
].join("\n"),
|
|
233
|
+
system: "You are a helpful translator."
|
|
234
|
+
});
|
|
235
|
+
return result.object.translations;
|
|
236
|
+
})
|
|
237
|
+
);
|
|
238
|
+
return translations.flat(3);
|
|
253
239
|
};
|
|
254
240
|
};
|
|
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
241
|
|
|
263
242
|
// src/translate/mock.ts
|
|
264
243
|
var mock = (translation = "REPLACED") => {
|
|
265
|
-
return (_,
|
|
244
|
+
return (_, originals) => {
|
|
266
245
|
const response = [];
|
|
267
|
-
for (const
|
|
268
|
-
response.push({ ...
|
|
246
|
+
for (const original of originals) {
|
|
247
|
+
response.push({ ...original, translation });
|
|
269
248
|
}
|
|
270
249
|
return response;
|
|
271
250
|
};
|
|
272
251
|
};
|
|
273
252
|
export {
|
|
274
|
-
|
|
253
|
+
ai,
|
|
275
254
|
createI18nPlugin as i18n,
|
|
276
255
|
mock
|
|
277
256
|
};
|
|
@@ -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.6",
|
|
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": {
|
|
@@ -52,8 +52,12 @@
|
|
|
52
52
|
"vite": "^5.4.2"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
+
"@ai-sdk/openai": "^1.3.23",
|
|
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",
|
|
@@ -64,7 +68,7 @@
|
|
|
64
68
|
"scripts": {
|
|
65
69
|
"test": "pnpm code test",
|
|
66
70
|
"build": "pnpm tsup src/index.ts --format cjs,esm --dts --clean",
|
|
67
|
-
"build-svelte": "pnpm tsup src/framework/svelte.ts --format cjs,esm --dts",
|
|
71
|
+
"build-svelte": "pnpm tsup src/framework/svelte.svelte.ts --format cjs,esm --dts",
|
|
68
72
|
"prepublish": "if pnpm test; then pnpm build; pnpm build-svelte; else exit; fi"
|
|
69
73
|
}
|
|
70
74
|
}
|
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
|
-
};
|