browser-extension-manager 1.2.12 → 1.2.13
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/gulp/config/locales.js +30 -0
- package/dist/gulp/tasks/audit.js +65 -1
- package/dist/gulp/tasks/translate.js +14 -46
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Locale field limits (Chrome Web Store requirements)
|
|
2
|
+
// https://developer.chrome.com/docs/webstore/i18n
|
|
3
|
+
module.exports = {
|
|
4
|
+
// Field character limits
|
|
5
|
+
limits: {
|
|
6
|
+
appName: 50,
|
|
7
|
+
appNameShort: 25,
|
|
8
|
+
appDescription: 200,
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
// Languages to translate (code: name)
|
|
12
|
+
languages: {
|
|
13
|
+
zh: 'Chinese (Simplified)',
|
|
14
|
+
es: 'Spanish',
|
|
15
|
+
hi: 'Hindi',
|
|
16
|
+
ar: 'Arabic',
|
|
17
|
+
pt: 'Portuguese',
|
|
18
|
+
ru: 'Russian',
|
|
19
|
+
ja: 'Japanese',
|
|
20
|
+
de: 'German',
|
|
21
|
+
fr: 'French',
|
|
22
|
+
ko: 'Korean',
|
|
23
|
+
ur: 'Urdu',
|
|
24
|
+
id: 'Indonesian',
|
|
25
|
+
bn: 'Bengali',
|
|
26
|
+
tl: 'Tagalog/Filipino',
|
|
27
|
+
vi: 'Vietnamese',
|
|
28
|
+
it: 'Italian',
|
|
29
|
+
},
|
|
30
|
+
};
|
package/dist/gulp/tasks/audit.js
CHANGED
|
@@ -15,6 +15,7 @@ const rootPathProject = Manager.getRootPath('project');
|
|
|
15
15
|
// Audit results tracker
|
|
16
16
|
const auditResults = {
|
|
17
17
|
externalScripts: [],
|
|
18
|
+
localeWarnings: [],
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
// Patterns to detect external script references
|
|
@@ -38,6 +39,44 @@ const EXTERNAL_SCRIPT_PATTERNS = [
|
|
|
38
39
|
/["'](https?:\/\/(?:www\.)?(?:google\.com\/recaptcha|apis\.google\.com)[^"']*)["']/gi,
|
|
39
40
|
];
|
|
40
41
|
|
|
42
|
+
// Locale config (shared with translate.js)
|
|
43
|
+
const { limits: LOCALE_LIMITS } = require('../config/locales.js');
|
|
44
|
+
|
|
45
|
+
// Check locale files for warnings
|
|
46
|
+
function checkLocaleFiles(packagedDir) {
|
|
47
|
+
const localesDir = path.join(packagedDir, '_locales');
|
|
48
|
+
|
|
49
|
+
if (!jetpack.exists(localesDir)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const localeFiles = jetpack.find(localesDir, { matching: '*/messages.json' });
|
|
54
|
+
|
|
55
|
+
localeFiles.forEach(filePath => {
|
|
56
|
+
try {
|
|
57
|
+
const content = jetpack.read(filePath);
|
|
58
|
+
const messages = JSON.parse(content);
|
|
59
|
+
|
|
60
|
+
// Check each field against its limit
|
|
61
|
+
Object.entries(LOCALE_LIMITS).forEach(([field, limit]) => {
|
|
62
|
+
const message = messages[field]?.message;
|
|
63
|
+
|
|
64
|
+
if (message && message.length > limit) {
|
|
65
|
+
auditResults.localeWarnings.push({
|
|
66
|
+
file: path.relative(rootPathProject, filePath),
|
|
67
|
+
field: field,
|
|
68
|
+
length: message.length,
|
|
69
|
+
limit: limit,
|
|
70
|
+
value: message,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
} catch (e) {
|
|
75
|
+
logger.warn(`Error parsing locale file ${filePath}: ${e.message}`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
41
80
|
// Check a single file for external script references
|
|
42
81
|
function checkFileForExternalScripts(filePath) {
|
|
43
82
|
try {
|
|
@@ -86,6 +125,7 @@ async function auditFn(complete) {
|
|
|
86
125
|
|
|
87
126
|
// Reset results
|
|
88
127
|
auditResults.externalScripts = [];
|
|
128
|
+
auditResults.localeWarnings = [];
|
|
89
129
|
|
|
90
130
|
try {
|
|
91
131
|
// Find all files in packaged directory (JS, HTML, etc.)
|
|
@@ -100,7 +140,7 @@ async function auditFn(complete) {
|
|
|
100
140
|
|
|
101
141
|
logger.log(`Auditing ${files.length} files (JS, HTML)...`);
|
|
102
142
|
|
|
103
|
-
// Check each file
|
|
143
|
+
// Check each file for external scripts
|
|
104
144
|
files.forEach(filePath => {
|
|
105
145
|
const externalScripts = checkFileForExternalScripts(filePath);
|
|
106
146
|
if (externalScripts.length > 0) {
|
|
@@ -108,6 +148,9 @@ async function auditFn(complete) {
|
|
|
108
148
|
}
|
|
109
149
|
});
|
|
110
150
|
|
|
151
|
+
// Check locale files
|
|
152
|
+
checkLocaleFiles(packagedDir);
|
|
153
|
+
|
|
111
154
|
// Display results
|
|
112
155
|
displayAuditResults();
|
|
113
156
|
|
|
@@ -142,6 +185,23 @@ function displayAuditResults() {
|
|
|
142
185
|
console.log(chalk.green('✅ No external scripts detected'));
|
|
143
186
|
}
|
|
144
187
|
|
|
188
|
+
console.log('');
|
|
189
|
+
|
|
190
|
+
// Locale Warnings
|
|
191
|
+
if (auditResults.localeWarnings.length > 0) {
|
|
192
|
+
console.log(chalk.yellow.bold('⚠️ LOCALE FIELD LENGTH WARNINGS'));
|
|
193
|
+
console.log(chalk.gray('Some locale fields exceed recommended character limits.\n'));
|
|
194
|
+
|
|
195
|
+
auditResults.localeWarnings.forEach((item, index) => {
|
|
196
|
+
console.log(chalk.yellow(` ${index + 1}. ${item.file}`));
|
|
197
|
+
console.log(chalk.gray(` Field: ${item.field} (${item.length}/${item.limit} chars)`));
|
|
198
|
+
console.log(chalk.gray(` Value: "${item.value}"`));
|
|
199
|
+
console.log('');
|
|
200
|
+
});
|
|
201
|
+
} else {
|
|
202
|
+
console.log(chalk.green('✅ All locale fields within limits'));
|
|
203
|
+
}
|
|
204
|
+
|
|
145
205
|
// Summary
|
|
146
206
|
console.log(chalk.bold('\n───────────────────────────────────────────────────'));
|
|
147
207
|
console.log(chalk.bold('SUMMARY'));
|
|
@@ -151,6 +211,10 @@ function displayAuditResults() {
|
|
|
151
211
|
const externalScriptColor = externalScriptCount > 0 ? chalk.red : chalk.green;
|
|
152
212
|
console.log(externalScriptColor(`External Scripts: ${externalScriptCount}`));
|
|
153
213
|
|
|
214
|
+
const localeWarningCount = auditResults.localeWarnings.length;
|
|
215
|
+
const localeWarningColor = localeWarningCount > 0 ? chalk.yellow : chalk.green;
|
|
216
|
+
console.log(localeWarningColor(`Locale Warnings: ${localeWarningCount}`));
|
|
217
|
+
|
|
154
218
|
console.log(chalk.bold('═══════════════════════════════════════════════════\n'));
|
|
155
219
|
}
|
|
156
220
|
|
|
@@ -7,25 +7,8 @@ const path = require('path');
|
|
|
7
7
|
const { execute } = require('node-powertools');
|
|
8
8
|
const JSON5 = require('json5');
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
const LANGUAGES =
|
|
12
|
-
'zh',
|
|
13
|
-
'es',
|
|
14
|
-
'hi',
|
|
15
|
-
'ar',
|
|
16
|
-
'pt',
|
|
17
|
-
'ru',
|
|
18
|
-
'ja',
|
|
19
|
-
'de',
|
|
20
|
-
'fr',
|
|
21
|
-
'ko',
|
|
22
|
-
'ur',
|
|
23
|
-
'id',
|
|
24
|
-
'bn',
|
|
25
|
-
'tl',
|
|
26
|
-
'vi',
|
|
27
|
-
'it',
|
|
28
|
-
];
|
|
10
|
+
// Locale config (shared with audit.js)
|
|
11
|
+
const { limits: LOCALE_LIMITS, languages: LANGUAGES } = require('../config/locales.js');
|
|
29
12
|
|
|
30
13
|
// Paths
|
|
31
14
|
const localesDir = path.join(process.cwd(), 'src', '_locales');
|
|
@@ -80,7 +63,7 @@ async function translate(complete) {
|
|
|
80
63
|
// Check which languages need translation
|
|
81
64
|
const languagesToTranslate = [];
|
|
82
65
|
|
|
83
|
-
for (const lang of LANGUAGES) {
|
|
66
|
+
for (const lang of Object.keys(LANGUAGES)) {
|
|
84
67
|
const langDir = path.join(localesDir, lang);
|
|
85
68
|
const langMessagesPath = path.join(langDir, 'messages.json');
|
|
86
69
|
|
|
@@ -156,21 +139,30 @@ async function translate(complete) {
|
|
|
156
139
|
async function translateAllWithClaude(enMessages, languagesToTranslate) {
|
|
157
140
|
// Build language info for prompt
|
|
158
141
|
const languageList = languagesToTranslate.map(({ lang }) =>
|
|
159
|
-
`- "${lang}": ${
|
|
142
|
+
`- "${lang}": ${LANGUAGES[lang]}`
|
|
160
143
|
).join('\n');
|
|
161
144
|
|
|
145
|
+
// Build character limits info
|
|
146
|
+
const limitsInfo = Object.entries(LOCALE_LIMITS)
|
|
147
|
+
.map(([field, limit]) => `- ${field}: max ${limit} characters`)
|
|
148
|
+
.join('\n');
|
|
149
|
+
|
|
162
150
|
const prompt = `Translate the following Chrome extension messages.json content from English to multiple languages.
|
|
163
151
|
|
|
164
152
|
TARGET LANGUAGES:
|
|
165
153
|
${languageList}
|
|
166
154
|
|
|
155
|
+
CHARACTER LIMITS (Chrome Web Store requirements):
|
|
156
|
+
${limitsInfo}
|
|
157
|
+
|
|
167
158
|
IMPORTANT RULES:
|
|
168
159
|
1. Only translate the "message" field values
|
|
169
160
|
2. Keep the "description" field values in English (they are for developers)
|
|
170
161
|
3. Keep all JSON keys exactly as they are
|
|
171
162
|
4. Return ONLY valid JSON, no markdown, no explanation
|
|
172
163
|
5. Preserve any placeholders like $1, $2, etc.
|
|
173
|
-
6.
|
|
164
|
+
6. IMPORTANT: Respect the character limits above for each field
|
|
165
|
+
7. Return a JSON object where each key is the language code and the value is the translated messages object
|
|
174
166
|
|
|
175
167
|
INPUT (English):
|
|
176
168
|
${JSON.stringify(enMessages, null, 2)}
|
|
@@ -225,29 +217,5 @@ Output the translated JSON:`;
|
|
|
225
217
|
}
|
|
226
218
|
}
|
|
227
219
|
|
|
228
|
-
// Get full language name
|
|
229
|
-
function getLanguageName(code) {
|
|
230
|
-
const names = {
|
|
231
|
-
zh: 'Chinese (Simplified)',
|
|
232
|
-
es: 'Spanish',
|
|
233
|
-
hi: 'Hindi',
|
|
234
|
-
ar: 'Arabic',
|
|
235
|
-
pt: 'Portuguese',
|
|
236
|
-
ru: 'Russian',
|
|
237
|
-
ja: 'Japanese',
|
|
238
|
-
de: 'German',
|
|
239
|
-
fr: 'French',
|
|
240
|
-
ko: 'Korean',
|
|
241
|
-
ur: 'Urdu',
|
|
242
|
-
id: 'Indonesian',
|
|
243
|
-
bn: 'Bengali',
|
|
244
|
-
tl: 'Tagalog/Filipino',
|
|
245
|
-
vi: 'Vietnamese',
|
|
246
|
-
it: 'Italian',
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
return names[code] || code;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
220
|
// Export task
|
|
253
221
|
module.exports = series(translate);
|