Skip to content

Husky i18n tracking #240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// use this if you want to match all subfolders:
// '<%= config.src %>/templates/pages/**/*.hbs'

const pkg = require('./package.json');

module.exports = function(grunt) {

require('time-grunt')(grunt);
Expand Down Expand Up @@ -87,11 +89,7 @@ module.exports = function(grunt) {
'assemble-contrib-i18n'
],
i18n: {
languages: [
'en',
'es',
'zh-Hans'
],
languages: pkg.languages,
templates: [
"<%= config.src %>/templates/pages/**/*.hbs",
]
Expand Down Expand Up @@ -347,4 +345,4 @@ module.exports = function(grunt) {
'build'
]);

};
};
178 changes: 81 additions & 97 deletions i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,113 +5,97 @@
// source files (en.yml) should be committed before translating
// and removing entries in the i18n-tracking.yml file.

var Git = require('nodegit');
var fs = require('fs');
var yaml = require('js-yaml');
var _ = require('lodash');

var lang = ['es', 'zh-Hans'];
const fs = require('fs');
const yaml = require('js-yaml');
const _ = require('lodash');
const git = require('simple-git/promise');

const pkg = require('./package.json');

const enSrcFile = 'src/data/en.yml';

function parseDiff(diff) {
return new Promise((resolve, reject) => {
const changes = [];
let [, lineNum] = diff.match(/@@ -(\d+),.*@@/);
lineNum = parseInt(lineNum, 10) - 1;
let lines = diff.split('\n');
const startAt = lines.findIndex(line => line.startsWith('@@'));
lines = lines.slice(startAt);
lines.forEach((line, index) => {
if (line.startsWith('+')) {
changes.push([lineNum, line.replace(/^\+/, '')]);
}
lineNum++;
});
writeTracker(enSrcFile, changes, resolve, reject);
});
}

var task = function(done) {
Git.Repository.open(process.cwd())
.then(repo => {
return Git.Diff.indexToWorkdir(repo);
})
.then(diff => {
return diff.patches();
const repo = git();
repo
.status()
.then(data => {
if (data.modified.includes(enSrcFile)) {
return repo.diff(['-p', '--cached', enSrcFile]);
}
return Promise.reject(`${enSrcFile} file was not modified.`);
})
.then(patches => {
var enFileChanged = false;

patches.forEach(function(patch) {
// Each patch represent a file
if (patch.oldFile().path() === 'src/data/en.yml') {
enFileChanged = true;
patch
.hunks()
.then(hunks => {
var hunksPromises = [];
hunks.forEach(function(hunk) {
hunksPromises.push(hunk.lines());
});

return Promise.all(hunksPromises);
})
.then(hunks => {
var changes = [];

hunks.forEach(function(lines) {
lines.forEach(function(line) {
// If a line has changed, add it to i18n-tracking.json
var changedLineNumber = 0;
var changedLine = '';

if (String.fromCharCode(line.origin()) === '+') {
changedLineNumber = line.newLineno();
changedLine = line.content().trim();
changes.push([changedLineNumber, changedLine]);
}
});
});

writeTracker(patch.oldFile().path(), changes);
});
}
});

if (!enFileChanged) done();
.then(parseDiff)
.then(done)
.catch(e => {
done();
});
};

function writeTracker(path, changes) {
var dest = {};

// Read once, write once
fs.readFile('./i18n-tracking.yml', 'utf-8', (err, data) => {
if (err) done(err);

lang.forEach(langCode => {
dest[langCode] = {};
dest[langCode][path] = {};
var newObj = {};
newObj[path] = {};
var currentObj = yaml.safeLoad(data) ? yaml.safeLoad(data)[langCode] : {};

changes.forEach(change => {
var i = `line ${change[0]}`;
newObj[path][i] = change[1].split(':')[0];
});
function writeTracker(path, changes, resolve, reject) {
fs.readFile('./i18n-tracking.yml', 'utf-8', (err, data) => {
if (err) reject(err);

const dest = {};
const lang = pkg.languages.filter(v => v !== 'en');
lang.forEach(langCode => {
dest[langCode] = {};
dest[langCode][path] = {};
var newObj = {};
newObj[path] = {};
var currentObj = yaml.safeLoad(data) ? yaml.safeLoad(data)[langCode] : {};

changes.forEach(change => {
var i = `line ${change[0]}`;
newObj[path][i] = change[1].split(':')[0];
});

var intersect = _.intersection(
_.keys(currentObj[path]),
_.keys(newObj[path])
);
var diffAB = _.difference(_.keys(currentObj[path]), _.keys(newObj[path]));
var diffBA = _.difference(_.keys(newObj[path]), _.keys(currentObj[path]));
var intersect = _.intersection(
_.keys(currentObj[path]),
_.keys(newObj[path])
);
var diffAB = _.difference(_.keys(currentObj[path]), _.keys(newObj[path]));
var diffBA = _.difference(_.keys(newObj[path]), _.keys(currentObj[path]));

intersect.forEach(line => {
dest[langCode][path][line] = newObj[path][line];
});
diffAB.forEach(line => {
dest[langCode][path][line] = currentObj[path][line];
});
diffBA.forEach(line => {
dest[langCode][path][line] = newObj[path][line];
});
intersect.forEach(line => {
dest[langCode][path][line] = newObj[path][line];
});
var dump = yaml.safeDump(dest, {
styles: {
'!!null': 'canonical'
},
sortKeys: false
diffAB.forEach(line => {
dest[langCode][path][line] = currentObj[path][line];
});

fs.writeFile('./i18n-tracking.yml', dump, (err, res) => {
if (err) done(err);

done();
diffBA.forEach(line => {
dest[langCode][path][line] = newObj[path][line];
});
});
}
};
var dump = yaml.safeDump(dest, {
styles: {
'!!null': 'canonical'
},
sortKeys: false
});

fs.writeFile('./i18n-tracking.yml', dump, (err, res) => {
if (err) reject(err);
resolve();
});
});
}

module.exports = task;
Loading