mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-30 10:58:23 -05:00
4165132a3e
thanks @rschamp!
168 lines
5.8 KiB
JavaScript
Executable file
168 lines
5.8 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
/*
|
|
Converts the existing .po translation files in the module to JSON files.
|
|
Requires po2json in order to work. Takes as input a directory
|
|
in which to store the resulting json translation files.
|
|
|
|
Takes in as an argument an output directory to put translation files.
|
|
Searches for files named `l10n.json` in the `src/views/` directory to get
|
|
template english strings (as well as the general template at `src/l10n.json`).
|
|
|
|
It compiles the template strings into a flat object that is compared against the
|
|
translations in the .po files from the `scratchr2_translations` dependency, using
|
|
an md5 of the template string without whitespace, and an md5 of the .po msgid string
|
|
without whitespace.
|
|
|
|
The output files are javascript files that declare objects by locale. Each locale
|
|
has a sub-object with FormattedMessage ids as keys, and translated strings as
|
|
values. If no translation was found for a string, the default english will be the
|
|
value.
|
|
|
|
Output Example:
|
|
'''
|
|
var message = {
|
|
en: {
|
|
'general.inAWorld': 'In a world, where bears are invisible...',
|
|
'general.question': 'Are there bears here?',
|
|
'general.answer': 'I dunno, but there could be...'
|
|
},
|
|
es: {
|
|
'general.inAWorld': 'En un mundo, donde hay osos invisibles',
|
|
'general.question': 'Are there bears here?',
|
|
'general.answer': 'No sé, pero es posible...'
|
|
}
|
|
}
|
|
'''
|
|
*/
|
|
var fs = require('fs');
|
|
var merge = require('lodash.merge');
|
|
var path = require('path');
|
|
|
|
var languages = require('../languages.json');
|
|
var localeCompare = require('./lib/locale-compare');
|
|
var localizedUrls = require('./lib/localized-urls');
|
|
var routes = require('../src/routes.json');
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Main script
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
var args = process.argv.slice(2);
|
|
|
|
if (!args.length) {
|
|
process.stdout.write('A destination directory must be specified.');
|
|
process.exit(1);
|
|
}
|
|
|
|
var outputDir = path.resolve(__dirname, '../', args[0]);
|
|
try {
|
|
fs.accessSync(outputDir, fs.F_OK);
|
|
} catch (err) {
|
|
// Doesn't exist - create it.
|
|
fs.mkdirSync(outputDir);
|
|
}
|
|
|
|
// get global locale strings first.
|
|
var globalTemplateFile = path.resolve(__dirname, '../src/l10n.json');
|
|
var ids = require(globalTemplateFile);
|
|
// var ids = JSON.parse(fs.readFileSync(globalTemplateFile, 'utf8'));
|
|
|
|
// message key with english string values (i.e. default values)
|
|
var viewLocales = {
|
|
general: {
|
|
en: ids
|
|
}
|
|
};
|
|
var idsWithICU = localeCompare.idToICUMap('general', ids);
|
|
var icuWithIds = localeCompare.icuToIdMap('general', ids);
|
|
|
|
var views = [];
|
|
var localizedAssetUrls = {};
|
|
|
|
// start with all views, and remove localized ones as they are iterated over
|
|
for (var v in routes) {
|
|
if (typeof routes[v].redirect !== 'undefined') {
|
|
continue;
|
|
}
|
|
|
|
views.push(routes[v].name);
|
|
try {
|
|
var subdir = routes[v].view.split('/');
|
|
subdir.pop();
|
|
var l10n = path.resolve(__dirname, '../src/views/' + subdir.join('/') + '/l10n.json');
|
|
ids = require(l10n);
|
|
viewLocales[routes[v].name] = {
|
|
en: ids
|
|
};
|
|
idsWithICU = merge(idsWithICU, localeCompare.idToICUMap(routes[v].name, ids));
|
|
icuWithIds = merge(icuWithIds, localeCompare.icuToIdMap(routes[v].name, ids));
|
|
} catch (err) {
|
|
if (err.code !== 'MODULE_NOT_FOUND') {
|
|
throw err;
|
|
}
|
|
|
|
try {
|
|
fs.accessSync(path.resolve(__dirname, '../src/views/' + routes[v].view + '.jsx'));
|
|
} catch (err) {
|
|
// the config for the view is not set up correctly, so throw the error.
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// get asset url translations
|
|
try {
|
|
subdir = routes[v].view.split('/');
|
|
subdir.pop();
|
|
var l10nStatic = path.resolve(__dirname, '../src/views/' + subdir.join('/') + '/l10n-static.json');
|
|
localizedAssetUrls[routes[v].name] = {};
|
|
|
|
var assetUrls = require(l10nStatic);
|
|
for (var lang in localizedUrls) {
|
|
localizedAssetUrls[routes[v].name][lang] = {};
|
|
for (var key in assetUrls) {
|
|
if (localizedUrls[lang].hasOwnProperty(key)) {
|
|
localizedAssetUrls[routes[v].name][lang][key] = localizedUrls[lang][key];
|
|
} else {
|
|
localizedAssetUrls[routes[v].name][lang][key] = assetUrls[key];
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
if (err.code !== 'MODULE_NOT_FOUND') {
|
|
throw err;
|
|
}
|
|
|
|
try {
|
|
fs.accessSync(path.resolve(__dirname, '../src/views/' + routes[v].view + '.jsx'));
|
|
} catch (err) {
|
|
// the config for the view is not set up correctly, so throw the error.
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
// md5 of english strings with message key as the value for searching po files.
|
|
// Sample structure: { 'sdfas43534sdfasdf': 'general-general.blah', 'lkjfasdf4t342asdfa': 'about-about.blah' }
|
|
var md5WithIds = localeCompare.getMD5Map(icuWithIds);
|
|
|
|
// Get ui localization strings first
|
|
var isoCodes = Object.keys(languages);
|
|
for (var isoCode in isoCodes) {
|
|
var translations = localeCompare.getTranslationsForLanguage(isoCodes[isoCode], idsWithICU, md5WithIds);
|
|
for (var messageId in translations) {
|
|
viewLocales[messageId] = merge(viewLocales[messageId], translations[messageId]);
|
|
}
|
|
}
|
|
|
|
for (var view in views) {
|
|
var viewTranslations = viewLocales['general'];
|
|
if (views[view] in viewLocales) {
|
|
viewTranslations = merge(viewLocales[views[view]], viewTranslations);
|
|
}
|
|
if (views[view] in localizedAssetUrls) {
|
|
viewTranslations = merge(viewTranslations, localizedAssetUrls[[views[view]]]);
|
|
}
|
|
localeCompare.writeTranslationsToJS(outputDir, views[view], viewTranslations);
|
|
}
|