Skip to content

Commit 6c3c4fc

Browse files
committed
Language generation and file structure
* Move language files to strings/ subdir to be consistent with react-sdk * Only copy static list of languages (to avoid including languages that are only a few percent translated) * Make copy-res script work with watch mode * Other general cleanups like only write each language file once, rather than n times.
1 parent e07f9a8 commit 6c3c4fc

File tree

12 files changed

+81
-79
lines changed

12 files changed

+81
-79
lines changed

scripts/copy-res.js

Lines changed: 81 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33
// copies the resources into the webapp directory.
44
//
55

6+
// Languages are listed manually so we can choose when to include
7+
// a translation in the app (because having a translation with only
8+
// 3 strings translated is just frustrating)
9+
// This could readily be automated, but it's nice to explicitly
10+
// control when we languages are available.
11+
const INCLUDE_LANGS = [
12+
//'be' Omitted because no translations in react-sdk
13+
'en_EN',
14+
'da',
15+
'de_DE',
16+
'fr',
17+
'be',
18+
'pt',
19+
'pt_BR',
20+
'ru',
21+
];
22+
623
// cpx includes globbed parts of the filename in the destination, but excludes
724
// common parents. Hence, "res/{a,b}/**": the output will be "dest/a/..." and
825
// "dest/b/...".
@@ -14,32 +31,20 @@ const COPY_LIST = [
1431
["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"],
1532
["node_modules/emojione/assets/png/*", "webapp/emojione/png/"],
1633
["./config.json", "webapp", { directwatch: 1 }],
17-
["src/i18n/", "webapp/i18n/", { languages: 1 }],
18-
["node_modules/matrix-react-sdk/src/i18n/strings/", "webapp/i18n/", { languages: 1 }],
1934
];
2035

36+
INCLUDE_LANGS.forEach(function(l) {
37+
COPY_LIST.push([
38+
l, "webapp/i18n/", { lang: 1 },
39+
]);
40+
});
41+
2142
const parseArgs = require('minimist');
2243
const Cpx = require('cpx');
2344
const chokidar = require('chokidar');
2445
const fs = require('fs');
2546
const rimraf = require('rimraf');
2647

27-
// cleanup language files before copying them.
28-
//rimraf("webapp/", function () { console.log('cleanup language files'); });
29-
30-
//From http://stackoverflow.com/a/20525865/4929236
31-
function generateFileArray(dir, files_) {
32-
files_ = files_ || [];
33-
var files = fs.readdirSync(dir);
34-
for (var i in files) {
35-
var name = files[i];
36-
if (name != 'basefile.json') {
37-
files_.push(name);
38-
}
39-
}
40-
return files_;
41-
}
42-
4348
const argv = parseArgs(
4449
process.argv.slice(2), {}
4550
);
@@ -54,6 +59,15 @@ function errCheck(err) {
5459
}
5560
}
5661

