Merge commit 'eeaa2c11ee64761b706a41478bc74fedbf4162d7' as 'thirdparty/jed'

This commit is contained in:
Florian Dold 2016-10-04 11:55:31 +02:00
commit 1c26d75f62
12 changed files with 2008 additions and 0 deletions

1
thirdparty/jed/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules/*

4
thirdparty/jed/.travis.yml vendored Normal file
View File

@ -0,0 +1,4 @@
language: node_js
node_js:
- node
- 4

19
thirdparty/jed/LICENSE vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright jQuery Foundation and other contributors, https://jquery.org/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

13
thirdparty/jed/Makefile vendored Normal file
View File

@ -0,0 +1,13 @@
REPORTER = dot
test:
@./node_modules/.bin/mocha \
--require test/common \
--reporter $(REPORTER) \
--growl \
test/tests.js
test-browser:
@./node_modules/.bin/serve .
.PHONY: test

63
thirdparty/jed/README.md vendored Normal file
View File

@ -0,0 +1,63 @@
[![Build Status](https://secure.travis-ci.org/SlexAxton/Jed.png)](http://travis-ci.org/SlexAxton/Jed)
# Jed
*Gettext Style i18n for Modern JavaScript Apps*
For more info, please visit the docs site at <http://slexaxton.github.com/Jed>.
## You sure you don't want something more modern?
Jed is feature complete in my opinion. I am happy to fix bugs, but generally am not interested in adding more to the library.
I also maintain [messageformat.js](https://github.com/SlexAxton/messageformat.js). If you don't specifically need a gettext implementation, I might suggest using MessageFormat instead, as it has better support for plurals/gender and has built-in locale data.
## Parsing Gettext Files
Jed doesn't include a Gettext file parser, but several third-party parsers exist that can have their output adapted for Jed.
#### Node
Just search the npm repository, there are several PO and MO file parsers available.
#### Browser
[Jed Gettext Parser](https://github.com/WrinklyNinja/jed-gettext-parser) is the only known browser MO file parser, and it also works in Node, and outputs Jed-compatible data directly.
[gettext.js](https://code.google.com/p/gettext-js) and [Pomo.js](https://github.com/cfv1984/pomo) both include browser-compatible PO file parsers.
## Todo
* Build time generation of plural form functions
* Web interface for building translation sets
* Code introspection for default values
## License
Jed is a member project of the [jQuery Foundation](https://jquery.org/)
You may use this software under the MIT License.
You may contribute to this software under the jQuery Foundation CLA - <https://contribute.jquery.org/CLA/>
## Author
* Alex Sexton - @slexaxton - <https://alexsexton.com/>
## Credits
A good chunk of sanity checking was done against the gettext.js tests. That was written by:
* Joshua I. Miller
The sprintf implementation is from:
* Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
## The name
The name jed.js is an homage to Jed Schmidt (<https://github.com/jed>) the JavaScript community member who is a japanese translator by day, and a "hobbyist" JavaScript programmer by night. Give your kids three character names and they'll probably get software named after them too.

1033
thirdparty/jed/jed.js vendored Normal file

File diff suppressed because it is too large Load Diff

27
thirdparty/jed/package.json vendored Normal file
View File

@ -0,0 +1,27 @@
{
"name": "jed",
"version": "1.1.1",
"author": "Alex Sexton <alexsexton@gmail.com>",
"description": "Gettext Style i18n for Modern JavaScript Apps",
"repository": {
"type": "git",
"url": "https://SlexAxton@github.com/SlexAxton/Jed.git"
},
"scripts": {
"test": "make test"
},
"main": "./jed",
"keywords": [
"i18n",
"Jed",
"gettext",
"internationalization"
],
"dependencies" : {},
"devDependencies" : {
"mocha" : "*",
"expect.js" : "*",
"serve": "*"
},
"license": "MIT"
}

72
thirdparty/jed/plurals.jison vendored Normal file
View File

@ -0,0 +1,72 @@
/* description: Parses end executes mathematical expressions. */
/* lexical grammar */
%lex
%%
\s+ /* skip whitespace */
[0-9]+("."[0-9]+)?\b return 'NUMBER'
"n" return 'n'
"||" return '||'
"&&" return '&&'
"?" return '?'
":" return ':'
"<=" return '<='
">=" return '>='
"<" return '<'
">" return '>'
"!=" return '!='
"==" return '=='
"%" return '%'
"(" return '('
")" return ')'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
/* operator associations and precedence */
%right <code> '?' ':'
%left '||'
%left '&&'
%left '<=' '>=' '<' '>' '!=' '=='
%left '%'
%start expressions
%% /* language grammar */
expressions
: e EOF
{ return { type : 'GROUP', expr: $1 }; }
;
e
: e '?' e ':' e
{$$ = { type: 'TERNARY', expr: $1, truthy : $3, falsey: $5 }; }
| e '||' e
{$$ = { type: "OR", left: $1, right: $3 };}
| e '&&' e
{$$ = { type: "AND", left: $1, right: $3 };}
| e '<' e
{$$ = { type: 'LT', left: $1, right: $3 }; }
| e '<=' e
{$$ = { type: 'LTE', left: $1, right: $3 };}
| e '>' e
{$$ = { type: 'GT', left: $1, right: $3 };}
| e '>=' e
{$$ = { type: 'GTE', left: $1, right: $3 };}
| e '!=' e
{$$ = { type: 'NEQ', left: $1, right: $3 };}
| e '==' e
{$$ = { type: 'EQ', left: $1, right: $3 };}
| e '%' e
{$$ = { type: 'MOD', left: $1, right: $3 };}
| '(' e ')'
{$$ = { type: 'GROUP', expr: $2 }; }
| 'n'
{$$ = { type: 'VAR' }; }
| NUMBER
{$$ = { type: 'NUM', val: Number(yytext) }; }
;

