poly-lexis 0.5.3 → 0.8.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/dist/index.d.ts CHANGED
@@ -225,6 +225,16 @@ interface UnusedKeysResult {
225
225
  totalKeys: number;
226
226
  searchedFiles: number;
227
227
  }
228
+ interface DuplicateTranslation {
229
+ namespace: string;
230
+ key: string;
231
+ commonKey: string;
232
+ value: string;
233
+ }
234
+ interface DuplicateKeysResult {
235
+ duplicates: DuplicateTranslation[];
236
+ totalKeysChecked: number;
237
+ }
228
238
  declare const DEFAULT_CONFIG: Required<TranslationConfig>;
229
239
  declare const DEFAULT_LANGUAGES: readonly ["en", "fr", "it", "pl", "es", "pt", "de", "nl", "sv", "hu", "cs", "ja"];
230
240
 
@@ -282,6 +292,11 @@ declare function findUnusedKeys(projectRoot?: string): UnusedKeysResult;
282
292
  */
283
293
  declare function printUnusedKeysResult(result: UnusedKeysResult): void;
284
294
 
295
+ /**
296
+ * Extract base keys from plural-suffixed keys (e.g., "items_one" -> "items")
297
+ * Follows CLDR plural categories used by i18next and similar libraries.
298
+ */
299
+ declare function extractPluralBaseKeys(keys: string[]): string[];
285
300
  /**
286
301
  * Generate TypeScript types from translation files
287
302
  */
