Skip to content

Instantly share code, notes, and snippets.

@Justkant
Created August 16, 2019 11:37
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Justkant/85c716c036a1ba8847b5b41270593575 to your computer and use it in GitHub Desktop.
Save Justkant/85c716c036a1ba8847b5b41270593575 to your computer and use it in GitHub Desktop.
Scan + merge except for defaultLng, with support for removeUnusedKeys option
/* eslint-disable import/no-extraneous-dependencies */
const _ = require('lodash');
const fs = require('fs');
const eol = require('eol');
const path = require('path');
const VirtualFile = require('vinyl');
const flattenObjectKeys = require('i18next-scanner/lib/flatten-object-keys')
.default;
const omitEmptyObject = require('i18next-scanner/lib/omit-empty-object')
.default;
function getFileJSON(resPath) {
try {
return JSON.parse(
fs
.readFileSync(fs.realpathSync(path.join('src', resPath)))
.toString('utf-8'),
);
} catch (e) {
return {};
}
}
function flush(done) {
const { parser } = this;
const { options } = parser;
// Flush to resource store
const resStore = parser.get({ sort: options.sort });
const { jsonIndent } = options.resource;
const lineEnding = String(options.resource.lineEnding).toLowerCase();
Object.keys(resStore).forEach(lng => {
const namespaces = resStore[lng];
Object.keys(namespaces).forEach(ns => {
let obj = namespaces[ns];
const resPath = parser.formatResourceSavePath(lng, ns);
// if not defaultLng then Get, Merge & removeUnusedKeys of old JSON content
if (lng !== options.defaultLng) {
let resContent = getFileJSON(resPath);
if (options.removeUnusedKeys) {
const namespaceKeys = flattenObjectKeys(obj);
const resContentKeys = flattenObjectKeys(resContent);
const unusedKeys = _.differenceWith(
resContentKeys,
namespaceKeys,
_.isEqual,
);
for (let i = 0; i < unusedKeys.length; ++i) {
_.unset(resContent, unusedKeys[i]);
}
resContent = omitEmptyObject(resContent);
}
obj = { ...obj, ...resContent };
}
let text = `${JSON.stringify(obj, null, jsonIndent)}\n`;
if (lineEnding === 'auto') {
text = eol.auto(text);
} else if (lineEnding === '\r\n' || lineEnding === 'crlf') {
text = eol.crlf(text);
} else if (lineEnding === '\n' || lineEnding === 'lf') {
text = eol.lf(text);
} else if (lineEnding === '\r' || lineEnding === 'cr') {
text = eol.cr(text);
} else {
// Defaults to LF
text = eol.lf(text);
}
this.push(
new VirtualFile({
path: resPath,
contents: Buffer.from(text),
}),
);
});
});
done();
}
module.exports = {
input: [
'src/**/*.{js,jsx}',
// Use ! to filter out files or directories
'!src/**/*.spec.{js,jsx}',
'!src/i18n/**',
'!**/node_modules/**',
],
output: './src',
options: {
debug: false,
removeUnusedKeys: true,
sort: true,
func: {
list: ['i18next.t', 'i18n.t', 't'],
extensions: ['.js', '.jsx'],
},
lngs: ['en', 'fr'],
defaultLng: 'en',
keySeparator: false,
resource: {
loadPath: 'i18n/locales/{{lng}}.json',
savePath: 'i18n/locales/{{lng}}.json',
},
},
flush,
};
@Justkant
Copy link
Author

Inspiration taken from i18next/i18next-scanner#140

@chomamateusz
Copy link

Great! Thanks!

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