2
thirdparty/jed/test/common.js vendored Normal file
View File

@ -0,0 +1,2 @@
expect = require('expect.js');
Jed = require('../jed');

24
thirdparty/jed/test/index.html vendored Normal file
View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8 />
<title>Jed.js Test Suite</title>
<link rel="stylesheet" href="/node_modules/mocha/mocha.css" />
<script src="/test/jquery.min.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<script src="/node_modules/expect.js/expect.js"></script>
<script>mocha.setup('bdd')</script>
<script src="/jed.js"></script>
<script src="/test/tests.js"></script>
</head>
<body>
<h1>Jed.js Test Suite</h1>
<div id="mocha"></div>
<script>
window.onload = function () {
mocha.run().globals(['Jed']);
};
</script>
</body>
</html>

4
thirdparty/jed/test/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

746
thirdparty/jed/test/tests.js vendored Normal file
View File

@ -0,0 +1,746 @@
(function (Jed){
describe("Property Checks", function () {
it("should exist", function () {
expect( Jed ).to.be.ok();
});
it("should have a context delimiter as per the gettext spec", function () {
expect( Jed.context_delimiter ).to.be( "\u0004" );
expect( Jed.context_delimiter ).to.be( String.fromCharCode( 4 ) );
});
});
// Group tests that need similar data
(function () {
var locale_data = {
"messages" : {
"" : {
"domain" : "messages",
"lang" : "en",
"plural-forms" : "nplurals=2; plural=(n != 1);"
},
"test" : ["test_translation_output"]
}
};
var locale_data2 = {
"some_domain" : {
"" : {
"domain" : "some_domain",
"lang" : "en",
"plural-forms" : "nplurals=2; plural=(n != 1);"
},
"test" : ["test_translation_output2"],
"zero length translation" : [""]
}
};
var locale_data3 = {
"some_domain" : {
"" : {
"domain" : "some_domain",
"lang" : "ar",
"plural-forms" : "nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);"
},
"test" : ["test_translation_output3"],
"zero length translation" : [""]
}
};
var i18n = new Jed({
"domain" : "messages",
"locale_data" : locale_data
});
var i18n_2 = new Jed({
"domain" : "some_domain",
"locale_data" : locale_data2
});
var i18n_3 = new Jed({
"domain" : "some_domain",
"locale_data" : locale_data3
});
// Standard shorthand function
function _(msgid) {
return i18n_2.gettext(msgid);
}
// Actual tests
describe("Instantiation", function () {
it("should exist", function () {
expect( i18n ).to.be.ok();
expect( i18n_2 ).to.be.ok();
expect( i18n_3 ).to.be.ok();
expect( _ ).to.be.ok();
});
});
describe("Basic", function () {
it("should translate a key that exists in the translation", function () {
expect( i18n.gettext('test') ).to.be( 'test_translation_output' );
});
it("should just pass through strings that aren't translatable", function () {
expect( i18n.gettext('missing') ).to.be( 'missing' );
});
it("should translate a key in a locale with plural-forms rules that don't assume n==1 will return 0", function () {
expect(i18n_3.gettext('test')).to.be('test_translation_output3');
});
it("should allow you to wrap it as a shorthand function", function () {
expect( _('test') ).to.be( 'test_translation_output2' );
expect( _('missing') ).to.be( 'missing' );
});
it("should have identical output for wrapped and non-wrapped instances", function () {
expect( _('test') ).to.be( i18n_2.gettext('test') );
expect( _('missing') ).to.be( i18n_2.gettext('missing') );
});
it("should not allow you to use domains that don't exist", function () {
function badCreate() {
var x = new Jed({
"domain" : "missing_domain",
"locale_data" : locale_data
});
return x;
}
expect( badCreate ).to.throwException();
});
it("should just pass through translations that are empty strings", function () {
expect( _('zero length translation') ).to.be('zero length translation' );
});
it("should call the callback function (if given) when a key is missing", function() {
var callbackCalled;
function missingKeyCallback(key) {
callbackCalled = true;
}
callbackCalled = false;
var jedWithCallback = new Jed({
"missing_key_callback" : missingKeyCallback
});
jedWithCallback.gettext('missing key');
expect(callbackCalled).to.be(true);
callbackCalled = false;
var jedWithoutCallback = new Jed({});
jedWithoutCallback.gettext('missing key');
expect(callbackCalled).to.be(false);
});
});
})();
(function () {
var locale_data = {
"messages_1": {
"": {
"domain": "messages_1",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test": ["test_1"],
"test singular": ["test_1 singular", "test_1 plural"],
"context\u0004test": ["test_1 context"],
"context\u0004test singular": ["test_1 context singular", "test_1 context plural"]
},
"messages_2": {
"": {
"domain": "messages_2",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test": ["test_2"],
"test singular": ["test_2 singular", "test_2 plural"],
"context\u0004test": ["test_2 context"],
"context\u0004test singular": ["test_2 context singular", "test_2 context plural"]
}
};
describe("Domain", function () {
var i18n1 = new Jed({
domain : "messages_1",
locale_data : locale_data
});
var i18n_2 = new Jed({
domain : "messages_2",
locale_data : locale_data
});
// No default domain
var i18n_3 = new Jed({
locale_data : locale_data
});
it("should use the correct domain when there are multiple", function () {
expect( i18n1.gettext('test') ).to.be('test_1');
expect( i18n_2.gettext('test') ).to.be('test_2');
});
it("should still pass through non-existent keys", function () {
expect( i18n1.gettext('nope') ).to.be('nope');
expect( i18n_2.gettext('nope again') ).to.be('nope again');
});
it("should reveal the current domain on any instance", function () {
expect( i18n1.textdomain() ).to.be( 'messages_1' );
expect( i18n_2.textdomain() ).to.be( 'messages_2' );
});
it("should use `messages` as the default domain if none given", function () {
expect( i18n_3.textdomain() ).to.be('messages');
});
it("should allow on the fly domain switching", function () {
// Switch these up
i18n1.textdomain('messages_2');
i18n_2.textdomain('messages_1');
expect( i18n1.gettext('test') ).to.be('test_2');
expect( i18n_2.gettext('test') ).to.be('test_1');
expect( i18n1.textdomain() ).to.be( 'messages_2' );
expect( i18n_2.textdomain() ).to.be( 'messages_1' );
});
describe("#dgettext", function () {
it("should have the dgettext function", function () {
expect( i18n_3.dgettext ).to.be.ok();
});
it("should allow you to call the domain on the fly", function () {
expect( i18n_3.dgettext('messages_1', 'test') ).to.be('test_1');
expect( i18n_3.dgettext('messages_2', 'test') ).to.be('test_2');
});
it("should pass through non-existent keys", function () {
expect( i18n_3.dgettext('messages_1', 'nope') ).to.be('nope');
expect( i18n_3.dgettext('messages_2', 'nope again') ).to.be('nope again');
});
});
describe("#dcgettext", function () {
var i18n_4 = new Jed({
locale_data : locale_data
});
it("should have the dcgettext function", function () {
expect( i18n_4.dcgettext ).to.be.ok();
});
it("should ignore categories altogether", function () {
expect( i18n_4.dcgettext('messages_1', 'test', 'A_CATEGORY') ).to.be('test_1');
});
});
});
describe("Pluralization", function () {
var locale_data1 = {
"plural_test": {
"": {
"domain": "plural_test",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test singular": ["test_1"],
"test plural %1$d": ["test_1_singular %1$d", "test_1_plural %1$d"],
"context\u0004test context": ["test_1context"],
"test2": ["test_2"],
"zero length translation": [""],
"context\u0004test2": ["test_2context"],
"Not translated plural": ["asdf", "asdf"], // this should never hit, since it's msgid2
"context\u0004context plural %1$d": ["context_plural_1 singular %1$d", "context_plural_1 plural %1$d"]
}
};
var locale_data2 = {
"plural_test2": {
"": {
"domain": "plural_test2",
"lang": "sl",
// actual Slovenian pluralization rules
"plural_forms": "nplurals=4; plural=(n==1 ? 0 : n%10==2 ? 1 : n%10==3 || n%10==4 ? 2 : 3);"
},
"Singular" : ["Numerus 0", "Numerus 1", "Numerus 2", "Numerus 3" ]
}
};
var i18n = new Jed({
domain: "plural_test",
locale_data: locale_data1
});
var i18n_2 = new Jed({
domain: "plural_test2",
locale_data: locale_data2
});
describe("#ngettext", function () {
it("should have a ngettext function", function () {
expect( i18n.ngettext ).to.be.ok();
});
it("should choose the correct pluralization translation", function () {
expect( i18n.ngettext('test plural %1$d', 'test plural %1$d', 1) ).to.be( 'test_1_singular %1$d' );
expect( i18n.ngettext('test plural %1$d', 'test plural %1$d', 2) ).to.be( 'test_1_plural %1$d' );
expect( i18n.ngettext('test plural %1$d', 'test plural %1$d', 0) ).to.be( 'test_1_plural %1$d' );
});
it("should still pass through on plurals", function () {
expect(i18n.ngettext('Not translated', 'Not translated plural', 1) ).to.be( 'Not translated' );
expect(i18n.ngettext('Not translated', 'Not translated plural', 2) ).to.be( 'Not translated plural' );
expect(i18n.ngettext('Not translated', 'Not translated plural', 0) ).to.be( 'Not translated plural' );
expect(i18n_2.ngettext('Not translated', 'Not translated plural', 3) ).to.be( 'Not translated plural' );
});
it("should be able to parse complex pluralization rules", function () {
var strings = ['Singular', 'Plural'];
for (var i=0; i<=40; i++) {
var translation = i18n_2.ngettext(strings[0], strings[1], i);
var plural = ((i == 1) ? 0 :
(i % 10 == 2) ? 1 :
(i % 10 == 3 || i % 10 == 4) ? 2 : 3);
expect(translation).to.be( 'Numerus ' + plural );
}
});
});
var locale_data_multi = {
"messages_3": {
"": {
"domain": "messages_3",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test": ["test_1"],
"test singular": ["test_1 singular", "test_1 plural"],
"context\u0004test": ["test_1 context"],
"context\u0004test singular": ["test_1 context singular", "test_1 context plural"]
},
"messages_4": {
"": {
"domain": "messages_4",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test": ["test_2"],
"test singular": ["test_2 singular", "test_2 plural"],
"context\u0004test": ["test_2 context"],
"context\u0004test singular": ["test_2 context singular", "test_2 context plural"]
}
};
describe("#dngettext", function () {
var i18n = new Jed({
locale_data : locale_data_multi
});
it("should have a dngettext function", function () {
expect( i18n.dngettext).to.be.ok();
});
it("should pluralize correctly, based on domain rules", function () {
expect(i18n.dngettext('messages_3', 'test singular', 'test plural', 1)).to.be('test_1 singular');
expect(i18n.dngettext('messages_3', 'test singular', 'test plural', 2)).to.be('test_1 plural');
expect(i18n.dngettext('messages_3', 'test singular', 'test plural', 0)).to.be('test_1 plural');
expect(i18n.dngettext('messages_4', 'test singular', 'test plural', 1)).to.be('test_2 singular');
expect(i18n.dngettext('messages_4', 'test singular', 'test plural', 2)).to.be('test_2 plural');
expect(i18n.dngettext('messages_4', 'test singular', 'test plural', 0)).to.be('test_2 plural');
});
it("should passthrough non-found keys regardless of pluralization addition", function (){
expect(i18n.dngettext('messages_3', 'Not translated', 'Not translated plural', 1)).to.be('Not translated');
expect(i18n.dngettext('messages_3', 'Not translated', 'Not translated plural', 2)).to.be('Not translated plural');
expect(i18n.dngettext('messages_3', 'Not translated', 'Not translated plural', 0)).to.be('Not translated plural');
expect(i18n.dngettext('messages_4', 'Not translated', 'Not translated plural', 1)).to.be('Not translated');
expect(i18n.dngettext('messages_4', 'Not translated', 'Not translated plural', 2)).to.be('Not translated plural');
expect(i18n.dngettext('messages_4', 'Not translated', 'Not translated plural', 0)).to.be('Not translated plural');
});
});
describe("#dcngettext", function () {
var i18n = new Jed({
locale_data : locale_data_multi
});
it("should more or less ignore the category", function () {
expect(i18n.dcngettext('messages_3', 'test singular', 'test plural', 1, 'LC_MESSAGES')).to.be('test_1 singular');
expect(i18n.dcngettext('messages_3', 'test singular', 'test plural', 2, 'LC_MESSAGES')).to.be('test_1 plural');
expect(i18n.dcngettext('messages_3', 'test singular', 'test plural', 0, 'LC_MESSAGES')).to.be('test_1 plural');
expect(i18n.dcngettext('messages_4', 'test singular', 'test plural', 1, 'LC_MESSAGES')).to.be('test_2 singular');
expect(i18n.dcngettext('messages_4', 'test singular', 'test plural', 2, 'LC_MESSAGES')).to.be('test_2 plural');
expect(i18n.dcngettext('messages_4', 'test singular', 'test plural', 0, 'LC_MESSAGES')).to.be('test_2 plural');
expect(i18n.dcngettext('messages_3', 'Not translated', 'Not translated plural', 1, 'LC_MESSAGES')).to.be('Not translated');
expect(i18n.dcngettext('messages_3', 'Not translated', 'Not translated plural', 2, 'LC_MESSAGES')).to.be('Not translated plural');
expect(i18n.dcngettext('messages_3', 'Not translated', 'Not translated plural', 0, 'LC_MESSAGES')).to.be('Not translated plural');
expect(i18n.dcngettext('messages_4', 'Not translated', 'Not translated plural', 1, 'LC_MESSAGES')).to.be('Not translated');
expect(i18n.dcngettext('messages_4', 'Not translated', 'Not translated plural', 2, 'LC_MESSAGES')).to.be('Not translated plural');
expect(i18n.dcngettext('messages_4', 'Not translated', 'Not translated plural', 0, 'LC_MESSAGES')).to.be('Not translated plural');
});
});
describe("#pgettext", function () {
var locale_data_w_context = {
"context_test": {
"": {
"domain": "context_test",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test singular": ["test_1"],
"test plural %1$d": ["test_1_singular %1$d", "test_1_plural %1$d"],
"context\u0004test context": ["test_1context"],
"test2": ["test_2"],
"zero length translation": [""],
"context\u0004test2": ["test_2context"],
"context\u0004context plural %1$d": ["context_plural_1 singular %1$d", "context_plural_1 plural %1$d"]
}
};
var i18n = new Jed({
domain : "context_test",
locale_data : locale_data_w_context
});
it("should expose the pgettext function", function () {
expect( i18n.pgettext ).to.be.ok();
});
it("should accept a context and look up a new key using the context_glue", function () {
expect( i18n.pgettext('context', 'test context') ).to.be( 'test_1context' );
});
it("should still pass through missing keys", function () {
expect( i18n.pgettext('context', 'Not translated') ).to.be( 'Not translated' );
});
it("should make sure same msgid returns diff results w/ context when appropriate", function () {
expect(i18n.gettext('test2')).to.be('test_2');
expect(i18n.pgettext('context', 'test2')).to.be( 'test_2context' );
});
});
describe("#dpgettext", function () {
var i18n = new Jed({
locale_data : locale_data_multi
});
it("should have a dpgettext function", function () {
expect( i18n.dpgettext ).to.be.ok();
});
it("should use the domain and the context simultaneously", function () {
expect(i18n.dpgettext('messages_3', 'context', 'test')).to.be('test_1 context');
expect(i18n.dpgettext('messages_4', 'context', 'test')).to.be('test_2 context');
});
it("should pass through if either the domain, the key or the context isn't found", function () {
expect(i18n.dpgettext('messages_3', 'context', 'Not translated')).to.be('Not translated');
expect(i18n.dpgettext('messages_4', 'context', 'Not translated')).to.be('Not translated');
});
});
describe("#dcpgettext", function () {
var i18n = new Jed({
locale_data : locale_data_multi
});
it("should have a dcpgettext function", function () {
expect( i18n.dcpgettext ).to.be.ok();
});
it("should use the domain and the context simultaneously - ignore the category", function () {
expect(i18n.dcpgettext('messages_3', 'context', 'test', 'LC_MESSAGES')).to.be('test_1 context');
expect(i18n.dcpgettext('messages_4', 'context', 'test', 'LC_MESSAGES')).to.be('test_2 context');
});
it("should pass through if either the domain, the key or the context isn't found", function () {
expect(i18n.dcpgettext('messages_3', 'context', 'Not translated', 'LC_MESSAGES')).to.be('Not translated');
expect(i18n.dcpgettext('messages_4', 'context', 'Not translated', 'LC_MESSAGES')).to.be('Not translated');
});
});
describe("#npgettext", function () {
var locale_data_w_context = {
"context_plural_test": {
"": {
"domain": "context_plural_test",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test singular": ["test_1"],
"test plural %1$d": ["test_1_singular %1$d", "test_1_plural %1$d"],
"context\u0004test context": ["test_1context"],
"test2": ["test_2"],
"zero length translation": [""],
"context\u0004test2": ["test_2context"],
"context\u0004context plural %1$d": ["context_plural_1 singular %1$d", "context_plural_1 plural %1$d"]
}
};
var i18n = new Jed({
domain : "context_plural_test",
locale_data : locale_data_w_context
});
it("should have a dcpgettext function", function () {
expect( i18n.dcpgettext ).to.be.ok();
});
it("should handle plurals at the same time as contexts", function () {
expect(i18n.npgettext('context', 'context plural %1$d', 'plural %1$d', 1)).to.be('context_plural_1 singular %1$d');
expect(i18n.npgettext('context', 'context plural %1$d', 'plural %1$d', 2)).to.be('context_plural_1 plural %1$d');
expect(i18n.npgettext('context', 'context plural %1$d', 'plural %1$d', 0)).to.be('context_plural_1 plural %1$d');
});
it("should just pass through on not-found cases", function () {
expect(i18n.npgettext('context', 'Not translated', 'Not translated plural', 1)).to.be('Not translated');
expect(i18n.npgettext('context', 'Not translated', 'Not translated plural', 2)).to.be('Not translated plural');
expect(i18n.npgettext('context', 'Not translated', 'Not translated plural', 0)).to.be('Not translated plural');
});
});
describe("#dnpgettext", function () {
var i18n = new Jed({
locale_data : locale_data_multi
});
it("should have a dnpgettext function", function () {
expect( i18n.dnpgettext ).to.be.ok();
});
it("should be able to do a domain, context, and pluralization lookup all at once", function () {
expect(i18n.dnpgettext('messages_3', 'context', 'test singular', 'test plural', 1)).to.be('test_1 context singular');
expect(i18n.dnpgettext('messages_3', 'context', 'test singular', 'test plural', 2)).to.be('test_1 context plural');
expect(i18n.dnpgettext('messages_3', 'context', 'test singular', 'test plural', 0)).to.be('test_1 context plural');
expect(i18n.dnpgettext('messages_4', 'context', 'test singular', 'test plural', 1)).to.be('test_2 context singular');
expect(i18n.dnpgettext('messages_4', 'context', 'test singular', 'test plural', 2)).to.be('test_2 context plural');
expect(i18n.dnpgettext('messages_4', 'context', 'test singular', 'test plural', 0)).to.be('test_2 context plural');
});
it("should pass through if everything doesn't point towards a key", function () {
expect(i18n.dnpgettext('messages_3', 'context', 'Not translated', 'Not translated plural', 1)).to.be('Not translated');
expect(i18n.dnpgettext('messages_3', 'context', 'Not translated', 'Not translated plural', 2)).to.be('Not translated plural');
expect(i18n.dnpgettext('messages_3', 'context', 'Not translated', 'Not translated plural', 0)).to.be('Not translated plural');
expect(i18n.dnpgettext('messages_4', 'context', 'Not translated', 'Not translated plural', 1)).to.be('Not translated');
expect(i18n.dnpgettext('messages_4', 'context', 'Not translated', 'Not translated plural', 2)).to.be('Not translated plural');
expect(i18n.dnpgettext('messages_4', 'context', 'Not translated', 'Not translated plural', 0)).to.be('Not translated plural');
});
});
describe("#dcnpgettext", function () {
var i18n = new Jed({
locale_data : locale_data_multi
});
it("should have a dcnpgettext function", function () {
expect( i18n.dcnpgettext ).to.be.ok();
});
it("should be able to do a domain, context, and pluralization lookup all at once - ignore category", function () {
expect(i18n.dcnpgettext('messages_3', 'context', 'test singular', 'test plural', 1, "LC_MESSAGES")).to.be('test_1 context singular');
expect(i18n.dcnpgettext('messages_3', 'context', 'test singular', 'test plural', 2, "LC_MESSAGES")).to.be('test_1 context plural');
expect(i18n.dcnpgettext('messages_3', 'context', 'test singular', 'test plural', 0, "LC_MESSAGES")).to.be('test_1 context plural');
expect(i18n.dcnpgettext('messages_4', 'context', 'test singular', 'test plural', 1, "LC_MESSAGES")).to.be('test_2 context singular');
expect(i18n.dcnpgettext('messages_4', 'context', 'test singular', 'test plural', 2, "LC_MESSAGES")).to.be('test_2 context plural');
expect(i18n.dcnpgettext('messages_4', 'context', 'test singular', 'test plural', 0, "LC_MESSAGES")).to.be('test_2 context plural');
});
it("should pass through if everything doesn't point towards a key", function () {
expect(i18n.dcnpgettext('messages_3', 'context', 'Not translated', 'Not translated plural', 1, "LC_MESSAGES")).to.be('Not translated');
expect(i18n.dcnpgettext('messages_3', 'context', 'Not translated', 'Not translated plural', 2, "LC_MESSAGES")).to.be('Not translated plural');
expect(i18n.dcnpgettext('messages_3', 'context', 'Not translated', 'Not translated plural', 0, "LC_MESSAGES")).to.be('Not translated plural');
expect(i18n.dcnpgettext('messages_4', 'context', 'Not translated', 'Not translated plural', 1, "LC_MESSAGES")).to.be('Not translated');
expect(i18n.dcnpgettext('messages_4', 'context', 'Not translated', 'Not translated plural', 2, "LC_MESSAGES")).to.be('Not translated plural');
expect(i18n.dcnpgettext('messages_4', 'context', 'Not translated', 'Not translated plural', 0, "LC_MESSAGES")).to.be('Not translated plural');
});
});
});
describe("Plural Forms Parsing", function (){
// This is the method from the original gettext.js that uses new Function
function evalParse( plural_forms ) {
var pf_re = new RegExp('^(\\s*nplurals\\s*=\\s*[0-9]+\\s*;\\s*plural\\s*=\\s*(?:\\s|[-\\?\\|&=!<>+*/%:;a-zA-Z0-9_\(\)])+)', 'm');
if (pf_re.test(plural_forms)) {
var pf = plural_forms;
if (! /;\s*$/.test(pf)) pf = pf.concat(';');
var code = 'var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) };';
return (new Function("n", code));
} else {
throw new Error("Syntax error in language file. Plural-Forms header is invalid ["+plural_forms+"]");
}
}
// http://translate.sourceforge.net/wiki/l10n/pluralforms
it("should have the same result as doing an eval on the expression for all known plural-forms.", function (){
var pfs = ["nplurals=2; plural=(n > 1)","nplurals=2; plural=(n != 1)","nplurals=6; plural= n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;","nplurals=1; plural=0","nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)","nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2","nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2","nplurals=4; plural= (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3","nplurals=2; plural=n > 1","nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4","nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3","nplurals=2; plural= (n > 1)","nplurals=2; plural=(n%10!=1 || n%100==11)","nplurals=2; plural=n!=0","nplurals=2; plural=(n!=1)","nplurals=2; plural=(n!= 1)","nplurals=4; plural= (n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3","nplurals=2; plural=n>1;","nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)","nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)","nplurals=2; plural= n==1 || n%10==1 ? 0 : 1","nplurals=3; plural=(n==0 ? 0 : n==1 ? 1 : 2)","nplurals=4; plural=(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)","nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)","nplurals=2; plural=(n!=1);","nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);","nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0)","nplurals=2; plural=n != 1","nplurals=2; plural=(n>1)","nplurals=1; plural=0;"],
pf, pfc, pfe, pfi, i;
for ( pfi = 0; pfi < pfs.length; pfi++ ) {
pf = ""+pfs[ pfi ];
for( i = 0; i < 106; i++ ){
pfc = Jed.PF.compile( ""+pf )( i );
pfe = evalParse( ""+pf )( i ).plural;
if (pfc !== pfe) {
throw new Error('expected ' + pfe + ' but got ' + pfc);
}
}
}
});
});
describe("Chainable API", function () {
var locale_data_w_context = {
"context_sprintf_test": {
"": {
"domain": "context_sprintf_test",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test singular": ["test_1"],
"test plural %1$d": ["test_1_singular %1$d", "test_1_plural %1$d"],
"context\u0004test context": ["test_1context"],
"test2": ["test_2"],
"zero length translation": [""],
"context\u0004test2": ["test_2context"],
"context\u0004context plural %1$d": ["context_plural_1 singular %1$d", "context_plural_1 plural %1$d"]
},
"other_domain": {
"": {
"domain": "other_domain",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test other_domain singular": ["other domain test 1"],
"context\u0004context other plural %1$d": ["context_plural_1 singular %1$d", "context_plural_1 plural %1$d"]
}
};
var i18n = new Jed({
"locale_data" : locale_data_w_context,
"domain": "context_sprintf_test"
});
it("should handle a simple gettext passthrough", function (){
expect( i18n.translate('test singular').fetch() ).to.be('test_1');
});
it("should handle changing domains", function (){
expect( i18n.translate('test other_domain singular').onDomain('other_domain').fetch() ).to.be('other domain test 1');
});
it("should allow you to add plural information in the chain.", function () {
expect( i18n.translate("test plural %1$d").ifPlural(5, "dont matta").fetch() ).to.be( "test_1_plural %1$d" );
});
it("should take in a sprintf set of args (as array) on the plural lookup", function(){
expect( i18n.translate("test plural %1$d").ifPlural(5, "dont matta").fetch([5]) ).to.be( "test_1_plural 5" );
expect( i18n.translate("test plural %1$d %2$d").ifPlural(5, "dont matta %1$d %2$d").fetch([5, 6]) ).to.be( "dont matta 5 6" );
expect( i18n.translate("test plural %1$d %2$d").ifPlural(1, "dont matta %1$d %2$d").fetch([1, 6]) ).to.be( "test plural 1 6" );
});
it("should take in a sprintf set of args (as args) on the plural lookup", function(){
expect( i18n.translate("test plural %1$d %2$d").ifPlural(5, "dont matta %1$d %2$d").fetch(5, 6) ).to.be( "dont matta 5 6" );
expect( i18n.translate("test plural %1$d %2$d").ifPlural(1, "dont matta %1$d %2$d").fetch(1, 6) ).to.be( "test plural 1 6" );
});
it("should handle context information.", function () {
expect(i18n.translate('test context').withContext('context').fetch() ).to.be('test_1context');
});
it("should be able to do all at the same time.", function () {
expect( i18n.translate("context other plural %1$d").withContext('context').onDomain('other_domain').ifPlural(5, "ignored %1$d").fetch(5) ).to.be( "context_plural_1 plural 5" );
expect( i18n.translate("context other plural %1$d").withContext('context').onDomain('other_domain').ifPlural(1, "ignored %1$d").fetch(1) ).to.be( "context_plural_1 singular 1" );
});
});
describe("Sprintf", function () {
var locale_data_w_context = {
"context_sprintf_test": {
"": {
"domain": "context_sprintf_test",
"lang": "en",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"test singular": ["test_1"],
"test plural %1$d": ["test_1_singular %1$d", "test_1_plural %1$d"],
"context\u0004test context": ["test_1context"],
"test2": ["test_2"],
"zero length translation": [""],
"context\u0004test2": ["test_2context"],
"context\u0004context plural %1$d": ["context_plural_1 singular %1$d", "context_plural_1 plural %1$d"]
}
};
var i18n = new Jed({
"locale_data" : locale_data_w_context,
"domain": "context_sprintf_test"
});
it("should take multiple types of arrays as input", function () {
var strings = {
"blah" : "blah",
"thing%1$sbob" : "thing[one]bob",
"thing%1$s%2$sbob" : "thing[one][two]bob",
"thing%1$sasdf%2$sasdf" : "thing[one]asdf[two]asdf",
"%1$s%2$s%3$s" : "[one][two]",
"tom%1$saDick" : "tom[one]aDick"
};
var args = ["[one]", "[two]"];
for (var i in strings) {
// test using new Array
expect(Jed.sprintf(i, ["[one]","[two]"])).to.be(strings[i]);
expect(i18n.sprintf(i, ["[one]","[two]"])).to.be(strings[i]);
// test using predefined array
expect(Jed.sprintf(i, args)).to.be(strings[i]);
expect(i18n.sprintf(i, args)).to.be(strings[i]);
}
});
it("should accept a single string instead of an array", function () {
// test using scalar rather than array
var strings = {
"blah" : "blah",
"" : "",
"%%" : "%",
"tom%%dick" : "tom%dick",
"thing%1$sbob" : "thing[one]bob",
"thing%1$s%2$sbob" : "thing[one]bob",
"thing%1$sasdf%2$sasdf" : "thing[one]asdfasdf",
"%1$s%2$s%3$s" : "[one]"
};
var arg = "[one]";
for (var i in strings) {
expect(Jed.sprintf(i, arg)).to.be(strings[i]);
expect(i18n.sprintf(i, arg)).to.be(strings[i]);
}
});
});
})();
})( Jed );