Skip to content

Commit deaec3d

Browse files
authored
Merge pull request #58 from BeyteFlow/pr-56
refactor(i18n):
2 parents 42b7ccf + 9e5b545 commit deaec3d

6 files changed

Lines changed: 39 additions & 36 deletions

File tree

bin/index.js

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,38 +118,28 @@ program
118118
});
119119

120120
// ----------------- ANALYZE COMMAND -----------------
121-
program
121+
program
122122
.command("analyze <errorString>")
123123
.description("Analyze a specific error string")
124124
.option("--lang <code>", "output language (e.g. hi, es, fr)", "en")
125-
.argument("<error>", "error to explain")
126-
127-
128-
.action(async (errorString,options) => {
125+
.action(async (errorString, options) => {
129126
const { default: chalk } = await import("chalk");
130127
const isJson = Boolean(program.opts().json);
131-
const { count, matches } = findError(errorString,options.lang);
128+
const { count, matches } = findError(errorString, options.lang);
132129
const exitCode = count > 0 ? 1 : 0;
133130

134131
if (isJson) {
135-
console.log(
136-
JSON.stringify({ code: exitCode, count, matches }, null, 2)
137-
);
132+
console.log(JSON.stringify({ code: exitCode, count, matches }, null, 2));
138133
process.exit(exitCode);
139134
}
140135

141136
if (count > 0) {
142-
console.log(
143-
chalk.bold.cyan(`\n🚀 ErrLens Analysis (${count} Issue(s)):`)
144-
);
137+
console.log(chalk.bold.cyan(`\n🚀 ErrLens Analysis (${count} Issue(s)):`));
145138
matches.forEach((m) => console.log(formatError(m)));
146139
} else {
147-
console.log(
148-
chalk.red.bold("\n❌ Crash detected (No known fix in database):")
149-
);
140+
console.log(chalk.red.bold("\n❌ Crash detected (No known fix in database):"));
150141
console.log(chalk.gray(errorString));
151142
}
152-
153143

154144
process.exit(exitCode);
155145
});

lib/matcher.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,29 @@ const path = require("path");
44

55
// Loading the locale file
66
function loadLocale(lang = "en"){
7-
const filepath = path.join(__dirname,"../locales", `${lang}.json`);
8-
const fallback = path.join(__dirname,"../locales/en.json");
7+
const localesDir = path.resolve(__dirname, "../locales");
8+
const normalizedLang =
9+
typeof lang === "string" && /^[a-zA-Z0-9_-]+$/.test(lang)
10+
? lang
11+
: "en";
12+
const filepath = path.resolve(localesDir, `${normalizedLang}.json`);
13+
const fallback = path.resolve(localesDir, "en.json");
14+
const relativeToLocales = path.relative(localesDir, filepath);
15+
const safeFilepath =
16+
!relativeToLocales.startsWith("..") && !path.isAbsolute(relativeToLocales)
17+
? filepath
18+
: fallback;
19+
920
try {
10-
return JSON.parse(fs.readFileSync(filepath,"utf8"))
11-
} catch (error) {
12-
return JSON.parse(fs.readFileSync(fallback,"utf8"))
13-
21+
return JSON.parse(fs.readFileSync(safeFilepath,"utf8"))
22+
} catch (primaryError) {
23+
try {
24+
return JSON.parse(fs.readFileSync(fallback,"utf8"))
25+
} catch (fallbackError) {
26+
throw new Error(
27+
`Failed to load locale \"${normalizedLang}\" at \"${safeFilepath}\" and fallback \"${fallback}\". Primary error: ${primaryError.message}. Fallback error: ${fallbackError.message}`
28+
)
29+
}
1430
}
1531
}
1632

@@ -21,7 +37,7 @@ function translateEntry(entry,locale){
2137
...entry,
2238
explanation:locale[`${key}__explanation`] || entry.explanation,
2339
why: locale[`${key}__why`] || entry.why,
24-
fixes: entry.fixes.map(
40+
fixes: (Array.isArray(entry.fixes) ? entry.fixes : []).map(
2541
(fix,i) =>locale[`${key}__fix_${i}`] || fix
2642
)
2743
}

locales/de.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,13 @@
187187
"npm ERR! 404__why": "Tippfehler im Paketnamen oder es ist ein privates Paket.",
188188
"npm ERR! 404__fix_0": "Prüfe die Schreibweise des Pakets",
189189
"npm ERR! 404__fix_1": "npm login",
190-
"Unexpected end of input__explanation": "Dein Code wurde abrupt beendet, wahrscheinlich fehlt eine schließende Klammer.",
191-
"Unexpected end of input__why": "Du hast eine ( [ oder { geöffnet, aber vergessen, sie mit ) ] oder } zu schließen.",
192-
"Unexpected end of input__fix_0": "Prüfe auf fehlende schließende Klammern )",
193-
"Unexpected end of input__fix_1": "Prüfe auf fehlende geschweifte Klammern }",
190+
"Unexpected end of input__explanation": "Ihr Code wurde abrupt beendet, wahrscheinlich fehlt eine schließende Klammer.",
191+
"Unexpected end of input__why": "Sie haben eine ( [ oder { geöffnet, aber vergessen, sie mit ) ] oder } zu schließen.",
192+
"Unexpected end of input__fix_0": "Prüfen Sie auf fehlende schließende Klammern )",
193+
"Unexpected end of input__fix_1": "Prüfen Sie auf fehlende geschweifte Klammern }",
194194
"Unexpected end of input__fix_2": "Stelle sicher, dass alle Anführungszeichen ' oder \" geschlossen sind",
195-
"missing ) after argument list__explanation": "Du hast vergessen, einen Funktionsaufruf mit ')' zu schließen.",
195+
"missing ) after argument list__explanation": "Sie haben vergessen, einen Funktionsaufruf mit ')' zu schließen.",
196196
"missing ) after argument list__why": "Eine Klammer wurde geöffnet, aber die Zeile endete oder ein anderes Symbol erschien, bevor sie geschlossen wurde.",
197-
"missing ) after argument list__fix_0": "Füge eine ')' am Ende deines Funktionsaufrufs hinzu",
198-
"missing ) after argument list__fix_1": "Prüfe, ob du versehentlich eine ')' beim Tippen gelöscht hast"
197+
"missing ) after argument list__fix_0": "Fügen Sie eine ')' am Ende Ihres Funktionsaufrufs hinzu",
198+
"missing ) after argument list__fix_1": "Prüfen Sie, ob Sie versehentlich eine ')' beim Tippen gelöscht haben"
199199
}

locales/es.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
"EACCES__explanation": "No tienes permiso para acceder a este archivo/puerto.",
100100
"EACCES__why": "Necesitas permisos de administrador o el archivo está bloqueado.",
101101
"EACCES__fix_0": "Usa 'sudo' (Linux/Mac)",
102-
"EACCES__fix_1": "Verificar los permisos del archivo",
102+
"EACCES__fix_1": "Verifica los permisos del archivo",
103103
"has already been declared__explanation": "Declaraste el mismo nombre de variable dos veces.",
104104
"has already been declared__why": "Usar 'let' o 'const' en un nombre que ya existe en el mismo ámbito.",
105105
"has already been declared__fix_0": "Renombrar una de las variables",

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
32
"name": "errlens",
43
"version": "1.0.9",
54
"description": "Professional CLI tool that explains JavaScript and Node.js errors in plain English with actionable fixes directly in your terminal.",
@@ -34,8 +33,6 @@
3433
],
3534
"scripts": {
3635
"test": "node --test test/**/*.test-lang.js"
37-
38-
3936
},
4037
"repository": {
4138
"type": "git",
@@ -59,4 +56,4 @@
5956
"directories": {
6057
"lib": "lib"
6158
}
62-
}
59+
}

scripts/extractlocals.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ for (const entry of db){
1313
en[`${key}__explanation`] = entry.explanation
1414
en[`${key}__why`] = entry.why
1515

16-
entry.fixes.forEach((fix,i) => {
16+
(Array.isArray(entry.fixes) ? entry.fixes : []).forEach((fix,i) => {
1717
en[`${key}__fix_${i}`] = fix
1818
})
1919
}

0 commit comments

Comments
 (0)