03c860d961
* Update jquery.i18n to 1.07 and add missing rule parser Fixes #2700 Adds missing CLDRPluralRuleParser.js so that plurals are supported. Updates all files to jquery.i18n 1.07 Includes a bunch of specialty language support, but only Finnish and Russian are loaded as examples. * Add some missing translations, including plurals Fix some cases of Javascript string concatenation and plural conditionalization to demonstrate that plurals work in both English and French now. NOTE: Corresponding updates need to be made to all the other language files since some keys were renamed or eliminated.
169 lines
5.3 KiB
JavaScript
169 lines
5.3 KiB
JavaScript
/*!
|
|
* jQuery Internationalization library
|
|
*
|
|
* Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
|
|
*
|
|
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
|
|
* anything special to choose one license or the other and you don't have to
|
|
* notify anyone which license you are using. You are free to use
|
|
* UniversalLanguageSelector in commercial projects as long as the copyright
|
|
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
|
|
*
|
|
* @licence GNU General Public Licence 2.0 or later
|
|
* @licence MIT License
|
|
*/
|
|
|
|
( function ( $ ) {
|
|
'use strict';
|
|
|
|
var MessageParserEmitter = function () {
|
|
this.language = $.i18n.languages[ String.locale ] || $.i18n.languages[ 'default' ];
|
|
};
|
|
|
|
MessageParserEmitter.prototype = {
|
|
constructor: MessageParserEmitter,
|
|
|
|
/**
|
|
* (We put this method definition here, and not in prototype, to make
|
|
* sure it's not overwritten by any magic.) Walk entire node structure,
|
|
* applying replacements and template functions when appropriate
|
|
*
|
|
* @param {Mixed} node abstract syntax tree (top node or subnode)
|
|
* @param {Array} replacements for $1, $2, ... $n
|
|
* @return {Mixed} single-string node or array of nodes suitable for
|
|
* jQuery appending.
|
|
*/
|
|
emit: function ( node, replacements ) {
|
|
var ret, subnodes, operation,
|
|
messageParserEmitter = this;
|
|
|
|
switch ( typeof node ) {
|
|
case 'string':
|
|
case 'number':
|
|
ret = node;
|
|
break;
|
|
case 'object':
|
|
// node is an array of nodes
|
|
subnodes = $.map( node.slice( 1 ), function ( n ) {
|
|
return messageParserEmitter.emit( n, replacements );
|
|
} );
|
|
|
|
operation = node[ 0 ].toLowerCase();
|
|
|
|
if ( typeof messageParserEmitter[ operation ] === 'function' ) {
|
|
ret = messageParserEmitter[ operation ]( subnodes, replacements );
|
|
} else {
|
|
throw new Error( 'unknown operation "' + operation + '"' );
|
|
}
|
|
|
|
break;
|
|
case 'undefined':
|
|
// Parsing the empty string (as an entire expression, or as a
|
|
// paramExpression in a template) results in undefined
|
|
// Perhaps a more clever parser can detect this, and return the
|
|
// empty string? Or is that useful information?
|
|
// The logical thing is probably to return the empty string here
|
|
// when we encounter undefined.
|
|
ret = '';
|
|
break;
|
|
default:
|
|
throw new Error( 'unexpected type in AST: ' + typeof node );
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
|
|
/**
|
|
* Parsing has been applied depth-first we can assume that all nodes
|
|
* here are single nodes Must return a single node to parents -- a
|
|
* jQuery with synthetic span However, unwrap any other synthetic spans
|
|
* in our children and pass them upwards
|
|
*
|
|
* @param {Array} nodes Mixed, some single nodes, some arrays of nodes.
|
|
* @return {string}
|
|
*/
|
|
concat: function ( nodes ) {
|
|
var result = '';
|
|
|
|
$.each( nodes, function ( i, node ) {
|
|
// strings, integers, anything else
|
|
result += node;
|
|
} );
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Return escaped replacement of correct index, or string if
|
|
* unavailable. Note that we expect the parsed parameter to be
|
|
* zero-based. i.e. $1 should have become [ 0 ]. if the specified
|
|
* parameter is not found return the same string (e.g. "$99" ->
|
|
* parameter 98 -> not found -> return "$99" ) TODO throw error if
|
|
* nodes.length > 1 ?
|
|
*
|
|
* @param {Array} nodes One element, integer, n >= 0
|
|
* @param {Array} replacements for $1, $2, ... $n
|
|
* @return {string} replacement
|
|
*/
|
|
replace: function ( nodes, replacements ) {
|
|
var index = parseInt( nodes[ 0 ], 10 );
|
|
|
|
if ( index < replacements.length ) {
|
|
// replacement is not a string, don't touch!
|
|
return replacements[ index ];
|
|
} else {
|
|
// index not found, fallback to displaying variable
|
|
return '$' + ( index + 1 );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Transform parsed structure into pluralization n.b. The first node may
|
|
* be a non-integer (for instance, a string representing an Arabic
|
|
* number). So convert it back with the current language's
|
|
* convertNumber.
|
|
*
|
|
* @param {Array} nodes List [ {String|Number}, {String}, {String} ... ]
|
|
* @return {string} selected pluralized form according to current
|
|
* language.
|
|
*/
|
|
plural: function ( nodes ) {
|
|
var count = parseFloat( this.language.convertNumber( nodes[ 0 ], 10 ) ),
|
|
forms = nodes.slice( 1 );
|
|
|
|
return forms.length ? this.language.convertPlural( count, forms ) : '';
|
|
},
|
|
|
|
/**
|
|
* Transform parsed structure into gender Usage
|
|
* {{gender:gender|masculine|feminine|neutral}}.
|
|
*
|
|
* @param {Array} nodes List [ {String}, {String}, {String} , {String} ]
|
|
* @return {string} selected gender form according to current language
|
|
*/
|
|
gender: function ( nodes ) {
|
|
var gender = nodes[ 0 ],
|
|
forms = nodes.slice( 1 );
|
|
|
|
return this.language.gender( gender, forms );
|
|
},
|
|
|
|
/**
|
|
* Transform parsed structure into grammar conversion. Invoked by
|
|
* putting {{grammar:form|word}} in a message
|
|
*
|
|
* @param {Array} nodes List [{Grammar case eg: genitive}, {String word}]
|
|
* @return {string} selected grammatical form according to current
|
|
* language.
|
|
*/
|
|
grammar: function ( nodes ) {
|
|
var form = nodes[ 0 ],
|
|
word = nodes[ 1 ];
|
|
|
|
return word && form && this.language.convertGrammar( word, form );
|
|
}
|
|
};
|
|
|
|
$.extend( $.i18n.parser.emitter, new MessageParserEmitter() );
|
|
}( jQuery ) );
|