@wbcom/i18n-ai 0.1.0 → 0.1.2

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.
Files changed (2) hide show
  1. package/lib/translate.js +27 -8
  2. package/package.json +1 -1
package/lib/translate.js CHANGED
@@ -59,16 +59,31 @@ async function translatePo(poPath, loc, cfg, log = () => {}) {
59
59
  const total = items.length;
60
60
  log(`${loc.locale}: ${total} strings to fill (model=${model}, engine=${engine}, nplurals=${nplurals})`);
61
61
  let filled = 0;
62
- for (let i = 0; i < total; i += batchSize) {
63
- const chunk = items.slice(i, i + batchSize);
62
+ const tries = cfg.retries || 3;
63
+
64
+ // Translate a chunk; on persistent malformed-JSON failure, split and recurse so
65
+ // a single quote-breaking string is isolated and skipped alone — not its 40
66
+ // neighbours. (A 1-string chunk that still fails is the one bad string.)
67
+ async function processChunk(chunk) {
68
+ if (!chunk.length) return;
64
69
  const input = {};
65
70
  chunk.forEach((it, j) => { input[j] = it.src; });
66
- let res;
67
- try {
68
- res = await translateBatch(buildPrompt(cfg, loc, input), model, engine);
69
- } catch (err) {
70
- log(` ${loc.locale}: batch ${i} error: ${err.message}`);
71
- continue;
71
+ let res = null;
72
+ for (let attempt = 1; attempt <= tries && !res; attempt++) {
73
+ try {
74
+ res = await translateBatch(buildPrompt(cfg, loc, input), model, engine);
75
+ } catch (err) {
76
+ if (attempt === tries && chunk.length === 1) {
77
+ log(` ${loc.locale}: skipped 1 unparseable string: ${err.message}`);
78
+ }
79
+ }
80
+ }
81
+ if (!res) {
82
+ if (chunk.length === 1) return; // give up on the single bad string
83
+ const mid = Math.floor(chunk.length / 2);
84
+ await processChunk(chunk.slice(0, mid));
85
+ await processChunk(chunk.slice(mid));
86
+ return;
72
87
  }
73
88
  chunk.forEach((it, j) => {
74
89
  const t = res[j] != null ? String(res[j]) : '';
@@ -77,6 +92,10 @@ async function translatePo(poPath, loc, cfg, log = () => {}) {
77
92
  touched.add(it.e);
78
93
  filled++;
79
94
  });
95
+ }
96
+
97
+ for (let i = 0; i < total; i += batchSize) {
98
+ await processChunk(items.slice(i, i + batchSize));
80
99
  log(` ${loc.locale}: ${Math.min(i + batchSize, total)}/${total}`);
81
100
  }
82
101
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbcom/i18n-ai",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "AI-translate WordPress plugin/theme .po files: sync new strings (msgmerge), translate (Claude), validate placeholders, compile .mo + .json. Wires into grunt/release.",
5
5
  "keywords": [
6
6
  "wordpress",