Skip to content

Commit

Permalink
Implemented pluralization mechanism (p11n:)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxMotovilov committed Jul 18, 2014
1 parent c26a2b2 commit 02e740f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
10 changes: 8 additions & 2 deletions libs/dojox/jtlc/CHT.js
@@ -1,4 +1,5 @@
// Copyright (C) 2010-2014 Adstream Holdings
// Copyright (C) 2013-2014 12 Quarters Consulting
// Copyright (C) 2010-2013 Adstream Holdings
// All rights reserved.
// Redistribution and use are permitted under the modified BSD license
// available at https://github.com/MaxMotovilov/adstream-js-frameworks/wiki/License
Expand All @@ -9,6 +10,7 @@ dojo.require( "dojox.jtlc.CHT.scanner" );
dojo.require( "dojox.jtlc.CHT.instance" );
dojo.require( "dojox.jtlc.CHT.elements" );
dojo.require( "dojox.jtlc.CHT.tags" );
dojo.require( "dojox.jtlc.CHT.p11nAlgorithm" );

dojo.require( "dojox.jtlc.qplus" );

Expand Down Expand Up @@ -54,6 +56,9 @@ dojo.declare( 'dojox.jtlc.CHT', dj._qplusL, {
if( !settings.tags )
settings.tags = this.tags;

if( !settings.p11nAlgorithm )
settings.p11nAlgorithm = this.p11nAlgorithm;

this.qplus = new dj.qplus( settings );
},

Expand Down Expand Up @@ -547,7 +552,8 @@ dojo.declare( 'dojox.jtlc.CHT', dj._qplusL, {

// at this point, dojox.jtlc.CHT.tags and dojox.jtlc.CHT.elements are not yet overwritten!
tags: dojo.delegate( dj.qplus.prototype.tags, dj.CHT.tags ),
elements: dj.CHT.elements
elements: dj.CHT.elements,
p11nAlgorithm: dj.CHT.p11nAlgorithm
});

})();
Expand Down
51 changes: 51 additions & 0 deletions libs/dojox/jtlc/CHT/p11nAlgorithm.js
@@ -0,0 +1,51 @@
// Copyright (C) 2014 12 Quarters Consulting
// All rights reserved.
// Redistribution and use are permitted under the modified BSD license
// available at https://github.com/MaxMotovilov/adstream-js-frameworks/wiki/License

dojo.provide( "dojox.jtlc.CHT.p11nAlgorithm" );

