msgai-cli 1.1.1 → 1.2.0
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/CHANGELOG.md +6 -0
- package/README.md +2 -1
- package/dist/src/cli/index.js +22 -2
- package/dist/src/cli/runTranslate.js +4 -4
- package/dist/src/po.js +6 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [1.2.0](https://github.com/AlexMost/msgai/compare/v1.1.1...v1.2.0) (2026-03-02)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- add configurable po fold length ([343775c](https://github.com/AlexMost/msgai/commit/343775c8046abf6705ca02d687305d1db1e2c9c6))
|
|
10
|
+
|
|
5
11
|
## [1.1.1](https://github.com/AlexMost/msgai/compare/v1.1.0...v1.1.1) (2026-03-01)
|
|
6
12
|
|
|
7
13
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ msgai messages.po --api-key sk-...
|
|
|
79
79
|
Usage:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--debug]
|
|
82
|
+
msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--fold-length N] [--debug]
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
Options:
|
|
@@ -89,6 +89,7 @@ Options:
|
|
|
89
89
|
- `--source-lang LANG`: set the source language of `msgid` strings as an ISO 639-1 code such as `en` or `uk`
|
|
90
90
|
- `--model MODEL`: set the OpenAI model used for translation; default is `gpt-4o`. Only models with `json_schema` structured outputs are supported.
|
|
91
91
|
- `--api-key KEY`: pass the OpenAI API key directly instead of using `OPENAI_API_KEY`
|
|
92
|
+
- `--fold-length N`: set PO line fold length when writing files. Use `0` to disable folding and minimize formatting-only diffs. Default: `0`
|
|
92
93
|
- `--debug`: print debug logs for batch preparation, OpenAI request retries, request payloads, and raw response validation
|
|
93
94
|
- `--help`: print command usage
|
|
94
95
|
|
package/dist/src/cli/index.js
CHANGED
|
@@ -8,11 +8,23 @@ const yargs_1 = __importDefault(require("yargs/yargs"));
|
|
|
8
8
|
const helpers_1 = require("yargs/helpers");
|
|
9
9
|
const debug_1 = require("../debug");
|
|
10
10
|
const runTranslate_1 = require("./runTranslate");
|
|
11
|
+
function normalizeFoldLength(value) {
|
|
12
|
+
if (value == null) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || !Number.isInteger(value)) {
|
|
16
|
+
throw new Error('Invalid --fold-length. Expected a non-negative integer.');
|
|
17
|
+
}
|
|
18
|
+
if (value < 0) {
|
|
19
|
+
throw new Error('Invalid --fold-length. Expected a non-negative integer.');
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
11
23
|
function parseArgs(argv) {
|
|
12
24
|
try {
|
|
13
25
|
const parsedArgs = (0, yargs_1.default)(argv)
|
|
14
26
|
.scriptName('msgai')
|
|
15
|
-
.usage('Usage: msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--debug]')
|
|
27
|
+
.usage('Usage: msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--fold-length N] [--debug]')
|
|
16
28
|
.option('dry-run', {
|
|
17
29
|
type: 'boolean',
|
|
18
30
|
default: false,
|
|
@@ -33,6 +45,10 @@ function parseArgs(argv) {
|
|
|
33
45
|
.option('model', {
|
|
34
46
|
type: 'string',
|
|
35
47
|
description: 'OpenAI model to use for translation. Default: gpt-4o',
|
|
48
|
+
})
|
|
49
|
+
.option('fold-length', {
|
|
50
|
+
type: 'number',
|
|
51
|
+
description: 'PO line fold length when writing files. Use 0 to disable folding. Default: 0',
|
|
36
52
|
})
|
|
37
53
|
.option('help', {
|
|
38
54
|
alias: 'h',
|
|
@@ -61,6 +77,7 @@ function parseArgs(argv) {
|
|
|
61
77
|
: undefined;
|
|
62
78
|
const modelRaw = parsedArgs.model;
|
|
63
79
|
const model = modelRaw != null && String(modelRaw).trim() !== '' ? String(modelRaw).trim() : undefined;
|
|
80
|
+
const foldLength = normalizeFoldLength(parsedArgs['fold-length']);
|
|
64
81
|
if (positionalArgs.length > 1) {
|
|
65
82
|
const result = {
|
|
66
83
|
dryRun: Boolean(parsedArgs['dry-run']),
|
|
@@ -69,6 +86,7 @@ function parseArgs(argv) {
|
|
|
69
86
|
sourceLang,
|
|
70
87
|
model,
|
|
71
88
|
includeFuzzy: Boolean(parsedArgs['include-fuzzy']),
|
|
89
|
+
foldLength,
|
|
72
90
|
debug: Boolean(parsedArgs.debug),
|
|
73
91
|
error: `Unexpected argument: ${positionalArgs[1]}`,
|
|
74
92
|
};
|
|
@@ -82,6 +100,7 @@ function parseArgs(argv) {
|
|
|
82
100
|
sourceLang,
|
|
83
101
|
model,
|
|
84
102
|
includeFuzzy: Boolean(parsedArgs['include-fuzzy']),
|
|
103
|
+
foldLength,
|
|
85
104
|
debug: Boolean(parsedArgs.debug),
|
|
86
105
|
};
|
|
87
106
|
return result;
|
|
@@ -91,7 +110,7 @@ function parseArgs(argv) {
|
|
|
91
110
|
return { dryRun: false, help: false, error: message };
|
|
92
111
|
}
|
|
93
112
|
}
|
|
94
|
-
const USAGE = 'Usage: msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--debug]';
|
|
113
|
+
const USAGE = 'Usage: msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--fold-length N] [--debug]';
|
|
95
114
|
function main(argv) {
|
|
96
115
|
const args = parseArgs(argv);
|
|
97
116
|
(0, debug_1.initDebugLogger)(args.debug);
|
|
@@ -116,6 +135,7 @@ function main(argv) {
|
|
|
116
135
|
sourceLang: args.sourceLang,
|
|
117
136
|
model: args.model,
|
|
118
137
|
includeFuzzy: args.includeFuzzy,
|
|
138
|
+
foldLength: args.foldLength,
|
|
119
139
|
debug: args.debug,
|
|
120
140
|
});
|
|
121
141
|
if (result instanceof Promise) {
|
|
@@ -48,7 +48,7 @@ function getInvalidModelMessage(model) {
|
|
|
48
48
|
`Supported model families: ${translate_1.SUPPORTED_STRUCTURED_OUTPUT_MODELS.join(', ')}.`,
|
|
49
49
|
].join(' ');
|
|
50
50
|
}
|
|
51
|
-
async function runTranslate(poFilePath, apiKey, sourceLang, model, includeFuzzy, debug) {
|
|
51
|
+
async function runTranslate(poFilePath, apiKey, sourceLang, model, includeFuzzy, foldLength, debug) {
|
|
52
52
|
(0, debug_1.initDebugLogger)(debug);
|
|
53
53
|
const debugLogger = (0, debug_1.getDebugLogger)();
|
|
54
54
|
try {
|
|
@@ -117,7 +117,7 @@ async function runTranslate(poFilePath, apiKey, sourceLang, model, includeFuzzy,
|
|
|
117
117
|
if (includeFuzzy) {
|
|
118
118
|
(0, po_1.clearFuzzyFromEntries)(parsedPo, batchResults);
|
|
119
119
|
}
|
|
120
|
-
node_fs_1.default.writeFileSync(poFilePath, (0, po_1.compilePo)(parsedPo));
|
|
120
|
+
node_fs_1.default.writeFileSync(poFilePath, (0, po_1.compilePo)(parsedPo, { foldLength }));
|
|
121
121
|
debugLogger.log('cli.runTranslate', 'Wrote translated batch back to PO file', {
|
|
122
122
|
batch: batchNum,
|
|
123
123
|
poFilePath,
|
|
@@ -139,7 +139,7 @@ async function runTranslate(poFilePath, apiKey, sourceLang, model, includeFuzzy,
|
|
|
139
139
|
return 1;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
const USAGE = 'Usage: msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--debug]';
|
|
142
|
+
const USAGE = 'Usage: msgai <file.po> [--dry-run] [--api-key KEY] [--source-lang LANG] [--model MODEL] [--include-fuzzy] [--fold-length N] [--debug]';
|
|
143
143
|
function runTranslateCommand(args) {
|
|
144
144
|
(0, debug_1.initDebugLogger)(args.debug);
|
|
145
145
|
const debugLogger = (0, debug_1.getDebugLogger)();
|
|
@@ -190,7 +190,7 @@ function runTranslateCommand(args) {
|
|
|
190
190
|
console.warn(message.replace('pass apiKey in options', 'pass --api-key'));
|
|
191
191
|
return 1;
|
|
192
192
|
}
|
|
193
|
-
return runTranslate(args.poFilePath, resultApiKey, args.sourceLang, args.model, args.includeFuzzy, args.debug);
|
|
193
|
+
return runTranslate(args.poFilePath, resultApiKey, args.sourceLang, args.model, args.includeFuzzy, args.foldLength, args.debug);
|
|
194
194
|
}
|
|
195
195
|
try {
|
|
196
196
|
const poContent = node_fs_1.default.readFileSync(args.poFilePath, 'utf8');
|
package/dist/src/po.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.applyTranslations = applyTranslations;
|
|
|
10
10
|
exports.clearFuzzyFromEntries = clearFuzzyFromEntries;
|
|
11
11
|
exports.compilePo = compilePo;
|
|
12
12
|
const gettext_parser_1 = require("gettext-parser");
|
|
13
|
+
const DEFAULT_FOLD_LENGTH = 0;
|
|
13
14
|
function getUntranslatedMsgids(parsedPo) {
|
|
14
15
|
const untranslatedMsgids = [];
|
|
15
16
|
const translations = parsedPo.translations;
|
|
@@ -154,6 +155,9 @@ function clearFuzzyFromEntries(parsedPo, results) {
|
|
|
154
155
|
/**
|
|
155
156
|
* Compiles the parsed PO to a buffer (no file I/O).
|
|
156
157
|
*/
|
|
157
|
-
function compilePo(parsedPo) {
|
|
158
|
-
return gettext_parser_1.po.compile(parsedPo
|
|
158
|
+
function compilePo(parsedPo, options) {
|
|
159
|
+
return gettext_parser_1.po.compile(parsedPo, {
|
|
160
|
+
foldLength: options?.foldLength ?? DEFAULT_FOLD_LENGTH,
|
|
161
|
+
sort: false,
|
|
162
|
+
});
|
|
159
163
|
}
|