@adminforth/i18n 1.0.18-next.1 → 1.0.18-next.10

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 (3) hide show
  1. package/dist/index.js +103 -77
  2. package/index.ts +140 -100
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13,6 +13,9 @@ import path from 'path';
13
13
  import fs from 'fs-extra';
14
14
  import chokidar from 'chokidar';
15
15
  import { AsyncQueue } from '@sapphire/async-queue';
16
+ console.log = (...args) => {
17
+ process.stdout.write(args.join(" ") + "\n");
18
+ };
16
19
  const processFrontendMessagesQueue = new AsyncQueue();
17
20
  const SLAVIC_PLURAL_EXAMPLES = {
18
21
  uk: 'яблук | Яблуко | Яблука | Яблук', // zero | singular | 2-4 | 5+
@@ -141,6 +144,7 @@ export default class I18N extends AdminForthPlugin {
141
144
  if (!enColumn) {
142
145
  throw new Error(`Field ${this.enFieldName} not found column to store english original string in resource ${resourceConfig.resourceId}`);
143
146
  }
147
+ enColumn.editReadonly = true;
144
148
  // if sourceFieldName defined, check it exists
145
149
  if (this.options.sourceFieldName) {
146
150
  if (!resourceConfig.columns.find(c => c.name === this.options.sourceFieldName)) {
@@ -282,15 +286,17 @@ export default class I18N extends AdminForthPlugin {
282
286
  translatedCount = yield this.bulkTranslate({ selectedIds });
283
287
  }
284
288
  catch (e) {
289
+ process.env.HEAVY_DEBUG && console.error('🪲⛔ bulkTranslate error', e);
285
290
  if (e instanceof AiTranslateError) {
286
- process.env.HEAVY_DEBUG && console.error('🪲⛔ bulkTranslate error', e);
287
291
  return { ok: false, error: e.message };
288
292
  }
293
+ throw e;
289
294
  }
290
- process.env.HEAVY_DEBUG && console.log('🪲bulkTranslate done', selectedIds);
295
+ process.env.HEAVY_DEBUG && console.log('🪲bulkTranslate done', translatedCount);
291
296
  this.updateUntranslatedMenuBadge();
292
297
  return {
293
- ok: true, error: undefined,
298
+ ok: true,
299
+ error: undefined,
294
300
  successMessage: yield tr(`Translated {count} items`, 'backend', {
295
301
  count: translatedCount,
296
302
  }),
@@ -323,6 +329,84 @@ export default class I18N extends AdminForthPlugin {
323
329
  });
324
330
  });
325
331
  }
332
+ translateToLang(langIsoCode_1, strings_1) {
333
+ return __awaiter(this, arguments, void 0, function* (langIsoCode, strings, plurals = false, translations, updateStrings = {}) {
334
+ const maxKeysInOneReq = 10;
335
+ if (strings.length === 0) {
336
+ return [];
337
+ }
338
+ if (strings.length > maxKeysInOneReq) {
339
+ let totalTranslated = [];
340
+ for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
341
+ const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
342
+ process.env.HEAVY_DEBUG && console.log('🪲🔪slicedStrings len', slicedStrings.length);
343
+ const madeKeys = yield this.translateToLang(langIsoCode, slicedStrings, plurals, translations, updateStrings);
344
+ totalTranslated = totalTranslated.concat(madeKeys);
345
+ }
346
+ return totalTranslated;
347
+ }
348
+ const lang = langIsoCode;
349
+ const langName = iso6391.getName(lang);
350
+ const requestSlavicPlurals = Object.keys(SLAVIC_PLURAL_EXAMPLES).includes(lang) && plurals;
351
+ const prompt = `
352
+ I need to translate strings in JSON to ${lang} (${langName}) language from English for my web app.
353
+ ${requestSlavicPlurals ? `You should provide 4 translations (in format zero | singular | 2-4 | 5+) e.g. ${SLAVIC_PLURAL_EXAMPLES[lang]}` : ''}
354
+ Keep keys, as is, write translation into values! Here are the strings:
355
+
356
+ \`\`\`json
357
+ ${JSON.stringify(strings.reduce((acc, s) => {
358
+ acc[s.en_string] = '';
359
+ return acc;
360
+ }, {}), null, 2)}
361
+ \`\`\`
362
+ `;
363
+ // process.env.HEAVY_DEBUG && console.log('🧠 llm prompt', prompt);
364
+ // call OpenAI
365
+ const resp = yield this.options.completeAdapter.complete(prompt, [], 300);
366
+ // process.env.HEAVY_DEBUG && console.log('🧠 llm resp', resp);
367
+ if (resp.error) {
368
+ throw new AiTranslateError(resp.error);
369
+ }
370
+ // parse response like
371
+ // Here are the translations for the strings you provided:
372
+ // ```json
373
+ // [{"live": "canlı"}, {"Table Games": "Masa Oyunları"}]
374
+ // ```
375
+ let res;
376
+ try {
377
+ res = resp.content.split("```json")[1].split("```")[0];
378
+ }
379
+ catch (e) {
380
+ console.error(`Error in parsing LLM resp: ${resp}\n Prompt was: ${prompt}\n Resp was: ${JSON.stringify(resp)}`);
381
+ return [];
382
+ }
383
+ try {
384
+ res = JSON.parse(res);
385
+ }
386
+ catch (e) {
387
+ console.error(`Error in parsing LLM resp json: ${resp}\n Prompt was: ${prompt}\n Resp was: ${JSON.stringify(resp)}`);
388
+ return [];
389
+ }
390
+ for (const [enStr, translatedStr] of Object.entries(res)) {
391
+ const translationsTargeted = translations.filter(t => t[this.enFieldName] === enStr);
392
+ // might be several with same en_string
393
+ for (const translation of translationsTargeted) {
394
+ //translation[this.trFieldNames[lang]] = translatedStr;
395
+ // process.env.HEAVY_DEBUG && console.log(`🪲translated to ${lang} ${translation.en_string}, ${translatedStr}`)
396
+ if (!updateStrings[translation[this.primaryKeyFieldName]]) {
397
+ updateStrings[translation[this.primaryKeyFieldName]] = {
398
+ updates: {},
399
+ translatedStr,
400
+ category: translation[this.options.categoryFieldName],
401
+ strId: translation[this.primaryKeyFieldName],
402
+ };
403
+ }
404
+ updateStrings[translation[this.primaryKeyFieldName]].updates[this.trFieldNames[lang]] = translatedStr;
405
+ }
406
+ }
407
+ return Object.keys(updateStrings);
408
+ });
409
+ }
326
410
  // returns translated count