@@ -462,8 +477,29 @@ declare function translateText(text: string, targetLang: string, sourceLang?: st
462
477
  */
463
478
  declare function translateBatch(texts: string[], targetLang: string, sourceLang?: string, apiKey?: string, delayMs?: number): Promise<string[]>;
464
479
 
480
+ /**
481
+ * Nested translation structure (allows nested objects)
482
+ */
483
+ type NestedTranslationFile = {
484
+ [key: string]: string | NestedTranslationFile;
485
+ };
486
+ /**
487
+ * Flatten a nested object into a flat key-value structure using dot notation
488
+ * Example: { home: { title: "Hello" } } -> { "home.title": "Hello" }
489
+ */
490
+ declare function flattenObject(obj: NestedTranslationFile, prefix?: string): TranslationFile;
491
+ /**
492
+ * Unflatten a flat object with dot notation keys into a nested structure
493
+ * Example: { "home.title": "Hello" } -> { home: { title: "Hello" } }
494
+ */
495
+ declare function unflattenObject(obj: TranslationFile): NestedTranslationFile;
496
+ /**
497
+ * Check if an object is flat (all values are strings) or nested
498
+ */
499
+ declare function isNestedObject(obj: Record<string, unknown>): boolean;
465
500
  /**
466
501
  * Read all translation files for a specific language
502
+ * Automatically flattens nested structures into dot notation
467
503
  */
468
504
  declare function readTranslations(translationsPath: string, language: string): TranslationFiles;
469
505
  /**
@@ -536,4 +572,4 @@ interface SyncResult {
536
572
  */
537
573
  declare function syncTranslationStructure(translationsPath: string, languages: string[], sourceLanguage: string): SyncResult;
538
574
 
539
- export { DEEPL_LANGUAGES, DEFAULT_CONFIG, DEFAULT_LANGUAGES, type DeepLLanguage, GOOGLE_LANGUAGES, type GoogleLanguage, GoogleTranslateProvider, type LanguageFallbackResult, type ManageTranslationsOptions, type MissingTranslation, type OrphanedTranslation, SUPPORTED_LANGUAGES, type SupportedLanguage, type SyncResult, TRANSLATION_CONFIG_SCHEMA, TRANSLATION_PROVIDERS, type TranslateOptions, type TranslationConfig, type TranslationEntry, type TranslationFile, type TranslationFiles, type TranslationProvider, type TranslationProviderFactory, type TranslationProviderType, type TranslationResult, type UnusedKeysResult, type UnusedTranslation, type ValidationResult, addTranslationKey, addTranslationKeys, autoFillTranslations, createEmptyTranslationStructure, detectExistingTranslations, ensureTranslationsStructure, extractVariables, fillNamespace, findUnusedKeys, generateTranslationTypes, getAvailableLanguages, getFallbackMappings, getMissingForLanguage, getNamespaces, getSupportedLanguages, getTranslationProvider, hasInterpolation, initTranslations, initTranslationsInteractive, isValidDeepLLanguage, isValidGoogleLanguage, isValidLanguage, isValidLanguageForProvider, loadConfig, logLanguageFallback, manageTranslations, printUnusedKeysResult, readTranslations, resetTranslationProvider, resolveLanguageWithFallback, setTranslationProvider, sortKeys, syncTranslationStructure, translateBatch, translateText, validateLanguages, validateLanguagesForProvider, validateTranslations, validateVariables, writeTranslation };
575
+ export { DEEPL_LANGUAGES, DEFAULT_CONFIG, DEFAULT_LANGUAGES, type DeepLLanguage, type DuplicateKeysResult, type DuplicateTranslation, GOOGLE_LANGUAGES, type GoogleLanguage, GoogleTranslateProvider, type LanguageFallbackResult, type ManageTranslationsOptions, type MissingTranslation, type NestedTranslationFile, type OrphanedTranslation, SUPPORTED_LANGUAGES, type SupportedLanguage, type SyncResult, TRANSLATION_CONFIG_SCHEMA, TRANSLATION_PROVIDERS, type TranslateOptions, type TranslationConfig, type TranslationEntry, type TranslationFile, type TranslationFiles, type TranslationProvider, type TranslationProviderFactory, type TranslationProviderType, type TranslationResult, type UnusedKeysResult, type UnusedTranslation, type ValidationResult, addTranslationKey, addTranslationKeys, autoFillTranslations, createEmptyTranslationStructure, detectExistingTranslations, ensureTranslationsStructure, extractPluralBaseKeys, extractVariables, fillNamespace, findUnusedKeys, flattenObject, generateTranslationTypes, getAvailableLanguages, getFallbackMappings, getMissingForLanguage, getNamespaces, getSupportedLanguages, getTranslationProvider, hasInterpolation, initTranslations, initTranslationsInteractive, isNestedObject, isValidDeepLLanguage, isValidGoogleLanguage, isValidLanguage, isValidLanguageForProvider, loadConfig, logLanguageFallback, manageTranslations, printUnusedKeysResult, readTranslations, resetTranslationProvider, resolveLanguageWithFallback, setTranslationProvider, sortKeys, syncTranslationStructure, translateBatch, translateText, unflattenObject, validateLanguages, validateLanguagesForProvider, validateTranslations, validateVariables, writeTranslation };
package/dist/index.js CHANGED
@@ -626,6 +626,37 @@ var init_language_fallback = __esm({
626
626
  // src/translations/utils/utils.ts
627
627
  import * as fs from "fs";
628
628
  import * as path from "path";
629
+ function flattenObject(obj, prefix = "") {
630
+ const result = {};
631
+ for (const [key, value] of Object.entries(obj)) {
632
+ const newKey = prefix ? `${prefix}.${key}` : key;
633
+ if (typeof value === "string") {
634
+ result[newKey] = value;
635
+ } else if (typeof value === "object" && value !== null) {
636
+ Object.assign(result, flattenObject(value, newKey));
637
+ }
638
+ }
639
+ return result;
640
+ }
641
+ function unflattenObject(obj) {
642
+ const result = {};
643
+ for (const [key, value] of Object.entries(obj)) {
644
+ const parts = key.split(".");
645
+ let current = result;
646
+ for (let i = 0; i < parts.length - 1; i++) {
647
+ const part = parts[i];
648
+ if (!(part in current) || typeof current[part] === "string") {
649
+ current[part] = {};
650
+ }
651
+ current = current[part];
652
+ }
653
+ current[parts[parts.length - 1]] = value;
654
+ }
655
+ return result;
656
+ }
657
+ function isNestedObject(obj) {
658
+ return Object.values(obj).some((value) => typeof value === "object" && value !== null);
659
+ }
629
660
  function readTranslations(translationsPath, language) {
630
661
  const langPath = path.join(translationsPath, language);
631
662
  if (!fs.existsSync(langPath)) {
@@ -637,7 +668,12 @@ function readTranslations(translationsPath, language) {
637
668
  const namespace = path.basename(file, ".json");
638
669
  const filePath = path.join(langPath, file);
639
670
  const content = fs.readFileSync(filePath, "utf-8");
640
- translations[namespace] = JSON.parse(content);
671
+ const parsed = JSON.parse(content);
672
+ if (isNestedObject(parsed)) {
673
+ translations[namespace] = flattenObject(parsed);
674
+ } else {
675
+ translations[namespace] = parsed;
676
+ }
641
677
  }
642
678
  return translations;
643
679
  }
@@ -1159,6 +1195,23 @@ init_init();
1159
1195
  import { execSync } from "child_process";
1160
1196
  import * as fs3 from "fs";
1161
1197
  import * as path3 from "path";
1198
+ var PLURAL_SUFFIXES = ["_zero", "_one", "_two", "_few", "_many", "_other"];
1199
+ function extractPluralBaseKeys(keys) {
1200
+ const keySet = new Set(keys);
1201
+ const baseKeys = /* @__PURE__ */ new Set();
1202
+ for (const key of keys) {
1203
+ for (const suffix of PLURAL_SUFFIXES) {
1204
+ if (key.endsWith(suffix)) {
1205
+ const baseKey = key.slice(0, -suffix.length);
1206
+ if (baseKey && !keySet.has(baseKey)) {
1207
+ baseKeys.add(baseKey);
1208
+ }
1209
+ break;
1210
+ }
1211
+ }
1212
+ }
1213
+ return Array.from(baseKeys);
1214
+ }
1162
1215
  var typeTemplate = (translationKeys, namespaceKeys) => `
1163
1216
  export const translationKeys = [${translationKeys.map((key) => `"${key}"`).join(", ")}] as const;
1164
1217
  export const namespaceKeys = [${namespaceKeys.map((key) => `"${key}"`).join(", ")}] as const;
@@ -1189,6 +1242,8 @@ function generateTranslationTypes(projectRoot = process.cwd()) {
1189
1242
  const keys = Object.keys(translations[namespace] || {});
1190
1243
  allKeys = allKeys.concat(keys);
1191
1244
  }
1245
+ const pluralBaseKeys = extractPluralBaseKeys(allKeys);
1246
+ allKeys = allKeys.concat(pluralBaseKeys);
1192
1247
  const outputDir = path3.dirname(outputFilePath);
1193
1248
  if (!fs3.existsSync(outputDir)) {
1194
1249
  fs3.mkdirSync(outputDir, { recursive: true });
@@ -2178,9 +2233,11 @@ export {
2178
2233
  createEmptyTranslationStructure,
2179
2234
  detectExistingTranslations,
2180
2235
  ensureTranslationsStructure,
2236
+ extractPluralBaseKeys,
2181
2237
  extractVariables,
2182
2238
  fillNamespace,
2183
2239
  findUnusedKeys,
2240
+ flattenObject,
2184
2241
  generateTranslationTypes,
2185
2242
  getAvailableLanguages,
2186
2243
  getFallbackMappings,
@@ -2191,6 +2248,7 @@ export {
2191
2248
  hasInterpolation,
2192
2249
  initTranslations,
2193
2250
  initTranslationsInteractive,
2251
+ isNestedObject,
2194
2252
  isValidDeepLLanguage,
2195
2253
  isValidGoogleLanguage,
2196
2254
  isValidLanguage,
@@ -2207,6 +2265,7 @@ export {
2207
2265
  syncTranslationStructure,
2208
2266
  translateBatch,
2209
2267
  translateText,
2268
+ unflattenObject,
2210
2269
  validateLanguages,
2211
2270
  validateLanguagesForProvider,
2212
2271
  validateTranslations,