dojox.jtlc.CHT.p11nAlgorithm = (function(){

// Based on https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_and_Plurals

var rules = {
// FIXME: add all other locales
en: 1, es: 1, it: 1, de:1, pt: 1, 'pt-br': 2, fr: 2, ru: 7, uk: 7, be: 7
},

algorithms = [
function() { return 0 },
function( n ) { return n==1 ? 0 : 1 },
function( n ) { return n==0 || n==1 ? 0 : 1 },
function( n ) { return n==0 ? 0 : n!=11 && n%10==1 ? 1 : 2 },
function( n ) { return n==1 || n==11 ? 0 : n==2 || n==12 ? 1 : inRange( 3, n, 10 ) || inRange( 13, n, 19 ) ? 2 : 3 },
function( n ) { return n==1 ? 0 : n==0 || inRange( 1, n%100, 19 ) ? 1 : 2 },
function( n ) { return n%10==1 && n!=11 ? 0 : n%10==0 || inRange( 11, n%100, 19 ) ? 1 : 2 },
function( n ) { return n%10==1 && n!=11 ? 0 : inRange( 2, n%10, 4 ) && !inRange( 12, n, 14 ) ? 1 : 2 },
function( n ) { return n==1 ? 0 : inRange( 2, n, 4 ) ? 1 : 2 },
function( n ) { return n==1 ? 0 : inRange( 2, n%10, 4 ) && !inRange( 12, n, 14 ) ? 1 : 2 },
function( n ) { return n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3 },
function( n ) { return n==1 ? 0 : n==2 ? 1 : inRange( 3, n, 6 ) ? 2 : inRange( 7, n, 10 ) ? 3 : 4 },
function( n ) { return n==0 ? 5 : n==1 ? 0 : n==2 ? 1 : inRange( 3, n%100, 10 ) ? 2 : inRange( 0, n%100, 2 ) ? 4 : 3 },
function( n ) { return n==1 ? 0 : n==0 || inRange( 1, n%100, 10 ) ? 1 : inRange( 11, n%100, 19 ) ? 2 : 3 },
function( n ) { return n%10==1 ? 0 : n%10==2 ? 1 : 2 },
function( n ) { return n%10==1 && n!=11 ? 0 : 1 },
function( n ) { return n==1 ? 0 : n%10==1 && !{11:1, 71:1, 91:1}[n] ? 1 : n%10==2 && !{12:1, 72:1, 92:1}[n] ? 2 :
{3:1, 4:1, 9:1}[n%10] && !{13:1, 14:1, 19:1, 73:1, 74:1, 79:1, 93:1, 94:1, 99:1}[n] ? 3 : n%1000000==0 ? 4 : 5 }
];

function inRange( a, b, c ) {
return a <= b && b <= c;
}

return function( value, words ) {
var n = Number( value );
if( Number.isNaN( n ) )
throw Error( "p11nAlgorithm: \"" + value + "\" is not a number" );
n = Math.round( Math.abs( n ) );

var i = algorithms[ rules[dojo.locale.toLowerCase()] || rules[dojo.locale.substr(0,2).toLowerCase()] || 0 ]( value );
return words[i] || words[0];
}
})();
40 changes: 40 additions & 0 deletions libs/dojox/jtlc/CHT/tags.js
@@ -1,3 +1,4 @@
// Copyright (C) 2013-2014 12 Quarters Consulting
// Copyright (C) 2010-2012 Adstream Holdings
// All rights reserved.
// Redistribution and use are permitted under the modified BSD license
Expand Down Expand Up @@ -35,6 +36,10 @@ dojo.require( 'dojox.jtlc.tags' );
return v.join( ' ' );
}

function isLowerCase(c) {
return c == c.toLowerCase();
}

dj.CHT._declareTag( 'foreachBody', {

constructor: function( body, input ) {
Expand Down Expand Up @@ -149,6 +154,41 @@ dojo.require( 'dojox.jtlc.tags' );
}
} ) );

dj.CHT._declareTag( 'p11n', {
constructor: function( words, arg ) {
if( typeof words !== 'string' )
throw Error( "p11n() expects a string, not " + words.toString() );
this.words = words.replace( /^\s*|\s*$/g, '' ).replace( /\s*\+\s*/g, '+' );
if( this.words.indexOf( '+' ) < 0 ) {
if( "sS".indexOf( this.words.charAt( this.words.length-1 ) ) )
this.words = this.words.substr(0,this.words.length-1) + '+' + this.words;
else
this.words += '+' + this.words + ( isLowerCase( this.words.charAt( this.words.length-1 ) ) ? 's' : 'S' );
}
if( arg ) this.arg = arg;
},

compile: function( self ) {
var d = this.i18nDictionary;
if( self.arg ) this.compile( self.arg );
else this.generator();

this._pluralizeFunction = this._pluralizeFunction || this.addGlobal( this.p11nAlgorithm );

this.expressions.push(
this._pluralizeFunction + '('
+ this.popExpression() + ',['
+ (
d && self.words in d ? d[self.words] : self.words
).replace( /^\s*|\s*$/g, '' )
.split( /\s*\+\s*/g )
.map( dj.stringLiteral )
.join(',')
+ '])'
);
}
} );

var escapeTag = dojo.declare( null, {
constructor: function( arg ) {
this.arg = arg;
Expand Down

0 comments on commit 02e740f

Please sign in to comment.