327
411
  bulkTranslate(_a) {
328
412
  return __awaiter(this, arguments, void 0, function* ({ selectedIds }) {
@@ -345,96 +429,35 @@ export default class I18N extends AdminForthPlugin {
345
429
  }
346
430
  }
347
431
  }
348
- const maxKeysInOneReq = 10;
349
432
  const updateStrings = {};
350
- const translateToLang = (langIsoCode_1, strings_1, ...args_1) => __awaiter(this, [langIsoCode_1, strings_1, ...args_1], void 0, function* (langIsoCode, strings, plurals = false) {
351
- if (strings.length === 0) {
352
- return 0;
353
- }
354
- if (strings.length > maxKeysInOneReq) {
355
- let totalTranslated = 0;
356
- for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
357
- const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
358
- process.env.HEAVY_DEBUG && console.log('🪲🔪slicedStrings len', slicedStrings.length);
359
- totalTranslated += yield translateToLang(langIsoCode, slicedStrings, plurals);
360
- }
361
- return totalTranslated;
362
- }
363
- const lang = langIsoCode;
364
- const requestSlavicPlurals = Object.keys(SLAVIC_PLURAL_EXAMPLES).includes(lang) && plurals;
365
- const prompt = `
366
- I need to translate strings in JSON to ${lang} language from English for my web app.
367
- ${requestSlavicPlurals ? `You should provide 4 translations (in format zero | singular | 2-4 | 5+) e.g. ${SLAVIC_PLURAL_EXAMPLES[lang]}` : ''}
368
- Keep keys, as is, write translation into values! Here are the strings:
369
-
370
- \`\`\`json
371
- ${JSON.stringify(strings.reduce((acc, s) => {
372
- acc[s.en_string] = '';
373
- return acc;
374
- }, {}), null, 2)}
375
- \`\`\`
376
- `;
377
- process.env.HEAVY_DEBUG && console.log('🧠 llm prompt', prompt);
378
- // call OpenAI
379
- const resp = yield this.options.completeAdapter.complete(prompt, [], 300);
380
- process.env.HEAVY_DEBUG && console.log('🧠 llm resp', resp);
381
- if (resp.error) {
382
- throw new AiTranslateError(resp.error);
383
- }
384
- // parse response like
385
- // Here are the translations for the strings you provided:
386
- // ```json
387
- // [{"live": "canlı"}, {"Table Games": "Masa Oyunları"}]
388
- // ```
389
- let res;
390
- try {
391
- res = resp.content.split("```json")[1].split("```")[0];
392
- }
393
- catch (e) {
394
- console.error('error in parsing OpenAI', resp);
395
- throw new AiTranslateError('Error in parsing OpenAI response');
396
- }
397
- res = JSON.parse(res);
398
- for (const [enStr, translatedStr] of Object.entries(res)) {
399
- const translationsTargeted = translations.filter(t => t[this.enFieldName] === enStr);
400
- // might be several with same en_string
401
- for (const translation of translationsTargeted) {
402
- //translation[this.trFieldNames[lang]] = translatedStr;
403
- // process.env.HEAVY_DEBUG && console.log(`🪲translated to ${lang} ${translation.en_string}, ${translatedStr}`)
404
- if (!updateStrings[translation[this.primaryKeyFieldName]]) {
405
- updateStrings[translation[this.primaryKeyFieldName]] = {
406
- updates: {},
407
- translatedStr,
408
- category: translation[this.options.categoryFieldName],
409
- strId: translation[this.primaryKeyFieldName],
410
- };
411
- }
412
- updateStrings[translation[this.primaryKeyFieldName]].updates[this.trFieldNames[lang]] = translatedStr;
413
- }
414
- }
415
- return Object.keys(updateStrings).length;
416
- });
417
433
  const langsInvolved = new Set(Object.keys(needToTranslateByLang));
