Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

i18n-core

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

i18n-core - npm Package Compare versions

Comparing version 2.1.1 to 3.0.0

.codeclimate.yml

74

index.js

@@ -1,69 +0,9 @@

"use strict";
'use strict'
function defaultFallback(key) {
if (!key) {
return "(?)";
}
return key;
module.exports = function (data) {
try {
return require('./full')(data)
} catch (e) {
return require('./simple')(data)
}
}
function getLookup(data) {
if (data && typeof data.get === "function") {
// Direct lookup implementation pass-through
return data;
} else if (typeof data === "string") {
return require("./lookup/fs")(data);
}
return require("./lookup/object")(data || {});
}
function _defaultTranslation(that, value, fallbackKey, namedValues, args) {
if (value === null || value === undefined) {
value = that.fallback(fallbackKey);
}
if (namedValues && (/{{.*}}/).test(value)) {
value = that.mustache.render(value, namedValues);
}
if (args !== null && args !== undefined && args.length > 0 && /%/.test(value)) {
return that.vsprintf(value, args);
}
return value;
}
function defaultTranslation(key, namedValues, args) {
return _defaultTranslation(this, this.raw(key), key, namedValues, args);
}
function defaultTranslationFirst(keys, fallbackKey, namedValues, args) {
var value = null,
keyNo = 0;
while ((value === undefined || value === null) && keyNo < keys.length) {
var key = keys[keyNo];
value = this.raw(key);
keyNo += 1;
}
return _defaultTranslation(this, value, fallbackKey, namedValues, args);
}
function has(key) {
var val = this.raw(key);
return val !== undefined && val !== null;
}
function raw(key) {
return this.lookup.get(key);
}
module.exports = function (data, allowModification) {
var translator = require("./lib/createTranslator")("", null, allowModification),
lookup = getLookup(data);
translator.lookup = lookup;
translator.fallback = defaultFallback;
translator.has = has;
translator.raw = raw;
translator.mustache = require("mustache");
translator.vsprintf = require("sprintf").vsprintf;
translator.translate = defaultTranslation.bind(translator);
translator.translateFirst = defaultTranslationFirst.bind(translator)
return translator;
}

@@ -1,17 +0,17 @@

"use strict";
'use strict'
function makeFlat(object, target, prefix) {
if (!prefix) {
prefix = "";
}
Object.keys(object).forEach(function (key) {
var val = object[key];
if (typeof val === "object" && val !== null) {
makeFlat(val, target, prefix + key + ".");
}
target[prefix + key] = val;
});
return target;
function makeFlat (object, target, prefix) {
if (!prefix) {
prefix = ''
}
Object.keys(object).forEach(function (key) {
var val = object[key]
if (typeof val === 'object' && val !== null) {
makeFlat(val, target, prefix + key + '.')
}
target[prefix + key] = val
})
return target
}
module.exports = makeFlat;
module.exports = makeFlat

@@ -1,32 +0,44 @@

"use strict";
'use strict'
module.exports = function i18nChain() {
var first = null,
current;
for (var i = 0; i<arguments.length; i++) {
var handler = arguments[i];
module.exports = function i18nChain () {
var first = null
var current
for (var i = 0; i < arguments.length; i++) {
var handler = arguments[i]
if (handler) {
if (!handler.get && typeof handler === 'function') {
handler = {
get: handler
}
}
var next = {
handler: handler
};
}
if (!first) {
first = next;
first = next
} else {
current.next = next;
current.next = next
}
current = next;
current = next
}
}
return {
get: function (key) {
var current = first;
while (current) {
var value = current.handler.get(key);
if (value !== null && value !== undefined) {
return value;
}
current = current.next;
if (!first) {
return {
get: function () { return undefined }
}
}
if (!first.next) {
return first.handler
}
first.get = function (key) {
var current = first
while (current) {
var value = current.handler.get(key)
if (value !== null && value !== undefined) {
return value
}
current = current.next
}
};
};
}
return first
}

@@ -1,16 +0,3 @@

"use strict";
'use strict'
module.exports = function i18nExtend(i18n, lookup) {
if (lookup) {
return {
get: function (key) {
return i18n.has(key) ? i18n.__(key) : lookup.get(key);
}
};
}
return {
get: function (key) {
return i18n.has(key) ? i18n.__(key) : null;
}
};
};
module.exports = require('./chain.js')
module.exports = {
getFile: function (partPath) {
return partPath + ".json";
},
load: JSON.parse
};
getFile: function (partPath) {
return partPath + '.json'
},
load: JSON.parse
}

@@ -1,58 +0,57 @@

"use strict";
'use strict'
var path = require("path"),
makeFlat = require("../lib/makeFlat");
var path = require('path')
var makeFlat = require('../lib/makeFlat')
module.exports = function (folder, strategy) {
// need to load here, because it needs a mock for testing.
var fs = require("fs"),
getRaw = function getRaw(file) {
try {
return fs.readFileSync(file, "utf8");
} catch (e) {}
return null;
},
exists = function exists(file) {
var exists = false;
try {
exists = fs.existsSync(file);
} catch(e) {}
return exists;
};
if (!strategy) {
strategy = require("./folder/json.js");
}
// need to load here, because it needs a mock for testing.
var fs = require('fs')
var getRaw = function getRaw (file) {
try {
return fs.readFileSync(file, 'utf8')
} catch (e) {}
return null
}
var exists = function exists (file) {
var exists = false
try {
exists = fs.existsSync(file)
} catch (e) {}
return exists
}
if (!strategy) {
strategy = require('./folder/json.js')
}
return Object.create({
cache: {},
folder: folder,
strategy: strategy,
get: function get(key) {
var keyParts = /^([^\.]*)(\.(.*))?$/m.exec(key),
prefix = keyParts[1],
property = keyParts[3] || "",
file = this.strategy.getFile(path.resolve(this.folder, prefix)),
keyStorage = this.cache[file],
raw;
return Object.create({
cache: {},
folder: folder,
strategy: strategy,
get: function (key) {
var keyParts = /^([^.]*)(\.(.*))?$/m.exec(key)
var prefix = keyParts[1]
var property = keyParts[3] || ''
var file = this.strategy.getFile(path.resolve(this.folder, prefix))
var keyStorage = this.cache[file]
var raw
if (!keyStorage) {
keyStorage = {
data: {},
file: file
};
if (exists(file)) {
raw = getRaw(file);
if (raw) {
try {
keyStorage.data = makeFlat(this.strategy.load(raw) || {}, {});
} catch(e) {}
}
}
keyStorage.time = Date.now();
this.cache[file] = keyStorage;
}
return keyStorage.data[property];
}
});
};
if (!keyStorage) {
keyStorage = {
data: {},
file: file
}
if (exists(file)) {
raw = getRaw(file)
if (raw) {
try {
keyStorage.data = makeFlat(this.strategy.load(raw) || {}, {})
} catch (e) {}
}
}
keyStorage.time = Date.now()
this.cache[file] = keyStorage
}
return keyStorage.data[property]
}
})
}

@@ -1,13 +0,13 @@

"use strict";
'use strict'
var makeFlat = require("../lib/makeFlat");
var makeFlat = require('../lib/makeFlat')
module.exports = function (object) {
var flat = makeFlat(object, {});
var flat = makeFlat(object, {})
return {
get: function lookup(key) {
return flat[key];
}
};
};
return {
get: function lookup (key) {
return flat[key]
}
}
}
{
"name": "i18n-core",
"version": "2.1.1",
"version": "3.0.0",
"description": "Basic i18n translation.",
"main": "index.js",
"config": {
"tests": "test/**/*.js test/*.js"
},
"scripts": {
"test": "lab -c"
"test": "if-env CODECLIMATE_REPO_TOKEN && npm run cov:code-climate || npm run test:simple",
"test:simple": "if-env CI=true && npm run test:unit || npm run test:dev",
"test:dev": "npm run lint && npm run cov:dev",
"test:unit": "tap -- $npm_package_config_tests",
"cov": "if-env CODECLIMATE_REPO_TOKEN && npm run cov:code-climate || npm run cov:dev",
"cov:code-climate": "tap --coverage --coverage-report=text-lcov -- $npm_package_config_tests | codeclimate-test-reporter",
"cov:dev": "tap --coverage --coverage-report=html -- $npm_package_config_tests",
"lint": "eslint .",
"release": "standard-version"
},

@@ -16,6 +27,2 @@ "author": {

"license": "ISC",
"dependencies": {
"mustache": "^0.8.2",
"sprintf": "^0.1.4"
},
"repository": {

@@ -26,6 +33,12 @@ "type": "git",

"devDependencies": {
"code": "^1.2.1",
"lab": "^5.1.0",
"mockery": "^1.4.0"
"csv-stringify": "^1.0.4",
"eslint": "^3.13.1",
"eslint-config-standard": "^6.2.1",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"if-env": "^1.0.0",
"mockery": "^2.0.0",
"standard-version": "^4.0.0",
"tap": "^9.0.3"
}
}
# i18n-core
[![Join the chat at https://gitter.im/martinheidegger/i18n-core](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/martinheidegger/i18n-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[![Build Status](https://travis-ci.org/martinheidegger/i18n-core.svg)](https://travis-ci.org/martinheidegger/i18n-core)
[![Code Climate](https://codeclimate.com/github/martinheidegger/i18n-core/badges/gpa.svg)](https://codeclimate.com/github/martinheidegger/i18n-core)
[![Test Coverage](https://codeclimate.com/github/martinheidegger/i18n-core/badges/coverage.svg)](https://codeclimate.com/github/martinheidegger/i18n-core/coverage)
[i18n-core](https://github.io/martinheidegger/i18n-core) is a no-fuzz Node.js implementation of i18n. It doesn't connect to express or any other fancy Node framework and is extensible where it needs to be and allows to reduce the complexity of other i18n implementations (thus the name).
[i18n-core](https://github.io/martinheidegger/i18n-core) is a no-fuzz Node.js
implementation of i18n. It doesn't connect to express or any other fancy Node
framework and is extensible where it needs to be and allows to reduce the
complexity of other i18n implementations (thus the name).
It implements basic variable replacements in the mustache and sprintf manner.
# Installation
## Installation

@@ -17,6 +21,6 @@ To use *i18n-core* all you need to do is install it using ```npm```

```bash
$ npm i i18n-core --save
npm i i18n-core --save
```
# Usage
## Usage

@@ -29,3 +33,4 @@ ```JavaScript

To have different namespaces for different languages you can get a prefixed subpart using `.lang()`.
To have different namespaces for different languages you can get a prefixed
translations using `.section()`.

@@ -39,13 +44,16 @@ ```JavaScript

var en = i18n.lang("en")
var en = i18n.section("en")
en.__("greeting") // hello!
var de = i18n.lang("de")
var de = i18n.section("de")
de.__("greeting") // guten tag!
```
*Note: `.lang(<lang>)` is the same thing as `.sub(<lang> + ".")`*
_Note:_ `.section(<section>)` is the same thing as `.prefix(<section> + ".")`
## Lookups
The system is based on `lookup` implementations that allow the system to use different sources to get its strings from. The examples before used an object and because of this the former example would be equal to:
The system is based on `lookup` implementations that allow the system to use
different sources to get its strings from. The examples before used an object
and because of this the former example would be equal to:

@@ -68,3 +76,4 @@ ```JavaScript

You can pass in your own strategy by given an object to the constructor that contains a "get"-method:
You can pass in your own strategy by given an object to the constructor that
contains a "get"-method:

@@ -90,3 +99,4 @@ ```JavaScript

In case you have an `i18n` object that you want to use as lookup for another `i18` object you can **extend** them:
In case you have an `i18n` object that you want to use as lookup for another
`i18` object you can **extend** them:

@@ -113,5 +123,6 @@ ```JavaScript

following the logic of [sprintf](https://github.com/maritz/node-sprintf).
following the logic of [`sprintf`](https://github.com/maritz/node-sprintf).
It also offers [mustache](https://github.com/janl/mustache.js) pattern replacement like this:
It also offers [`mustache`](https://github.com/janl/mustache.js)-like pattern
replacement like this:

@@ -122,3 +133,24 @@ ```JavaScript

### Substitution variants
By default `i18n-core` does not have any dependencies and the default
substitution is `mustache`-like and `sprintf`-like with limited compatibility.
_Without `mustache` and `sprintf` installed, it will use
`require('i18n-core/simple')`_
In order to get full compatibility you can simply install the peer dependency.
_With `mustache` and `sprintf` installed, it will use
`require('i18n-core/full')`_
It is furthermore possible to customize the formatting by specifying own
implementations:
```javascript
var i18n_core = require('i18n-core')
i18n_core.mustache = require('mustache')
i18n_core.vsprintf = require('sprintf').vsprintf
```
## Advanced Namespaces

@@ -129,3 +161,3 @@

```JavaScript
var at = i18n_core({de:{at: {hello: "Zewas!"}}}).lang("de").lang("at");
var at = i18n_core({de:{at: {hello: "Zewas!"}}}).section("de").section("at");
at.__("hello") // Zewas!

@@ -140,11 +172,13 @@ ```

en: {title: "My Website"}
}).lang("de", true) // <- this true is important :)
}).section("de", true) // <- this true is important :)
translate.__("title") // Meine Website
translate.changeLang("en")
translate.changeSection("en")
translate.__("title") // My Website
```
To prevent malicious use the changing of the language is prevented unless you pass a `true` flag to it.
To prevent malicious use the changing of the section is prevented unless you
pass a `true` flag to it.
In some instances it is necessary to know in advance if a key has a value or not, in this case you can use `has`.
In some instances it is necessary to know in advance if a key has a value or
not, in this case you can use `has`.

@@ -157,3 +191,4 @@ ```JavaScript

Additionally, for module development, its possible to access the raw data using `raw`:
Additionally, for module development, its possible to access the raw data
using `raw`:

@@ -165,4 +200,100 @@ ```JavaScript

## Absolute Lookups
`i18n-core` supports the use of absolute roots. Absolute roots allow to lookup
entries in absolute locked roots rather than the given level.
```javascript
var translate = i18n_core({
title: "Meine Webseite",
sectionA: {
title: "Lebenslauf"
}
})
var sub = translate.section('sectionA')
sub('title') // Lebenslauf
sub.abs('title') // Meine Webseite
```
This allows to crate things like footers where you can pass one section to a
module and it is still able to access absolute code.
However, this also creates the problem that subsections _(for languages)_ can be
escaped from. In order to prevent that, you can lock the absolute root to
`.lock()`. You can lock any section and any subsequent sections will get the
same root.
```javascript
var translate = i18n_core({
de: {
title: "Meine Webseite",
sectionA: { title: "Lebenslauf" }
},
en: {
title: "My Website",
sectionA: { title: "Curriculum Vitae" }
}
})
var lang = translate
.section('de', true)
.lock() // This locks the absolute root to the language level
var sub = lang.section('sectionA')
sub('title') // Lebenslauf
sub.abs('title') // Meine Webseite
lang.changeSection('en')
sub('title') // Curriculum Vitae
sub.abs('title') // My Website
```
## Core API's
The default API is made to provide a simple solutions to common problems but
`i18n-core` also offers a reduced, faster API without conveniences. You can get
access to the core by using `require('i18n-core/core')`.
```javascript
var core = require('i18n-core/core')({
get: function lookupValue (key) {
return // Return a value for the key or undefined
}
}, function translate (value, fallbackKey, namedArgs, args) {
// value ......... value that should be translated
// fallbackKey ... fallbackKey that should be passed on to `fallback`
// namedArgs ..... named arguments passed in through the API, can be undefined
// args .......... regular arguments passed in through the API, can be undefined
})
core.get(key) // looks up a key
core.has(key) // .get(key) !== undefined
// translate the key with named & regular args
core.translate(key, namedArgs, args)
// translate the first found entry with a fallback
// keys .......... Array of keys to test
// fallbackKey ... Key to be passed on to `fallback`
// namedArgs ..... `namedArgs` to be used when translating
// args .......... `args` to be used when translating
core.translateFirst(keys, fallbackKey, namedArgs, args)
// Creates a api node where each key is prefixed
// prefix .............. prefix to be set for each translation request
// allowModification ... allows changePrefix API
core.prefix(prefix, allowModification)
// Changes the prefix of the API (undefined when modification forbidden)
core.changePrefix(prefix)
core.lock(locked) // Locks, unlocks the absolute root.
core.absRoot // Holds the root fallback
// Fields used for internal processing
core.parent // Parent node (or undefined)
core.translator // Quick lookup of the translation method
core.currentPrefix // Prefix of the current node '' == null
```
## Outro
If you have any questions, please post them as issue, thanks!

@@ -1,152 +0,188 @@

"use strict";
var code = require('code'),
lab = exports.lab = require('lab').script(),
test = lab.test,
i18n = require("../"),
path = require("path"),
fsFolder = path.join(__dirname, "lookup", "fs"),
expect = code.expect;
'use strict'
var test = require('tap').test
var i18n = require('../')
var path = require('path')
var fsFolder = path.join(__dirname, 'lookup', 'fs')
test("basic object lookup", function (done) {
var translator = i18n({a: "b"})
expect(translator.__("a")).to.equal("b");
expect(translator.__("c")).to.equal("c");
done();
});
test('basic object lookup', function (t) {
var translator = i18n({a: 'b'})
t.equals(translator.__('a'), 'b')
t.equals(translator.__('c'), 'c')
t.end()
})
test("basic existance object lookup", function (done) {
var translator = i18n({a: "b", c: null, d: {e: "f", g: null}}),
d = translator.lang('d');
expect(translator.has("a")).to.equal(true);
expect(translator.has("b")).to.equal(false);
expect(translator.has("c")).to.equal(false);
expect(translator.has("d")).to.equal(true);
expect(d.has("e")).to.equal(true);
expect(d.has("g")).to.equal(false);
expect(d.has("h")).to.equal(false);
done();
});
test('basic existance object lookup', function (t) {
var translator = i18n({a: 'b', c: null, d: {e: 'f', g: null}})
var d = translator.section('d')
t.equals(translator.has('a'), true)
t.equals(translator.has('b'), false)
t.equals(translator.has('c'), false)
t.equals(translator.has('d'), true)
t.equals(d.has('e'), true)
t.equals(d.has('g'), false)
t.equals(d.has('h'), false)
t.end()
})
test("raw passthrough lookup", function (done) {
var translator = i18n({a: "b", c: null, d: {e: "f", g: null}}),
d = translator.lang('d');
expect(translator.raw("a")).to.equal("b");
expect(translator.raw("b")).to.equal(undefined);
expect(translator.raw("c")).to.equal(null);
expect(translator.raw("d")).to.deep.equal({
e: "f",
g: null
});
expect(d.raw("e")).to.equal("f");
expect(d.raw("g")).to.equal(null);
expect(d.raw("h")).to.equal(undefined);
done();
});
test('get passthrough lookup', function (t) {
var translator = i18n({a: 'b', c: null, d: {e: 'f', g: null}})
var d = translator.section('d')
t.equals(translator.get('a'), 'b')
t.equals(translator.get('b'), undefined)
t.equals(translator.get('c'), null)
t.deepEquals(translator.get('d'), {
e: 'f',
g: null
})
t.equals(d.get('e'), 'f')
t.equals(d.get('g'), null)
t.equals(d.get('h'), undefined)
t.end()
})
test("custom lookup", function (done) {
expect(i18n(require("../lookup/object")({"en": {c:"d"}})).lang("en").__("c")).to.equal("d");
done();
});
test('custom lookup', function (t) {
t.equals(i18n(require('../lookup/object')({'en': {c: 'd'}})).section('en').__('c'), 'd')
t.end()
})
test("basic file lookup is used when string is given", function (done) {
expect(i18n(fsFolder).lang("en").__("b")).to.equal("c");
done();
});
test('custom function lookup', function (t) {
t.equals(i18n(function (key) {
t.equals(key, 'en.c')
return 'd'
}).section('en').__('c'), 'd')
t.end()
})
test('basic file lookup is used when string is given', function (t) {
t.equals(i18n(fsFolder).section('en').__('b'), 'c')
t.end()
})
test("same translator", function (done) {
var set = i18n();
expect(set.lang("en")).to.equal(set.lang("en"));
done();
});
test('same translator', function (t) {
var set = i18n()
t.equals(set.section('en'), set.section('en'))
t.end()
})
test("null namespace with key", function (done) {
try {
var translator = i18n(fsFolder).sub(null);
} catch(e) {
return done();
}
throw new Error("Should not be allowed.");
});
test('null namespace with key', function (t) {
try {
i18n(fsFolder).prefix(null)
} catch (e) {
return t.end()
}
throw new Error('Should not be allowed.')
})
test("undefined namespace with key", function (done) {
try {
var translator = i18n(fsFolder).sub(undefined);
} catch(e) {
return done();
}
throw new Error("Should not be allowed.");
});
test('undefined namespace with key', function (t) {
try {
i18n(fsFolder).prefix(undefined)
} catch (e) {
return t.end()
}
throw new Error('Should not be allowed.')
})
test('changing of the section should be possible after the fact if allowed', function (t) {
var translator = i18n(fsFolder).section('en', true)
var __ = translator.__
test("changing of the language should be possible after the fact if allowed", function (done) {
var translator = i18n(fsFolder).lang("en", true),
__ = translator.__;
t.equals(__('d'), 'e')
translator.changeSection('gr')
t.equals(__('d'), 'g')
t.end()
})
expect(__("d")).to.equal("e");
translator.changeLang("gr");
expect(__("d")).to.equal("g");
done();
});
test('changing of the prefix should be possible after the fact if allowed', function (t) {
var translator = i18n(fsFolder).section('en', true)
var __ = translator.__
test("changing of the prefix should be possible after the fact if allowed", function (done) {
var translator = i18n(fsFolder).lang("en", true),
__ = translator.__;
t.equals(__('d'), 'e')
translator.changePrefix('gr.')
t.equals(__('d'), 'g')
t.end()
})
expect(__("d")).to.equal("e");
translator.changePrefix("gr.");
expect(__("d")).to.equal("g");
done();
});
test('changing of the section should not be possible after the fact', function (t) {
var translator = i18n(fsFolder).section('en')
var __ = translator.__
test("changing of the language should not be possible after the fact", function (done) {
var translator = i18n(fsFolder).lang("en"),
__ = translator.__;
t.equals(__('d'), 'e')
t.equals(translator.changeSection, undefined)
try {
translator.changeSection('gr')
} catch (e) {
t.equals(__('d'), 'e')
t.end()
return
}
throw new Error('Translation should be blocked.')
})
expect(__("d")).to.equal("e");
try {
translator.changeLang("gr");
} catch(e) {
expect(__("d")).to.equal("e");
done();
return;
}
throw new Error("Translation should be blocked.")
});
test('changing of the prefix should affect the subprefix', function (t) {
var translator = i18n(fsFolder).prefix('g', true)
var translator2 = translator.section('n')
var __ = translator2.__
test("changing of the prefix should affect the subprefix", function (done) {
var translator = i18n(fsFolder).sub("g", true),
translator2 = translator.lang("n"),
__ = translator2.__;
translator.changePrefix('e')
translator.changePrefix("e");
t.equals(__('d'), 'e')
t.end()
})
expect(__("d")).to.equal("e");
done();
});
test('undefined fallback', function (t) {
var translator = i18n({a: null, b: undefined})
t.equals(translator.__(null), '(?)')
t.equals(translator.__(undefined), '(?)')
t.equals(translator.__('a'), 'a')
t.equals(translator.__('b'), 'b')
t.end()
})
test("undefined fallback", function (done) {
var translator = i18n({a: null, b: undefined});
expect(translator.__(null)).to.equal("(?)");
expect(translator.__(undefined)).to.equal("(?)");
expect(translator.__("a")).to.equal("a");
expect(translator.__("b")).to.equal("b");
done();
});
test('sprintf should be ignored when the given array has a length = 0', function (t) {
t.equals(i18n().translate('a %2', {}, []), 'a %2')
t.end()
})
test("sprintf should be ignored when the given array has a length = 0", function (done) {
expect(i18n().translate("a %2", {}, [])).to.equal("a %2");
done();
});
test('An undefined prefix should work just fine', function (t) {
t.equals(i18n({en: 'a'}).prefix('en').__(undefined), 'a')
t.equals(i18n({en: 'a'}).prefix('en').__(null), 'a')
t.end()
})
test("An undefined sub should work just fine", function (done) {
expect(i18n({en: "a"}).sub("en").__(undefined)).to.equal("a");
expect(i18n({en: "a"}).sub("en").__(null)).to.equal("a");
done();
});
test('A repeated prefix should work after a changePrefix', function (t) {
var i = i18n({
en: {x: '1'},
de: {x: '2'}
})
var enA = i.prefix('en.')
var enB = i.prefix('en.', true)
var enC = i.prefix('en.')
enB.changePrefix('de.')
t.equals(enA.__('x'), '1')
t.equals(enB.__('x'), '2')
t.equals(enC.__('x'), '1')
t.end()
})
test("multiple keys with one being an empty string", function (done) {
var translate = i18n({"a": "", "b": "ho"}).translate;
expect(translate("a")).to.equal("");
done();
});
test('A repeated sub should work after a changePrefix on the first', function (t) {
var i = i18n({
en: {x: '1'},
de: {x: '2'},
ja: {x: '3'}
})
var enA = i.prefix('en.', true)
var enB = i.prefix('en.')
var enC = i.prefix('en.', true)
enA.changePrefix('de.')
enC.changePrefix('ja.')
t.equals(enA.__('x'), '2')
t.equals(enB.__('x'), '1')
t.equals(enC.__('x'), '3')
t.end()
})
test('multiple keys with one being an empty string', function (t) {
var translate = i18n({'a': '', 'b': 'ho'}).translate
t.equals(translate('a'), '')
t.end()
})

@@ -1,34 +0,31 @@

"use strict";
var code = require('code'),
lab = exports.lab = require('lab').script(),
test = lab.test,
i18n = require("../"),
expect = code.expect;
'use strict'
var test = require('tap').test
var i18n = require('../')
test("fallback", function (done) {
var translator = i18n(),
__ = translator.__;
expect(__("a")).to.equal("a");
expect(__("")).to.equal("(?)");
done();
});
test('fallback', function (t) {
var translator = i18n()
var __ = translator.__
t.equals(__('a'), 'a')
t.equals(__(''), '(?)')
t.end()
})
test("custom root fallback", function (done) {
var translator = i18n();
translator.fallback = function () {
return "x";
};
translator = translator.lang("en");
expect(translator.__("a")).to.equal("x");
expect(translator.__("")).to.equal("x");
done();
});
test('custom root fallback', function (t) {
var translator = i18n()
translator.fallback = function () {
return 'x'
}
translator = translator.section('en')
t.equals(translator.__('a'), 'x')
t.equals(translator.__(''), 'x')
t.end()
})
test("custom child fallback should not work!", function (done) {
var translator = i18n().lang("en");
translator.fallback = function () {
return "x";
};
expect(translator.__("a")).to.equal("en.a");
done();
});
test('custom child fallback should not work!', function (t) {
var translator = i18n().section('en')
translator.fallback = function () {
return 'x'
}
t.equals(translator.__('a'), 'en.a')
t.end()
})

@@ -1,38 +0,45 @@

"use strict";
var code = require('code'),
lab = exports.lab = require('lab').script(),
test = lab.test,
chain = require("../../lookup/chain"),
expect = code.expect;
'use strict'
var test = require('tap').test
var chain = require('../../lookup/chain')
test("empty chain", function (done) {
expect(chain().get("a")).to.be.equals(undefined);
expect(chain().get("b")).to.be.equals(undefined);
done();
});
test('empty chain', function (t) {
t.equals(chain().get('a'), undefined)
t.equals(chain().get('b'), undefined)
t.end()
})
test("chain with one element", function (done) {
expect(chain({get: function() { return "a"; }}).get("b")).to.be.equals("a");
done();
});
test('chain with one element', function (t) {
t.equals(chain({get: function () { return 'a' }}).get('b'), 'a')
t.end()
})
test("chain with two elements", function (done) {
var chained = chain(
{get: function(x) { return x === "a" ? "b" : null; }},
{get: function(x) { return "c" }}
);
expect(chained.get("a")).to.be.equals("b");
expect(chained.get("b")).to.be.equals("c");
done();
});
test('chain with two elements', function (t) {
var chained = chain(
{get: function (x) { return x === 'a' ? 'b' : null }},
{get: function (x) { return 'c' }}
)
t.equals(chained.get('a'), 'b')
t.equals(chained.get('b'), 'c')
t.end()
})
test("chain with null element", function (done) {
var chained = chain(
{get: function(x) { return x === "a" ? "b" : null; }},
null,
{get: function(x) { return "c" }}
);
expect(chained.get("a")).to.be.equals("b");
expect(chained.get("b")).to.be.equals("c");
done();
});
test('chain with two functions', function (t) {
var chained = chain(
function (x) { return x === 'a' ? 'b' : null },
function (x) { return 'c' }
)
t.equals(chained.get('a'), 'b')
t.equals(chained.get('b'), 'c')
t.end()
})
test('chain with null element', function (t) {
var chained = chain(
{get: function (x) { return x === 'a' ? 'b' : null }},
null,
{get: function (x) { return 'c' }}
)
t.equals(chained.get('a'), 'b')
t.equals(chained.get('b'), 'c')
t.end()
})

@@ -1,27 +0,24 @@

"use strict";
var code = require('code'),
lab = exports.lab = require('lab').script(),
test = lab.test,
extend = require("../../lookup/extend"),
i18n = require("../../"),
expect = code.expect;
'use strict'
var test = require('tap').test
var extend = require('../../lookup/extend')
var i18n = require('../../')
test("extend i18n", function (done) {
var extended = extend(i18n({
"a": "b"
}), { get: function () {
return "c";
}})
expect(extended.get("a")).to.be.equals("b");
expect(extended.get("b")).to.be.equals("c");
done();
});
test('extend i18n', function (t) {
var extended = extend(i18n({
'a': 'b'
}), { get: function () {
return 'c'
}})
t.equals(extended.get('a'), 'b')
t.equals(extended.get('b'), 'c')
t.end()
})
test("extend i18n without lookup", function (done) {
var extended = extend(i18n({
"a": "b"
}))
expect(extended.get("a")).to.be.equals("b");
expect(extended.get("b")).to.be.equals(null);
done();
});
test('extend i18n without lookup', function (t) {
var extended = extend(i18n({
'a': 'b'
}))
t.equals(extended.get('a'), 'b')
t.equals(extended.get('b'), undefined)
t.end()
})

@@ -1,112 +0,111 @@

"use strict";
var code = require('code'),
lab = exports.lab = require('lab').script(),
test = lab.test,
fs = require("../../lookup/fs"),
path = require("path"),
expect = code.expect,
folder = path.join(__dirname, 'fs');
'use strict'
var tap = require('tap')
var afterEach = tap.afterEach
var test = tap.test
var fs = require('fs')
var fsLookup = require('../../lookup/fs')
var path = require('path')
var jsonFolderLookup = require('../../lookup/folder/json')
var folder = path.join(__dirname, 'fs')
test("custom strategy", function (done) {
var strategy = {},
lookup = fs("", strategy);
test('custom strategy', function (t) {
var strategy = {}
var lookup = fsLookup('', strategy)
expect(lookup.strategy).to.equal(strategy);
done();
});
t.equals(lookup.strategy, strategy)
t.end()
})
test("missing file lookup", function (done) {
expect(fs(folder).get("de.b")).to.equal(undefined);
done();
});
test('missing file lookup', function (t) {
t.equals(fsLookup(folder).get('de.b'), undefined)
t.end()
})
test("undefined subkey", function (done) {
var strategy = {},
lookup = fs("");
test('undefined subkey', function (t) {
var lookup = fsLookup('')
expect(lookup.get("en")).to.equal(undefined);
done();
});
t.equals(lookup.get('en'), undefined)
t.end()
})
test("same file more than once", function (done) {
var strategy = {},
lookup = fs(folder);
test('same file more than once', function (t) {
var lookup = fsLookup(folder)
expect(lookup.get("en.b")).to.equal("c");
expect(lookup.get("en.d")).to.equal("e");
done();
});
t.equals(lookup.get('en.b'), 'c')
t.equals(lookup.get('en.d'), 'e')
t.end()
})
test("empty file", function (done) {
var strategy = {},
lookup = fs(folder);
test('empty file', function (t) {
var lookup = fsLookup(folder)
var hiddenFile = path.join(folder, 'hidden.json')
var originalMode = fs.statSync(hiddenFile).mode
try {
fs.chmodSync(hiddenFile, 64)
t.equals(lookup.get('hidden.d'), undefined)
} catch (e) {
console.log(e)
fs.chmodSync(hiddenFile, originalMode)
throw e
}
fs.chmodSync(hiddenFile, originalMode)
t.end()
})
expect(lookup.get("ja.d")).to.equal(undefined);
done();
});
test('load strategy returns null', function (t) {
var lookup = fsLookup(folder, jsonFolderLookup)
test("load strategy returns null", function (done) {
var strategy = require("../../lookup/folder/json"),
lookup = fs(folder, strategy);
strategy.load = function () { return null; };
jsonFolderLookup.load = function () { return null }
expect(lookup.get("en.d")).to.equal(undefined);
done();
});
t.equals(lookup.get('en.d'), undefined)
t.end()
})
test("load a problematic string", function (done) {
var strategy = require("../../lookup/folder/json"),
lookup = fs(folder, strategy),
problemString = ".\n";
strategy.load = function () { return null; };
test('load a problematic string', function (t) {
var lookup = fsLookup(folder, jsonFolderLookup)
var problemString = '.\n'
expect(lookup.get(problemString)).to.equal(undefined);
done();
});
jsonFolderLookup.load = function () { return null }
lab.experiment("fs errors", function () {
var mockery = require("mockery"),
existsMock = {
existsSync: function () {
throw new Error("fun!");
}
},
allowables = ['../../lookup/fs', './folder/json.js'],
readMock = {
existsSync: function () { return true; },
readFileSync: function () {
throw new Error("fax");
}
};
t.equals(lookup.get(problemString), undefined)
t.end()
})
lab.before(function (done) {
mockery.enable();
mockery.registerAllowables(allowables);
done();
});
var mockery = require('mockery')
var allowables = ['../../lookup/fs', './folder/json.js']
test("fs exists error", function (done) {
mockery.registerMock("fs", existsMock);
var lookup = require("../../lookup/fs")(folder);
expect(lookup.get("en")).to.equal(undefined);
done();
});
mockery.enable()
mockery.registerAllowables(allowables)
test("fs readFile error", function (done) {
mockery.registerMock("fs", readMock);
var lookup = require("../../lookup/fs")(folder);
expect(lookup.get("en")).to.equal(undefined);
done();
});
afterEach(function (cb) {
mockery.deregisterMock('fs')
cb()
})
lab.afterEach(function (done) {
mockery.deregisterMock("fs");
done();
});
test('fs exists error', function (t) {
var existsMock = {
existsSync: function () {
throw new Error('fun!')
}
}
mockery.registerMock('fs', existsMock)
var lookup = require('../../lookup/fs')(folder)
t.equals(lookup.get('en'), undefined)
t.end()
})
lab.after(function (done) {
mockery.disable();
mockery.deregisterAllowables(allowables);
done();
});
})
test('fs readFile error', function (t) {
var readMock = {
existsSync: function () { return true },
readFileSync: function () {
throw new Error('fax')
}
}
mockery.registerMock('fs', readMock)
var lookup = require('../../lookup/fs')(folder)
t.equals(lookup.get('en'), undefined)
t.end()
})
mockery.disable()
mockery.deregisterAllowables(allowables)

@@ -1,76 +0,88 @@

"use strict";
var code = require('code'),
lab = exports.lab = require('lab').script(),
test = lab.test,
i18n = require("../"),
path = require("path"),
fsFolder = path.join(__dirname, "lookup", "fs"),
expect = code.expect;
'use strict'
var test = require('tap').test
var i18n = require('../')
var path = require('path')
var fsFolder = path.join(__dirname, 'lookup', 'fs')
test("mustache testing", function (done) {
expect(i18n({"en": {a: "{{hello}}"}}).lang("en").__("a", {hello: "d"})).to.equal("d");
done();
});
test('mustache testing', function (t) {
t.equals(i18n({'en': {a: '{{hello}}'}}).section('en').__('a', {hello: 'd'}), 'd')
t.end()
})
test("args testing", function (done) {
expect(i18n({"en": {a: "%s"}}).lang("en").__("a", "e")).to.equal("e");
done();
});
test('args testing', function (t) {
t.equals(i18n({'en': {a: '%s'}}).section('en').__('a', 'e'), 'e')
t.end()
})
test("args without placeholder", function (done) {
expect(i18n({"en": {a: ""}}).lang("en").__("a", "e")).to.equal("");
done();
});
test('args without placeholder', function (t) {
t.equals(i18n({'en': {a: ''}}).section('en').__('a', 'e'), '')
t.end()
})
test("mixed mustache & args testing", function (done) {
expect(i18n({"en": {a: "%s {{hello}}"}}).lang("en").__("a", {hello: "g"}, "f")).to.equal("f g");
done();
});
test('mixed mustache & args testing', function (t) {
t.equals(i18n({'en': {a: '%s {{hello}}'}}).section('en').__('a', {hello: 'g'}, 'f'), 'f g')
t.end()
})
test("empty key", function (done) {
var translator = i18n(fsFolder);
expect(translator.__("")).to.equal("(?)");
done();
});
test('empty key', function (t) {
var translator = i18n(fsFolder)
t.equals(translator.__(''), '(?)')
t.end()
})
test("empty key in namespace", function (done) {
var translator = i18n(fsFolder).lang("en");
expect(translator.__("")).to.equal("en.");
done();
});
test('empty key in namespace', function (t) {
var translator = i18n(fsFolder).section('en')
t.equals(translator.__(''), 'en.')
t.end()
})
test("undefined key in namespace", function (done) {
var translator = i18n(fsFolder).lang("en");
expect(translator.__(undefined)).to.equal("en.");
done();
});
test('undefined key in namespace', function (t) {
var translator = i18n(fsFolder).section('en')
t.equals(translator.__(undefined), 'en.')
t.end()
})
test("sprintf strings to be treated as strings", function (done) {
var __ = i18n().__;
expect(__('%s', 1)).to.equal("1");
expect(__('%s', "01")).to.equal("01");
expect(__('%s', false)).to.equal("false");
expect(__('%s', "false")).to.equal("false");
expect(__('%s', true)).to.equal("true");
expect(__('%s', "true")).to.equal("true");
expect(__('%s', null)).to.equal("null");
expect(__('%s', "null")).to.equal("null");
expect(__('%s', undefined)).to.equal("undefined");
expect(__('%s', "undefined")).to.equal("undefined");
done();
});
test('sprintf strings to be treated as strings', function (t) {
var __ = i18n().__
t.equals(__('%s', 1), '1')
t.equals(__('%s', '01'), '01')
t.equals(__('%s', false), 'false')
t.equals(__('%s', 'false'), 'false')
t.equals(__('%s', true), 'true')
t.equals(__('%s', 'true'), 'true')
t.equals(__('%s', null), 'null')
t.equals(__('%s', 'null'), 'null')
t.equals(__('%s', undefined), '%s')
t.equals(__('%s', 'undefined'), 'undefined')
t.end()
})
test("mustache strings to be treated as strings", function (done) {
var __ = i18n({"$": "{{data}}"}).__;
expect(__('$', {data: 1})).to.equal("1");
expect(__('$', {data: "01"})).to.equal("01");
expect(__('$', {data: false})).to.equal("false");
expect(__('$', {data: "false"})).to.equal("false");
expect(__('$', {data: true})).to.equal("true");
expect(__('$', {data: "true"})).to.equal("true");
expect(__('$', {data: null})).to.equal("");
expect(__('$', {data: "null"})).to.equal("null");
expect(__('$', {data: undefined})).to.equal("");
expect(__('$', {data: "undefined"})).to.equal("undefined");
done();
});
test('sprintf strings should be cut with the last undefined string', function (t) {
var __ = i18n().__
t.equals(__('%s %s %s', 1, undefined), '1 undefined undefined')
t.equals(__('%s %s %s', '01', undefined), '01 undefined undefined')
t.equals(__('%s %s %s', false, undefined), 'false undefined undefined')
t.equals(__('%s %s %s', 'false', undefined), 'false undefined undefined')
t.equals(__('%s %s %s', true, undefined), 'true undefined undefined')
t.equals(__('%s %s %s', 'true', undefined), 'true undefined undefined')
t.equals(__('%s %s %s', null, undefined), 'null undefined undefined')
t.equals(__('%s %s %s', 'null', undefined), 'null undefined undefined')
t.equals(__('%s %s %s', undefined, undefined), '%s %s %s')
t.equals(__('%s %s %s', 'undefined', undefined), 'undefined undefined undefined')
t.end()
})
test('mustache strings to be treated as strings', function (t) {
var __ = i18n({'$': '{{data}}'}).__
t.equals(__('$', {data: 1}), '1')
t.equals(__('$', {data: '01'}), '01')
t.equals(__('$', {data: false}), 'false')
t.equals(__('$', {data: 'false'}), 'false')
t.equals(__('$', {data: true}), 'true')
t.equals(__('$', {data: 'true'}), 'true')
t.equals(__('$', {data: null}), '')
t.equals(__('$', {data: 'null'}), 'null')
t.equals(__('$', {data: undefined}), '')
t.equals(__('$', {data: 'undefined'}), 'undefined')
t.end()
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc