Mirror of
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: plural suffixes with line numbers issue

+54 -42
+54 -42
src/utils.ts
··· 33 33 return key; 34 34 } 35 35 36 - // Utility to fetch the remote .ts file and parse it 37 - async function fetchTranslationFile( 38 - url: string 39 - ): Promise<{ data: TranslationMap; enLineNumbers: Record<string, number> }> { 36 + async function fetchTranslationFileRaw(url: string): Promise<string> { 40 37 const res = await fetch(url); 41 - const text = await res.text(); 42 - const lines = text.split("\n"); 38 + if (!res.ok) throw new Error(`Failed to fetch ${url}`); 39 + return await res.text(); 40 + } 43 41 42 + async function fetchTranslationFile(url: string): Promise<TranslationMap> { 43 + const text = await fetchTranslationFileRaw(url); 44 + 45 + // Extract the JSON-ish Translations object code 44 46 const match = text.match(/export const Translations\s*=\s*(\{[\s\S]*\});?/); 45 47 if (!match) throw new Error("Could not find Translations object in the file"); 46 48 47 49 const translationObject = new Function( 48 50 `return ${match[1]}` 49 51 )() as TranslationMap; 50 - 51 - // Line number extraction (for English keys only) 52 - const enLineNumbers: Record<string, number> = {}; 53 - let insideEn = false; 54 - 55 - for (let i = 0; i < lines.length; i++) { 56 - const line = lines[i]; 57 - 58 - if (!insideEn) { 59 - if (/en:\s*\{/.test(line)) { 60 - insideEn = true; 61 - } 62 - continue; 63 - } 64 - 65 - if (/^\s*\}/.test(line)) break; 66 - 67 - const keyMatch = line.match(/['"`]([^'"`]+)['"`]\s*:/); 68 - if (keyMatch) { 69 - const rawKey = keyMatch[1]; 70 - const normalized = normalizeKey(rawKey); 71 - enLineNumbers[normalized] = i + 1; 72 - } 73 - } 74 - 75 - return { data: translationObject, enLineNumbers }; 52 + return translationObject; 76 53 } 77 54 78 55 export async function processPlugins(): Promise<DataPerPlugin[]> { 79 56 const results: DataPerPlugin[] = []; 80 57 81 58 for (const plugin of DashboardData.plugins) { 82 - const { data, enLineNumbers } = await fetchTranslationFile( 59 + // Fetch raw file text to extract line numbers for English keys 60 + const rawText = await fetchTranslationFileRaw( 83 61 plugin.translationFileLinkRaw 84 62 ); 63 + const lines = rawText.split(/\r?\n/); 64 + 65 + // Map base normalized key -> first line number (1-based) 66 + const baseKeyToLine = new Map<string, number>(); 67 + 68 + // Simple key extractor regex: match keys in the 'en' object only 69 + // Assumes key strings are single-quoted or double-quoted, e.g. 'key': or "key": 70 + let insideEnBlock = false; 71 + for (let i = 0; i < lines.length; i++) { 72 + const line = lines[i].trim(); 73 + 74 + if (/^en:\s*\{/.test(line)) { 75 + insideEnBlock = true; 76 + continue; 77 + } 78 + if (insideEnBlock && line === "},") { 79 + // end of 'en' block 80 + insideEnBlock = false; 81 + } 82 + if (insideEnBlock) { 83 + // Try to extract key string from line like: 84 + // 'starlightBlog.authors.count_one': '{{count}} post by {{author}}', 85 + // or 86 + // "some.key_here": "value", 87 + const keyMatch = line.match(/^['"]([^'"]+)['"]\s*:/); 88 + if (keyMatch) { 89 + const rawKey = keyMatch[1]; 90 + const baseKey = normalizeKey(rawKey); 91 + if (!baseKeyToLine.has(baseKey)) { 92 + baseKeyToLine.set(baseKey, i + 1); // line numbers 1-based 93 + } 94 + } 95 + } 96 + } 97 + 98 + // Now fetch parsed translations object for all locales 99 + const data = await fetchTranslationFile(plugin.translationFileLinkRaw); 85 100 86 101 const defaultLang = "en"; 87 - const defaultKeys = Object.keys(data[defaultLang] || {}); 88 - const normalizedDefaultKeys = defaultKeys.map(normalizeKey); 102 + const defaultKeys = new Set(Object.keys(data[defaultLang] || {})); 103 + const normalizedDefaultKeys = new Set([...defaultKeys].map(normalizeKey)); 89 104 const allLocales = DashboardData.locales.map((l) => l.lang); 90 105 91 106 const keysStatus: DataPerKey[] = []; 92 107 93 108 for (const key of normalizedDefaultKeys) { 94 - const line = enLineNumbers[key] ?? null; 95 - const localesStatus: Record<string, Status> = {}; 109 + const localesStatus: Record<string, "done" | "missing"> = {}; 96 110 97 111 for (const lang of allLocales) { 98 112 if (lang === defaultLang) continue; ··· 103 117 localesStatus[lang] = hasTranslation ? "done" : "missing"; 104 118 } 105 119 106 - keysStatus.push({ 107 - key, 108 - line, 109 - locales: localesStatus, 110 - }); 120 + const line = baseKeyToLine.get(key)!; // must exist 121 + 122 + keysStatus.push({ key, locales: localesStatus, line }); 111 123 } 112 124 113 125 results.push({