From 2b860986e8218f8178c8531fe6b268d3bc2b5d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Mon, 17 Dec 2012 18:18:07 +0100 Subject: [PATCH] support for json in i18n --- src/node/hooks/i18n.js | 125 +++++++++++++++++++++++++++++++++++------ 1 file changed, 107 insertions(+), 18 deletions(-) diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index a45d46fee..c892c7450 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -2,35 +2,124 @@ var languages = require('languages4translatewiki') , fs = require('fs') , path = require('path') , express = require('express') + , _ = require('underscore'); -var localesPath = __dirname+"/../../locales"; +/* +* PRIVATE +*/ -// Serve English strings directly with /locales.ini -var localeIndex = fs.readFileSync(localesPath+'/en.ini')+'\r\n'; +// locales will store all locales ini files merged (core+plugins) in RAM +var locales = {}; -exports.availableLangs = {'en': {'nativeName': 'English', 'direction': 'ltr'}}; +//explore recursive subdirectories from root and execute callback +//don't explore symbolic links +var exploreDir = function (root, callback) { + var stat = fs.lstatSync(root); + if (stat.isDirectory() && !stat.isSymbolicLink()) { + var names = fs.readdirSync(root), + subdirs = [], + files = []; + names.forEach (function(file) { + file = path.resolve(root,file); + stat = fs.lstatSync(file); + if (stat.isDirectory() && !stat.isSymbolicLink()) { + subdirs.push(file); + } else { + files.push(file); + } + }); + callback(root, subdirs, files); + subdirs.forEach(function (d) { + exploreDir(d, callback); + }); + } +}; -fs.readdir(localesPath, function(er, files) { - files.forEach(function(locale) { - var ext = path.extname(locale); - locale = path.basename(locale, ext).toLowerCase(); - if(locale == 'en' || ext != '.ini') return; +// return all files languages absolute path group by langcode +// {es: [pathcore, pathplugin1...], en:...} +var getAllLocalesPaths = function () { + var result = {}; - // build locale index - localeIndex += '['+locale+']\r\n@import url(locales/'+locale+'.ini)\r\n' - - // add info language {nativeName, direction} to availableLangs - exports.availableLangs[locale]=languages.getLanguageInfo(locale); - }) -}) + //extract only files paths with name is a supported language code and have json extension + var extractLangs = function (root, subdirs, files) { + _.each(files, function(file) { + var ext = path.extname(file), + locale = path.basename(file, ext).toLowerCase(); + if ((ext == '.json') && languages.isValid(locale)) { + if (!(_.has(result, locale))) result[locale] = []; + result[locale].push(file); + } + }); + } + //add core supported languages first + var root = path.resolve(__dirname+"/../../locales"); + exploreDir (root, extractLangs); + //add plugins languages (if any) + root = path.resolve(__dirname+"/../../../node_modules"); + exploreDir (root, extractLangs); + + return result; +} + +//save in locales all json files merged by language code +var getAllLocales = function () { + _.each (getAllLocalesPaths(), function(files, langcode) { + locales[langcode]={} + _.each (files, function(file) { + _.extend(locales[langcode], JSON.parse(fs.readFileSync(file,'utf8'))[langcode]); + }); + }); +} + +//return all languages availables with nativeName and direction +//{es: {nativeName: "espaƱol", direction: "ltr"},...} +var getAvailableLangs = function () { + var result = {}; + if (_.isEmpty(locales)) getAllLocales(); + _.each(_.keys(locales), function(langcode) { + result[langcode]=languages.getLanguageInfo(langcode); + }); + return result; +} + +//return locale index that will be served in /locales.json +var generateLocaleIndex = function () { + if (_.isEmpty(locales)) getAllLocales(); + var result = _.clone(locales); + _.each(_.keys(locales), function(langcode) { + if (langcode != 'en') result[langcode]='/locales/'+langcode+'.json'; + }); + return JSON.stringify(result); +} + + +/* +* PUBLIC +*/ exports.expressCreateServer = function(n, args) { - args.app.use('/locales', express.static(localesPath)); + //regenerate locales when server restart + locales = {}; + var localeIndex = generateLocaleIndex(); + exports.availableLangs = getAvailableLangs(); + + args.app.get ('/locales/:locale', function(req, res) { + //works with /locale/en and /locale/en.json requests + var locale = req.params.locale.split('.')[0]; + if (exports.availableLangs.hasOwnProperty(locale)) { + res.setHeader('Content-Type', 'application/json; charset=utf8'); + res.send('{"'+locale+'":'+JSON.stringify(locales[locale])+'}'); + } else { + res.send(404, 'Language not available'); + } + }) - args.app.get('/locales.ini', function(req, res) { + args.app.get('/locales.json', function(req, res) { + res.setHeader('Content-Type', 'application/json; charset=utf8'); res.send(localeIndex); }) } +