-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Stanislav Lysak
committed
Sep 12, 2024
1 parent
36087a4
commit 93c5320
Showing
1 changed file
with
39 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |