@ccgp/i18n-ai 0.2.0 → 0.2.1
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 +25 -8
- package/dist/cli.js +10 -1
- package/dist/cli.mjs +10 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -5,10 +5,10 @@ AI-powered internationalization (i18n) translation and synchronization library.
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- 🤖 **AI-Powered**: Uses Google Gemini (via OpenRouter) to generate context-aware translations.
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
8
|
+
- ⚡ **Parallel Processing**: Translations run concurrently for maximum speed (5x faster).
|
|
9
|
+
- 🔄 **Smart Synchronization**: Detects new, modified, and obsolete keys.
|
|
10
|
+
- ⛔ **Variable Protection**: Automatically preserves variables like `{name}` or `{count}`.
|
|
11
|
+
- 🔒 **Lock File System**: Prevents unnecessary re-translations of already translated content.
|
|
12
12
|
- 🧩 **Framework Agnostic**: Works with any i18n library that uses JSON files (next-intl, react-i18next, etc.).
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
@@ -47,6 +47,25 @@ This will create an `i18n-ai.config.json` file:
|
|
|
47
47
|
bun x i18n-ai sync
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
### CLI Options
|
|
51
|
+
|
|
52
|
+
The `sync` command supports these options:
|
|
53
|
+
|
|
54
|
+
| Option | Description |
|
|
55
|
+
|--------|-------------|
|
|
56
|
+
| `-d, --dir <path>` | Messages directory (default: `messages`) |
|
|
57
|
+
| `-l, --locales <items>` | Comma-separated list of locales |
|
|
58
|
+
| `--default <locale>` | Default locale (default: `en`) |
|
|
59
|
+
| `--lock <path>` | Lock file path (default: `translation-lock.json`) |
|
|
60
|
+
| `--api-key <key>` | OpenRouter API key (or set `OPENROUTER_API_KEY`) |
|
|
61
|
+
| `--model <model>` | AI model to use (default: `google/gemini-2.5-flash`) |
|
|
62
|
+
|
|
63
|
+
Example with custom options:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bun x i18n-ai sync --locales es,fr,de --model anthropic/claude-3-haiku
|
|
67
|
+
```
|
|
68
|
+
|
|
50
69
|
### Environment Variables
|
|
51
70
|
|
|
52
71
|
You need to provide an API key for the AI provider.
|
|
@@ -79,10 +98,8 @@ jobs:
|
|
|
79
98
|
steps:
|
|
80
99
|
- uses: actions/checkout@v4
|
|
81
100
|
- uses: oven-sh/setup-bun@v1
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
env:
|
|
85
|
-
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
101
|
+
- run: bun install
|
|
102
|
+
- run: bun x i18n-ai sync --api-key ${{ secrets.OPENROUTER_API_KEY }}
|
|
86
103
|
- run: |
|
|
87
104
|
git config --global user.name "github-actions[bot]"
|
|
88
105
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
package/dist/cli.js
CHANGED
|
@@ -24,6 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/cli.ts
|
|
27
|
+
var import_dotenv = require("dotenv");
|
|
27
28
|
var import_commander = require("commander");
|
|
28
29
|
var import_node_path2 = require("path");
|
|
29
30
|
var import_promises3 = require("fs/promises");
|
|
@@ -288,7 +289,8 @@ var TranslationService = class {
|
|
|
288
289
|
// src/cli.ts
|
|
289
290
|
var import_prompts = __toESM(require("prompts"));
|
|
290
291
|
var import_chalk = __toESM(require("chalk"));
|
|
291
|
-
|
|
292
|
+
(0, import_dotenv.config)({ path: (0, import_node_path2.resolve)(process.cwd(), ".env") });
|
|
293
|
+
var VERSION = "0.2.1";
|
|
292
294
|
var program = new import_commander.Command();
|
|
293
295
|
program.name("i18n-ai").description("AI-powered translation CLI").version(VERSION);
|
|
294
296
|
var CONFIG_FILE = "i18n.config.json";
|
|
@@ -350,6 +352,13 @@ program.command("init").description("Initialize i18n-ai configuration").action(a
|
|
|
350
352
|
await (0, import_promises3.writeFile)(baseFilePath, JSON.stringify({ welcome: "Hello World" }, null, 2));
|
|
351
353
|
console.log(import_chalk.default.green(`\u2705 Created base file ${response.messagesDir}/${response.defaultLocale}.json`));
|
|
352
354
|
}
|
|
355
|
+
if (process.env.OPENROUTER_API_KEY) {
|
|
356
|
+
console.log(import_chalk.default.green("\u2705 OPENROUTER_API_KEY detected in .env"));
|
|
357
|
+
} else {
|
|
358
|
+
console.log(import_chalk.default.yellow("\n\u26A0\uFE0F OPENROUTER_API_KEY not found in .env"));
|
|
359
|
+
console.log(import_chalk.default.dim(" Add it to your .env file: OPENROUTER_API_KEY=your_key"));
|
|
360
|
+
console.log(import_chalk.default.dim(" Get one at: https://openrouter.ai"));
|
|
361
|
+
}
|
|
353
362
|
console.log(import_chalk.default.blue('\n\u{1F389} Setup complete! You can now run "i18n-ai sync"'));
|
|
354
363
|
});
|
|
355
364
|
program.command("sync").description("Synchronize translations using AI").option("-d, --dir <path>", "Messages directory").option("-l, --locales <items>", "Comma separated list of locales").option("--default <locale>", "Default locale").option("--lock <path>", "Lock file path", "translation-lock.json").option("--api-key <key>", "OpenRouter API key (or set OPENROUTER_API_KEY)").option("--model <model>", "AI model to use", "google/gemini-2.5-flash").action(async (options) => {
|
package/dist/cli.mjs
CHANGED
|
@@ -4,12 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-5QO2MVWV.mjs";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
|
+
import { config as loadEnv } from "dotenv";
|
|
7
8
|
import { Command } from "commander";
|
|
8
9
|
import { resolve, join } from "path";
|
|
9
10
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
10
11
|
import prompts from "prompts";
|
|
11
12
|
import chalk from "chalk";
|
|
12
|
-
|
|
13
|
+
loadEnv({ path: resolve(process.cwd(), ".env") });
|
|
14
|
+
var VERSION = "0.2.1";
|
|
13
15
|
var program = new Command();
|
|
14
16
|
program.name("i18n-ai").description("AI-powered translation CLI").version(VERSION);
|
|
15
17
|
var CONFIG_FILE = "i18n.config.json";
|
|
@@ -71,6 +73,13 @@ program.command("init").description("Initialize i18n-ai configuration").action(a
|
|
|
71
73
|
await writeFile(baseFilePath, JSON.stringify({ welcome: "Hello World" }, null, 2));
|
|
72
74
|
console.log(chalk.green(`\u2705 Created base file ${response.messagesDir}/${response.defaultLocale}.json`));
|
|
73
75
|
}
|
|
76
|
+
if (process.env.OPENROUTER_API_KEY) {
|
|
77
|
+
console.log(chalk.green("\u2705 OPENROUTER_API_KEY detected in .env"));
|
|
78
|
+
} else {
|
|
79
|
+
console.log(chalk.yellow("\n\u26A0\uFE0F OPENROUTER_API_KEY not found in .env"));
|
|
80
|
+
console.log(chalk.dim(" Add it to your .env file: OPENROUTER_API_KEY=your_key"));
|
|
81
|
+
console.log(chalk.dim(" Get one at: https://openrouter.ai"));
|
|
82
|
+
}
|
|
74
83
|
console.log(chalk.blue('\n\u{1F389} Setup complete! You can now run "i18n-ai sync"'));
|
|
75
84
|
});
|
|
76
85
|
program.command("sync").description("Synchronize translations using AI").option("-d, --dir <path>", "Messages directory").option("-l, --locales <items>", "Comma separated list of locales").option("--default <locale>", "Default locale").option("--lock <path>", "Lock file path", "translation-lock.json").option("--api-key <key>", "OpenRouter API key (or set OPENROUTER_API_KEY)").option("--model <model>", "AI model to use", "google/gemini-2.5-flash").action(async (options) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ccgp/i18n-ai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "AI-powered i18n translation and synchronization library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"ai": "^6.0.37",
|
|
40
40
|
"chalk": "^5.6.2",
|
|
41
41
|
"commander": "^14.0.2",
|
|
42
|
+
"dotenv": "^17.2.3",
|
|
42
43
|
"p-queue": "^9.1.0",
|
|
43
44
|
"prompts": "^2.4.2",
|
|
44
45
|
"proper-lockfile": "^4.1.2",
|