@tuhama/translation-manager 0.6.1 → 0.7.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/LICENSE +21 -21
- package/README.md +37 -21
- package/bin/index.js +87 -45
- package/package.json +76 -66
- package/src/core/Scanner.js +204 -128
- package/src/core/TranslatorManager.js +97 -33
- package/src/core/Utilities.js +59 -55
- package/src/core/services/AITranslator.js +111 -0
- package/translations.skill +40 -0
- package/web/dist/assets/{index-DtMLkoQW.css → index-C4pKyQzR.css} +1 -1
- package/web/dist/assets/{index-p37Bqu5O.js → index-CecH4D-L.js} +2 -2
- package/web/dist/index.html +19 -19
- package/web/package.json +29 -22
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Tuhama
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tuhama
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
# Translation Manager UI 🌍
|
|
2
2
|
|
|
3
|
-
A modern, web-based interface for managing i18n translation files in React and other JavaScript projects.
|
|
3
|
+
A modern, web-based interface for managing i18n translation files in React and other JavaScript projects. Now with **AI-Friendly** features and an **AI Skill File** to make localization faster and more accurate.
|
|
4
|
+
|
|
5
|
+
> [!TIP]
|
|
6
|
+
> This project is **AI-Ready**. AI agents can use the included `translations.skill` to automatically audit and manage your translations.
|
|
4
7
|
|
|
5
8
|
## Features
|
|
6
9
|
- **Modern UI**: Dark mode, glassmorphism, and smooth animations.
|
|
7
|
-
- **
|
|
10
|
+
- **AI-Powered Translation**: Support for **OpenAI (GPT-4o)**, **Google Gemini**, and Google Cloud Translate.
|
|
11
|
+
- **Context-Aware Scanning**: Extracts code snippets where translation keys are used, providing crucial context for AI translations.
|
|
8
12
|
- **Missing Keys Detection**: Identifies translation keys used in source code but missing from files.
|
|
9
13
|
- **Cleanup Tool**: Detects and batch-removes unused translation keys.
|
|
10
14
|
- **Normalization**: Synchronizes keys across all languages and sorts them alphabetically with one click.
|
|
11
|
-
- **
|
|
15
|
+
- **Export/Import**: Export all missing translations to an **AI-Friendly** JSON file (including code context) for external translation.
|
|
16
|
+
- **CLI Status**: Machine-readable JSON output for project health monitoring.
|
|
12
17
|
- **Tree View**: Easy navigation and management of translation keys.
|
|
13
18
|
- **Zero Config**: Auto-detects common locales folders.
|
|
14
19
|
|
|
@@ -24,25 +29,41 @@ npx @tuhama/translation-manager
|
|
|
24
29
|
|
|
25
30
|
## Usage
|
|
26
31
|
|
|
27
|
-
###
|
|
28
|
-
The
|
|
32
|
+
### 🤖 AI-Friendly Localization
|
|
33
|
+
The manager now extracts the **surrounding code** for every translation key it finds. This context is passed to AI models (like OpenAI or Gemini) to ensure highly accurate translations that respect your code's intent.
|
|
29
34
|
|
|
30
|
-
###
|
|
31
|
-
|
|
35
|
+
### 📤📥 Export/Import (AI-Enhanced)
|
|
36
|
+
You can export all missing translation keys to a single JSON file. This export is **AI-Ready**, containing code snippets for each key so you can feed it to an LLM for context-aware translations.
|
|
32
37
|
|
|
33
|
-
###
|
|
34
|
-
|
|
38
|
+
### 📊 CLI Status
|
|
39
|
+
Check your translation coverage programmatically:
|
|
40
|
+
```bash
|
|
41
|
+
npx @tuhama/translation-manager status
|
|
42
|
+
```
|
|
43
|
+
Outputs a machine-readable JSON summary of missing keys, coverage percentage, and project health.
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
2. Add your Google Cloud Project ID in Settings
|
|
39
|
-
3. Start translating!
|
|
45
|
+
### ⚠️ Missing Keys Detection
|
|
46
|
+
The application automatically scans your source code for translation keys used (e.g., `t('key.name')`) but missing from your translation files. Click the "**Missing**" button in the sidebar to review and create them instantly.
|
|
40
47
|
|
|
41
|
-
### 🪄
|
|
42
|
-
|
|
48
|
+
### 🪄 Auto-Translation
|
|
49
|
+
Configure Google Cloud, OpenAI, or Gemini in the settings to enable auto-translation. Use the "**Source-to-All**" button in the editor to quickly populate all languages.
|
|
43
50
|
|
|
44
51
|
## Configuration
|
|
45
52
|
You can optionally create a `translation.config.json` in your project root:
|
|
53
|
+
|
|
54
|
+
### Using OpenAI (Recommended for AI Quality)
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"path": "src/locales",
|
|
58
|
+
"aiTranslate": {
|
|
59
|
+
"provider": "openai",
|
|
60
|
+
"apiKey": "your-openai-api-key",
|
|
61
|
+
"model": "gpt-4o"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Using Google Cloud Translate
|
|
46
67
|
```json
|
|
47
68
|
{
|
|
48
69
|
"path": "src/locales",
|
|
@@ -52,11 +73,6 @@ You can optionally create a `translation.config.json` in your project root:
|
|
|
52
73
|
}
|
|
53
74
|
```
|
|
54
75
|
|
|
55
|
-
**Authentication Options:**
|
|
56
|
-
- **Recommended**: Use Google Cloud CLI (`gcloud auth application-default login`)
|
|
57
|
-
- **Alternative**: Specify `keyFilename` path to service account JSON file
|
|
58
|
-
- **Environment**: Set `GOOGLE_APPLICATION_CREDENTIALS` environment variable
|
|
59
|
-
|
|
60
76
|
## Development
|
|
61
77
|
To work on this repo:
|
|
62
78
|
1. `npm install`
|
|
@@ -64,7 +80,7 @@ To work on this repo:
|
|
|
64
80
|
3. `npm run dev` (starts both the API and the Vite UI)
|
|
65
81
|
|
|
66
82
|
## Limitations
|
|
67
|
-
- **Dynamic Keys**:
|
|
83
|
+
- **Dynamic Keys**: Highly dynamic keys (e.g. `t(someVar + '.key')`) may not be detected by the "Missing Keys" tool.
|
|
68
84
|
- **Namespaces**: Currently optimized for single-namespace or default-namespace projects.
|
|
69
85
|
|
|
70
86
|
## License
|
package/bin/index.js
CHANGED
|
@@ -1,45 +1,87 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { program } = require('commander');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const fs = require('fs-extra');
|
|
6
|
-
const { startServer } = require('../src/server');
|
|
7
|
-
const open = (...args) => import('open').then(m => m.default(...args));
|
|
8
|
-
|
|
9
|
-
program
|
|
10
|
-
.version('0.1.0')
|
|
11
|
-
.description('Translation Manager CLI - Manage your React translations with a modern UI')
|
|
12
|
-
.option('-p, --port <number>', 'Port to run the UI on', 3000)
|
|
13
|
-
.option('-c, --config <path>', 'Path to config file')
|
|
14
|
-
.action(async (options) => {
|
|
15
|
-
const targetDir = process.cwd();
|
|
16
|
-
let config =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { program } = require('commander');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const { startServer } = require('../src/server');
|
|
7
|
+
const open = (...args) => import('open').then(m => m.default(...args));
|
|
8
|
+
|
|
9
|
+
program
|
|
10
|
+
.version('0.1.0')
|
|
11
|
+
.description('Translation Manager CLI - Manage your React translations with a modern UI')
|
|
12
|
+
.option('-p, --port <number>', 'Port to run the UI on', 3000)
|
|
13
|
+
.option('-c, --config <path>', 'Path to config file')
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const targetDir = process.cwd();
|
|
16
|
+
let config = await loadConfig(targetDir, options.config);
|
|
17
|
+
|
|
18
|
+
console.log('\x1b[36mℹ\x1b[0m Starting Translation Manager...');
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
startServer(targetDir, options.port, config);
|
|
22
|
+
|
|
23
|
+
// Open the browser
|
|
24
|
+
await open(`http://localhost:${options.port}`);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error('\x1b[31m✖\x1b[0m Error:', err.message);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
program
|
|
32
|
+
.command('status')
|
|
33
|
+
.description('Get translation status in JSON format')
|
|
34
|
+
.option('-c, --config <path>', 'Path to config file')
|
|
35
|
+
.action(async (options) => {
|
|
36
|
+
const targetDir = process.cwd();
|
|
37
|
+
const config = await loadConfig(targetDir, options.config);
|
|
38
|
+
const TranslatorManager = require('../src/core/TranslatorManager');
|
|
39
|
+
const manager = new TranslatorManager(targetDir, config);
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const data = await manager.scan();
|
|
43
|
+
const status = {
|
|
44
|
+
languages: data.languages,
|
|
45
|
+
totalKeys: data.allKeys.length,
|
|
46
|
+
missingKeysFromCode: data.missingFromFiles.length,
|
|
47
|
+
unusedKeys: data.unused.length,
|
|
48
|
+
maybeUsedKeys: data.maybeUsed.length,
|
|
49
|
+
coverage: {}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
data.languages.forEach(lang => {
|
|
53
|
+
const untranslated = data.allKeys.filter(key => {
|
|
54
|
+
const val = require('lodash').get(data.translations[lang], key);
|
|
55
|
+
return val === undefined || val === '';
|
|
56
|
+
}).length;
|
|
57
|
+
|
|
58
|
+
status.coverage[lang] = {
|
|
59
|
+
translated: data.allKeys.length - untranslated,
|
|
60
|
+
total: data.allKeys.length,
|
|
61
|
+
percentage: Math.round(((data.allKeys.length - untranslated) / data.allKeys.length) * 100)
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log(JSON.stringify(status, null, 2));
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error(JSON.stringify({ error: err.message }, null, 2));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
async function loadConfig(targetDir, configPath) {
|
|
73
|
+
let config = {};
|
|
74
|
+
const absoluteConfigPath = path.resolve(targetDir, configPath || 'translation.config.json');
|
|
75
|
+
|
|
76
|
+
if (await fs.pathExists(absoluteConfigPath)) {
|
|
77
|
+
config = await fs.readJson(absoluteConfigPath);
|
|
78
|
+
} else {
|
|
79
|
+
const jsConfigPath = path.resolve(targetDir, 'translation.config.js');
|
|
80
|
+
if (await fs.pathExists(jsConfigPath)) {
|
|
81
|
+
config = require(jsConfigPath);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return config;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,66 +1,76 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@tuhama/translation-manager",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"author": "Tuhama <tuhama.gh.qlyshi@gmail.com>",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=18"
|
|
9
|
-
},
|
|
10
|
-
"publishConfig": {
|
|
11
|
-
"access": "public"
|
|
12
|
-
},
|
|
13
|
-
"main": "src/server.js",
|
|
14
|
-
"bin": {
|
|
15
|
-
"translation-manager": "bin/index.js"
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"bin",
|
|
19
|
-
"src",
|
|
20
|
-
"web/dist",
|
|
21
|
-
"README.md",
|
|
22
|
-
"package.json"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"dev-server"
|
|
27
|
-
"dev-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
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
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@tuhama/translation-manager",
|
|
3
|
+
"version": "0.7.1",
|
|
4
|
+
"description": "AI-powered i18n management with context-aware scanning and support for OpenAI, Gemini, and Google Translate.",
|
|
5
|
+
"author": "Tuhama <tuhama.gh.qlyshi@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"main": "src/server.js",
|
|
14
|
+
"bin": {
|
|
15
|
+
"translation-manager": "bin/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"bin",
|
|
19
|
+
"src",
|
|
20
|
+
"web/dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"package.json",
|
|
23
|
+
"translations.skill"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "concurrently \"npm run dev-server\" \"npm run dev-web\"",
|
|
27
|
+
"dev-server": "nodemon bin/index.js",
|
|
28
|
+
"dev-web": "cd web && npm run dev",
|
|
29
|
+
"build": "cd web && npm run build",
|
|
30
|
+
"start": "node bin/index.js",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:web": "cd web && npx vitest run"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/Tuhama/translationManager.git"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"translation",
|
|
40
|
+
"i18n",
|
|
41
|
+
"localization",
|
|
42
|
+
"l10n",
|
|
43
|
+
"react",
|
|
44
|
+
"ui",
|
|
45
|
+
"cli",
|
|
46
|
+
"translation-manager",
|
|
47
|
+
"internationalization",
|
|
48
|
+
"ai",
|
|
49
|
+
"openai",
|
|
50
|
+
"gemini",
|
|
51
|
+
"context-aware",
|
|
52
|
+
"automation"
|
|
53
|
+
],
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/Tuhama/translationManager/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/Tuhama/translationManager#readme",
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@google-cloud/translate": "^8.0.0",
|
|
60
|
+
"chokidar": "^5.0.0",
|
|
61
|
+
"commander": "^14.0.3",
|
|
62
|
+
"cors": "^2.8.6",
|
|
63
|
+
"express": "^5.2.1",
|
|
64
|
+
"express-history-api-fallback": "^2.2.1",
|
|
65
|
+
"fs-extra": "^11.3.4",
|
|
66
|
+
"lodash": "^4.17.23",
|
|
67
|
+
"open": "^11.0.0",
|
|
68
|
+
"picocolors": "^1.1.1"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@vitest/ui": "^4.1.4",
|
|
72
|
+
"concurrently": "^9.2.1",
|
|
73
|
+
"nodemon": "^3.1.14",
|
|
74
|
+
"vitest": "^4.1.4"
|
|
75
|
+
}
|
|
76
|
+
}
|