Mirror of
0
fork

Configure Feed

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

feat: filter languages that have 0 translations in any plugin

+49 -11
+22 -1
src/components/DropdownLinks.astro
··· 1 1 --- 2 2 import { DashboardData } from "../data"; 3 + import { processPlugins } from "../utils"; 3 4 5 + const plugins = await processPlugins(); 6 + 7 + // Collect all languages with 'done' translation anywhere 8 + const languagesWithTranslations = new Set<string>(); 9 + for (const plugin of plugins) { 10 + for (const keyData of plugin.keys) { 11 + for (const [lang, status] of Object.entries(keyData.locales)) { 12 + if (status === "done") { 13 + languagesWithTranslations.add(lang); 14 + } 15 + } 16 + } 17 + } 18 + 19 + // Now filter the locales array accordingly 20 + const filteredLocales = DashboardData.locales.filter((locale) => 21 + languagesWithTranslations.has(locale.lang) 22 + ); 23 + 24 + // Keep pluginLinks unchanged (or filter similarly if needed) 4 25 const pluginLinks = DashboardData.plugins.map((plugin) => ({ 5 26 name: plugin.name, 6 27 link: `/plugins/${plugin.packageName}`, 7 28 })); 8 29 9 - const localeLinks = DashboardData.locales.map((locale) => ({ 30 + const localeLinks = filteredLocales.map((locale) => ({ 10 31 label: locale.label, 11 32 link: `/languages/${locale.lang}`, 12 33 }));
+27 -10
src/utils.ts
··· 65 65 // Map base normalized key -> first line number (1-based) 66 66 const baseKeyToLine = new Map<string, number>(); 67 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 68 let insideEnBlock = false; 71 69 for (let i = 0; i < lines.length; i++) { 72 70 const line = lines[i].trim(); ··· 76 74 continue; 77 75 } 78 76 if (insideEnBlock && line === "},") { 79 - // end of 'en' block 80 77 insideEnBlock = false; 81 78 } 82 79 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 80 const keyMatch = line.match(/^['"]([^'"]+)['"]\s*:/); 88 81 if (keyMatch) { 89 82 const rawKey = keyMatch[1]; 90 83 const baseKey = normalizeKey(rawKey); 91 84 if (!baseKeyToLine.has(baseKey)) { 92 - baseKeyToLine.set(baseKey, i + 1); // line numbers 1-based 85 + baseKeyToLine.set(baseKey, i + 1); 93 86 } 94 87 } 95 88 } 96 89 } 97 90 98 - // Now fetch parsed translations object for all locales 99 91 const data = await fetchTranslationFile(plugin.translationFileLinkRaw); 100 92 101 93 const defaultLang = "en"; ··· 117 109 localesStatus[lang] = hasTranslation ? "done" : "missing"; 118 110 } 119 111 120 - const line = baseKeyToLine.get(key)!; // must exist 112 + const line = baseKeyToLine.get(key)!; 121 113 122 114 keysStatus.push({ key, locales: localesStatus, line }); 123 115 } ··· 129 121 translationFileLinkRaw: plugin.translationFileLinkRaw, 130 122 keys: keysStatus, 131 123 }); 124 + } 125 + 126 + // Now filter out languages with no 'done' status anywhere in any plugin 127 + // Collect all languages that have 'done' status in any plugin's keys 128 + const languagesWithTranslations = new Set<string>(); 129 + 130 + for (const plugin of results) { 131 + for (const keyData of plugin.keys) { 132 + for (const [lang, status] of Object.entries(keyData.locales)) { 133 + if (status === "done") { 134 + languagesWithTranslations.add(lang); 135 + } 136 + } 137 + } 138 + } 139 + 140 + // Filter out locales in plugins keys for languages that never have any translation 141 + for (const plugin of results) { 142 + for (const keyData of plugin.keys) { 143 + for (const lang of Object.keys(keyData.locales)) { 144 + if (!languagesWithTranslations.has(lang)) { 145 + delete keyData.locales[lang]; 146 + } 147 + } 148 + } 132 149 } 133 150 134 151 return results;