browser-extension-manager 1.2.0 → 1.2.1

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.
@@ -61,71 +61,73 @@ async function translate(complete) {
61
61
  const enKeys = Object.keys(enMessages);
62
62
  logger.log(`Found ${enKeys.length} keys in English messages`);
63
63
 
64
- // Build translation tasks for all languages in parallel
65
- const translationTasks = LANGUAGES.map(async (lang) => {
64
+ // Check which languages need translation
65
+ const languagesToTranslate = [];
66
+
67
+ for (const lang of LANGUAGES) {
66
68
  const langDir = path.join(localesDir, lang);
67
69
  const langMessagesPath = path.join(langDir, 'messages.json');
68
70
 
69
71
  // Check if translation exists
70
72
  const exists = jetpack.exists(langMessagesPath);
71
- let needsTranslation = !exists;
72
- let existingMessages = {};
73
- let missingKeys = [];
74
-
75
- // If exists, check for missing keys
76
- if (exists) {
77
- try {
78
- existingMessages = JSON5.parse(jetpack.read(langMessagesPath));
79
- missingKeys = enKeys.filter(key => !existingMessages[key]);
80
- needsTranslation = missingKeys.length > 0;
81
-
82
- if (needsTranslation) {
83
- logger.log(`[${lang}] Found ${missingKeys.length} missing keys`);
84
- }
85
- } catch (e) {
86
- logger.warn(`[${lang}] Failed to parse existing messages, will retranslate: ${e.message}`);
87
- needsTranslation = true;
88
- missingKeys = enKeys;
89
- }
90
- } else {
91
- missingKeys = enKeys;
73
+
74
+ if (!exists) {
75
+ languagesToTranslate.push({ lang, missingKeys: enKeys, existingMessages: {} });
76
+ continue;
92
77
  }
93
78
 
94
- // Skip if no translation needed
95
- if (!needsTranslation) {
96
- logger.log(`[${lang}] Up to date, skipping`);
97
- return;
79
+ // Check for missing keys
80
+ try {
81
+ const existingMessages = JSON5.parse(jetpack.read(langMessagesPath));
82
+ const missingKeys = enKeys.filter(key => !existingMessages[key]);
83
+
84
+ if (missingKeys.length > 0) {
85
+ logger.log(`[${lang}] Found ${missingKeys.length} missing keys`);
86
+ languagesToTranslate.push({ lang, missingKeys, existingMessages });
87
+ } else {
88
+ logger.log(`[${lang}] Up to date, skipping`);
89
+ }
90
+ } catch (e) {
91
+ logger.warn(`[${lang}] Failed to parse existing messages, will retranslate: ${e.message}`);
92
+ languagesToTranslate.push({ lang, missingKeys: enKeys, existingMessages: {} });
98
93
  }
94
+ }
99
95
 
100
- // Build messages to translate
101
- const messagesToTranslate = {};
102
- missingKeys.forEach(key => {
103
- messagesToTranslate[key] = enMessages[key];
104
- });
96
+ // Skip if nothing to translate
97
+ if (languagesToTranslate.length === 0) {
98
+ logger.log('All translations up to date');
99
+ return complete();
100
+ }
105
101
 
106
- // Translate using Claude CLI
107
- try {
108
- logger.log(`[${lang}] Translating ${missingKeys.length} keys...`);
102
+ logger.log(`Translating ${languagesToTranslate.length} languages in one call...`);
109
103
 
110
- const translated = await translateWithClaude(messagesToTranslate, lang);
104
+ // Translate all languages at once
105
+ try {
106
+ const translations = await translateAllWithClaude(enMessages, languagesToTranslate);
111
107
 
112
- // Merge with existing messages
113
- const finalMessages = { ...existingMessages, ...translated };
108
+ // Write each translation
109
+ for (const { lang, existingMessages } of languagesToTranslate) {
110
+ const langDir = path.join(localesDir, lang);
111
+ const langMessagesPath = path.join(langDir, 'messages.json');
114
112
 
115
- // Ensure directory exists
116
- jetpack.dir(langDir);
113
+ if (translations[lang]) {
114
+ // Merge with existing messages
115
+ const finalMessages = { ...existingMessages, ...translations[lang] };
117
116
 
118
- // Write translated messages
119
- jetpack.write(langMessagesPath, JSON.stringify(finalMessages, null, 2));
117
+ // Ensure directory exists
118
+ jetpack.dir(langDir);
120
119
 
121
- logger.log(`[${lang}] Translation complete`);
122
- } catch (e) {
123
- logger.error(`[${lang}] Translation failed: ${e.message}`);
124
- }
125
- });
120
+ // Write translated messages
121
+ jetpack.write(langMessagesPath, JSON.stringify(finalMessages, null, 2));
126
122
 
127
- // Run all translations in parallel
128
- await Promise.all(translationTasks);
123
+ logger.log(`[${lang}] Translation saved`);
124
+ } else {
125
+ logger.warn(`[${lang}] No translation returned`);
126
+ }
127
+ }
128
+ } catch (e) {
129
+ logger.error(`Translation failed: ${e.message}`);
130
+ }
129
131
 
130
132
  // Log
131
133
  logger.log('Translation finished!');
@@ -134,9 +136,17 @@ async function translate(complete) {
134
136
  return complete();
135
137
  }
136
138
 
137
- // Translate using Claude CLI
138
- async function translateWithClaude(messages, targetLang) {
139
- const prompt = `Translate the following Chrome extension messages.json content from English to ${getLanguageName(targetLang)} (${targetLang}).
139
+ // Translate all languages using a single Claude CLI call
140
+ async function translateAllWithClaude(enMessages, languagesToTranslate) {
141
+ // Build language info for prompt
142
+ const languageList = languagesToTranslate.map(({ lang }) =>
143
+ `- "${lang}": ${getLanguageName(lang)}`
144
+ ).join('\n');
145
+
146
+ const prompt = `Translate the following Chrome extension messages.json content from English to multiple languages.
147
+
148
+ TARGET LANGUAGES:
149
+ ${languageList}
140
150
 
141
151
  IMPORTANT RULES:
142
152
  1. Only translate the "message" field values
@@ -144,15 +154,23 @@ IMPORTANT RULES:
144
154
  3. Keep all JSON keys exactly as they are
145
155
  4. Return ONLY valid JSON, no markdown, no explanation
146
156
  5. Preserve any placeholders like $1, $2, etc.
157
+ 6. Return a JSON object where each key is the language code and the value is the translated messages object
147
158
 
148
- Input JSON:
149
- ${JSON.stringify(messages, null, 2)}
159
+ INPUT (English):
160
+ ${JSON.stringify(enMessages, null, 2)}
161
+
162
+ OUTPUT FORMAT:
163
+ {
164
+ "zh": { ... translated messages ... },
165
+ "es": { ... translated messages ... },
166
+ ...
167
+ }
150
168
 
151
169
  Output the translated JSON:`;
152
170
 
153
171
  // Write prompt to temp file to avoid shell escaping issues
154
172
  const tempDir = path.join(process.cwd(), '.temp');
155
- const tempFile = path.join(tempDir, `translate-${targetLang}.txt`);
173
+ const tempFile = path.join(tempDir, 'translate-all.txt');
156
174
 
157
175
  try {
158
176
  // Ensure temp dir exists and write prompt
@@ -163,13 +181,13 @@ Output the translated JSON:`;
163
181
  const command = `cat "${tempFile}" | claude -p -`;
164
182
 
165
183
  // Log start
166
- logger.log(`[${targetLang}] Calling Claude CLI...`);
184
+ logger.log('Calling Claude CLI...');
167
185
 
168
186
  // Run Claude CLI
169
187
  const result = await execute(command);
170
188
 
171
189
  // Log response received
172
- logger.log(`[${targetLang}] Claude CLI responded (${result.length} chars)`);
190
+ logger.log(`Claude CLI responded (${result.length} chars)`);
173
191
 
174
192
  // Clean up temp file
175
193
  jetpack.remove(tempFile);
@@ -181,7 +199,7 @@ Output the translated JSON:`;
181
199
  }
182
200
 
183
201
  // Log success
184
- logger.log(`[${targetLang}] Parsed JSON successfully`);
202
+ logger.log('Parsed JSON successfully');
185
203
 
186
204
  return JSON.parse(jsonMatch[0]);
187
205
  } catch (e) {
@@ -824,3 +824,31 @@
824
824
  [debug] [2025-11-26T00:17:52.900Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
825
825
  [debug] [2025-11-26T00:17:52.900Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
826
826
  [debug] [2025-11-26T00:17:52.900Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
827
+ [debug] [2025-11-26T11:15:13.684Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
828
+ [debug] [2025-11-26T11:15:13.687Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
829
+ [debug] [2025-11-26T11:15:13.687Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
830
+ [debug] [2025-11-26T11:15:13.687Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
831
+ [debug] [2025-11-26T11:15:13.698Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
832
+ [debug] [2025-11-26T11:15:13.699Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
833
+ [debug] [2025-11-26T11:15:13.740Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
834
+ [debug] [2025-11-26T11:15:13.740Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
835
+ [debug] [2025-11-26T11:15:13.741Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
836
+ [debug] [2025-11-26T11:15:13.741Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
837
+ [debug] [2025-11-26T11:15:13.743Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
838
+ [debug] [2025-11-26T11:15:13.743Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
839
+ [debug] [2025-11-26T11:15:13.743Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
840
+ [debug] [2025-11-26T11:15:13.743Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
841
+ [debug] [2025-11-26T11:15:17.115Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
842
+ [debug] [2025-11-26T11:15:17.117Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
843
+ [debug] [2025-11-26T11:15:17.117Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
844
+ [debug] [2025-11-26T11:15:17.117Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
845
+ [debug] [2025-11-26T11:15:17.129Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
846
+ [debug] [2025-11-26T11:15:17.130Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
847
+ [debug] [2025-11-26T11:15:17.164Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
848
+ [debug] [2025-11-26T11:15:17.164Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
849
+ [debug] [2025-11-26T11:15:17.165Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
850
+ [debug] [2025-11-26T11:15:17.165Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
851
+ [debug] [2025-11-26T11:15:17.166Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
852
+ [debug] [2025-11-26T11:15:17.166Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
853
+ [debug] [2025-11-26T11:15:17.167Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
854
+ [debug] [2025-11-26T11:15:17.167Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-extension-manager",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Browser Extension Manager dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {