Skip to content

Commit

Permalink
Merge pull request #38 from enb-bem/issue-33
Browse files Browse the repository at this point in the history
Implement merge for i18n-js tech
  • Loading branch information
blond committed Jun 8, 2015
2 parents b07e409 + b613a01 commit 9e29a7d
Show file tree
Hide file tree
Showing 12 changed files with 610 additions and 277 deletions.
3 changes: 3 additions & 0 deletions .bowerrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"directory": "test/fixtures"
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
coverage
test/fixtures
npm-debug.log
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ npm install --save-dev enb-bem-i18n
Технологии
----------

* [i18n-keysets-xml](#i18n-keysets-xml)
* [i18n-lang-js](#i18n-lang-js)
* [i18n-js](#i18n-js)
* [keysets](#keysets)
* [i18n-keysets-xml](#i18n-keysets-xml)
* [i18n-bemjson-to-html](#i18n-bemjson-to-html)

### i18n-lang-js
### i18n-js

Собирает `?.lang.<язык>.js`-файлы на основе `?.keysets.<язык>.js`-файлов.

Expand All @@ -43,8 +43,8 @@ npm install --save-dev enb-bem-i18n

```javascript
nodeConfig.addTechs([
[ require('enb-bem-i18n/techs/i18n-lang-js'), { lang: 'all'} ],
[ require('enb-bem-i18n/techs/i18n-lang-js'), { lang: '{lang}'} ]
[ require('enb-bem-i18n/techs/i18n-js'), { lang: 'all'} ],
[ require('enb-bem-i18n/techs/i18n-js'), { lang: '{lang}'} ]
]);
```

Expand Down
15 changes: 15 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "enb-bem-i18n",
"description": "Enb bem i18n package",
"version": "0.0.1",
"private": true,
"dependencies": {
"bem-core": "2.6.0",
"bem-core-v3": "git://github.com/bem/bem-core.git#issues/576@v3"
},
"ignore": [
"coverage",
"node_modules",
"test"
]
}
67 changes: 67 additions & 0 deletions lib/compile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
var EOL = require('os').EOL,
format = require('util').format,
serialize = require('serialize-javascript'),
tanker = require('../exlib/tanker');

/**
* Compile code of i18n.
*
* @param {Object} parsed info from keysets file,
* @param {String} language - language of keysets,
* example: `{ scope: { key: 'val' } }`. The value can be a function,
* example: `{ scope: { key: function (params, i18n) { return 'res'; } } }`.
*
* @returns {String}
*/
module.exports = function (parsed, language) {
return parsed.version === 2 ?
'((' + parsed.core + ')()).decl(' + serialize(parsed.keysets) + ')' :
compileForVersion1(parsed.core, parsed.keysets, language);
};

/**
* Compile i18n function for bem-bl localization system
* @param {String} core - bem-core i18n core code string
* @param {Object} keysets - keysets hash
* @param {String} language - language of keysets
* @returns {String}
*/
function compileForVersion1(core, keysets, language) {
return [
'(function () {',
' var __bem__ = {};',
' (function (BEM) {',
core,
' }(__bem__));',
' var i18n = __bem__.I18N;',
Object.keys(keysets).sort().reduce(function (prev, keysetName, index) {
index === 0 && prev.push(EOL);
prev.push(_getKeysetBuildResult(keysetName, keysets[keysetName], language));
return prev;
}, []).join(EOL),
format('\ti18n.lang(\'%s\');', language),
' return i18n;',
'}())'
].join(EOL);
}

/**
* Return decl function call code string for given keyset scope
* @param {String} scopeName - name of scope
* @param {Object} scope hash object
* @param {String} lang - language option value
* @returns {string|*}
* @private
*/
function _getKeysetBuildResult(scopeName, scope, lang) {
var res = Object.keys(scope).reduce(function (prev, key, i, arr) {
tanker.xmlToJs(scope[key], function (js) {
var endSymbol = i === arr.length - 1 ? '' : ',';
prev.push(format('\t %s: %s%s', JSON.stringify(key), js, endSymbol));
});
return prev;
}, []);
res.unshift(format('\ti18n.decl(\'%s\', {', scopeName));
res.push(format('\t}, {%s\t "lang": "%s"%s\t});', EOL, lang, EOL));
return res.join(EOL);
}
51 changes: 51 additions & 0 deletions lib/keysets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Parse object with keysets.
*
* It separates the core of i18n from other keysets. The core will be searched in the `i18n` scope with `i18n` key.
*
* @param {(Object.<String, String>|Object.<String, String, Function>)} keysets Object with keysets,
* example: `{ scope: { key: 'val' } }`. The value can be a function,
* example: `{ scope: { key: function (params, i18n) { return 'res'; } } }`.
*
* @throws Will throw an error if the core is not found.
*
* @returns {{ core: Function|String, keysets: (Object.<String, String>|Object.<String, String, Function>) }}
*/
function parse(keysets) {
var core,
data = {},
version = 2;

// Pull core from source keysets
keysets && Object.keys(keysets).forEach(function (scope) {
// Search core in `i18n:i18n`
if (scope === 'i18n') {
var keyset = keysets[scope];

if (keyset && typeof keyset.i18n === 'function') {
core = keyset.i18n;
}
// Search deprecated core in `all` scope
} else if (scope === 'all') {
var possibleCore = keysets[scope][''];
if (possibleCore && (typeof possibleCore === 'string') && possibleCore.match(/BEM\.I18N/g)) {
version = 1;
core = possibleCore;
}
} else {
data[scope] = keysets[scope];
}
});

if (!core) {
throw new Error('Core of i18n is not found!');
}

return {
core: core,
keysets: data,
version: version
};
}

exports.parse = parse;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"serialize-javascript": "1.0.0"
},
"devDependencies": {
"bower": "1.3.9",
"enb": ">= 0.11.0 < 1.0.0",
"istanbul": "0.3.14",
"jscs": "1.13.1",
Expand All @@ -48,9 +49,10 @@
"must": "0.12.0"
},
"scripts": {
"deps": "bower i",
"test": "npm run lint && npm run unit",
"lint": "jshint . && jscs -c .jscs.js .",
"unit": "mocha -R spec",
"unit": "npm run deps && mocha -R spec",
"cover": "istanbul cover _mocha",
"coveralls": "npm i coveralls && npm run cover -- --report lcovonly && cat ./coverage/lcov.info | coveralls"
}
Expand Down
82 changes: 82 additions & 0 deletions techs/i18n-js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* i18n-js
* ============
*
* Собирает `?.lang.<язык>.js`-файлы на основе `?.keysets.<язык>.js`-файлов.
*
* Используется для локализации в JS с помощью BEM.I18N.
*
* **Опции**
*
* * *String* **target** — Результирующий таргет. По умолчанию — `?.lang.{lang}.js`.
* * *String* **lang** — Язык, для которого небходимо собрать файл.
*
* **Пример**
*
* ```javascript
* nodeConfig.addTechs([
* [ require('enb-bem-i18n/techs/i18n-js'), { lang: 'all'} ],
* [ require('enb-bem-i18n/techs/i18n-js'), { lang: '{lang}'} ],
* ]);
* ```
*/
var EOL = require('os').EOL,
path = require('path'),
asyncRequire = require('enb/lib/fs/async-require'),
dropRequireCache = require('enb/lib/fs/drop-require-cache'),
keysets = require('../lib/keysets'),
compile = require('../lib/compile');

module.exports = require('enb/lib/build-flow').create()
.name('i18n')
.target('target', '?.lang.{lang}.js')
.defineRequiredOption('lang')
.useSourceFilename('keysetsFile', '?.keysets.{lang}.js')
.builder(function (keysetsFilename) {
var cache = this.node.getNodeCache(this._target),
cacheKey = 'keysets-file-' + path.basename(keysetsFilename),
promise;

if (cache.needRebuildFile(cacheKey, keysetsFilename)) {
dropRequireCache(require, keysetsFilename);
promise = asyncRequire(keysetsFilename)
.then(function (keysets) {
cache.cacheFileInfo(cacheKey, keysetsFilename);

return keysets;
});
} else {
promise = asyncRequire(keysetsFilename);
}

return promise
.then(function (sources) {
var parsed = keysets.parse(sources);
return [
'(function () {',
' var __i18n__ = ' + compile(parsed, this._lang) + ',',
' defineAsGlobal = true;',
'',
' // CommonJS',
' if (typeof exports === "object") {',
' module.exports = __i18n__;',
' defineAsGlobal = false;',
' }',
'',
' // YModules',
' if (typeof modules === "object") {',
' modules.define("i18n", function (provide) {',
' provide(__i18n__);',
' });',
' defineAsGlobal = false;',
' }',
'',
' if (defineAsGlobal) {',
' global.BEM || (global.BEM = {});',
' global.BEM.I18N = __i18n__;',
' }',
'})();'
].join(EOL);
}, this);
})
.createTech();
86 changes: 0 additions & 86 deletions techs/i18n-lang-js.js

This file was deleted.

Loading

0 comments on commit 9e29a7d

Please sign in to comment.