418
- let totalTranslated = 0;
434
+ let totalTranslated = [];
435
+ process.env.HEAVY_DEBUG && console.log(' 🐛starting Promise.all Object.entries(needToTranslateByLang)');
419
436
  yield Promise.all(Object.entries(needToTranslateByLang).map((_b) => __awaiter(this, [_b], void 0, function* ([lang, strings]) {
420
437
  // first translate without plurals
421
438
  const stringsWithoutPlurals = strings.filter(s => !s.en_string.includes('|'));
422
- totalTranslated += yield translateToLang(lang, stringsWithoutPlurals, false);
439
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} noplurals started ${stringsWithoutPlurals.length}`);
440
+ const noPluralKeys = yield this.translateToLang(lang, stringsWithoutPlurals, false, translations, updateStrings);
441
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} noplurals finished`);
423
442
  const stringsWithPlurals = strings.filter(s => s.en_string.includes('|'));
424
- totalTranslated += yield translateToLang(lang, stringsWithPlurals, true);
443
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} plurals started ${stringsWithPlurals.length}`);
444
+ const pluralKeys = yield this.translateToLang(lang, stringsWithPlurals, true, translations, updateStrings);
445
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} plurals finished`);
446
+ totalTranslated = totalTranslated.concat(noPluralKeys, pluralKeys);
425
447
  })));
448
+ process.env.HEAVY_DEBUG && console.log('✅ updateStrings were formed', (new Set(totalTranslated)));
426
449
  yield Promise.all(Object.entries(updateStrings).map((_c) => __awaiter(this, [_c], void 0, function* ([_, { updates, strId }]) {
427
450
  // because this will translate all languages, we can set completedLangs to all languages
428
451
  const futureCompletedFieldValue = this.fullCompleatedFieldValue;
429
452
  yield this.adminforth.resource(this.resourceConfig.resourceId).update(strId, Object.assign(Object.assign({}, updates), { [this.options.completedFieldName]: futureCompletedFieldValue }));
430
453
  })));
