Skip to content

Instantly share code, notes, and snippets.

@predragnikolic
Created April 14, 2022 11:03
Show Gist options
  • Save predragnikolic/61917737c22c55cbeb74fdb18f7bb76f to your computer and use it in GitHub Desktop.
Save predragnikolic/61917737c22c55cbeb74fdb18f7bb76f to your computer and use it in GitHub Desktop.
/*
This script *tries* to find unused tranlations. :)
Do not expect 100% perfect detection, but it should give good enough results.
This script can detect:
```
t('some_translation_key') // can be detected
let x: TranslationKey = "some_translation_key" // can be detected, because of the use of `t()`
let x = "some_translation_key" as TranslationKey // can be detected, because of the use of TranslationKey
<Trans i18nKey="some_translation_key"` /> can be detected, because of the use of prop i18nKey
```
This script cannot detect:
```
{message: "some_translation_key"} // cannot be detected.
```
A way to solve it is to use the `as TranslationKey`
```
{message: "some_translation_key" as TranslationKey} // can be detected, because of the use of TranslationKey
```
You can tweak the linePatternsThatMayContainTranslations to extend the detection of lines with translations.
You can twaek the ignoreTranslations to ignore some translations.
*/
/**
* Regex patterns that should detect a translation key.
* Specify them here:
*/
const linePatternsThatMayContainTranslations = [
/.*t\(.*/, // should find `{t('some_key')}` or `i18n.t('some_key')` calls
/.*TranslationKey.*/, // should find `message: "some_key" as TranslationKey` or `let title: TranslationKey = "some_key"`
/.*i18nKey.*/ // should find `<Trans i18nKey="diversity_page.openness.effects"`
]
/**
* There are some translations that shuold be ignored.
* Specify them here:
*/
const ignoreTranslations = [
/^enums/, // dynamically generated
/^hello_processing\.error_code/, // dynamically generated
/^hello_processing\.error_code/, // dynamically generated
/^assessment_detail\..*\.title/, // dynamically generated
/^assessment_detail\..*\.low/, // dynamically generated
/^assessment_detail\..*\.mid/, // dynamically generated
/^assessment_detail\..*\.high/, // dynamically generated
/^hello_results_page.populations/, // dynamically generated
/^video_recording.color_scheme/, // dynamically generated
/^hellovima.error_codes/, // dynamically generated
/^video_recording.fields_type.enum/, // dynamically generated
]
// --- You should not be interested in the bellow, but you can take a look.
const path = require('path');
var findInFiles = require("find-in-files")
const targetDir = path.join(__dirname, '..', 'src')
const targetFiles = "(.ts|.tsx|.js|.jsx)$"
const allTranslationKeys = Object.keys(require("../src/i18n/locales/en.json"))
const notIgnoredTranslationKeys = allTranslationKeys.filter(translationKey => !isIgnored(translationKey))
/**
* Ignore thanslations that are dynamically generated like `t{`some_key.{dynamicValue}`}`
* @param {string} translationKey The value
* @return {boolean} { description_of_the_return_value }
*/
function isIgnored(translationKey) {
return ignoreTranslations.some(ignoredTraslationRegex => ignoredTraslationRegex.test(translationKey))
}
async function main() {
const linesThatMaybeContainTranslations = []
for (const pattern of linePatternsThatMayContainTranslations) {
const results = await findInFiles.find(pattern, targetDir, targetFiles)
const linesWithTranslations = extractLinesFromResults(results)
linesThatMaybeContainTranslations.push(...linesWithTranslations)
}
const unusedKeys = notIgnoredTranslationKeys.filter(translationKey => {
return !linesThatMaybeContainTranslations.some(line => line.includes(translationKey))
})
console.log(`Found ${unusedKeys.length} unused keys:`)
console.log(unusedKeys)
}
main()
/**
* @param {Results} results The results
* @return {string[]} The used translations.
*/
function extractLinesFromResults(results) {
/** @type {string[]} */
let usedTranslations = []
for (const fileName in results) {
const result = results[fileName]
usedTranslations = usedTranslations.concat(result.matches)
}
return usedTranslations
}
@predragnikolic
Copy link
Author

Package.json

{
  "scripts": {
    "find-unused-translations": "node ./scripts/findUnusedTranslations.js"
  },
  "devDependencies": {
    "find-in-files": "^0.5.0",
  }
}

@johnfelipe
Copy link

root@ubuntu21:~/XREngine# cd /root/XREngine/packages/
root@ubuntu21:~/XREngine/packages# wget https://gist.githubusercontent.com/predragnikolic/61917737c22c55cbeb74fdb18f7bb76f/raw/8f1064581e4d08d84285a1088653a594cc8006a3/findUnusedTranslations.js
--2022-06-08 04:26:43--  https://gist.githubusercontent.com/predragnikolic/61917737c22c55cbeb74fdb18f7bb76f/raw/8f1064581e4d08d84285a1088653a594cc8006a3/findUnusedTranslations.js
Resolving gist.githubusercontent.com (gist.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.109.133, ...
Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3894 (3.8K) [text/plain]
Saving to: ‘findUnusedTranslations.js’

findUnusedTranslati 100%[===================>]   3.80K  --.-KB/s    in 0.001s

2022-06-08 04:26:44 (5.24 MB/s) - ‘findUnusedTranslations.js’ saved [3894/3894]

root@ubuntu21:~/XREngine/packages# cd ..
root@ubuntu21:~/XREngine# npm run find-unused-translations                      
> [email protected] find-unused-translations
> node ./root/XREngine/packages/findUnusedTranslations.js

node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module '/root/XREngine/root/XREngine/packages/findUnusedTranslations.js'
	at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
	at Function.Module._load (node:internal/modules/cjs/loader:778:27)
	at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
	at node:internal/main/run_main_module:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

how solve this?

@predragnikolic
Copy link
Author

Did you install the find-in-files dependency?

@johnfelipe
Copy link

johnfelipe commented Jun 8, 2022

Package.json

{
  "scripts": {
    "find-unused-translations": "node ./scripts/findUnusedTranslations.js"
  },
  "devDependencies": {
    "find-in-files": "^0.5.0",
  }
}

yes i put this one in json file
but my question is how run wich one command

node

?

or

yarn run

or

npx?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment