diff --git a/scripts/scan-locales.mjs b/scripts/scan-locales.mjs index 6c1df9f9d..5089c79ee 100644 --- a/scripts/scan-locales.mjs +++ b/scripts/scan-locales.mjs @@ -1,108 +1,62 @@ import fs from 'fs' -import path from 'path' + +import glob from 'glob' import { BASE_LOCALE, getLocaleData, getLocalePaths } from './locale-utils.mjs' const baseLocale = getLocalePaths(BASE_LOCALE) -;(() => { - const { keys, namespaces } = getLocaleData(baseLocale) - - function createRegex(text, { caseInsensitive = true } = {}) { - const escapedPattern = text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - const flags = caseInsensitive ? 'gi' : 'g' - return new RegExp(`\\b${escapedPattern}`, flags) - } +const { keys: translationKeys, namespaces } = getLocaleData(baseLocale) - function filterByExt(text, exts = []) { - const regex = new RegExp(`(${exts.join('|')})$`) - return regex.test(text) - } +const translationKeysWoNs = translationKeys.map((key) => + key.replace(new RegExp(`^(${namespaces.join('|')}).`), ''), +) - const dir = './src' - const search = `t('` - const regex = createRegex(search) +// Search for translation keys in the source code +function searchForTranslationKeysInCode() { + const regex = /t[cs]?\(['"`]([a-zA-Z0-9_.]+)['"`]\s*,?\s*{?/g + // = /t\(['"`]([a-zA-Z0-9_.]+)['"`]\s*,?\s*{?/g + // /t\(['"`]([a-zA-Z0-9_.]+)['"`]\)/g // regex to match t('key') + const files = [ + ...glob.sync(`./src/**/*.{js,jsx,ts,tsx}`), + ...glob.sync(`./src/*.{js,jsx,ts,tsx}`), + ] - const results = { - results: [], - files: [], - } + const foundKeys = new Set() - function extractKey(str) { - const keyRegex = /t\(\s*['"](.+?)['"]\s*,?/ - const keyMatch = str.match(keyRegex) - return keyMatch ? keyMatch[1] : null - } + files.forEach((file) => { + const content = fs.readFileSync(file, 'utf-8') + let match - function extractMatch(filePath) { - let match = true - const matches = [] - let content = fs.readFileSync(filePath, 'utf-8') - - while ((match = regex.exec(content))) { - // /\b(?:t)\s*\(\s*(['\s\S']*?)\s*\)/g - const line = /\b(?:t)\s*\(['"][^'"]+['"][^)]*\)/g.exec(content)?.at(0) - content = content.replace(match?.[0], '').replace(line, '') - matches.push(extractKey(line)) + while ((match = regex.exec(content)) !== null) { + foundKeys.add(match[1]) // Add the matched key } - return matches - } - - function handleResults(filePath) { - const matches = extractMatch(filePath) - - if (!matches.length) return - - // console.log(`Found ${matches.length} ${search} in ${filePath}:`) - matches.forEach((m) => console.log(m)) - // console.log('\n') - results.results = [...results.results, ...matches] - results.files = [...results.files, filePath] - } + const keys = translationKeysWoNs.filter((key) => new RegExp(`['"\`]${key}['"\`]`).test(content)) - // Function to recursively scan files in a directory - function scanFiles({ dir, fn, ext = [] }) { - const files = fs.readdirSync(dir) - - files.forEach((file) => { - const filePath = path.join(dir, file) - const stat = fs.statSync(filePath) + for (const key of keys) { + foundKeys.add(key) + } + }) - if (stat.isDirectory()) { - scanFiles({ dir: filePath, fn, ext }) // Recursively scan subdirectories - } else if (stat.isFile() && filterByExt(file, ext)) { - fn(filePath) - } - }) - } + return foundKeys +} - scanFiles({ - dir, - fn: handleResults, - ext: ['.ts', '.tsx'], - }) +// Find unused translation keys +function findUnusedKeys() { + const usedKeys = searchForTranslationKeysInCode() const unusedKeys = [] - const foundKeys = [ - ...new Set( - results.results.map((key) => key.replace(new RegExp(`^(${namespaces.join('|')}).`), '')), - ), - ] - const modifiedKeys = [ - ...new Set(keys.map((key) => key.replace(new RegExp(`^(${namespaces.join('|')}).`), ''))), - ] - - for (const key of modifiedKeys) { - const foundKey = foundKeys.find((k) => key === k) - if (!foundKey) { + for (const key of translationKeysWoNs) { + if (!usedKeys.has(key)) { unusedKeys.push(key) } } - - console.log('PROBABLY UNSED KEYS\n') - for (const key of unusedKeys) { + console.log(`PROBABLY ${unusedKeys.length} UNSED KEYS:`) + unusedKeys.forEach((key) => { console.log(key) - } -})() + }) +} + +findUnusedKeys()