ai-l10n-sdk 1.1.3 → 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/README.md CHANGED
@@ -94,6 +94,38 @@ const result = await translator.translate({
94
94
  - **Automatic Metadata Updates**: The API automatically updates `@@locale` to the target language code and `@@last_modified` to the current UTC timestamp
95
95
  - **Custom Prefixes**: Supports custom file naming patterns (e.g., `app_en_US.arb`, `my_app_fr.arb`)
96
96
 
97
+ ### JSONC Files
98
+
99
+ Full support for JSONC (JSON with Comments) files:
100
+
101
+ ```typescript
102
+ const result = await translator.translate({
103
+ sourceFile: './locales/en.jsonc',
104
+ targetLanguages: ['es', 'fr', 'de']
105
+ });
106
+ ```
107
+
108
+ **JSONC Features:**
109
+ - Works exactly like JSON files but with `.jsonc` extension
110
+ - Auto-detects `.jsonc` files in project structure alongside `.json` files
111
+
112
+ ### Shopify Theme Localization
113
+
114
+ Full support for Shopify theme localization file patterns:
115
+
116
+ ```typescript
117
+ const result = await translator.translate({
118
+ sourceFile: './locales/en.default.schema.json',
119
+ targetLanguages: ['es-ES', 'fr', 'de']
120
+ });
121
+ // Creates: es-ES.schema.json, fr.schema.json, de.schema.json
122
+ ```
123
+
124
+ **Shopify Theme Features:**
125
+ - **Automatic Pattern Recognition**: Detects files with `.default.` in the name (e.g., `en.default.schema.json`)
126
+ - **Smart Output Naming**: Removes `.default.` from target files while preserving the `.schema.` suffix
127
+ - **Language Detection**: Auto-detects target languages from existing files (e.g., `es-ES.schema.json`, `fr.schema.json`)
128
+
97
129
  ### Multiple Files
98
130
 
99
131
  ```typescript
@@ -14,6 +14,7 @@ export declare class I18nProjectManager {
14
14
  * Extracts language code from file name, handling custom prefixes for ARB files
15
15
  * ARB files: app_en_US.arb -> en_US, my_app_fr.arb -> fr
16
16
  * JSON files: en-US.json -> en-US
17
+ * Shopify theme: en.default.schema.json -> en, es-ES.schema.json -> es-ES
17
18
  */
18
19
  private extractLanguageCodeFromFileName;
19
20
  }
@@ -80,17 +80,22 @@ class I18nProjectManager {
80
80
  }
81
81
  else if (structureInfo.type === ProjectStructureType.FileBased) {
82
82
  // For file-based, scan the base path for language files
83
- const fileExtension = isArbFile ? ".arb" : ".json";
83
+ const fileExtensions = isArbFile ? [".arb"] : [".json", ".jsonc"];
84
84
  try {
85
85
  const entries = fs.readdirSync(structureInfo.basePath, {
86
86
  withFileTypes: true,
87
87
  });
88
88
  for (const entry of entries) {
89
- if (entry.isFile() && entry.name.endsWith(fileExtension)) {
90
- const fileName = path.basename(entry.name, fileExtension);
91
- const languageCode = this.extractLanguageCodeFromFileName(fileName, isArbFile);
92
- if (languageCode) {
93
- languageCodes.add(languageCode);
89
+ if (entry.isFile()) {
90
+ for (const ext of fileExtensions) {
91
+ if (entry.name.endsWith(ext)) {
92
+ const fileName = path.basename(entry.name, ext);
93
+ const languageCode = this.extractLanguageCodeFromFileName(fileName, isArbFile);
94
+ if (languageCode) {
95
+ languageCodes.add(languageCode);
96
+ }
97
+ break;
98
+ }
94
99
  }
95
100
  }
96
101
  }
@@ -141,8 +146,12 @@ class I18nProjectManager {
141
146
  return targetFilePath;
142
147
  }
143
148
  else {
149
+ // Handle Shopify theme pattern: en.default.schema.json -> es-ES.schema.json
150
+ // Extract suffix (e.g., ".schema") if present
151
+ const schemaMatch = sourceFileName.match(/\.(schema)$/);
152
+ const suffix = schemaMatch ? `.${schemaMatch[1]}` : "";
144
153
  // Save in the same directory with target language as filename
145
- const targetFilePath = path.join(structureInfo.basePath, `${languageCode}${fileExtension}`);
154
+ const targetFilePath = path.join(structureInfo.basePath, `${languageCode}${suffix}${fileExtension}`);
146
155
  return targetFilePath;
147
156
  }
148
157
  }
@@ -226,6 +235,7 @@ class I18nProjectManager {
226
235
  * Extracts language code from file name, handling custom prefixes for ARB files
227
236
  * ARB files: app_en_US.arb -> en_US, my_app_fr.arb -> fr
228
237
  * JSON files: en-US.json -> en-US
238
+ * Shopify theme: en.default.schema.json -> en, es-ES.schema.json -> es-ES
229
239
  */
230
240
  extractLanguageCodeFromFileName(fileName, isArbFile) {
231
241
  if (isArbFile) {
@@ -242,8 +252,15 @@ class I18nProjectManager {
242
252
  return null;
243
253
  }
244
254
  else {
255
+ // Handle Shopify theme pattern: en.default.schema, es-ES.schema
256
+ // Remove .schema first, then .default before extracting language code
257
+ let cleanedFileName = fileName
258
+ .replace(/\.schema$/, "")
259
+ .replace(/\.default$/, "");
245
260
  // For JSON files, the entire filename should be the language code
246
- return this.languageCodeRegex.test(fileName) ? fileName : null;
261
+ return this.languageCodeRegex.test(cleanedFileName)
262
+ ? cleanedFileName
263
+ : null;
247
264
  }
248
265
  }
249
266
  }
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { ILogger } from "./logger";
4
4
  */
5
5
  export interface TranslationConfig {
6
6
  /**
7
- * Path to the source file to translate (JSON or ARB)
7
+ * Path to the source file to translate (JSON, JSONC, or ARB)
8
8
  */
9
9
  sourceFile: string;
10
10
  /**
package/dist/index.js CHANGED
@@ -70,9 +70,9 @@ class AiTranslator {
70
70
  }
71
71
  const fileExtension = path.extname(sourceFilePath);
72
72
  const isArbFile = fileExtension === ".arb";
73
- const isJsonFile = fileExtension === ".json";
73
+ const isJsonFile = fileExtension === ".json" || fileExtension === ".jsonc";
74
74
  if (!isArbFile && !isJsonFile) {
75
- throw new Error(`Unsupported file type: ${fileExtension}. Only .json and .arb files are supported.`);
75
+ throw new Error(`Unsupported file type: ${fileExtension}. Only .json, .jsonc, and .arb files are supported.`);
76
76
  }
77
77
  if (verbose) {
78
78
  console.log(`📂 Source file: ${sourceFilePath}`);
@@ -140,6 +140,7 @@ class AiTranslator {
140
140
  for (const result of results) {
141
141
  totalCharsUsed += result.charsUsed || 0;
142
142
  if (result.remainingBalance !== undefined &&
143
+ result.remainingBalance !== null &&
143
144
  result.remainingBalance < (remainingBalance ?? Infinity)) {
144
145
  remainingBalance = result.remainingBalance;
145
146
  }
@@ -151,7 +152,7 @@ class AiTranslator {
151
152
  console.log(`${"=".repeat(50)}`);
152
153
  console.log(`✅ Successful: ${successCount}/${targetLanguages.length}`);
153
154
  console.log(`📝 Total characters used: ${totalCharsUsed.toLocaleString()}`);
154
- if (remainingBalance !== undefined) {
155
+ if (remainingBalance !== undefined && remainingBalance !== null) {
155
156
  console.log(`💰 Remaining balance: ${remainingBalance.toLocaleString()} characters`);
156
157
  }
157
158
  if (successCount < targetLanguages.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-l10n-sdk",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "description": "Lightweight SDK for AI-powered localization automation - programmatic API (no CLI)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",