62+
// Check if webapp exists
63+
if (!fs.existsSync('webapp')) {
64+
fs.mkdirSync('webapp');
65+
}
66+
// Check if i18n exists
67+
if (!fs.existsSync('webapp/i18n/')) {
68+
fs.mkdirSync('webapp/i18n/');
69+
}
70+
5771
function next(i, err) {
5872
errCheck(err);
5973

@@ -67,32 +81,11 @@ function next(i, err) {
6781
const opts = ent[2] || {};
6882
let cpx = undefined;
6983

70-
if (opts.languages) {
71-
const sourceFiles = generateFileArray(source);
72-
let Sourcelanguages = {};
73-
if (!fs.existsSync(dest)) {
74-
fs.mkdirSync(dest);
75-
}
76-
sourceFiles.forEach(file => {
77-
const fileContents = fs.readFileSync(source + file).toString();
78-
Sourcelanguages[file] = JSON.parse(fileContents);
79-
});
80-
sourceFiles.forEach(file => {
81-
if (!fs.existsSync(dest + file)) {
82-
let o = Object.assign({}, Sourcelanguages[file]);
83-
fs.writeFileSync(dest + file, JSON.stringify(o, null, 4));
84-
} else {
85-
const fileContents = fs.readFileSync(dest + file).toString();
86-
let o = Object.assign(JSON.parse(fileContents), Sourcelanguages[file]);
87-
fs.writeFileSync(dest + file, JSON.stringify(o, null, 4));
88-
}
89-
});
90-
91-
} else {
84+
if (!opts.lang) {
9285
cpx = new Cpx.Cpx(source, dest);
9386
}
9487

95-
if (verbose) {
88+
if (verbose && cpx) {
9689
cpx.on("copy", (event) => {
9790
console.log(`Copied: ${event.srcPath} --> ${event.dstPath}`);
9891
});
@@ -115,59 +108,68 @@ function next(i, err) {
115108
.on('change', copy)
116109
.on('ready', cb)
117110
.on('error', errCheck);
118-
} else if (opts.languages) {
119-
if (verbose) {
120-
console.log('don\'t copy language file');
121-
}
111+
} else if (opts.lang) {
112+
const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + source + '.json';
113+
const riotWebFile = 'src/i18n/strings/' + source + '.json';
114+
115+
const translations = {};
116+
const makeLang = () => { genLangFile(source, dest) };
117+
[reactSdkFile, riotWebFile].forEach(function(f) {
118+
chokidar.watch(f)
119+
.on('add', makeLang)
120+
.on('change', makeLang)
121+
//.on('ready', cb) We'd have to do this when both files are ready
122+
.on('error', errCheck);
123+
});
122124
next(i + 1, err);
123125
} else {
124126
cpx.on('watch-ready', cb);
125127
cpx.on("watch-error", cb);
126128
cpx.watch();
127129
}
128-
} else if (opts.languages) {
129-
if (verbose) {
130-
console.log('don\'t copy language file');
131-
}
130+
} else if (opts.lang) {
131+
genLangFile(source, dest);
132132
next(i + 1, err);
133133
} else {
134134
cpx.copy(cb);
135135
}
136136
}
137137

138-
// Generate Language List
139-
140-
const testFolder = 'src/i18n/';
141-
let languages = {};
142-
// Check if webapp exists
143-
if (!fs.existsSync('webapp')) {
144-
fs.mkdirSync('webapp');
145-
}
146-
// Check if i18n exists
147-
if (!fs.existsSync('webapp/i18n/')) {
148-
fs.mkdirSync('webapp/i18n/');
149-
}
150-
151-
if (!fs.existsSync('webapp/i18n/languages.json')) {
152-
rimraf("webapp/i18n/languages.json", function() { console.log('cleanup languages.json file'); });
138+
function genLangFile(lang, dest) {
139+
const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + lang + '.json';
140+
const riotWebFile = 'src/i18n/strings/' + lang + '.json';
141+
142+
const translations = {};
143+
[reactSdkFile, riotWebFile].forEach(function(f) {
144+
if (fs.existsSync(f)) {
145+
Object.assign(
146+
translations,
147+
JSON.parse(fs.readFileSync(f).toString())
148+
);
149+
}
150+
});
151+
fs.writeFileSync(dest + lang + '.json', JSON.stringify(translations, null, 4));
152+
if (verbose) {
153+
console.log("Generated language file: " + lang);
154+
}
153155
}
154156

155-
fs.readdir(testFolder, function(err, files) {
156-
if (err) {
157-
throw err;
158-
}
159-
files.forEach(function(file) {
160-
var normalizedLanguage = file.toLowerCase().replace("_", "-").split('.json')[0];
161-
var languageParts = normalizedLanguage.split('-');
162-
if (file != 'basefile.json') {
163-
if (languageParts.length == 2 && languageParts[0] == languageParts[1]) {
164-
languages[languageParts[0]] = file;
165-
} else {
166-
languages[normalizedLanguage] = file;
167-
}
157+
function genLangList() {
158+
const languages = {};
159+
INCLUDE_LANGS.forEach(function(lang) {
160+
const normalizedLanguage = lang.toLowerCase().replace("_", "-");
161+
const languageParts = normalizedLanguage.split('-');
162+
if (languageParts.length == 2 && languageParts[0] == languageParts[1]) {
163+
languages[languageParts[0]] = lang;
164+
} else {
165+
languages[normalizedLanguage] = lang;
168166
}
169167
});
170168
fs.writeFile('webapp/i18n/languages.json', JSON.stringify(languages, null, 4));
171-
})
169+
if (verbose) {
170+
console.log("Generated language list");
171+
}
172+
}
172173

173-
next(0);
174+
genLangList();
175+
next(0);

0 commit comments

Comments
 (0)