Skip to content

Commit

Permalink
refactor: allow the removeUnusedKeys function to be passed in to de…
Browse files Browse the repository at this point in the history
…termine if an unused key should be removed
  • Loading branch information
cheton committed Oct 14, 2024
1 parent 56675a2 commit 0c23fa8
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 54 deletions.
42 changes: 20 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,6 @@ Below are the configuration options with their default values:
compatibilityJSON: 'v3', // One of: 'v1', 'v2', 'v3', 'v4
debug: false,
removeUnusedKeys: false,
filterUnusedKeys: false,
sort: false,
attr: {
list: ['data-i18n'],
Expand Down Expand Up @@ -571,31 +570,30 @@ Set to `true` to turn on debug output.

#### removeUnusedKeys

Type: `Boolean` Default: `false`

Set to `true` to remove unused translation keys from i18n resource files.

#### filterUnusedKeys
Type: `Boolean` or `Function` Default: `false`

Type: `Object` Default: `false`
Set to `true` to remove unused translation keys from i18n resource files. By default, this is set to `false`.
```js
{ // Default
removeUnusedKeys: false,
}
```

If an `Object` is supplied and `removeUnusedKeys` is set to `true`, to leave specific keys you can specify a function like so:
If a function is provided, it will be used to decide whether an unused translation key should be removed.
```js
filterUnusedKeys: ({ lng, ns, unusedKey }) => {
// Available since 4.6.0
//
// @param {string} lng The language of the unused translation key.
// @param {string} ns The namespace of the unused translation key.
// @param {array} key The translation key in its array form.
// @return {boolean} Returns true if the unused translation key should be removed.
removeUnusedKeys: function(lng, ns, key) {
if (ns === 'resource') {
const exceptionKeys = ['word', 'key.word', ...];
if (exceptionKeys.includes(unusedKey)) {
// leave key
return true;
}
}
if (ns === 'other_resource') {
// leave key
return true;
}
// remove key
return false;
}
```

#### sort

Expand All @@ -617,7 +615,7 @@ If an `Object` is supplied, you can either specify a list of attributes and exte
}
```

You can set attr to `false` to disable parsing attribute as below:
You can set `attr` to `false` to disable parsing attribute as below:
```js
{
attr: false
Expand All @@ -638,7 +636,7 @@ If an `Object` is supplied, you can either specify a list of translation functio
}
```

You can set func to `false` to disable parsing translation function as below:
You can set `func` to `false` to disable parsing translation function as below:
```js
{
func: false
Expand Down Expand Up @@ -672,14 +670,14 @@ If an `Object` is supplied, you can specify a list of extensions, or override th
}
```

You can set trans to `false` to disable parsing Trans component as below:
You can set `trans` to `false` to disable parsing Trans component as below:
```js
{
trans: false
}
```

The fallbackKey can either be a boolean value, or a function like so:
The `fallbackKey` can either be a boolean value, or a function like so:
```js
fallbackKey: function(ns, value) {
// Returns a hash value as the fallback key
Expand Down
41 changes: 9 additions & 32 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ class Parser {
}

let resStore = {};
if (this.options.removeUnusedKeys) {
if (!!this.options.removeUnusedKeys) {
// Merge two objects `resStore` and `resScan` deeply, returning a new merged object with the elements from both `resStore` and `resScan`.
const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray;
const resMerged = deepMerge(this.resStore, this.resScan, { arrayMerge: overwriteMerge });
Expand All @@ -796,40 +796,17 @@ class Parser {
const resStoreKeys = flattenObjectKeys(_.get(this.resStore, [lng, ns], {}));
const resScanKeys = flattenObjectKeys(_.get(this.resScan, [lng, ns], {}));
const unusedKeys = _.differenceWith(resStoreKeys, resScanKeys, _.isEqual);
let filteredKey;

for (let i = 0; i < unusedKeys.length; ++i) {
filteredKey = false;

if (
this.options.filterUnusedKeys &&
typeof this.options.filterUnusedKeys === 'function'
) {
filteredKey = this.options.filterUnusedKeys({
lng,
ns,
unusedKey: unusedKeys[i].toString().replaceAll(',', '.'),
});
}

if (!filteredKey) {
_.unset(resMerged[lng][ns], unusedKeys[i]);
this.log(
`Removed an unused translation key { ${chalk.red(
JSON.stringify(unusedKeys[i])
)} } from ${chalk.red(
JSON.stringify(this.formatResourceLoadPath(lng, ns))
)}`
);
continue;
const unusedKey = unusedKeys[i];
const isRemovable = (typeof this.options.removeUnusedKeys === 'function')
? this.options.removeUnusedKeys(lng, ns, unusedKey)
: !!this.options.removeUnusedKeys;

if (isRemovable) {
_.unset(resMerged[lng][ns], unusedKey);
this.log(`Removed an unused translation key { ${chalk.red(JSON.stringify(unusedKey))} } from ${chalk.red(JSON.stringify(this.formatResourceLoadPath(lng, ns)))}`);
}
this.log(
`Skipped removing an unused translation key { ${chalk.yellow(
JSON.stringify(unusedKeys[i])
)} } from ${chalk.yellow(
JSON.stringify(this.formatResourceLoadPath(lng, ns))
)}`
);
}

// Omit empty object
Expand Down

0 comments on commit 0c23fa8

Please sign in to comment.