work-in-progress commit for #4655

v1.18.x
Julian Lam 9 years ago
parent 81bbe93640
commit 437770538c

@ -3,8 +3,48 @@
var fs = require('fs'), var fs = require('fs'),
path = require('path'), path = require('path'),
async = require('async'), async = require('async'),
LRU = require('lru-cache'),
_ = require('underscore');
Languages = {}; var plugins = require('./plugins');
var Languages = {};
Languages.init = function(next) {
if (Languages.hasOwnProperty('_cache')) {
Languages._cache.reset();
} else {
Languages._cache = LRU(100);
}
next();
};
Languages.get = function(code, key, callback) {
var combined = [code, key].join('/');
if (Languages._cache.has(combined)) {
return callback(null, Languages._cache.get(combined));
}
var languageData;
fs.readFile(path.join(__dirname, '../public/language/', code, key), { encoding: 'utf-8' }, function(err, data) {
// If language file in core cannot be read, then no language file present
try {
languageData = JSON.parse(data) || {};
} catch (e) {
languageData = {};
}
if (plugins.customLanguages.hasOwnProperty(combined)) {
_.extendOwn(languageData, plugins.customLanguages[combined]);
}
Languages._cache.set(combined, languageData);
callback(null, languageData);
});
};
Languages.list = function(callback) { Languages.list = function(callback) {
var languagesPath = path.join(__dirname, '../public/language'), var languagesPath = path.join(__dirname, '../public/language'),

@ -8,6 +8,7 @@ var async = require('async'),
user = require('./user'), user = require('./user'),
groups = require('./groups'), groups = require('./groups'),
languages = require('./languages'),
emitter = require('./emitter'), emitter = require('./emitter'),
pubsub = require('./pubsub'), pubsub = require('./pubsub'),
auth = require('./routes/authentication'), auth = require('./routes/authentication'),
@ -65,6 +66,7 @@ var async = require('async'),
async.apply(Meta.js.minify, 'nodebb.min.js'), async.apply(Meta.js.minify, 'nodebb.min.js'),
async.apply(Meta.js.minify, 'acp.min.js'), async.apply(Meta.js.minify, 'acp.min.js'),
async.apply(Meta.sounds.init), async.apply(Meta.sounds.init),
async.apply(languages.init),
async.apply(Meta.templates.compile), async.apply(Meta.templates.compile),
async.apply(auth.reloadRoutes), async.apply(auth.reloadRoutes),
function(next) { function(next) {

@ -16,6 +16,7 @@ var app,
toobusy = require('toobusy-js'), toobusy = require('toobusy-js'),
plugins = require('../plugins'), plugins = require('../plugins'),
languages = require('../languages'),
meta = require('../meta'), meta = require('../meta'),
user = require('../user'), user = require('../user'),
groups = require('../groups'), groups = require('../groups'),
@ -314,6 +315,19 @@ middleware.applyBlacklist = function(req, res, next) {
}; };
middleware.processLanguages = function(req, res, next) { middleware.processLanguages = function(req, res, next) {
var code = req.params.code;
var key = req.path.match(/[\w]+\.json/);
if (code && key) {
languages.get(code, key[0], function(err, language) {
res.status(200).json(language);
})
} else {
res.status(404).json('{}');
}
};
middleware.processTimeagoLocales = function(req, res, next) {
var fallback = req.path.indexOf('-short') === -1 ? 'jquery.timeago.en.js' : 'jquery.timeago.en-short.js', var fallback = req.path.indexOf('-short') === -1 ? 'jquery.timeago.en.js' : 'jquery.timeago.en-short.js',
localPath = path.join(__dirname, '../../public/vendor/jquery/timeago/locales', req.path), localPath = path.join(__dirname, '../../public/vendor/jquery/timeago/locales', req.path),
exists; exists;

@ -31,7 +31,7 @@ var middleware;
Plugins.lessFiles = []; Plugins.lessFiles = [];
Plugins.clientScripts = []; Plugins.clientScripts = [];
Plugins.acpScripts = []; Plugins.acpScripts = [];
Plugins.customLanguages = []; Plugins.customLanguages = {};
Plugins.customLanguageFallbacks = {}; Plugins.customLanguageFallbacks = {};
Plugins.libraryPaths = []; Plugins.libraryPaths = [];
Plugins.versionWarning = []; Plugins.versionWarning = [];
@ -85,10 +85,10 @@ var middleware;
Plugins.acpScripts.length = 0; Plugins.acpScripts.length = 0;
Plugins.libraryPaths.length = 0; Plugins.libraryPaths.length = 0;
Plugins.registerHook('core', { // Plugins.registerHook('core', {
hook: 'static:app.load', // hook: 'static:app.load',
method: addLanguages // method: addLanguages
}); // });
async.waterfall([ async.waterfall([
function(next) { function(next) {
@ -415,27 +415,28 @@ var middleware;
], next); ], next);
}; };
function addLanguages(params, callback) { // function addLanguages(params, callback) {
Plugins.customLanguages.forEach(function(lang) { // Plugins.customLanguages.forEach(function(lang) {
params.router.get('/language' + lang.route, function(req, res, next) { // console.log('route for', '/language/' + lang.route);
res.json(lang.file); // params.router.get('/language' + lang.route, function(req, res, next) {
}); // res.json(lang.file);
// });
var components = lang.route.split('/'),
language = components[1], // var components = lang.route.split('/'),
filename = components[2].replace('.json', ''); // language = components[1],
// filename = components[2].replace('.json', '');
translator.addTranslation(language, filename, lang.file);
}); // translator.addTranslation(language, filename, lang.file);
// });
for(var resource in Plugins.customLanguageFallbacks) {
params.router.get('/language/:lang/' + resource + '.json', function(req, res, next) { // for(var resource in Plugins.customLanguageFallbacks) {
winston.verbose('[translator] No resource file found for ' + req.params.lang + '/' + path.basename(req.path, '.json') + ', using provided fallback language file'); // params.router.get('/language/:lang/' + resource + '.json', function(req, res, next) {
res.sendFile(Plugins.customLanguageFallbacks[path.basename(req.path, '.json')]); // winston.verbose('[translator] No resource file found for ' + req.params.lang + '/' + path.basename(req.path, '.json') + ', using provided fallback language file');
}); // res.sendFile(Plugins.customLanguageFallbacks[path.basename(req.path, '.json')]);
} // });
// }
callback(null);
} // callback(null);
// }
}(exports)); }(exports));

@ -219,26 +219,23 @@ module.exports = function(Plugins) {
fallbackMap = {}; fallbackMap = {};
utils.walk(pathToFolder, function(err, languages) { utils.walk(pathToFolder, function(err, languages) {
var arr = [];
async.each(languages, function(pathToLang, next) { async.each(languages, function(pathToLang, next) {
fs.readFile(pathToLang, function(err, file) { fs.readFile(pathToLang, function(err, file) {
if (err) { if (err) {
return next(err); return next(err);
} }
var json; var data;
var route = pathToLang.replace(pathToFolder + '/', '');
try { try {
json = JSON.parse(file.toString()); data = JSON.parse(file.toString());
} catch (err) { } catch (err) {
winston.error('[plugins] Unable to parse custom language file: ' + pathToLang + '\r\n' + err.stack); winston.error('[plugins] Unable to parse custom language file: ' + pathToLang + '\r\n' + err.stack);
return next(err); return next(err);
} }
arr.push({ Plugins.customLanguages[route] = Plugins.customLanguages[route] || {};
file: json, _.extendOwn(Plugins.customLanguages[route], data);
route: pathToLang.replace(pathToFolder, '')
});
if (pluginData.defaultLang && pathToLang.endsWith(pluginData.defaultLang + '/' + path.basename(pathToLang))) { if (pluginData.defaultLang && pathToLang.endsWith(pluginData.defaultLang + '/' + path.basename(pathToLang))) {
fallbackMap[path.basename(pathToLang, '.json')] = path.join(pathToFolder, pluginData.defaultLang, path.basename(pathToLang)); fallbackMap[path.basename(pathToLang, '.json')] = path.join(pathToFolder, pluginData.defaultLang, path.basename(pathToLang));
@ -251,7 +248,7 @@ module.exports = function(Plugins) {
return callback(err); return callback(err);
} }
Plugins.customLanguages = Plugins.customLanguages.concat(arr); // do I need this either?
_.extendOwn(Plugins.customLanguageFallbacks, fallbackMap); _.extendOwn(Plugins.customLanguageFallbacks, fallbackMap);
callback(); callback();

@ -144,10 +144,11 @@ module.exports = function(app, middleware, hotswapIds) {
} }
app.use(middleware.privateUploads); app.use(middleware.privateUploads);
app.use('/language/:code', middleware.processLanguages);
app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), {
maxAge: app.enabled('cache') ? 5184000000 : 0 maxAge: app.enabled('cache') ? 5184000000 : 0
})); }));
app.use('/vendor/jquery/timeago/locales', middleware.processLanguages); app.use('/vendor/jquery/timeago/locales', middleware.processTimeagoLocales);
app.use(controllers.handle404); app.use(controllers.handle404);
app.use(controllers.handleErrors); app.use(controllers.handleErrors);

@ -12,6 +12,7 @@ var path = require('path'),
emailer = require('./emailer'), emailer = require('./emailer'),
meta = require('./meta'), meta = require('./meta'),
languages = require('./languages'),
logger = require('./logger'), logger = require('./logger'),
plugins = require('./plugins'), plugins = require('./plugins'),
middleware = require('./middleware'), middleware = require('./middleware'),
@ -92,6 +93,7 @@ function initializeNodeBB(callback) {
async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, 'acp.min.js'), async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, 'acp.min.js'),
async.apply(meta.css.minify), async.apply(meta.css.minify),
async.apply(meta.sounds.init), async.apply(meta.sounds.init),
async.apply(languages.init),
async.apply(meta.blacklist.load) async.apply(meta.blacklist.load)
], next); ], next);
}, },

Loading…
Cancel
Save