431
454
  for (const lang of langsInvolved) {
432
- this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
455
+ yield this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
433
456
  for (const [enStr, { category }] of Object.entries(updateStrings)) {
434
- this.cache.clear(`${this.resourceConfig.resourceId}:${category}:${lang}:${enStr}`);
457
+ yield this.cache.clear(`${this.resourceConfig.resourceId}:${category}:${lang}:${enStr}`);
435
458
  }
436
459
  }
437
- return totalTranslated;
460
+ return new Set(totalTranslated).size;
438
461
  });
439
462
  }
440
463
  processExtractedMessages(adminforth, filePath) {
@@ -506,6 +529,9 @@ ${JSON.stringify(strings.reduce((acc, s) => {
506
529
  validateConfigAfterDiscover(adminforth, resourceConfig) {
507
530
  // optional method where you can safely check field types after database discovery was performed
508
531
  // ensure each trFieldName (apart from enFieldName) is nullable column of type string
532
+ if (this.options.completeAdapter) {
533
+ this.options.completeAdapter.validate();
534
+ }
509
535
  for (const lang of this.options.supportedLanguages) {
510
536
  if (lang === 'en') {
511
537
  continue;
package/index.ts CHANGED
@@ -7,6 +7,11 @@ import fs from 'fs-extra';
7
7
  import chokidar from 'chokidar';
8
8
  import { AsyncQueue } from '@sapphire/async-queue';
9
9
 
10
+
11
+ console.log = (...args) => {
12
+ process.stdout.write(args.join(" ") + "\n");
13
+ };
14
+
10
15
  const processFrontendMessagesQueue = new AsyncQueue();
11
16
 
12
17
  const SLAVIC_PLURAL_EXAMPLES = {
@@ -156,6 +161,8 @@ export default class I18N extends AdminForthPlugin {
156
161
  throw new Error(`Field ${this.enFieldName} not found column to store english original string in resource ${resourceConfig.resourceId}`);
157
162
  }
158
163
 
164
+ enColumn.editReadonly = true;
165
+
159
166
  // if sourceFieldName defined, check it exists
160
167
  if (this.options.sourceFieldName) {
161
168
  if (!resourceConfig.columns.find(c => c.name === this.options.sourceFieldName)) {
@@ -322,15 +329,17 @@ export default class I18N extends AdminForthPlugin {
322
329
  try {
323
330
  translatedCount = await this.bulkTranslate({ selectedIds });
324
331
  } catch (e) {
332
+ process.env.HEAVY_DEBUG && console.error('🪲⛔ bulkTranslate error', e);
325
333
  if (e instanceof AiTranslateError) {
326
- process.env.HEAVY_DEBUG && console.error('🪲⛔ bulkTranslate error', e);
327
334
  return { ok: false, error: e.message };
328
- }
335
+ }
336
+ throw e;
329
337
  }
330
- process.env.HEAVY_DEBUG && console.log('🪲bulkTranslate done', selectedIds);
338
+ process.env.HEAVY_DEBUG && console.log('🪲bulkTranslate done', translatedCount);
331
339
  this.updateUntranslatedMenuBadge();
332
340
  return {
333
- ok: true, error: undefined,
341
+ ok: true,
342
+ error: undefined,
334
343
  successMessage: await tr(`Translated {count} items`, 'backend', {
335
344
  count: translatedCount,
336
345
  }),
@@ -364,6 +373,107 @@ export default class I18N extends AdminForthPlugin {
364
373
  });
365
374
  }
366
375
 
376
+ async translateToLang (
377
+ langIsoCode: LanguageCode,
378
+ strings: { en_string: string, category: string }[],
379
+ plurals=false,
380
+ translations: any[],
381
+ updateStrings: Record<string, { updates: any, category: string, strId: string, translatedStr: string }> = {}
382
+ ): Promise<string[]> {
383
+ const maxKeysInOneReq = 10;
384
+ if (strings.length === 0) {
385
+ return [];
386
+ }
387
+
388
+ if (strings.length > maxKeysInOneReq) {
389
+ let totalTranslated = [];
390
+ for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
391
+ const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
392
+ process.env.HEAVY_DEBUG && console.log('🪲🔪slicedStrings len', slicedStrings.length);
393
+ const madeKeys = await this.translateToLang(langIsoCode, slicedStrings, plurals, translations, updateStrings);
394
+ totalTranslated = totalTranslated.concat(madeKeys);
395
+ }
396
+ return totalTranslated;
397
+ }
398
+ const lang = langIsoCode;
399
+ const langName = iso6391.getName(lang);
400
+ const requestSlavicPlurals = Object.keys(SLAVIC_PLURAL_EXAMPLES).includes(lang) && plurals;
401
+
402
+ const prompt = `
403
+ I need to translate strings in JSON to ${lang} (${langName}) language from English for my web app.
404
+ ${requestSlavicPlurals ? `You should provide 4 translations (in format zero | singular | 2-4 | 5+) e.g. ${SLAVIC_PLURAL_EXAMPLES[lang]}` : ''}
405
+ Keep keys, as is, write translation into values! Here are the strings:
406
+
407
+ \`\`\`json
408
+ ${
409
+ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object => {
410
+ acc[s.en_string] = '';
411
+ return acc;
412
+ }, {}), null, 2)
413
+ }
414
+ \`\`\`
415
+ `;
416
+
417
+ // process.env.HEAVY_DEBUG && console.log('🧠 llm prompt', prompt);
418
+
419
+ // call OpenAI
420
+ const resp = await this.options.completeAdapter.complete(
421
+ prompt,
422
+ [],
423
+ 300,
424
+ );
425
+
426
+ // process.env.HEAVY_DEBUG && console.log('🧠 llm resp', resp);
427
+
428
+ if (resp.error) {
429
+ throw new AiTranslateError(resp.error);
430
+ }
431
+
432
+ // parse response like
433
+ // Here are the translations for the strings you provided:
434
+ // ```json
435
+ // [{"live": "canlı"}, {"Table Games": "Masa Oyunları"}]
436
+ // ```
437
+ let res;
438
+ try {
439
+ res = resp.content.split("```json")[1].split("```")[0];
440
+ } catch (e) {
441
+ console.error(`Error in parsing LLM resp: ${resp}\n Prompt was: ${prompt}\n Resp was: ${JSON.stringify(resp)}`, );
442
+ return [];
443
+ }
444
+
445
+ try {
446
+ res = JSON.parse(res);
447
+ } catch (e) {
448
+ console.error(`Error in parsing LLM resp json: ${resp}\n Prompt was: ${prompt}\n Resp was: ${JSON.stringify(resp)}`, );
449
+ return [];
450
+ }
451
+
452
+
453
+ for (const [enStr, translatedStr] of Object.entries(res) as [string, string][]) {
454
+ const translationsTargeted = translations.filter(t => t[this.enFieldName] === enStr);
455
+ // might be several with same en_string
456
+ for (const translation of translationsTargeted) {
457
+ //translation[this.trFieldNames[lang]] = translatedStr;
458
+ // process.env.HEAVY_DEBUG && console.log(`🪲translated to ${lang} ${translation.en_string}, ${translatedStr}`)
459
+ if (!updateStrings[translation[this.primaryKeyFieldName]]) {
460
+
461
+ updateStrings[translation[this.primaryKeyFieldName]] = {
462
+ updates: {},
463
+ translatedStr,
464
+ category: translation[this.options.categoryFieldName],
465
+ strId: translation[this.primaryKeyFieldName],
466
+ };
467
+ }
468
+ updateStrings[
469
+ translation[this.primaryKeyFieldName]
470
+ ].updates[this.trFieldNames[lang]] = translatedStr;
471
+ }
472
+ }
473
+
474
+ return Object.keys(updateStrings);
475
+ }
476
+
367
477
  // returns translated count
368
478
  async bulkTranslate({ selectedIds }: { selectedIds: string[] }): Promise<number> {
369
479
 
@@ -397,8 +507,6 @@ export default class I18N extends AdminForthPlugin {
397
507
  }
398
508
  }
399
509
 
400
- const maxKeysInOneReq = 10;
401
-
402
510
  const updateStrings: Record<string, {
403
511
  updates: any,
404
512
  category: string,
@@ -406,104 +514,34 @@ export default class I18N extends AdminForthPlugin {
406
514
  translatedStr: string
407
515
  }> = {};
408
516
 
409
- const translateToLang = async (langIsoCode: LanguageCode, strings: { en_string: string, category: string }[], plurals=false): Promise<number> => {
410
- if (strings.length === 0) {
411
- return 0;
412
- }
413
-
414
- if (strings.length > maxKeysInOneReq) {
415
- let totalTranslated = 0;
416
- for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
417
- const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
418
- process.env.HEAVY_DEBUG && console.log('🪲🔪slicedStrings len', slicedStrings.length);
419
- totalTranslated += await translateToLang(langIsoCode, slicedStrings, plurals);
420
- }
421
- return totalTranslated;
422
- }
423
- const lang = langIsoCode;
424
-
425
- const requestSlavicPlurals = Object.keys(SLAVIC_PLURAL_EXAMPLES).includes(lang) && plurals;
426
-
427
- const prompt = `
428
- I need to translate strings in JSON to ${lang} language from English for my web app.
429
- ${requestSlavicPlurals ? `You should provide 4 translations (in format zero | singular | 2-4 | 5+) e.g. ${SLAVIC_PLURAL_EXAMPLES[lang]}` : ''}
430
- Keep keys, as is, write translation into values! Here are the strings:
431
-
432
- \`\`\`json
433
- ${
434
- JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object => {
435
- acc[s.en_string] = '';
436
- return acc;
437
- }, {}), null, 2)
438
- }
439
- \`\`\`
440
- `;
441
-
442
- process.env.HEAVY_DEBUG && console.log('🧠 llm prompt', prompt);
443
517
 
444
- // call OpenAI
445
- const resp = await this.options.completeAdapter.complete(
446
- prompt,
447
- [],
448
- 300,
449
- );
518
+ const langsInvolved = new Set(Object.keys(needToTranslateByLang));
450
519
 
451
- process.env.HEAVY_DEBUG && console.log('🧠 llm resp', resp);
520
+ let totalTranslated = [];
521
+ process.env.HEAVY_DEBUG && console.log(' 🐛starting Promise.all Object.entries(needToTranslateByLang)');
452
522
 
453
- if (resp.error) {
454
- throw new AiTranslateError(resp.error);
455
- }
523
+ await Promise.all(
524
+ Object.entries(needToTranslateByLang).map(
525
+ async ([lang, strings]: [LanguageCode, { en_string: string, category: string }[]]) => {
526
+ // first translate without plurals
527
+ const stringsWithoutPlurals = strings.filter(s => !s.en_string.includes('|'));
528
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} noplurals started ${stringsWithoutPlurals.length}`);
529
+ const noPluralKeys = await this.translateToLang(lang, stringsWithoutPlurals, false, translations, updateStrings);
530
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} noplurals finished`);
456
531
 
457
- // parse response like
458
- // Here are the translations for the strings you provided:
459
- // ```json
460
- // [{"live": "canlı"}, {"Table Games": "Masa Oyunları"}]
461
- // ```
462
- let res;
463
- try {
464
- res = resp.content.split("```json")[1].split("```")[0];
465
- } catch (e) {
466
- console.error('error in parsing OpenAI', resp);
467
- throw new AiTranslateError('Error in parsing OpenAI response');
468
- }
469
- res = JSON.parse(res);
470
532
 
533
+ const stringsWithPlurals = strings.filter(s => s.en_string.includes('|'));
471
534
 
472
- for (const [enStr, translatedStr] of Object.entries(res) as [string, string][]) {
473
- const translationsTargeted = translations.filter(t => t[this.enFieldName] === enStr);
474
- // might be several with same en_string
475
- for (const translation of translationsTargeted) {
476
- //translation[this.trFieldNames[lang]] = translatedStr;
477
- // process.env.HEAVY_DEBUG && console.log(`🪲translated to ${lang} ${translation.en_string}, ${translatedStr}`)
478
- if (!updateStrings[translation[this.primaryKeyFieldName]]) {
535
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} plurals started ${stringsWithPlurals.length}`);
536
+ const pluralKeys = await this.translateToLang(lang, stringsWithPlurals, true, translations, updateStrings);
537
+ process.env.HEAVY_DEBUG && console.log(`🔗 ${lang} plurals finished`);
479
538
 
480
- updateStrings[translation[this.primaryKeyFieldName]] = {
481
- updates: {},
482
- translatedStr,
483
- category: translation[this.options.categoryFieldName],
484
- strId: translation[this.primaryKeyFieldName],
485
- };
486
- }
487
- updateStrings[
488
- translation[this.primaryKeyFieldName]
489
- ].updates[this.trFieldNames[lang]] = translatedStr;
539
+ totalTranslated = totalTranslated.concat(noPluralKeys, pluralKeys);
490
540
  }
491
- }
492
-
493
- return Object.keys(updateStrings).length;
494
- }
495
-
496
- const langsInvolved = new Set(Object.keys(needToTranslateByLang));
497
-
498
- let totalTranslated = 0;
499
- await Promise.all(Object.entries(needToTranslateByLang).map(async ([lang, strings]: [LanguageCode, { en_string: string, category: string }[]]) => {
500
- // first translate without plurals
501
- const stringsWithoutPlurals = strings.filter(s => !s.en_string.includes('|'));
502
- totalTranslated += await translateToLang(lang, stringsWithoutPlurals, false);
541
+ )
542
+ );
503
543
 
504
- const stringsWithPlurals = strings.filter(s => s.en_string.includes('|'));
505
- totalTranslated += await translateToLang(lang, stringsWithPlurals, true);
506
- }));
544
+ process.env.HEAVY_DEBUG && console.log('✅ updateStrings were formed', (new Set(totalTranslated)));
507
545
 
508
546
  await Promise.all(
509
547
  Object.entries(updateStrings).map(
@@ -520,13 +558,13 @@ ${
520
558
  );
521
559
 
522
560
  for (const lang of langsInvolved) {
523
- this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
561
+ await this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
524
562
  for (const [enStr, { category }] of Object.entries(updateStrings)) {
525
- this.cache.clear(`${this.resourceConfig.resourceId}:${category}:${lang}:${enStr}`);
563
+ await this.cache.clear(`${this.resourceConfig.resourceId}:${category}:${lang}:${enStr}`);
526
564
  }
527
565
  }
528
566
 
529
- return totalTranslated;
567
+ return new Set(totalTranslated).size;
530
568
 
531
569
  }
532
570
 
@@ -593,12 +631,10 @@ ${
593
631
  });
594
632
  w.on('change', () => {
595
633
  process.env.HEAVY_DEBUG && console.log('🪲🔔messagesFile change', messagesFile);
596
-
597
634
  this.processExtractedMessages(adminforth, messagesFile);
598
635
  });
599
636
  w.on('add', () => {
600
637
  process.env.HEAVY_DEBUG && console.log('🪲🔔messagesFile add', messagesFile);
601
-
602
638
  this.processExtractedMessages(adminforth, messagesFile);
603
639
  });
604
640
 
@@ -607,6 +643,10 @@ ${
607
643
  validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
608
644
  // optional method where you can safely check field types after database discovery was performed
609
645
  // ensure each trFieldName (apart from enFieldName) is nullable column of type string
646
+ if (this.options.completeAdapter) {
647
+ this.options.completeAdapter.validate();
648
+ }
649
+
610
650
  for (const lang of this.options.supportedLanguages) {
611
651
  if (lang === 'en') {
612
652
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/i18n",
3
- "version": "1.0.18-next.1",
3
+ "version": "1.0.18-next.10",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",