@awsless/i18n 0.0.13 → 0.0.15

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 CHANGED
@@ -57,9 +57,9 @@ import { lang } from '@awsless/i18n/svelte'
57
57
 
58
58
  const count = 1
59
59
 
60
- lang.t.get(`${count} count`, {
61
- es: `${count} contar`,
62
- jp: `${count} カウント`,
60
+ lang.t.get(lang.s`${count} count`, {
61
+ es: lang.s`${count} contar`,
62
+ jp: lang.s`${count} カウント`,
63
63
  })
64
64
  ```
65
65
 
@@ -73,15 +73,15 @@ lang.locale = 'jp'
73
73
 
74
74
  ## Changing the AI-generated text
75
75
 
76
- A `i18n.json` file with all the translations will be generated in the root of your project the first time you run a build. We use this file as a cache to not translate any text that has already been translated before.
76
+ A `i18n.generated.json` file with the auto-generated translations will be created in the root of your project the first time you run a build. We use this file as a cache to not translate any text that has already been translated before.
77
77
 
78
- If you don't like the auto-generated translations by AI, you can safely change any of the ai generated translations here.
78
+ If you want to overwrite an AI-generated translation, create or edit `i18n.json`. Any translation in `i18n.json` takes precedence over the generated cache during build time.
79
79
 
80
80
  ```json
81
81
  {
82
- "${count} count": {
83
- "es": "${count} contar",
84
- "jp": "${count} カウント"
85
- }
82
+ "${count} count": {
83
+ "es": "${count} contar",
84
+ "jp": "${count} カウント"
85
+ }
86
86
  }
87
87
  ```
package/dist/index.d.ts CHANGED
@@ -23,8 +23,8 @@ type I18nPluginProps = {
23
23
  declare const i18n: (props: I18nPluginProps) => Plugin;
24
24
 
25
25
  type AiTranslationProps = {
26
- /** The maximum number of tokens allowed in the AI's response. */
27
- maxTokens: number;
26
+ /** The maximum number of output tokens allowed in the AI's response. */
27
+ maxOutputTokens: number;
28
28
  /** The language model to use for translations (e.g., gpt-4, gpt-3.5-turbo). */
29
29
  model: LanguageModel;
30
30
  /** Number of text entries to translate in a single batch.
package/dist/index.js CHANGED
@@ -4,8 +4,10 @@ import MagicString from "magic-string";
4
4
  // src/cache.ts
5
5
  import { readFile, stat, writeFile } from "fs/promises";
6
6
  import { join } from "path";
7
- var loadCache = async (cwd) => {
8
- const file = join(cwd, "i18n.json");
7
+ var GENERATED_CACHE_FILE = "i18n.generated.json";
8
+ var OVERRIDE_CACHE_FILE = "i18n.json";
9
+ var loadFile = async (cwd, fileName) => {
10
+ const file = join(cwd, fileName);
9
11
  try {
10
12
  await stat(file);
11
13
  } catch (error) {
@@ -14,8 +16,23 @@ var loadCache = async (cwd) => {
14
16
  const data = await readFile(file, "utf8");
15
17
  return new Cache(JSON.parse(data));
16
18
  };
19
+ var loadGeneratedCache = async (cwd) => {
20
+ return loadFile(cwd, GENERATED_CACHE_FILE);
21
+ };
22
+ var loadOverrideCache = async (cwd) => {
23
+ return loadFile(cwd, OVERRIDE_CACHE_FILE);
24
+ };
17
25
  var saveCache = async (cwd, cache) => {
18
- await writeFile(join(cwd, "i18n.json"), JSON.stringify(cache, void 0, 2));
26
+ await writeFile(join(cwd, GENERATED_CACHE_FILE), JSON.stringify(cache.toJSON(), void 0, 2) + "\n");
27
+ };
28
+ var mergeCaches = (...caches) => {
29
+ const merged = new Cache();
30
+ for (const cache of caches) {
31
+ for (const item of cache.entries()) {
32
+ merged.replace(item.source, item.locale, item.translation);
33
+ }
34
+ }
35
+ return merged;
19
36
  };
20
37
  var Cache = class {
21
38
  constructor(data = {}) {
@@ -29,6 +46,12 @@ var Cache = class {
29
46
  this.data[source][locale] = translation;
30
47
  }
31
48
  }
49
+ replace(source, locale, translation) {
50
+ if (!this.data[source]) {
51
+ this.data[source] = {};
52
+ }
53
+ this.data[source][locale] = translation;
54
+ }
32
55
  get(source, locale) {
33
56
  return this.data[source]?.[locale];
34
57
  }
@@ -51,7 +74,16 @@ var Cache = class {
51
74
  }
52
75
  }
53
76
  toJSON() {
54
- return this.data;
77
+ return Object.fromEntries(
78
+ Object.entries(this.data).sort(([left], [right]) => left.localeCompare(right)).map(([source, locales]) => {
79
+ return [
80
+ source,
81
+ Object.fromEntries(
82
+ Object.entries(locales).sort(([left], [right]) => left.localeCompare(right))
83
+ )
84
+ ];
85
+ })
86
+ );
55
87
  }
56
88
  };
57
89
 
@@ -162,6 +194,7 @@ var findTranslatable = async (cwd) => {
162
194
  // src/vite.ts
163
195
  var i18n = (props) => {
164
196
  let cache;
197
+ let generatedCache;
165
198
  return {
166
199
  name: "awsless/i18n",
167
200
  enforce: "pre",
@@ -169,18 +202,21 @@ var i18n = (props) => {
169
202
  const cwd = process.cwd();
170
203
  this.info("Finding all translatable text...");
171
204
  const sourceTexts = await findTranslatable(cwd);
172
- cache = await loadCache(cwd);
173
- removeUnusedTranslations(cache, sourceTexts, props.locales);
205
+ generatedCache = await loadGeneratedCache(cwd);
206
+ const overrideCache = await loadOverrideCache(cwd);
207
+ removeUnusedTranslations(generatedCache, sourceTexts, props.locales);
208
+ cache = mergeCaches(generatedCache, overrideCache);
174
209
  const newSourceTexts = findNewTranslations(cache, sourceTexts, props.locales);
175
210
  if (newSourceTexts.length > 0) {
176
211
  this.info(`Translating ${newSourceTexts.length} new texts.`);
177
212
  const translations = await props.translate(props.default ?? "en", newSourceTexts);
178
213
  this.info(`Translated ${translations.length} texts.`);
179
214
  for (const item of translations) {
180
- cache.set(item.source, item.locale, item.translation);
215
+ generatedCache.set(item.source, item.locale, item.translation);
181
216
  }
182
217
  }
183
- await saveCache(cwd, cache);
218
+ cache = mergeCaches(generatedCache, overrideCache);
219
+ await saveCache(cwd, generatedCache);
184
220
  this.info(`Translating done.`);
185
221
  },
186
222
  transform(code) {
@@ -221,7 +257,7 @@ var ai = (props) => {
221
257
  batches.map(async (texts2) => {
222
258
  const result = await generateObject({
223
259
  model: props.model,
224
- maxTokens: props.maxTokens,
260
+ maxOutputTokens: props.maxOutputTokens,
225
261
  schema: z.object({
226
262
  translations: z.object({
227
263
  source: z.string(),
@@ -1,3 +1,9 @@
1
+ type StringArgs = Array<string | number | {
2
+ toString(): string;
3
+ }>;
4
+ type Translate = {
5
+ (template: TemplateStringsArray, ...args: StringArgs): string;
6
+ };
1
7
  declare const lang: {
2
8
  /** Get the current locale.
3
9
  *
@@ -12,9 +18,7 @@ declare const lang: {
12
18
  * @example
13
19
  * lang.t`Hello world!`
14
20
  */
15
- readonly t: (template: TemplateStringsArray, ...args: Array<string | number | {
16
- toString(): string;
17
- }>) => string;
21
+ readonly t: Translate;
18
22
  };
19
23
 
20
24
  export { lang };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/i18n",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -9,7 +9,8 @@
9
9
  "internationalization",
10
10
  "i18n",
11
11
  "svelte",
12
- "sveltekit"
12
+ "sveltekit",
13
+ "ai"
13
14
  ],
14
15
  "repository": {
15
16
  "type": "git",
@@ -39,28 +40,28 @@
39
40
  ]
40
41
  },
41
42
  "devDependencies": {
42
- "@ai-sdk/openai": "^1.3.23",
43
+ "@ai-sdk/openai": "^2.0.42",
43
44
  "@sveltejs/vite-plugin-svelte": "^3.1.2",
44
- "svelte": "^4.2.19",
45
+ "svelte": "^5.46.0",
45
46
  "svelte-preprocess": "^6.0.2",
46
- "vite": "^5.4.2"
47
+ "vite": "^7.1.9"
47
48
  },
48
49
  "peerDependencies": {
49
- "svelte": "^4.2.19",
50
- "vite": "^5.4.2"
50
+ "svelte": "^5.46.0",
51
+ "vite": "^7.1.9"
51
52
  },
52
53
  "dependencies": {
53
54
  "@swc/core": "^1.3.70",
54
55
  "@types/chunk": "^0.0.0",
55
56
  "@types/line-column": "^1.0.2",
56
- "ai": "^4.3.19",
57
+ "ai": "^5.0.60",
57
58
  "chunk": "^0.0.3",
58
59
  "estree-walker": "^3.0.3",
59
60
  "glob": "^10.3.9",
60
61
  "line-column": "^1.0.2",
61
62
  "magic-string": "^0.30.18",
62
63
  "swc-walk": "1.0.0-rc.2",
63
- "zod": "^3.21.4"
64
+ "zod": "^4.1.11"
64
65
  },
65
66
  "scripts": {
66
67
  "test": "pnpm code test",