lingui-po-translate 1.0.3 → 1.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
CHANGED
|
@@ -77,13 +77,10 @@ t({
|
|
|
77
77
|
comment: "@manual:zh-Hans,zh-Hant"
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
-
// Combine with context
|
|
80
|
+
// Combine with context (use ; as separator)
|
|
81
81
|
t({
|
|
82
82
|
message: "Technical term",
|
|
83
|
-
comment:
|
|
84
|
-
@manual:zh-Hans
|
|
85
|
-
@context:Industry-specific terminology
|
|
86
|
-
`
|
|
83
|
+
comment: "@manual:zh-Hans; @context:Industry-specific terminology"
|
|
87
84
|
})
|
|
88
85
|
```
|
|
89
86
|
|
|
@@ -176,6 +173,8 @@ Options:
|
|
|
176
173
|
--baseUrl <url> Custom API base URL for OpenAI-compatible APIs
|
|
177
174
|
--prompt <prompt> Additional instructions for AI translation
|
|
178
175
|
--matcher <matcher> Interpolation matcher: "none", "icu", "i18next", "sprintf"
|
|
176
|
+
--model <model> Model for AI translation (default: "gpt-4o-mini")
|
|
177
|
+
--debug Print debug info including API requests/responses
|
|
179
178
|
-v, --version Output the version number
|
|
180
179
|
-h, --help Display help
|
|
181
180
|
```
|
|
@@ -234,6 +233,48 @@ lingui-po-translate \
|
|
|
234
233
|
--prompt="This is a medical application. Keep technical terms like 'MRI', 'CT scan' in English. Use polite Japanese (敬語)."
|
|
235
234
|
```
|
|
236
235
|
|
|
236
|
+
## Model Selection
|
|
237
|
+
|
|
238
|
+
Specify a different model for translation:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Use GPT-4o for higher quality translations
|
|
242
|
+
lingui-po-translate \
|
|
243
|
+
--srcFile=locales/en.po \
|
|
244
|
+
--targetFile=locales/zh.po \
|
|
245
|
+
--targetLng=zh \
|
|
246
|
+
--service=openai \
|
|
247
|
+
--serviceConfig="YOUR_API_KEY" \
|
|
248
|
+
--model=gpt-4o
|
|
249
|
+
|
|
250
|
+
# Use with DeepSeek
|
|
251
|
+
lingui-po-translate \
|
|
252
|
+
--baseUrl="https://api.deepseek.com/v1" \
|
|
253
|
+
--serviceConfig="YOUR_DEEPSEEK_KEY" \
|
|
254
|
+
--model=deepseek-chat \
|
|
255
|
+
...
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Default model: `gpt-4o-mini`
|
|
259
|
+
|
|
260
|
+
## Debugging
|
|
261
|
+
|
|
262
|
+
Use `--debug` to print API requests and responses:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
lingui-po-translate \
|
|
266
|
+
--srcFile=locales/en.po \
|
|
267
|
+
--targetFile=locales/zh.po \
|
|
268
|
+
--targetLng=zh \
|
|
269
|
+
--service=openai \
|
|
270
|
+
--serviceConfig="YOUR_API_KEY" \
|
|
271
|
+
--debug
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
This will print:
|
|
275
|
+
- System prompt and user prompt sent to the API
|
|
276
|
+
- Full API response including token usage
|
|
277
|
+
|
|
237
278
|
## Weblate Integration
|
|
238
279
|
|
|
239
280
|
For entries marked with `@manual`, the tool copies the original text to `msgstr`. This prevents Weblate from flagging them as "untranslated".
|
|
@@ -67,6 +67,7 @@ async function runTranslationService(rawInputs, args) {
|
|
|
67
67
|
prompt: args.prompt,
|
|
68
68
|
baseUrl: args.baseUrl,
|
|
69
69
|
debug: args.debug,
|
|
70
|
+
model: args.model,
|
|
70
71
|
};
|
|
71
72
|
console.info(`Invoke '${args.service}' from '${args.srcLng}' to '${args.targetLng}' with ${serviceArgs.strings.length} inputs...`);
|
|
72
73
|
const translationService = await (0, service_definitions_1.instantiateTService)(args.service);
|
|
@@ -32,7 +32,7 @@ function formatCliOptions(options) {
|
|
|
32
32
|
}
|
|
33
33
|
exports.formatCliOptions = formatCliOptions;
|
|
34
34
|
async function translateCli(cliArgs) {
|
|
35
|
-
var _a, _b, _c, _d;
|
|
35
|
+
var _a, _b, _c, _d, _e;
|
|
36
36
|
checkForEmptyStringOptions(cliArgs);
|
|
37
37
|
const fileFormats = (0, file_format_definitions_1.getTFileFormatList)();
|
|
38
38
|
const services = (0, service_definitions_1.getTServiceList)();
|
|
@@ -74,6 +74,7 @@ async function translateCli(cliArgs) {
|
|
|
74
74
|
sourceOverride: (0, core_definitions_1.parseSourceOverride)(cliArgs.sourceOverride),
|
|
75
75
|
baseUrl: (_c = cliArgs.baseUrl) !== null && _c !== void 0 ? _c : null,
|
|
76
76
|
debug: (_d = cliArgs.debug) !== null && _d !== void 0 ? _d : false,
|
|
77
|
+
model: (_e = cliArgs.model) !== null && _e !== void 0 ? _e : null,
|
|
77
78
|
};
|
|
78
79
|
const result = await (0, translate_core_1.translateCore)(coreArgs);
|
|
79
80
|
const flushTarget = !oldTarget || !(0, tset_ops_1.areEqual)(oldTarget, result.newTarget);
|
|
@@ -8,11 +8,13 @@ exports.hasManualMarking = exports.shouldSkipForManual = exports.parseExtractedC
|
|
|
8
8
|
* - @manual:zh-Hans,zh-Hant - languages requiring manual translation
|
|
9
9
|
* - @context:text - context for AI translation
|
|
10
10
|
* - Plain text (without @) - also treated as context
|
|
11
|
+
* - Multiple directives can be separated by ; or newline
|
|
11
12
|
*
|
|
12
13
|
* Example:
|
|
14
|
+
* #. @manual:zh-Hans; @context:This is a save button
|
|
15
|
+
* Or:
|
|
13
16
|
* #. @manual:zh-Hans
|
|
14
17
|
* #. @context:This is a save button
|
|
15
|
-
* #. Some additional context
|
|
16
18
|
*
|
|
17
19
|
* @param extracted - The extracted comment string from PO file
|
|
18
20
|
* @returns ParsedComment with manual languages and context
|
|
@@ -25,30 +27,38 @@ function parseExtractedComment(extracted) {
|
|
|
25
27
|
if (!extracted) {
|
|
26
28
|
return result;
|
|
27
29
|
}
|
|
28
|
-
|
|
30
|
+
// Split by newline first, then by ; for each line
|
|
31
|
+
const parts = [];
|
|
32
|
+
for (const line of extracted.split("\n")) {
|
|
33
|
+
for (const part of line.split(";")) {
|
|
34
|
+
const trimmed = part.trim();
|
|
35
|
+
if (trimmed) {
|
|
36
|
+
parts.push(trimmed);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
29
40
|
const contextParts = [];
|
|
30
|
-
for (const
|
|
31
|
-
|
|
32
|
-
if (trimmedLine.startsWith("@manual:")) {
|
|
41
|
+
for (const part of parts) {
|
|
42
|
+
if (part.startsWith("@manual:")) {
|
|
33
43
|
// Parse @manual:zh-Hans,zh-Hant
|
|
34
|
-
const langList =
|
|
44
|
+
const langList = part.substring("@manual:".length).trim();
|
|
35
45
|
if (langList) {
|
|
36
46
|
result.manual = langList.split(",").map((lang) => lang.trim()).filter(Boolean);
|
|
37
47
|
}
|
|
38
48
|
}
|
|
39
|
-
else if (
|
|
49
|
+
else if (part.startsWith("@context:")) {
|
|
40
50
|
// Parse @context:text
|
|
41
|
-
const contextText =
|
|
51
|
+
const contextText = part.substring("@context:".length).trim();
|
|
42
52
|
if (contextText) {
|
|
43
53
|
contextParts.push(contextText);
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
|
-
else if (
|
|
56
|
+
else if (!part.startsWith("@")) {
|
|
47
57
|
// Plain text without @ prefix is also context
|
|
48
|
-
contextParts.push(
|
|
58
|
+
contextParts.push(part);
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
|
-
result.context = contextParts.join("
|
|
61
|
+
result.context = contextParts.join(" ");
|
|
52
62
|
return result;
|
|
53
63
|
}
|
|
54
64
|
exports.parseExtractedComment = parseExtractedComment;
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ function run(process, cliBinDir) {
|
|
|
33
33
|
.option("--sourceOverride <mapping>", "override source language for specific targets (e.g., 'zh-Hant:zh-Hans,pt-BR:pt-PT')")
|
|
34
34
|
.option("--baseUrl <url>", "custom API base URL for OpenAI-compatible services (e.g., 'https://api.openai.com/v1')")
|
|
35
35
|
.option("--debug", "print debug information including API requests")
|
|
36
|
+
.option("--model <model>", "model to use for AI translation services (e.g., gpt-4o-mini, gpt-4o)")
|
|
36
37
|
.version((0, extract_version_1.extractVersion)({ cliBinDir }), "-v, --version")
|
|
37
38
|
.parse(process.argv);
|
|
38
39
|
if ((_a = commander_1.default.args) === null || _a === void 0 ? void 0 : _a.length) {
|
|
@@ -53,6 +54,7 @@ function run(process, cliBinDir) {
|
|
|
53
54
|
sourceOverride: commander_1.default.opts().sourceOverride,
|
|
54
55
|
baseUrl: commander_1.default.opts().baseUrl,
|
|
55
56
|
debug: commander_1.default.opts().debug,
|
|
57
|
+
model: commander_1.default.opts().model,
|
|
56
58
|
};
|
|
57
59
|
(0, translate_cli_1.translateCli)(args)
|
|
58
60
|
.then(() => {
|
|
@@ -5,7 +5,7 @@ const openai_1 = require("openai");
|
|
|
5
5
|
const util_1 = require("../util/util");
|
|
6
6
|
const lodash_1 = require("lodash");
|
|
7
7
|
async function translateSingleString(tString, args) {
|
|
8
|
-
var _a, _b, _c, _d;
|
|
8
|
+
var _a, _b, _c, _d, _e;
|
|
9
9
|
const OPENAI_API_KEY = args.serviceConfig;
|
|
10
10
|
if (!OPENAI_API_KEY || !OPENAI_API_KEY.trim().length) {
|
|
11
11
|
(0, util_1.logFatal)('Missing OpenAI API Key: Please get an API key from https://platform.openai.com/account/api-keys and then call lingui-po-translate with --serviceConfig="YOUR API KEY"');
|
|
@@ -26,9 +26,10 @@ async function translateSingleString(tString, args) {
|
|
|
26
26
|
content: userPrompt,
|
|
27
27
|
},
|
|
28
28
|
];
|
|
29
|
+
const model = (_c = args.model) !== null && _c !== void 0 ? _c : "gpt-4o-mini";
|
|
29
30
|
if (args.debug) {
|
|
30
31
|
console.log("\n[DEBUG] OpenAI Request:");
|
|
31
|
-
console.log(" Model:
|
|
32
|
+
console.log(" Model:", model);
|
|
32
33
|
console.log(" System:", systemPrompt);
|
|
33
34
|
console.log(" User:", userPrompt);
|
|
34
35
|
}
|
|
@@ -39,7 +40,7 @@ async function translateSingleString(tString, args) {
|
|
|
39
40
|
*/
|
|
40
41
|
try {
|
|
41
42
|
const completion = await openai.createChatCompletion({
|
|
42
|
-
model
|
|
43
|
+
model,
|
|
43
44
|
messages: messages,
|
|
44
45
|
temperature: 0,
|
|
45
46
|
max_tokens: 2048,
|
|
@@ -47,7 +48,7 @@ async function translateSingleString(tString, args) {
|
|
|
47
48
|
if (args.debug) {
|
|
48
49
|
console.log("\n[DEBUG] OpenAI Full Response:", JSON.stringify(completion.data, null, 2));
|
|
49
50
|
}
|
|
50
|
-
const text = (
|
|
51
|
+
const text = (_d = completion.data.choices[0].message) === null || _d === void 0 ? void 0 : _d.content;
|
|
51
52
|
if (text == undefined) {
|
|
52
53
|
(0, util_1.logFatal)("OpenAI returned undefined for prompt " + prompt);
|
|
53
54
|
}
|
|
@@ -58,7 +59,7 @@ async function translateSingleString(tString, args) {
|
|
|
58
59
|
(0, util_1.logFatal)("OpenAI: " +
|
|
59
60
|
e.message +
|
|
60
61
|
", Status text: " +
|
|
61
|
-
JSON.stringify((
|
|
62
|
+
JSON.stringify((_e = e === null || e === void 0 ? void 0 : e.response) === null || _e === void 0 ? void 0 : _e.statusText));
|
|
62
63
|
}
|
|
63
64
|
else {
|
|
64
65
|
throw e;
|