@concircle/i18n-ai-translator 0.1.2 β 0.1.3
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 +165 -353
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -3,33 +3,32 @@
|
|
|
3
3
|
<table>
|
|
4
4
|
<tr>
|
|
5
5
|
<td width="200" valign="top">
|
|
6
|
-
<img src="https://
|
|
6
|
+
<img src="https://raw.githubusercontent.com/concircle/i18n-ai-translator/main/assets/logo.png" alt="Concircle logo" />
|
|
7
7
|
</td>
|
|
8
8
|
<td valign="top">
|
|
9
|
-
|
|
9
|
+
Translates UI5 <code>i18n.properties</code> files with OpenAI, preserves placeholders, supports glossary terms, and writes language-specific <code>.properties</code> files.
|
|
10
10
|
</td>
|
|
11
11
|
</tr>
|
|
12
12
|
</table>
|
|
13
13
|
|
|
14
14
|
## Features
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- π¦ **Dual Format**: CommonJS and ES Modules support
|
|
23
|
-
- β
**Fully Tested**: Comprehensive test suite with focus on placeholder preservation
|
|
24
|
-
- π **TypeScript**: Full type safety and IntelliSense support
|
|
16
|
+
- Preserves placeholders like `{0}`, `{name}`, `%s`, `${variable}`, and `%1$s`
|
|
17
|
+
- Supports `missing` and `overwrite` translation modes
|
|
18
|
+
- Applies shared and language-specific glossary terms
|
|
19
|
+
- Writes UI5-style language files such as `i18n_de.properties`
|
|
20
|
+
- Supports optional Unicode escaping with per-language overrides
|
|
21
|
+
- Uses a local cache to avoid repeated translation requests
|
|
25
22
|
|
|
26
23
|
## Installation
|
|
27
24
|
|
|
28
25
|
```bash
|
|
29
|
-
npm install @concircle/i18n-ai-translator
|
|
26
|
+
npm install --save-dev @concircle/i18n-ai-translator
|
|
30
27
|
```
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
## CLI
|
|
30
|
+
|
|
31
|
+
Example `package.json` script:
|
|
33
32
|
|
|
34
33
|
```json
|
|
35
34
|
{
|
|
@@ -39,7 +38,13 @@ Then add a script in the consuming app:
|
|
|
39
38
|
}
|
|
40
39
|
```
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
Show CLI help:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx i18n-ai-translator --help
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Enable Unicode escaping:
|
|
43
48
|
|
|
44
49
|
```json
|
|
45
50
|
{
|
|
@@ -49,426 +54,233 @@ If your target system expects Java-style Unicode escapes in `.properties` files,
|
|
|
49
54
|
}
|
|
50
55
|
```
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```json
|
|
55
|
-
{
|
|
56
|
-
"encodeUnicode": true
|
|
57
|
-
}
|
|
58
|
-
```
|
|
57
|
+
## Configuration
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
Example `i18n-ai.config.json`:
|
|
61
60
|
|
|
62
61
|
```json
|
|
63
62
|
{
|
|
63
|
+
"sourceLanguage": "en",
|
|
64
|
+
"targetLanguages": ["de", "uk"],
|
|
65
|
+
"translationMode": "missing",
|
|
64
66
|
"encodeUnicode": false,
|
|
65
67
|
"languageOptions": {
|
|
66
68
|
"de": { "encodeUnicode": true },
|
|
67
69
|
"uk": { "encodeUnicode": false }
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
This keeps languages like Ukrainian readable in UTF-8:
|
|
73
|
-
|
|
74
|
-
```properties
|
|
75
|
-
ai.button_tooltip = Π¨Π ΠΏΠ»Π°Π½ΡΠ²Π°Π»ΡΠ½ΠΈΠΊ
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Run it with:
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
npm run i18n:translate
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Quick Start
|
|
85
|
-
|
|
86
|
-
### Basic Usage (ES Modules)
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
import { Translator } from '@concircle/i18n-ai-translator';
|
|
90
|
-
|
|
91
|
-
const translator = new Translator({
|
|
92
|
-
provider: 'openai',
|
|
93
|
-
openai: {
|
|
94
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
95
70
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
console.log('Translation complete!', result);
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### With Glossary (Domain Vocabulary)
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
const translator = new Translator({
|
|
111
|
-
provider: 'openai',
|
|
112
|
-
openai: { apiKey: process.env.OPENAI_API_KEY },
|
|
113
|
-
targetLanguages: ['de'],
|
|
114
|
-
glossary: {
|
|
115
|
-
'SAP': { doNotTranslate: true },
|
|
116
|
-
'HANA': { translation: 'SAP HANA', context: 'database' },
|
|
117
|
-
'Fiori': { doNotTranslate: true },
|
|
71
|
+
"provider": "openai",
|
|
72
|
+
"providerOptions": {
|
|
73
|
+
"apiKey": "sk-...",
|
|
74
|
+
"model": "gpt-4.1-mini",
|
|
75
|
+
"temperature": 0,
|
|
76
|
+
"maxOutputTokens": 4000
|
|
118
77
|
},
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const config = loadConfig('./config.json');
|
|
130
|
-
const translator = new Translator(config);
|
|
78
|
+
"files": {
|
|
79
|
+
"input": "./webapp/i18n/i18n.properties"
|
|
80
|
+
},
|
|
81
|
+
"cache": {
|
|
82
|
+
"enabled": true,
|
|
83
|
+
"ttlMs": 604800000
|
|
84
|
+
},
|
|
85
|
+
"batchSize": 20,
|
|
86
|
+
"verbose": false
|
|
87
|
+
}
|
|
131
88
|
```
|
|
132
89
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
### TranslatorConfig Interface
|
|
90
|
+
Supported top-level config fields:
|
|
136
91
|
|
|
137
|
-
```
|
|
92
|
+
```ts
|
|
138
93
|
interface TranslatorConfig {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
94
|
+
sourceLanguage?: string;
|
|
95
|
+
targetLanguages: string[];
|
|
96
|
+
translationMode?: 'missing' | 'overwrite';
|
|
97
|
+
encodeUnicode?: boolean;
|
|
98
|
+
languageOptions?: Record<string, { encodeUnicode?: boolean }>;
|
|
99
|
+
provider?: 'openai';
|
|
100
|
+
providerOptions?: {
|
|
101
|
+
apiKey?: string;
|
|
102
|
+
model?: string;
|
|
103
|
+
baseURL?: string;
|
|
104
|
+
organization?: string;
|
|
105
|
+
temperature?: number;
|
|
106
|
+
maxOutputTokens?: number;
|
|
107
|
+
};
|
|
108
|
+
files?: {
|
|
109
|
+
input?: string;
|
|
110
|
+
outputDir?: string;
|
|
111
|
+
languageFilePattern?: string;
|
|
145
112
|
};
|
|
146
|
-
|
|
147
|
-
encodeUnicode?: boolean; // Default: false, escape non-ASCII as \uXXXX
|
|
148
|
-
languageOptions?: Record<string, {
|
|
149
|
-
encodeUnicode?: boolean; // Per-language override
|
|
150
|
-
}>;
|
|
151
|
-
glossary?: Glossary; // Optional: Domain-specific vocabulary
|
|
113
|
+
glossary?: GlossaryConfig | string;
|
|
152
114
|
cache?: {
|
|
153
|
-
enabled?: boolean;
|
|
154
|
-
|
|
155
|
-
dir?: string;
|
|
115
|
+
enabled?: boolean;
|
|
116
|
+
ttlMs?: number;
|
|
117
|
+
dir?: string;
|
|
156
118
|
};
|
|
157
|
-
|
|
158
|
-
|
|
119
|
+
rules?: string[];
|
|
120
|
+
batchSize?: number;
|
|
121
|
+
verbose?: boolean;
|
|
159
122
|
}
|
|
160
123
|
```
|
|
161
124
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
```json
|
|
165
|
-
{
|
|
166
|
-
"provider": "openai",
|
|
167
|
-
"openai": {
|
|
168
|
-
"apiKey": "sk-...",
|
|
169
|
-
"model": "gpt-4",
|
|
170
|
-
"temperature": 0.3,
|
|
171
|
-
"maxTokens": 2000
|
|
172
|
-
},
|
|
173
|
-
"targetLanguages": ["de", "fr", "es"],
|
|
174
|
-
"encodeUnicode": false,
|
|
175
|
-
"languageOptions": {
|
|
176
|
-
"de": { "encodeUnicode": true },
|
|
177
|
-
"uk": { "encodeUnicode": false }
|
|
178
|
-
},
|
|
179
|
-
"glossary": "./glossary.json",
|
|
180
|
-
"cache": {
|
|
181
|
-
"enabled": true,
|
|
182
|
-
"ttl": 604800000
|
|
183
|
-
},
|
|
184
|
-
"batchSize": 10,
|
|
185
|
-
"debug": false
|
|
186
|
-
}
|
|
187
|
-
```
|
|
125
|
+
## Glossary
|
|
188
126
|
|
|
189
|
-
|
|
127
|
+
Example glossary file:
|
|
190
128
|
|
|
191
129
|
```json
|
|
192
130
|
{
|
|
193
|
-
"
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
"
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
"
|
|
208
|
-
|
|
131
|
+
"shared": [
|
|
132
|
+
{
|
|
133
|
+
"source": "Order",
|
|
134
|
+
"target": "Auftrag",
|
|
135
|
+
"context": "SAP sales document"
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"languages": {
|
|
139
|
+
"de": [
|
|
140
|
+
{
|
|
141
|
+
"source": "Plant",
|
|
142
|
+
"target": "Werk"
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"uk": [
|
|
146
|
+
{
|
|
147
|
+
"source": "AI",
|
|
148
|
+
"target": "Π¨I"
|
|
149
|
+
}
|
|
150
|
+
]
|
|
209
151
|
}
|
|
210
152
|
}
|
|
211
153
|
```
|
|
212
154
|
|
|
213
|
-
##
|
|
155
|
+
## Programmatic Usage
|
|
214
156
|
|
|
215
|
-
|
|
157
|
+
Translate a file directly:
|
|
216
158
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
new Translator(config: TranslatorConfig): Translator
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
#### Methods
|
|
159
|
+
```js
|
|
160
|
+
import { Translator } from '@concircle/i18n-ai-translator';
|
|
224
161
|
|
|
225
|
-
|
|
162
|
+
const translator = new Translator({
|
|
163
|
+
sourceLanguage: 'en',
|
|
164
|
+
targetLanguages: ['de'],
|
|
165
|
+
translationMode: 'missing',
|
|
166
|
+
provider: 'openai',
|
|
167
|
+
providerOptions: {
|
|
168
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
169
|
+
},
|
|
170
|
+
files: {
|
|
171
|
+
input: './webapp/i18n/i18n.properties'
|
|
172
|
+
}
|
|
173
|
+
});
|
|
226
174
|
|
|
227
|
-
|
|
175
|
+
const result = await translator.translateFile();
|
|
176
|
+
console.log(result);
|
|
177
|
+
```
|
|
228
178
|
|
|
229
|
-
|
|
230
|
-
- `job.inputPath`: Path to source `i18n.properties` file
|
|
231
|
-
- `job.outputFormat`: `'new-files'` | `'update-existing'` (default: `'new-files'`)
|
|
232
|
-
- `job.outputDir`: Output directory for new files
|
|
233
|
-
- `job.languages`: Override config languages for this job
|
|
179
|
+
Load config from file:
|
|
234
180
|
|
|
235
|
-
|
|
181
|
+
```js
|
|
182
|
+
import { Translator } from '@concircle/i18n-ai-translator';
|
|
236
183
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
inputPath: './src/i18n/i18n.properties',
|
|
240
|
-
outputFormat: 'new-files',
|
|
241
|
-
outputDir: './src/i18n',
|
|
242
|
-
languages: ['de'], // Optional: override
|
|
184
|
+
const translator = await Translator.fromConfig({
|
|
185
|
+
configPath: './i18n-ai.config.json'
|
|
243
186
|
});
|
|
244
187
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// sourceFile: './src/i18n/i18n.properties',
|
|
248
|
-
// translations: {
|
|
249
|
-
// de: {
|
|
250
|
-
// outputFile: './src/i18n/i18n_de.properties',
|
|
251
|
-
// success: true,
|
|
252
|
-
// translatedKeysCount: 42
|
|
253
|
-
// },
|
|
254
|
-
// fr: {
|
|
255
|
-
// outputFile: './src/i18n/i18n_fr.properties',
|
|
256
|
-
// success: true,
|
|
257
|
-
// translatedKeysCount: 42
|
|
258
|
-
// }
|
|
259
|
-
// }
|
|
260
|
-
// }
|
|
188
|
+
const result = await translator.translateProject();
|
|
189
|
+
console.log(result);
|
|
261
190
|
```
|
|
262
191
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
Clear the translation cache (useful for testing or after glossary changes)
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
translator.clearCache();
|
|
269
|
-
```
|
|
192
|
+
Use the top-level helper:
|
|
270
193
|
|
|
271
|
-
|
|
194
|
+
```js
|
|
195
|
+
import { translateProject } from '@concircle/i18n-ai-translator';
|
|
272
196
|
|
|
273
|
-
|
|
197
|
+
const result = await translateProject({
|
|
198
|
+
inputPath: './webapp/i18n/i18n.properties',
|
|
199
|
+
languages: ['de'],
|
|
200
|
+
dryRun: true
|
|
201
|
+
});
|
|
274
202
|
|
|
275
|
-
|
|
276
|
-
const stats = translator.getCacheStats();
|
|
277
|
-
// { enabled: true, cacheDir: '...', ttl: ..., entriesCount: 5 }
|
|
203
|
+
console.log(result);
|
|
278
204
|
```
|
|
279
205
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
Get current glossary
|
|
283
|
-
|
|
284
|
-
```javascript
|
|
285
|
-
const glossary = translator.getGlossary();
|
|
286
|
-
```
|
|
206
|
+
## Translation Modes
|
|
287
207
|
|
|
288
|
-
|
|
208
|
+
- `missing`: only translates keys that are missing or empty in the target file
|
|
209
|
+
- `overwrite`: retranslates all keys from the source file
|
|
289
210
|
|
|
290
|
-
|
|
211
|
+
## Placeholder Handling
|
|
291
212
|
|
|
292
|
-
|
|
293
|
-
const terms = translator.getGlossaryTerms();
|
|
294
|
-
```
|
|
213
|
+
The translator masks placeholders before sending text to the model and validates that they are still present afterwards.
|
|
295
214
|
|
|
296
|
-
|
|
215
|
+
Supported placeholder styles:
|
|
297
216
|
|
|
298
|
-
|
|
217
|
+
- `{0}`, `{1}`
|
|
218
|
+
- `{name}`, `{email}`
|
|
219
|
+
- `%s`, `%d`
|
|
220
|
+
- `%1$s`, `%2$d`
|
|
221
|
+
- `${variable}`
|
|
299
222
|
|
|
300
|
-
|
|
301
|
-
# Application messages
|
|
302
|
-
app.title=My Application
|
|
303
|
-
app.version=1.0.0
|
|
223
|
+
## Output Files
|
|
304
224
|
|
|
305
|
-
|
|
306
|
-
msg.save=Save {0} items
|
|
307
|
-
msg.delete=Delete {0} from {1}
|
|
225
|
+
By default, UI5-style language files are generated next to the source file:
|
|
308
226
|
|
|
309
|
-
|
|
310
|
-
|
|
227
|
+
- `i18n.properties`
|
|
228
|
+
- `i18n_de.properties`
|
|
229
|
+
- `i18n_fr.properties`
|
|
311
230
|
|
|
312
|
-
|
|
313
|
-
msg.count=Found %d results
|
|
314
|
-
msg.user=User %s not found
|
|
315
|
-
```
|
|
231
|
+
You can override the output directory or file naming pattern in `files.outputDir` and `files.languageFilePattern`.
|
|
316
232
|
|
|
317
|
-
|
|
233
|
+
## Cache
|
|
318
234
|
|
|
319
|
-
|
|
320
|
-
# Application messages
|
|
321
|
-
app.title=Meine Anwendung
|
|
322
|
-
app.version=1.0.0
|
|
235
|
+
Caching is enabled by default. Cache keys include:
|
|
323
236
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
237
|
+
- provider
|
|
238
|
+
- model
|
|
239
|
+
- source language
|
|
240
|
+
- target language
|
|
241
|
+
- source value
|
|
242
|
+
- glossary terms
|
|
243
|
+
- translation rules
|
|
327
244
|
|
|
328
|
-
|
|
329
|
-
form.email=Bitte geben Sie {email} ein
|
|
245
|
+
Default cache location:
|
|
330
246
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
msg.user=Benutzer %s nicht gefunden
|
|
247
|
+
```text
|
|
248
|
+
~/.i18n-ai-translator-cache/
|
|
334
249
|
```
|
|
335
250
|
|
|
336
|
-
## Placeholder Protection
|
|
337
|
-
|
|
338
|
-
All placeholder types are automatically detected and preserved during translation:
|
|
339
|
-
|
|
340
|
-
- `{0}`, `{1}`, etc. - Numeric placeholders
|
|
341
|
-
- `{name}`, `{email}`, etc. - Named placeholders
|
|
342
|
-
- `%s`, `%d`, etc. - Printf-style format specifiers
|
|
343
|
-
- `${variable}` - Template variable syntax
|
|
344
|
-
- `%1$s`, `%2$d`, etc. - Positional format specifiers
|
|
345
|
-
|
|
346
251
|
## Environment Variables
|
|
347
252
|
|
|
348
|
-
|
|
253
|
+
Supported environment variables:
|
|
349
254
|
|
|
350
255
|
```bash
|
|
351
256
|
export OPENAI_API_KEY=sk-...
|
|
352
|
-
export OPENAI_MODEL=gpt-4
|
|
353
|
-
export TARGET_LANGUAGES=de,fr,es
|
|
354
|
-
export GLOSSARY_FILE=./glossary.json
|
|
257
|
+
export OPENAI_MODEL=gpt-4.1-mini
|
|
355
258
|
```
|
|
356
259
|
|
|
357
260
|
## Examples
|
|
358
261
|
|
|
359
|
-
See `examples/`
|
|
360
|
-
|
|
361
|
-
- `basic.mjs` - Minimal setup with environment variables
|
|
362
|
-
- `with-glossary.mjs` - Using domain-specific vocabulary
|
|
363
|
-
- `advanced.mjs` - Full configuration with caching and debugging
|
|
364
|
-
|
|
365
|
-
Run examples:
|
|
262
|
+
See [`examples/`](./examples/) for small runnable examples:
|
|
366
263
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
## Caching
|
|
373
|
-
|
|
374
|
-
The translator uses smart, local file-based caching to:
|
|
375
|
-
|
|
376
|
-
- **Reduce API costs**: Skip repeated translations
|
|
377
|
-
- **Improve performance**: Instant retrieval from cache
|
|
378
|
-
- **Invalidate on glossary changes**: Cache is invalidated when glossary is updated
|
|
379
|
-
- **Support TTL**: Default 7-day cache expiration
|
|
380
|
-
|
|
381
|
-
Cache location: `~/.i18n-ai-translator-cache/`
|
|
382
|
-
|
|
383
|
-
### Cache Configuration
|
|
384
|
-
|
|
385
|
-
```javascript
|
|
386
|
-
cache: {
|
|
387
|
-
enabled: true, // Enable/disable caching
|
|
388
|
-
ttl: 7 * 24 * 60 * 60 * 1000, // 7 days in milliseconds
|
|
389
|
-
dir: '/custom/cache/dir' // Custom cache directory
|
|
390
|
-
}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
## Performance & Batching
|
|
394
|
-
|
|
395
|
-
Translations are processed in parallel batches for efficiency:
|
|
396
|
-
|
|
397
|
-
```javascript
|
|
398
|
-
batchSize: 10 // Process up to 10 translations in parallel
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
This balances between:
|
|
402
|
-
- **Throughput**: Parallel processing speeds up translation
|
|
403
|
-
- **API Limits**: Stays within OpenAI rate limits (default 10 concurrent)
|
|
404
|
-
- **Cost**: Fewer API calls due to combining texts
|
|
405
|
-
|
|
406
|
-
## Future Provider Support
|
|
264
|
+
- [`basic.mjs`](./examples/basic.mjs)
|
|
265
|
+
- [`with-glossary.mjs`](./examples/with-glossary.mjs)
|
|
266
|
+
- [`advanced.mjs`](./examples/advanced.mjs)
|
|
407
267
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
```typescript
|
|
411
|
-
interface AIProvider {
|
|
412
|
-
translateTexts(texts: string[], targetLanguage: string, context?: string): Promise<string[]>;
|
|
413
|
-
getName(): string;
|
|
414
|
-
}
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
Future providers planned:
|
|
418
|
-
- Claude (Anthropic)
|
|
419
|
-
- Gemini (Google)
|
|
420
|
-
- Offline/Local models
|
|
421
|
-
|
|
422
|
-
## Error Handling
|
|
423
|
-
|
|
424
|
-
The translator provides detailed error information:
|
|
425
|
-
|
|
426
|
-
```javascript
|
|
427
|
-
try {
|
|
428
|
-
const result = await translator.translate({...});
|
|
429
|
-
|
|
430
|
-
for (const [lang, langResult] of Object.entries(result.translations)) {
|
|
431
|
-
if (!langResult.success) {
|
|
432
|
-
console.error(`Translation failed for ${lang}: ${langResult.error}`);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
} catch (error) {
|
|
436
|
-
console.error('Translation job failed:', error.message);
|
|
437
|
-
}
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
## Testing
|
|
441
|
-
|
|
442
|
-
Run the comprehensive test suite:
|
|
268
|
+
## Development
|
|
443
269
|
|
|
444
270
|
```bash
|
|
445
|
-
npm
|
|
446
|
-
npm run
|
|
447
|
-
npm
|
|
271
|
+
npm run build
|
|
272
|
+
npm run lint
|
|
273
|
+
npm test
|
|
448
274
|
```
|
|
449
275
|
|
|
450
|
-
Tests include:
|
|
451
|
-
- β
Placeholder extraction and restoration (critical)
|
|
452
|
-
- β
Properties file parsing and writing
|
|
453
|
-
- β
Glossary management and injection
|
|
454
|
-
- β
Cache behavior and TTL
|
|
455
|
-
- β
Configuration validation
|
|
456
|
-
|
|
457
276
|
## License
|
|
458
277
|
|
|
459
278
|
MIT Β© 2026 Herbert Kaintz - Concircle
|
|
460
279
|
|
|
461
280
|
## Contributing
|
|
462
281
|
|
|
463
|
-
|
|
282
|
+
See [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
464
283
|
|
|
465
284
|
## Security
|
|
466
285
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
## Support
|
|
470
|
-
|
|
471
|
-
- π [API Documentation](./docs/)
|
|
472
|
-
- π [Examples](./examples/)
|
|
473
|
-
- π€ [Contributing Guide](./CONTRIBUTING.md)
|
|
474
|
-
- π [Security Policy](./SECURITY.md)
|
|
286
|
+
See [`SECURITY.md`](./SECURITY.md).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@concircle/i18n-ai-translator",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Translates UI5 i18n.properties files with OpenAI, preserving placeholders and glossary terms.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"i18n-ai-translator": "./bin/i18n-ai-translator.mjs"
|
|
@@ -64,12 +64,12 @@
|
|
|
64
64
|
"license": "MIT",
|
|
65
65
|
"repository": {
|
|
66
66
|
"type": "git",
|
|
67
|
-
"url": "https://
|
|
67
|
+
"url": "https://github.com/concircle/i18n-ai-translator.git"
|
|
68
68
|
},
|
|
69
69
|
"bugs": {
|
|
70
|
-
"url": "https://
|
|
70
|
+
"url": "https://github.com/concircle/i18n-ai-translator/issues"
|
|
71
71
|
},
|
|
72
|
-
"homepage": "https://
|
|
72
|
+
"homepage": "https://www.concircle.com/en/",
|
|
73
73
|
"engines": {
|
|
74
74
|
"node": ">=20.0.0"
|
|
75
75
|
}
|