Skip to content

Commit

Permalink
Resolve an issue where the 'removeUnusedKeys' option may re-order key…
Browse files Browse the repository at this point in the history
…s in the translation file (#64)
  • Loading branch information
cheton committed Jan 21, 2018
1 parent 891fa2c commit a6fa06c
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 15 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@
],
"dependencies": {
"chalk": "^2.3.0",
"clone-deep": "^3.0.1",
"commander": "^2.13.0",
"deepmerge": "^2.0.1",
"ensure-array": "^1.0.0",
"eol": "^0.9.1",
"esprima": "^4.0.0",
"gulp-sort": "^2.0.0",
Expand Down
11 changes: 0 additions & 11 deletions src/ensure-array.js

This file was deleted.

29 changes: 29 additions & 0 deletions src/flatten-object-keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import isPlainObject from 'lodash/isPlainObject';

// flattenObjectKeys({
// a: {
// b: {
// c: [],
// d: {
// e: [{ f: [] }, { b: 1 }],
// g: {}
// }
// }
// }
// });
//
// [ [ 'a', 'b', 'c' ],
// [ 'a', 'b', 'd', 'e', '0', 'f' ],
// [ 'a', 'b', 'd', 'e', '1', 'b' ],
// [ 'a', 'b', 'd', 'g' ] ]
//
const flattenObjectKeys = (obj, keys = []) => {
return Object.keys(obj).reduce((acc, key) => {
const o = ((isPlainObject(obj[key]) && Object.keys(obj[key]).length > 0) || (Array.isArray(obj[key]) && obj[key].length > 0))
? flattenObjectKeys(obj[key], keys.concat(key))
: [keys.concat(key)];
return acc.concat(o);
}, []);
};

export default flattenObjectKeys;
36 changes: 36 additions & 0 deletions src/omit-empty-object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import isPlainObject from 'lodash/isPlainObject';
import cloneDeep from 'clone-deep';

// omitEmptyObject({
// a: {
// b: {
// c: 1,
// d: {
// e: {
// }
// }
// }
// }
// });
//
// { a: { b: { c: 1 } } }
//
const unsetEmptyObject = (obj) => {
Object.keys(obj).forEach(key => {
if (!isPlainObject(obj[key])) {
return;
}

unsetEmptyObject(obj[key]);
if (isPlainObject(obj[key]) && Object.keys(obj[key]).length === 0) {
obj[key] = undefined;
delete obj[key];
}
});

return obj;
};

const omitEmptyObject = (obj) => unsetEmptyObject(cloneDeep(obj));

export default omitEmptyObject;
31 changes: 27 additions & 4 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
/* eslint no-eval: 0 */
import fs from 'fs';
import chalk from 'chalk';
import cloneDeep from 'clone-deep';
import deepMerge from 'deepmerge';
import ensureArray from 'ensure-array';
import { parse } from 'esprima';
import _ from 'lodash';
import parse5 from 'parse5';
import sortObject from 'sortobject';
import ensureArray from './ensure-array';
import flattenObjectKeys from './flatten-object-keys';
import omitEmptyObject from './omit-empty-object';
import { jsxToText } from './jsx-parser';

const defaults = {
Expand Down Expand Up @@ -521,15 +525,34 @@ class Parser {

let resStore = {};
if (this.options.removeUnusedKeys) {
resStore = this.resScan;
// Merge two objects `resStore` and `resScan` deeply, returning a new merged object with the elements from both `resStore` and `resScan`.
const resMerged = deepMerge(this.resStore, this.resScan);

Object.keys(this.resStore).forEach((lng) => {
Object.keys(this.resStore[lng]).forEach((ns) => {
const resStoreKeys = flattenObjectKeys(_.get(this.resStore, [lng, ns], {}));
const resScanKeys = flattenObjectKeys(_.get(this.resScan, [lng, ns], {}));
const unusedKeys = _.differenceWith(resStoreKeys, resScanKeys, _.isEqual);

for (let i = 0; i < unusedKeys.length; ++i) {
_.unset(resMerged[lng][ns], unusedKeys[i]);
}

// Omit empty object
resMerged[lng][ns] = omitEmptyObject(resMerged[lng][ns]);
});
});

resStore = resMerged;
} else {
resStore = this.resStore;
resStore = cloneDeep(this.resStore);
}

if (opts.sort) { // sort by key
if (opts.sort) {
Object.keys(resStore).forEach((lng) => {
const namespaces = resStore[lng];
Object.keys(namespaces).forEach((ns) => {
// Deeply sort an object by its keys without mangling any arrays inside of it
resStore[lng][ns] = sortObject(namespaces[ns]);
});
});
Expand Down

0 comments on commit a6fa06c

Please sign in to comment.