Comparing version 1.6.0 to 2.0.0
177
i18njs.js
if (typeof exports === 'object' && typeof define !== 'function') { | ||
'use strict'; | ||
var define = function (factory) { | ||
@@ -6,4 +8,5 @@ factory(require, exports, module); | ||
} | ||
define(function (require, exports, module) { | ||
var lng = 'en'; | ||
'use strict'; | ||
/*-------------------------------------------*\ | ||
@@ -15,2 +18,4 @@ | TEMPLATE SYSTEM | ||
\*-------------------------------------------*/ | ||
var noMatch = /(.)^/; | ||
var escaperRegEx = /\\|'|\r|\n|\u2028|\u2029/g; | ||
var escapeMap = { | ||
@@ -24,2 +29,11 @@ '&': '&', | ||
}; | ||
var escapes = { | ||
"'": "'", | ||
'\\': '\\', | ||
'\r': 'r', | ||
'\n': 'n', | ||
'\u2028': 'u2028', | ||
'\u2029': 'u2029' | ||
}; | ||
var createEscaper = function(map) { | ||
@@ -29,24 +43,23 @@ var escaper = function(match) { | ||
}; | ||
var source = '(?:' + Object.keys(map).join('|') + ')'; | ||
var testRegexp = RegExp(source); | ||
var replaceRegexp = RegExp(source, 'g'); | ||
return function(string) { | ||
string = string == null ? '' : '' + string; | ||
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; | ||
return testRegexp.test(string) ? | ||
string.replace(replaceRegexp, escaper) : string; | ||
}; | ||
}; | ||
var noMatch = /(.)^/; | ||
var escapes = { | ||
"'": "'", | ||
'\\': '\\', | ||
'\r': 'r', | ||
'\n': 'n', | ||
'\u2028': 'u2028', | ||
'\u2029': 'u2029' | ||
}; | ||
var escaper = /\\|'|\r|\n|\u2028|\u2029/g; | ||
var escapeChar = function(match) { | ||
return '\\' + escapes[match]; | ||
}; | ||
var template = function (text, settings) { | ||
var index = 0; | ||
var source = "__p+='"; | ||
var matcher = RegExp([ | ||
@@ -57,16 +70,23 @@ (settings.escape || noMatch).source, | ||
].join('|') + '|$', 'g'); | ||
var index = 0; | ||
var source = "__p+='"; | ||
text.replace(matcher, function (match, escape, interpolate, evaluate, offset) { | ||
source += text.slice(index, offset).replace(escaper, escapeChar); | ||
index = offset + match.length; | ||
if (escape) { | ||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; | ||
} else if (interpolate) { | ||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; | ||
} else if (evaluate) { | ||
source += "';\n" + evaluate + "\n__p+='"; | ||
text.replace(matcher, | ||
function (match, escape, interpolate, evaluate, offset) { | ||
source += text.slice(index, offset) | ||
.replace(escaperRegEx, escapeChar); | ||
index = offset + match.length; | ||
if (escape) { | ||
source += "'+\n((__t=(" + | ||
escape + "))==null?'':_.escape(__t))+\n'"; | ||
} else if (interpolate) { | ||
source += "'+\n((__t=(" + | ||
interpolate + "))==null?'':__t)+\n'"; | ||
} else if (evaluate) { | ||
source += "';\n" + evaluate + "\n__p+='"; | ||
} | ||
return match; | ||
} | ||
return match; | ||
}); | ||
); | ||
source += "';\n"; | ||
@@ -77,2 +97,3 @@ source = 'with(obj||{}){\n' + source + '}\n'; | ||
source + 'return __p;\n'; | ||
try { | ||
@@ -82,4 +103,6 @@ var render = new Function('obj', '_', source); | ||
e.source = source; | ||
throw e; | ||
} | ||
var template = function (data) { | ||
@@ -90,32 +113,43 @@ return render.call(this, data, { | ||
}; | ||
template.source = 'function(obj){\n' + source + '}'; | ||
return template; | ||
} | ||
}; | ||
/*---- END TEMPLATE ----*/ | ||
var parse = function (key, obj) { | ||
var ar = key.split('.'); | ||
while (obj && ar.length) { | ||
obj = obj[ar.shift()]; | ||
} | ||
return obj; | ||
} | ||
}; | ||
var I18n = function () { | ||
this.lng = lng; | ||
this.dico = {}; | ||
this.evaluate = /\{\{([\s\S]+?)\}\}/g; | ||
this.interpolate = /\{\{=([\s\S]+?)\}\}/g; | ||
this.escape = /\{\{-([\s\S]+?)\}\}/g; | ||
// PRIVATES | ||
var localLang = 'en'; | ||
var dico = {}; | ||
var defaults = {}; | ||
var evaluate = /\{\{([\s\S]+?)\}\}/g; | ||
var interpolate = /\{\{=([\s\S]+?)\}\}/g; | ||
var escape = /\{\{-([\s\S]+?)\}\}/g; | ||
this.add = function (lang, ns, locales) { | ||
var i; | ||
this.dico[lang] = this.dico[lang] || {}; | ||
var obj; | ||
dico[lang] = dico[lang] || {}; | ||
if (locales === undefined) { | ||
locales = ns; | ||
ns = undefined; | ||
obj = this.dico[lang]; | ||
obj = dico[lang]; | ||
} else { | ||
this.dico[lang][ns] = this.dico[lang][ns] || {}; | ||
obj = this.dico[lang][ns]; | ||
dico[lang][ns] = dico[lang][ns] || {}; | ||
obj = dico[lang][ns]; | ||
} | ||
for (i in locales) { | ||
@@ -127,8 +161,10 @@ if (locales.hasOwnProperty(i)) { | ||
}; | ||
this.has = function (key, lang) { | ||
lang = lang || this.lng; | ||
lang = lang || localLang; | ||
var keyToParse = lang + '.' + key; | ||
// Check for the lang | ||
if (this.dico[key]) { | ||
if (dico[key]) { | ||
return true; | ||
@@ -138,13 +174,35 @@ } | ||
// Check for the key and lang | ||
return parse(keyToParse, this.dico) ? true : false; | ||
return parse(keyToParse, dico) ? true : false; | ||
}; | ||
this.langs = function () { | ||
this.listLangs = function () { | ||
var langs = []; | ||
for (var i in this.dico) { | ||
for (var i in dico) { | ||
langs.push(i); | ||
} | ||
return langs; | ||
}; | ||
this.getCurrentLang = function () { | ||
return localLang; | ||
}; | ||
this.getDico = function () { | ||
return dico; | ||
}; | ||
this.setLang = function (lang) { | ||
localLang = lang; | ||
return localLang; | ||
}; | ||
this.setDefaults = function (options) { | ||
defaults = options || {}; | ||
}; | ||
this.get = function (key, data, options, lang) { | ||
var lng = lang || this.lng; | ||
var lng = lang || localLang; | ||
if (lang === undefined) { | ||
@@ -158,11 +216,31 @@ if (typeof data === 'string') { | ||
} | ||
var obj = parse(lng + '.' + key, this.dico); | ||
var obj = parse(lng + '.' + key, dico); | ||
options = options || {}; | ||
if (typeof obj === 'string') { | ||
var i; | ||
var settings = { | ||
evaluate: options.evaluate || this.evaluate, | ||
interpolate: options.interpolate || this.interpolate, | ||
escape: options.escape || this.escape | ||
evaluate: options.evaluate || evaluate, | ||
interpolate: options.interpolate || interpolate, | ||
escape: options.escape || escape | ||
}; | ||
obj = template(obj, settings)(data); | ||
var newDatas = {}; | ||
var defs = defaults[localLang] || defaults; | ||
for (i in defs) { | ||
if (defs.hasOwnProperty(i)) { | ||
newDatas[i] = defs[i]; | ||
} | ||
} | ||
for (i in data) { | ||
if (data.hasOwnProperty(i)) { | ||
newDatas[i] = data[i]; | ||
} | ||
} | ||
obj = template(obj, settings)(newDatas); | ||
return obj; | ||
@@ -172,7 +250,10 @@ } else if (typeof obj === 'object') { | ||
} | ||
return key; | ||
}; | ||
}; | ||
module.exports = new I18n(); | ||
return module.exports; | ||
}); | ||
}); |
{ | ||
"name": "i18njs", | ||
"version": "1.6.0", | ||
"version": "2.0.0", | ||
"description": "A simple i18n for Javascript with a templating feature.", | ||
"main": "i18njs.js", | ||
"scripts": { | ||
"test": "./node_modules/.bin/jasmine" | ||
"posttest": "npm run-script lint", | ||
"preversion": "npm test", | ||
"postversion": "npm run-script changelog", | ||
"test": "jasmine", | ||
"lint": "jscs i18njs.js", | ||
"changelog": "conventional-changelog -i CHANGELOG.md -w -b" | ||
}, | ||
@@ -25,4 +30,6 @@ "repository": { | ||
"devDependencies": { | ||
"jasmine": "^2.2.1" | ||
"conventional-changelog": "0.1.0-alpha.1", | ||
"jasmine": "^2.2.1", | ||
"jscs": "^1.13.1" | ||
} | ||
} |
@@ -7,2 +7,3 @@ # i18njs | ||
[![bower version](https://img.shields.io/bower/v/i18njs.svg?style=flat)](http://bower.io/search/?q=i18njs) | ||
[![travis](https://travis-ci.org/yoannmoinet/i18njs.svg)](https://travis-ci.org/yoannmoinet/i18njs) | ||
@@ -69,5 +70,21 @@ ## Installation | ||
i18n.lng = 'fr'; | ||
i18n.setLang('fr'); | ||
``` | ||
### Get current language | ||
```javascript | ||
i18n.getCurrentLang(); | ||
``` | ||
### Get dictionary | ||
```javascript | ||
i18n.getDico(); | ||
``` | ||
### Check for availability | ||
@@ -95,3 +112,3 @@ | ||
i18n.langs(); | ||
i18n.listLangs(); | ||
// ['en', 'fr'] | ||
@@ -138,4 +155,6 @@ | ||
You can also change delimeters by passing the third `options` arguments | ||
### Change delimiters | ||
You can also change delimiters by passing the third `options` arguments | ||
```javascript | ||
@@ -153,1 +172,32 @@ | ||
### Add default values for templates | ||
If you need to have a special key always replaced by the same value (brand for example), | ||
you can set it as default. | ||
```javascript | ||
var defaults = { | ||
fr: { | ||
key: 'default fr' | ||
}, | ||
en: { | ||
key: 'default en' | ||
} | ||
}; | ||
i18n.setDefaults(defaults); | ||
i18n.get('ns.inter') | ||
//default en | ||
``` | ||
If not needed, you don't have to use localized defaults : | ||
```javascript | ||
var defaults = { | ||
key: 'My Brand' | ||
}; | ||
i18n.setDefaults(defaults); | ||
i18n.get('ns.inter') | ||
//My Brand | ||
``` |
@@ -31,17 +31,17 @@ describe('i18njs', function () { | ||
it('should add locales to the dictionary', function () { | ||
expect(i18n.dico.en.ns.hello).toEqual('Hello'); | ||
expect(i18n.dico.en.ns.world).toEqual('World'); | ||
expect(i18n.dico.en.ns.inter).toEqual('{{=key}}'); | ||
expect(i18n.dico.en.ns.eval).toEqual('{{for(var i = 0, max = 3; i < 3; i += 1) {}}eval {{}}}'); | ||
expect(i18n.dico.en.ns.escape).toEqual('{{-escape}}'); | ||
expect(i18n.getDico().en.ns.hello).toEqual('Hello'); | ||
expect(i18n.getDico().en.ns.world).toEqual('World'); | ||
expect(i18n.getDico().en.ns.inter).toEqual('{{=key}}'); | ||
expect(i18n.getDico().en.ns.eval).toEqual('{{for(var i = 0, max = 3; i < 3; i += 1) {}}eval {{}}}'); | ||
expect(i18n.getDico().en.ns.escape).toEqual('{{-escape}}'); | ||
expect(i18n.dico.fr.ns.hello).toEqual('Bonjour'); | ||
expect(i18n.dico.fr.ns.world).toEqual('Monde'); | ||
expect(i18n.dico.fr.ns.inter).toEqual('{{=key}}'); | ||
expect(i18n.dico.fr.ns.eval).toEqual('{{for(var i = 0, max = 3; i < 3; i += 1) {}}eval {{}}}'); | ||
expect(i18n.dico.fr.ns.escape).toEqual('{{-escape}}'); | ||
expect(i18n.getDico().fr.ns.hello).toEqual('Bonjour'); | ||
expect(i18n.getDico().fr.ns.world).toEqual('Monde'); | ||
expect(i18n.getDico().fr.ns.inter).toEqual('{{=key}}'); | ||
expect(i18n.getDico().fr.ns.eval).toEqual('{{for(var i = 0, max = 3; i < 3; i += 1) {}}eval {{}}}'); | ||
expect(i18n.getDico().fr.ns.escape).toEqual('{{-escape}}'); | ||
}); | ||
it('should be in english by default', function () { | ||
expect(i18n.lng).toEqual('en'); | ||
expect(i18n.getCurrentLang()).toEqual('en'); | ||
expect(i18n.get('ns.hello')).toEqual('Hello'); | ||
@@ -52,3 +52,3 @@ expect(i18n.get('ns.world')).toEqual('World'); | ||
it('should be able to switch language', function () { | ||
i18n.lng = 'fr'; | ||
i18n.setLang('fr'); | ||
expect(i18n.get('ns.hello')).toEqual('Bonjour'); | ||
@@ -71,3 +71,3 @@ expect(i18n.get('ns.world')).toEqual('Monde'); | ||
it('should list all available languages', function () { | ||
var langs = i18n.langs(); | ||
var langs = i18n.listLangs(); | ||
expect(langs).toContain('en'); | ||
@@ -104,2 +104,28 @@ expect(langs).toContain('fr'); | ||
}); | ||
}); | ||
it('should have defaults', function () { | ||
i18n.setDefaults({ | ||
key: 'default' | ||
}); | ||
expect(i18n.get('ns.inter')).toEqual('default'); | ||
}); | ||
it('should have localized defaults', function () { | ||
i18n.setDefaults({ | ||
fr: { | ||
key: 'default_fr' | ||
}, | ||
en: { | ||
key: 'default_en' | ||
} | ||
}); | ||
i18n.setLang('en'); | ||
expect(i18n.get('ns.inter')).toEqual('default_en'); | ||
i18n.setLang('fr'); | ||
expect(i18n.get('ns.inter')).toEqual('default_fr'); | ||
}); | ||
it('should overwrite defaults', function () { | ||
expect(i18n.get('ns.inter', {key: 'overwrite'})).toEqual('overwrite'); | ||
}); | ||
}); |
@@ -0,0 +0,0 @@ { |
29495
12
348
199
3