Update jquery.i18n to 1.07 and fix non-English plural support (#2717)

* 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.
This commit is contained in:
Tom Morris 2020-06-14 04:23:23 -04:00 committed by GitHub
parent 683c00f535
commit 03c860d961
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 2869 additions and 34 deletions

View File

@ -345,16 +345,22 @@ function init() {
"externals/jquery.cookie.js",
"externals/jquery-ui/jquery-ui-1.10.3.custom.js",
"externals/date.js",
"externals/CLDRPluralRuleParser.js",
"externals/jquery.i18n.js",
"externals/jquery.i18n.messagestore.js",
"externals/jquery.i18n.fallbacks.js",
"externals/jquery.i18n.parser.js",
"externals/jquery.i18n.emitter.js",
"externals/jquery.i18n.language.js",
"externals/languages/fi.js",
"externals/languages/ru.js",
"externals/tablesorter/jquery.tablesorter.min.js",
"externals/moment-with-locales.min.js",
"externals/select2/select2.min.js",
"externals/jquery.lavalamp.min.js",
"externals/jquery.i18n.messagestore.js",
"externals/jquery.i18n.emitter.js",
"externals/jquery.i18n.parser.js",
"externals/jquery.i18n.emitter.js",
"externals/jquery.i18n.language.js",
"scripts/util/misc.js",
"scripts/util/url.js",
@ -550,11 +556,17 @@ function init() {
"externals/jquery-ui/jquery-ui-1.10.3.custom.js",
"externals/imgareaselect/jquery.imgareaselect.js",
"externals/date.js",
"externals/CLDRPluralRuleParser.js",
"externals/jquery.i18n.js",
"externals/jquery.i18n.messagestore.js",
"externals/jquery.i18n.fallbacks.js",
"externals/jquery.i18n.parser.js",
"externals/jquery.i18n.emitter.js",
"externals/jquery.i18n.language.js",
"externals/languages/fi.js",
"externals/languages/ru.js",
"externals/underscore-min.js",
"scripts/preferences.js",
]

View File

@ -0,0 +1,607 @@
/**
* cldrpluralparser.js
* A parser engine for CLDR plural rules.
*
* Copyright 2012-2014 Santhosh Thottingal and other contributors
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
* @source https://github.com/santhoshtr/CLDRPluralRuleParser
* @author Santhosh Thottingal <santhosh.thottingal@gmail.com>
* @author Timo Tijhof
* @author Amir Aharoni
*/
/**
* Evaluates a plural rule in CLDR syntax for a number
* @param {string} rule
* @param {integer} number
* @return {boolean} true if evaluation passed, false if evaluation failed.
*/
// UMD returnExports https://github.com/umdjs/umd/blob/master/returnExports.js
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.pluralRuleParser = factory();
}
}(this, function() {
function pluralRuleParser(rule, number) {
'use strict';
/*
Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules
-----------------------------------------------------------------
condition = and_condition ('or' and_condition)*
('@integer' samples)?
('@decimal' samples)?
and_condition = relation ('and' relation)*
relation = is_relation | in_relation | within_relation
is_relation = expr 'is' ('not')? value
in_relation = expr (('not')? 'in' | '=' | '!=') range_list
within_relation = expr ('not')? 'within' range_list
expr = operand (('mod' | '%') value)?
operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
range_list = (range | value) (',' range_list)*
value = digit+
digit = 0|1|2|3|4|5|6|7|8|9
range = value'..'value
samples = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
sampleRange = decimalValue '~' decimalValue
decimalValue = value ('.' value)?
*/
// We don't evaluate the samples section of the rule. Ignore it.
rule = rule.split('@')[0].replace(/^\s*/, '').replace(/\s*$/, '');
if (!rule.length) {
// Empty rule or 'other' rule.
return true;
}
// Indicates the current position in the rule as we parse through it.
// Shared among all parsing functions below.
var pos = 0,
operand,
expression,
relation,
result,
whitespace = makeRegexParser(/^\s+/),
value = makeRegexParser(/^\d+/),
_n_ = makeStringParser('n'),
_i_ = makeStringParser('i'),
_f_ = makeStringParser('f'),
_t_ = makeStringParser('t'),
_v_ = makeStringParser('v'),
_w_ = makeStringParser('w'),
_is_ = makeStringParser('is'),
_isnot_ = makeStringParser('is not'),
_isnot_sign_ = makeStringParser('!='),
_equal_ = makeStringParser('='),
_mod_ = makeStringParser('mod'),
_percent_ = makeStringParser('%'),
_not_ = makeStringParser('not'),
_in_ = makeStringParser('in'),
_within_ = makeStringParser('within'),
_range_ = makeStringParser('..'),
_comma_ = makeStringParser(','),
_or_ = makeStringParser('or'),
_and_ = makeStringParser('and');
function debug() {
// console.log.apply(console, arguments);
}
debug('pluralRuleParser', rule, number);
// Try parsers until one works, if none work return null
function choice(parserSyntax) {
return function() {
var i, result;
for (i = 0; i < parserSyntax.length; i++) {
result = parserSyntax[i]();
if (result !== null) {
return result;
}
}
return null;
};
}
// Try several parserSyntax-es in a row.
// All must succeed; otherwise, return null.
// This is the only eager one.
function sequence(parserSyntax) {
var i, parserRes,
originalPos = pos,
result = [];
for (i = 0; i < parserSyntax.length; i++) {
parserRes = parserSyntax[i]();
if (parserRes === null) {
pos = originalPos;
return null;
}
result.push(parserRes);
}
return result;
}
// Run the same parser over and over until it fails.
// Must succeed a minimum of n times; otherwise, return null.
function nOrMore(n, p) {
return function() {
var originalPos = pos,
result = [],
parsed = p();
while (parsed !== null) {
result.push(parsed);
parsed = p();
}
if (result.length < n) {
pos = originalPos;
return null;
}
return result;
};
}
// Helpers - just make parserSyntax out of simpler JS builtin types
function makeStringParser(s) {
var len = s.length;
return function() {
var result = null;
if (rule.substr(pos, len) === s) {
result = s;
pos += len;
}
return result;
};
}
function makeRegexParser(regex) {
return function() {
var matches = rule.substr(pos).match(regex);
if (matches === null) {
return null;
}
pos += matches[0].length;
return matches[0];
};
}
/**
* Integer digits of n.
*/
function i() {
var result = _i_();
if (result === null) {
debug(' -- failed i', parseInt(number, 10));
return result;
}
result = parseInt(number, 10);
debug(' -- passed i ', result);
return result;
}
/**
* Absolute value of the source number (integer and decimals).
*/
function n() {
var result = _n_();
if (result === null) {
debug(' -- failed n ', number);
return result;
}
result = parseFloat(number, 10);
debug(' -- passed n ', result);
return result;
}
/**
* Visible fractional digits in n, with trailing zeros.
*/
function f() {
var result = _f_();
if (result === null) {
debug(' -- failed f ', number);
return result;
}
result = (number + '.').split('.')[1] || 0;
debug(' -- passed f ', result);
return result;
}
/**
* Visible fractional digits in n, without trailing zeros.
*/
function t() {
var result = _t_();
if (result === null) {
debug(' -- failed t ', number);
return result;
}
result = (number + '.').split('.')[1].replace(/0$/, '') || 0;
debug(' -- passed t ', result);
return result;
}
/**
* Number of visible fraction digits in n, with trailing zeros.
*/
function v() {
var result = _v_();
if (result === null) {
debug(' -- failed v ', number);
return result;
}
result = (number + '.').split('.')[1].length || 0;
debug(' -- passed v ', result);
return result;
}
/**
* Number of visible fraction digits in n, without trailing zeros.
*/
function w() {
var result = _w_();
if (result === null) {
debug(' -- failed w ', number);
return result;
}
result = (number + '.').split('.')[1].replace(/0$/, '').length || 0;
debug(' -- passed w ', result);
return result;
}
// operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
operand = choice([n, i, f, t, v, w]);
// expr = operand (('mod' | '%') value)?
expression = choice([mod, operand]);
function mod() {
var result = sequence(
[operand, whitespace, choice([_mod_, _percent_]), whitespace, value]
);
if (result === null) {
debug(' -- failed mod');
return null;
}
debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10));
return parseFloat(result[0]) % parseInt(result[4], 10);
}
function not() {
var result = sequence([whitespace, _not_]);
if (result === null) {
debug(' -- failed not');
return null;
}
return result[1];
}
// is_relation = expr 'is' ('not')? value
function is() {
var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]);
if (result !== null) {
debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10));
return result[0] === parseInt(result[4], 10);
}
debug(' -- failed is');
return null;
}
// is_relation = expr 'is' ('not')? value
function isnot() {
var result = sequence(
[expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]
);
if (result !== null) {
debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10));
return result[0] !== parseInt(result[4], 10);
}
debug(' -- failed isnot');
return null;
}
function not_in() {
var i, range_list,
result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]);
if (result !== null) {
debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]);
range_list = result[4];
for (i = 0; i < range_list.length; i++) {
if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
return false;
}
}
return true;
}
debug(' -- failed not_in');
return null;
}
// range_list = (range | value) (',' range_list)*
function rangeList() {
var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]),
resultList = [];
if (result !== null) {
resultList = resultList.concat(result[0]);
if (result[1][0]) {
resultList = resultList.concat(result[1][0]);
}
return resultList;
}
debug(' -- failed rangeList');
return null;
}
function rangeTail() {
// ',' range_list
var result = sequence([_comma_, rangeList]);
if (result !== null) {
return result[1];
}
debug(' -- failed rangeTail');
return null;
}
// range = value'..'value
function range() {
var i, array, left, right,
result = sequence([value, _range_, value]);
if (result !== null) {
debug(' -- passed range');
array = [];
left = parseInt(result[0], 10);
right = parseInt(result[2], 10);
for (i = left; i <= right; i++) {
array.push(i);
}
return array;
}
debug(' -- failed range');
return null;
}
function _in() {
var result, range_list, i;
// in_relation = expr ('not')? 'in' range_list
result = sequence(
[expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]
);
if (result !== null) {
debug(' -- passed _in:' + result);
range_list = result[5];
for (i = 0; i < range_list.length; i++) {
if (parseInt(range_list[i], 10) === parseFloat(result[0])) {
return (result[1][0] !== 'not');
}
}
return (result[1][0] === 'not');
}
debug(' -- failed _in ');
return null;
}
/**
* The difference between "in" and "within" is that
* "in" only includes integers in the specified range,
* while "within" includes all values.
*/
function within() {
var range_list, result;
// within_relation = expr ('not')? 'within' range_list
result = sequence(
[expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]
);
if (result !== null) {
debug(' -- passed within');
range_list = result[5];
if ((result[0] >= parseInt(range_list[0], 10)) &&
(result[0] < parseInt(range_list[range_list.length - 1], 10))) {
return (result[1][0] !== 'not');
}
return (result[1][0] === 'not');
}
debug(' -- failed within ');
return null;
}
// relation = is_relation | in_relation | within_relation
relation = choice([is, not_in, isnot, _in, within]);
// and_condition = relation ('and' relation)*
function and() {
var i,
result = sequence([relation, nOrMore(0, andTail)]);
if (result) {
if (!result[0]) {
return false;
}
for (i = 0; i < result[1].length; i++) {
if (!result[1][i]) {
return false;
}
}
return true;
}
debug(' -- failed and');
return null;
}
// ('and' relation)*
function andTail() {
var result = sequence([whitespace, _and_, whitespace, relation]);
if (result !== null) {
debug(' -- passed andTail' + result);
return result[3];
}
debug(' -- failed andTail');
return null;
}
// ('or' and_condition)*
function orTail() {
var result = sequence([whitespace, _or_, whitespace, and]);
if (result !== null) {
debug(' -- passed orTail: ' + result[3]);
return result[3];
}
debug(' -- failed orTail');
return null;
}
// condition = and_condition ('or' and_condition)*
function condition() {
var i,
result = sequence([and, nOrMore(0, orTail)]);
if (result) {
for (i = 0; i < result[1].length; i++) {
if (result[1][i]) {
return true;
}
}
return result[0];
}
return false;
}
result = condition();
/**
* For success, the pos must have gotten to the end of the rule
* and returned a non-null.
* n.b. This is part of language infrastructure,
* so we do not throw an internationalizable message.
*/
if (result === null) {
throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule);
}
if (pos !== rule.length) {
debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule);
}
return result;
}
return pluralRuleParser;
}));

File diff suppressed because one or more lines are too long

View File

@ -1 +1,168 @@
!function(e){"use strict";var n=function(){this.language=e.i18n.languages[String.locale]||e.i18n.languages.default};n.prototype={constructor:n,emit:function(n,r){var t,a,u,i=this;switch(typeof n){case"string":case"number":t=n;break;case"object":if(a=e.map(n.slice(1),function(e){return i.emit(e,r)}),u=n[0].toLowerCase(),"function"!=typeof i[u])throw new Error('unknown operation "'+u+'"');t=i[u](a,r);break;case"undefined":t="";break;default:throw new Error("unexpected type in AST: "+typeof n)}return t},concat:function(n){var r="";return e.each(n,function(e,n){r+=n}),r},replace:function(e,n){var r=parseInt(e[0],10);return r<n.length?n[r]:"$"+(r+1)},plural:function(e){var n=parseFloat(this.language.convertNumber(e[0],10)),r=e.slice(1);return r.length?this.language.convertPlural(n,r):""},gender:function(e){var n=e[0],r=e.slice(1);return this.language.gender(n,r)},grammar:function(e){var n=e[0],r=e[1];return r&&n&&this.language.convertGrammar(r,n)}},e.extend(e.i18n.parser.emitter,new n)}(jQuery);
/*!
* 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 ) );

View File

@ -0,0 +1,186 @@
/*!
* jQuery Internationalization library
*
* Copyright (C) 2012 Santhosh Thottingal
*
* 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';
$.i18n = $.i18n || {};
$.extend( $.i18n.fallbacks, {
ab: [ 'ru' ],
ace: [ 'id' ],
aln: [ 'sq' ],
// Not so standard - als is supposed to be Tosk Albanian,
// but in Wikipedia it's used for a Germanic language.
als: [ 'gsw', 'de' ],
an: [ 'es' ],
anp: [ 'hi' ],
arn: [ 'es' ],
arz: [ 'ar' ],
av: [ 'ru' ],
ay: [ 'es' ],
ba: [ 'ru' ],
bar: [ 'de' ],
'bat-smg': [ 'sgs', 'lt' ],
bcc: [ 'fa' ],
'be-x-old': [ 'be-tarask' ],
bh: [ 'bho' ],
bjn: [ 'id' ],
bm: [ 'fr' ],
bpy: [ 'bn' ],
bqi: [ 'fa' ],
bug: [ 'id' ],
'cbk-zam': [ 'es' ],
ce: [ 'ru' ],
crh: [ 'crh-latn' ],
'crh-cyrl': [ 'ru' ],
csb: [ 'pl' ],
cv: [ 'ru' ],
'de-at': [ 'de' ],
'de-ch': [ 'de' ],
'de-formal': [ 'de' ],
dsb: [ 'de' ],
dtp: [ 'ms' ],
egl: [ 'it' ],
eml: [ 'it' ],
ff: [ 'fr' ],
fit: [ 'fi' ],
'fiu-vro': [ 'vro', 'et' ],
frc: [ 'fr' ],
frp: [ 'fr' ],
frr: [ 'de' ],
fur: [ 'it' ],
gag: [ 'tr' ],
gan: [ 'gan-hant', 'zh-hant', 'zh-hans' ],
'gan-hans': [ 'zh-hans' ],
'gan-hant': [ 'zh-hant', 'zh-hans' ],
gl: [ 'pt' ],
glk: [ 'fa' ],
gn: [ 'es' ],
gsw: [ 'de' ],
hif: [ 'hif-latn' ],
hsb: [ 'de' ],
ht: [ 'fr' ],
ii: [ 'zh-cn', 'zh-hans' ],
inh: [ 'ru' ],
iu: [ 'ike-cans' ],
jut: [ 'da' ],
jv: [ 'id' ],
kaa: [ 'kk-latn', 'kk-cyrl' ],
kbd: [ 'kbd-cyrl' ],
khw: [ 'ur' ],
kiu: [ 'tr' ],
kk: [ 'kk-cyrl' ],
'kk-arab': [ 'kk-cyrl' ],
'kk-latn': [ 'kk-cyrl' ],
'kk-cn': [ 'kk-arab', 'kk-cyrl' ],
'kk-kz': [ 'kk-cyrl' ],
'kk-tr': [ 'kk-latn', 'kk-cyrl' ],
kl: [ 'da' ],
'ko-kp': [ 'ko' ],
koi: [ 'ru' ],
krc: [ 'ru' ],
ks: [ 'ks-arab' ],
ksh: [ 'de' ],
ku: [ 'ku-latn' ],
'ku-arab': [ 'ckb' ],
kv: [ 'ru' ],
lad: [ 'es' ],
lb: [ 'de' ],
lbe: [ 'ru' ],
lez: [ 'ru' ],
li: [ 'nl' ],
lij: [ 'it' ],
liv: [ 'et' ],
lmo: [ 'it' ],
ln: [ 'fr' ],
ltg: [ 'lv' ],
lzz: [ 'tr' ],
mai: [ 'hi' ],
'map-bms': [ 'jv', 'id' ],
mg: [ 'fr' ],
mhr: [ 'ru' ],
min: [ 'id' ],
mo: [ 'ro' ],
mrj: [ 'ru' ],
mwl: [ 'pt' ],
myv: [ 'ru' ],
mzn: [ 'fa' ],
nah: [ 'es' ],
nap: [ 'it' ],
nds: [ 'de' ],
'nds-nl': [ 'nl' ],
'nl-informal': [ 'nl' ],
no: [ 'nb' ],
os: [ 'ru' ],
pcd: [ 'fr' ],
pdc: [ 'de' ],
pdt: [ 'de' ],
pfl: [ 'de' ],
pms: [ 'it' ],
pt: [ 'pt-br' ],
'pt-br': [ 'pt' ],
qu: [ 'es' ],
qug: [ 'qu', 'es' ],
rgn: [ 'it' ],
rmy: [ 'ro' ],
'roa-rup': [ 'rup' ],
rue: [ 'uk', 'ru' ],
ruq: [ 'ruq-latn', 'ro' ],
'ruq-cyrl': [ 'mk' ],
'ruq-latn': [ 'ro' ],
sa: [ 'hi' ],
sah: [ 'ru' ],
scn: [ 'it' ],
sg: [ 'fr' ],
sgs: [ 'lt' ],
sli: [ 'de' ],
sr: [ 'sr-ec' ],
srn: [ 'nl' ],
stq: [ 'de' ],
su: [ 'id' ],
szl: [ 'pl' ],
tcy: [ 'kn' ],
tg: [ 'tg-cyrl' ],
tt: [ 'tt-cyrl', 'ru' ],
'tt-cyrl': [ 'ru' ],
ty: [ 'fr' ],
udm: [ 'ru' ],
ug: [ 'ug-arab' ],
uk: [ 'ru' ],
vec: [ 'it' ],
vep: [ 'et' ],
vls: [ 'nl' ],
vmf: [ 'de' ],
vot: [ 'fi' ],
vro: [ 'et' ],
wa: [ 'fr' ],
wo: [ 'fr' ],
wuu: [ 'zh-hans' ],
xal: [ 'ru' ],
xmf: [ 'ka' ],
yi: [ 'he' ],
za: [ 'zh-hans' ],
zea: [ 'nl' ],
zh: [ 'zh-hans' ],
'zh-classical': [ 'lzh' ],
'zh-cn': [ 'zh-hans' ],
'zh-hant': [ 'zh-hans' ],
'zh-hk': [ 'zh-hant', 'zh-hans' ],
'zh-min-nan': [ 'nan' ],
'zh-mo': [ 'zh-hk', 'zh-hant', 'zh-hans' ],
'zh-my': [ 'zh-sg', 'zh-hans' ],
'zh-sg': [ 'zh-hans' ],
'zh-tw': [ 'zh-hant', 'zh-hans' ],
'zh-yue': [ 'yue' ]
} );
}( jQuery ) );

View File

@ -1,4 +1,290 @@
/* jQuery Internationalization library 1.0.4
/*!
* jQuery Internationalization library
*
* Copyright (C) 2012 Santhosh Thottingal
* Dual licensed GPLv2 or later and MIT. */
!function(e){"use strict";var n,a,o=Array.prototype.slice;(a=function(n){this.options=e.extend({},a.defaults,n),this.parser=this.options.parser,this.locale=this.options.locale,this.messageStore=this.options.messageStore,this.languages={},this.init()}).prototype={init:function(){var n=this;String.locale=n.locale,String.prototype.toLocaleString=function(){var a,o,t,i,l,r,s;for(t=this.valueOf(),i=n.locale,l=0;i;){o=(a=i.split("-")).length;do{if(r=a.slice(0,o).join("-"),s=n.messageStore.get(r,t))return s;o--}while(o);if("en"===i)break;i=e.i18n.fallbacks[n.locale]&&e.i18n.fallbacks[n.locale][l]||n.options.fallbackLocale,e.i18n.log("Trying fallback locale for "+n.locale+": "+i),l++}return""}},destroy:function(){e.removeData(document,"i18n")},load:function(n,a){var o,t,i,l={};if(n||a||(n="i18n/"+e.i18n().locale+".json",a=e.i18n().locale),"string"==typeof n&&"json"!==n.split(".").pop()){l[a]=n+"/"+a+".json",o=(e.i18n.fallbacks[a]||[]).concat(this.options.fallbackLocale);for(t in o)l[i=o[t]]=n+"/"+i+".json";return this.load(l)}return this.messageStore.load(n,a)},parse:function(n,a){var o=n.toLocaleString();return this.parser.language=e.i18n.languages[e.i18n().locale]||e.i18n.languages.default,""===o&&(o=n),this.parser.parse(o,a)}},e.i18n=function(n,t){var i,l=e.data(document,"i18n"),r="object"==typeof n&&n;return r&&r.locale&&l&&l.locale!==r.locale&&(String.locale=l.locale=r.locale),l||(l=new a(r),e.data(document,"i18n",l)),"string"==typeof n?(i=void 0!==t?o.call(arguments,1):[],l.parse(n,i)):l},e.fn.i18n=function(){var n=e.data(document,"i18n");return n||(n=new a,e.data(document,"i18n",n)),String.locale=n.locale,this.each(function(){var a=e(this),o=a.data("i18n");o?a.text(n.parse(o)):a.find("[data-i18n]").i18n()})},String.locale=String.locale||e("html").attr("lang"),String.locale||(void 0!==typeof window.navigator?(n=window.navigator,String.locale=n.language||n.userLanguage||""):String.locale=""),e.i18n.languages={},e.i18n.messageStore=e.i18n.messageStore||{},e.i18n.parser={parse:function(e,n){return e.replace(/\$(\d+)/g,function(e,a){var o=parseInt(a,10)-1;return void 0!==n[o]?n[o]:"$"+a})},emitter:{}},e.i18n.fallbacks={},e.i18n.debug=!1,e.i18n.log=function(){window.console&&e.i18n.debug&&window.console.log.apply(window.console,arguments)},a.defaults={locale:String.locale,fallbackLocale:"en",parser:e.i18n.parser,messageStore:e.i18n.messageStore},e.i18n.constructor=a}(jQuery);
*
* 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 I18N,
slice = Array.prototype.slice;
/**
* @constructor
* @param {Object} options
*/
I18N = function ( options ) {
// Load defaults
this.options = $.extend( {}, I18N.defaults, options );
this.parser = this.options.parser;
this.locale = this.options.locale;
this.messageStore = this.options.messageStore;
this.languages = {};
};
I18N.prototype = {
/**
* Localize a given messageKey to a locale.
* @param {string} messageKey
* @return {string} Localized message
*/
localize: function ( messageKey ) {
var localeParts, localePartIndex, locale, fallbackIndex,
tryingLocale, message;
locale = this.locale;
fallbackIndex = 0;
while ( locale ) {
// Iterate through locales starting at most-specific until
// localization is found. As in fi-Latn-FI, fi-Latn and fi.
localeParts = locale.split( '-' );
localePartIndex = localeParts.length;
do {
tryingLocale = localeParts.slice( 0, localePartIndex ).join( '-' );
message = this.messageStore.get( tryingLocale, messageKey );
if ( message ) {
return message;
}
localePartIndex--;
} while ( localePartIndex );
if ( locale === this.options.fallbackLocale ) {
break;
}
locale = ( $.i18n.fallbacks[ this.locale ] &&
$.i18n.fallbacks[ this.locale ][ fallbackIndex ] ) ||
this.options.fallbackLocale;
$.i18n.log( 'Trying fallback locale for ' + this.locale + ': ' + locale + ' (' + messageKey + ')' );
fallbackIndex++;
}
// key not found
return '';
},
/*
* Destroy the i18n instance.
*/
destroy: function () {
$.removeData( document, 'i18n' );
},
/**
* General message loading API This can take a URL string for
* the json formatted messages. Example:
* <code>load('path/to/all_localizations.json');</code>
*
* To load a localization file for a locale:
* <code>
* load('path/to/de-messages.json', 'de' );
* </code>
*
* To load a localization file from a directory:
* <code>
* load('path/to/i18n/directory', 'de' );
* </code>
* The above method has the advantage of fallback resolution.
* ie, it will automatically load the fallback locales for de.
* For most usecases, this is the recommended method.
* It is optional to have trailing slash at end.
*
* A data object containing message key- message translation mappings
* can also be passed. Example:
* <code>
* load( { 'hello' : 'Hello' }, optionalLocale );
* </code>
*
* A source map containing key-value pair of languagename and locations
* can also be passed. Example:
* <code>
* load( {
* bn: 'i18n/bn.json',
* he: 'i18n/he.json',
* en: 'i18n/en.json'
* } )
* </code>
*
* If the data argument is null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
* @param {string|Object} source
* @param {string} locale Language tag
* @return {jQuery.Promise}
*/
load: function ( source, locale ) {
var fallbackLocales, locIndex, fallbackLocale, sourceMap = {};
if ( !source && !locale ) {
source = 'i18n/' + $.i18n().locale + '.json';
locale = $.i18n().locale;
}
if ( typeof source === 'string' &&
// source extension should be json, but can have query params after that.
source.split( '?' )[ 0 ].split( '.' ).pop() !== 'json'
) {
// Load specified locale then check for fallbacks when directory is
// specified in load()
sourceMap[ locale ] = source + '/' + locale + '.json';
fallbackLocales = ( $.i18n.fallbacks[ locale ] || [] )
.concat( this.options.fallbackLocale );
for ( locIndex = 0; locIndex < fallbackLocales.length; locIndex++ ) {
fallbackLocale = fallbackLocales[ locIndex ];
sourceMap[ fallbackLocale ] = source + '/' + fallbackLocale + '.json';
}
return this.load( sourceMap );
} else {
return this.messageStore.load( source, locale );
}
},
/**
* Does parameter and magic word substitution.
*
* @param {string} key Message key
* @param {Array} parameters Message parameters
* @return {string}
*/
parse: function ( key, parameters ) {
var message = this.localize( key );
// FIXME: This changes the state of the I18N object,
// should probably not change the 'this.parser' but just
// pass it to the parser.
this.parser.language = $.i18n.languages[ $.i18n().locale ] || $.i18n.languages[ 'default' ];
if ( message === '' ) {
message = key;
}
return this.parser.parse( message, parameters );
}
};
/**
* Process a message from the $.I18N instance
* for the current document, stored in jQuery.data(document).
*
* @param {string} key Key of the message.
* @param {string} param1 [param...] Variadic list of parameters for {key}.
* @return {string|$.I18N} Parsed message, or if no key was given
* the instance of $.I18N is returned.
*/
$.i18n = function ( key, param1 ) {
var parameters,
i18n = $.data( document, 'i18n' ),
options = typeof key === 'object' && key;
// If the locale option for this call is different then the setup so far,
// update it automatically. This doesn't just change the context for this
// call but for all future call as well.
// If there is no i18n setup yet, don't do this. It will be taken care of
// by the `new I18N` construction below.
// NOTE: It should only change language for this one call.
// Then cache instances of I18N somewhere.
if ( options && options.locale && i18n && i18n.locale !== options.locale ) {
i18n.locale = options.locale;
}
if ( !i18n ) {
i18n = new I18N( options );
$.data( document, 'i18n', i18n );
}
if ( typeof key === 'string' ) {
if ( param1 !== undefined ) {
parameters = slice.call( arguments, 1 );
} else {
parameters = [];
}
return i18n.parse( key, parameters );
} else {
// FIXME: remove this feature/bug.
return i18n;
}
};
$.fn.i18n = function () {
var i18n = $.data( document, 'i18n' );
if ( !i18n ) {
i18n = new I18N();
$.data( document, 'i18n', i18n );
}
return this.each( function () {
var $this = $( this ),
messageKey = $this.data( 'i18n' ),
lBracket, rBracket, type, key;
if ( messageKey ) {
lBracket = messageKey.indexOf( '[' );
rBracket = messageKey.indexOf( ']' );
if ( lBracket !== -1 && rBracket !== -1 && lBracket < rBracket ) {
type = messageKey.slice( lBracket + 1, rBracket );
key = messageKey.slice( rBracket + 1 );
if ( type === 'html' ) {
$this.html( i18n.parse( key ) );
} else {
$this.attr( type, i18n.parse( key ) );
}
} else {
$this.text( i18n.parse( messageKey ) );
}
} else {
$this.find( '[data-i18n]' ).i18n();
}
} );
};
function getDefaultLocale() {
var locale = $( 'html' ).attr( 'lang' );
if ( !locale ) {
locale = navigator.language || navigator.userLanguage || '';
}
return locale;
}
$.i18n.languages = {};
$.i18n.messageStore = $.i18n.messageStore || {};
$.i18n.parser = {
// The default parser only handles variable substitution
parse: function ( message, parameters ) {
return message.replace( /\$(\d+)/g, function ( str, match ) {
var index = parseInt( match, 10 ) - 1;
return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
} );
},
emitter: {}
};
$.i18n.fallbacks = {};
$.i18n.debug = false;
$.i18n.log = function ( /* arguments */ ) {
if ( window.console && $.i18n.debug ) {
window.console.log.apply( window.console, arguments );
}
};
/* Static members */
I18N.defaults = {
locale: getDefaultLocale(),
fallbackLocale: 'en',
parser: $.i18n.parser,
messageStore: $.i18n.messageStore
};
// Expose constructor
$.i18n.constructor = I18N;
}( jQuery ) );

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,123 @@
/* jQuery Internationalization library 1.0.4
/*!
* jQuery Internationalization library - Message Store
*
* Copyright (C) 2012 Santhosh Thottingal
* Dual licensed GPLv2 or later and MIT. */
!function(e,s,t){"use strict";function n(s){var t=e.Deferred();return e.getJSON(s).done(t.resolve).fail(function(n,r,o){e.i18n.log("Error in loading messages from "+s+" Exception: "+o),t.resolve()}),t.promise()}var r=function(){this.messages={},this.sources={}};r.prototype={load:function(s,t){var r=null,o=[],i=this;if("string"==typeof s)return e.i18n.log("Loading messages from: "+s),n(s).done(function(e){i.set(t,e)}).promise();if(t)return i.set(t,s),e.Deferred().resolve();for(r in s)Object.prototype.hasOwnProperty.call(s,r)&&(t=r,o.push(i.load(s[r],t)));return e.when.apply(e,o)},set:function(s,t){this.messages[s]?this.messages[s]=e.extend(this.messages[s],t):this.messages[s]=t},get:function(e,s){return this.messages[e]&&this.messages[e][s]}},e.extend(e.i18n.messageStore,new r)}(jQuery,window);
*
* 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 MessageStore = function () {
this.messages = {};
this.sources = {};
};
function jsonMessageLoader( url ) {
var deferred = $.Deferred();
$.getJSON( url )
.done( deferred.resolve )
.fail( function ( jqxhr, settings, exception ) {
$.i18n.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
// Ignore 404 exception, because we are handling fallabacks explicitly
deferred.resolve();
} );
return deferred.promise();
}
/**
* See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
*/
MessageStore.prototype = {
/**
* General message loading API This can take a URL string for
* the json formatted messages.
* <code>load('path/to/all_localizations.json');</code>
*
* This can also load a localization file for a locale <code>
* load( 'path/to/de-messages.json', 'de' );
* </code>
* A data object containing message key- message translation mappings
* can also be passed Eg:
* <code>
* load( { 'hello' : 'Hello' }, optionalLocale );
* </code> If the data argument is
* null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
* @param {string|Object} source
* @param {string} locale Language tag
* @return {jQuery.Promise}
*/
load: function ( source, locale ) {
var key = null,
deferreds = [],
messageStore = this;
if ( typeof source === 'string' ) {
// This is a URL to the messages file.
$.i18n.log( 'Loading messages from: ' + source );
return jsonMessageLoader( source )
.then( function ( localization ) {
return messageStore.load( localization, locale );
} );
}
if ( locale ) {
// source is an key-value pair of messages for given locale
messageStore.set( locale, source );
return $.Deferred().resolve();
} else {
// source is a key-value pair of locales and their source
for ( key in source ) {
if ( Object.prototype.hasOwnProperty.call( source, key ) ) {
locale = key;
// No {locale} given, assume data is a group of languages,
// call this function again for each language.
deferreds.push( messageStore.load( source[ key ], locale ) );
}
}
return $.when.apply( $, deferreds );
}
},
/**
* Set messages to the given locale.
* If locale exists, add messages to the locale.
*
* @param {string} locale
* @param {Object} messages
*/
set: function ( locale, messages ) {
if ( !this.messages[ locale ] ) {
this.messages[ locale ] = messages;
} else {
this.messages[ locale ] = $.extend( this.messages[ locale ], messages );
}
},
/**
*
* @param {string} locale
* @param {string} messageKey
* @return {boolean}
*/
get: function ( locale, messageKey ) {
return this.messages[ locale ] && this.messages[ locale ][ messageKey ];
}
};
$.extend( $.i18n.messageStore, new MessageStore() );
}( jQuery ) );

View File

@ -1,4 +1,310 @@
/* jQuery Internationalization library 1.0.4
* Copyright (C) 2012 Santhosh Thottingal
* Dual licensed GPLv2 or later and MIT. */
!function(n){"use strict";var r=function(r){this.options=n.extend({},n.i18n.parser.defaults,r),this.language=n.i18n.languages[String.locale]||n.i18n.languages.default,this.emitter=n.i18n.parser.emitter};r.prototype={constructor:r,simpleParse:function(n,r){return n.replace(/\$(\d+)/g,function(n,t){var u=parseInt(t,10)-1;return void 0!==r[u]?r[u]:"$"+t})},parse:function(r,t){return r.indexOf("{{")<0?this.simpleParse(r,t):(this.emitter.language=n.i18n.languages[n.i18n().locale]||n.i18n.languages.default,this.emitter.emit(this.ast(r),t))},ast:function(n){function r(n){return function(){var r,t;for(r=0;r<n.length;r++)if(null!==(t=n[r]()))return t;return null}}function t(n){var r,t,u=F,l=[];for(r=0;r<n.length;r++){if(null===(t=n[r]()))return F=u,null;l.push(t)}return l}function u(n,r){return function(){for(var t=F,u=[],l=r();null!==l;)u.push(l),l=r();return u.length<n?(F=t,null):u}}function l(r){var t=r.length;return function(){var u=null;return n.substr(F,t)===r&&(u=r,F+=t),u}}function e(r){return function(){var t=n.substr(F).match(r);return null===t?null:(F+=t[0].length,t[0])}}function i(){var n=t([h,p]);return null===n?null:n[1]}function a(){var n=t([d,m]);return null===n?null:["REPLACE",parseInt(n[1],10)-1]}function o(){var n,r=t([g,u(0,b)]);return null===r?null:(n=r[1]).length>1?["CONCAT"].concat(n):n[0]}function c(){var n=t([w,v,a]);return null===n?null:[n[0],n[2]]}function f(){var n=t([w,v,b]);return null===n?null:[n[0],n[2]]}function s(){var n=t([E,j,O]);return null===n?null:n[1]}var g,v,h,p,d,m,$,x,C,A,P,j,w,E,O,S,b,y,F=0;if(g=l("|"),v=l(":"),h=l("\\"),p=e(/^./),d=l("$"),m=e(/^\d+/),$=e(/^[^{}\[\]$\\]/),x=e(/^[^{}\[\]$\\|]/),C=e(/^[^{}\[\]$\s]/),r([i,C]),A=r([i,x]),P=r([i,$]),w=function(n,r){return function(){var t=n();return null===t?null:r(t)}}(e(/^[ !"$&'()*,.\/0-9;=?@A-Z\^_`a-z~\x80-\xFF+\-]+/),function(n){return n.toString()}),j=r([function(){var n=t([r([c,f]),u(0,o)]);return null===n?null:n[0].concat(n[1])},function(){var n=t([w,u(0,o)]);return null===n?null:[n[0]].concat(n[1])}]),E=l("{{"),O=l("}}"),S=r([s,a,function(){var n=u(1,P)();return null===n?null:n.join("")}]),b=r([s,a,function(){var n=u(1,A)();return null===n?null:n.join("")}]),null===(y=function(){var n=u(0,S)();return null===n?null:["CONCAT"].concat(n)}())||F!==n.length)throw new Error("Parse error at position "+F.toString()+" in input: "+n);return y}},n.extend(n.i18n.parser,new r)}(jQuery);
/*!
* 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 MessageParser = function ( options ) {
this.options = $.extend( {}, $.i18n.parser.defaults, options );
this.language = $.i18n.languages[ String.locale ] || $.i18n.languages[ 'default' ];
this.emitter = $.i18n.parser.emitter;
};
MessageParser.prototype = {
constructor: MessageParser,
simpleParse: function ( message, parameters ) {
return message.replace( /\$(\d+)/g, function ( str, match ) {
var index = parseInt( match, 10 ) - 1;
return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
} );
},
parse: function ( message, replacements ) {
if ( message.indexOf( '{{' ) < 0 ) {
return this.simpleParse( message, replacements );
}
this.emitter.language = $.i18n.languages[ $.i18n().locale ] ||
$.i18n.languages[ 'default' ];
return this.emitter.emit( this.ast( message ), replacements );
},
ast: function ( message ) {
var pipe, colon, backslash, anyCharacter, dollar, digits, regularLiteral,
regularLiteralWithoutBar, regularLiteralWithoutSpace, escapedOrLiteralWithoutBar,
escapedOrRegularLiteral, templateContents, templateName, openTemplate,
closeTemplate, expression, paramExpression, result,
pos = 0;
// Try parsers until one works, if none work return null
function choice( parserSyntax ) {
return function () {
var i, result;
for ( i = 0; i < parserSyntax.length; i++ ) {
result = parserSyntax[ i ]();
if ( result !== null ) {
return result;
}
}
return null;
};
}
// Try several parserSyntax-es in a row.
// All must succeed; otherwise, return null.
// This is the only eager one.
function sequence( parserSyntax ) {
var i, res,
originalPos = pos,
result = [];
for ( i = 0; i < parserSyntax.length; i++ ) {
res = parserSyntax[ i ]();
if ( res === null ) {
pos = originalPos;
return null;
}
result.push( res );
}
return result;
}
// Run the same parser over and over until it fails.
// Must succeed a minimum of n times; otherwise, return null.
function nOrMore( n, p ) {
return function () {
var originalPos = pos,
result = [],
parsed = p();
while ( parsed !== null ) {
result.push( parsed );
parsed = p();
}
if ( result.length < n ) {
pos = originalPos;
return null;
}
return result;
};
}
// Helpers -- just make parserSyntax out of simpler JS builtin types
function makeStringParser( s ) {
var len = s.length;
return function () {
var result = null;
if ( message.slice( pos, pos + len ) === s ) {
result = s;
pos += len;
}
return result;
};
}
function makeRegexParser( regex ) {
return function () {
var matches = message.slice( pos ).match( regex );
if ( matches === null ) {
return null;
}
pos += matches[ 0 ].length;
return matches[ 0 ];
};
}
pipe = makeStringParser( '|' );
colon = makeStringParser( ':' );
backslash = makeStringParser( '\\' );
anyCharacter = makeRegexParser( /^./ );
dollar = makeStringParser( '$' );
digits = makeRegexParser( /^\d+/ );
regularLiteral = makeRegexParser( /^[^{}[\]$\\]/ );
regularLiteralWithoutBar = makeRegexParser( /^[^{}[\]$\\|]/ );
regularLiteralWithoutSpace = makeRegexParser( /^[^{}[\]$\s]/ );
// There is a general pattern:
// parse a thing;
// if it worked, apply transform,
// otherwise return null.
// But using this as a combinator seems to cause problems
// when combined with nOrMore().
// May be some scoping issue.
function transform( p, fn ) {
return function () {
var result = p();
return result === null ? null : fn( result );
};
}
// Used to define "literals" within template parameters. The pipe
// character is the parameter delimeter, so by default
// it is not a literal in the parameter
function literalWithoutBar() {
var result = nOrMore( 1, escapedOrLiteralWithoutBar )();
return result === null ? null : result.join( '' );
}
function literal() {
var result = nOrMore( 1, escapedOrRegularLiteral )();
return result === null ? null : result.join( '' );
}
function escapedLiteral() {
var result = sequence( [ backslash, anyCharacter ] );
return result === null ? null : result[ 1 ];
}
choice( [ escapedLiteral, regularLiteralWithoutSpace ] );
escapedOrLiteralWithoutBar = choice( [ escapedLiteral, regularLiteralWithoutBar ] );
escapedOrRegularLiteral = choice( [ escapedLiteral, regularLiteral ] );
function replacement() {
var result = sequence( [ dollar, digits ] );
if ( result === null ) {
return null;
}
return [ 'REPLACE', parseInt( result[ 1 ], 10 ) - 1 ];
}
templateName = transform(
// see $wgLegalTitleChars
// not allowing : due to the need to catch "PLURAL:$1"
makeRegexParser( /^[ !"$&'()*,./0-9;=?@A-Z^_`a-z~\x80-\xFF+-]+/ ),
function ( result ) {
return result.toString();
}
);
function templateParam() {
var expr,
result = sequence( [ pipe, nOrMore( 0, paramExpression ) ] );
if ( result === null ) {
return null;
}
expr = result[ 1 ];
// use a "CONCAT" operator if there are multiple nodes,
// otherwise return the first node, raw.
return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[ 0 ];
}
function templateWithReplacement() {
var result = sequence( [ templateName, colon, replacement ] );
return result === null ? null : [ result[ 0 ], result[ 2 ] ];
}
function templateWithOutReplacement() {
var result = sequence( [ templateName, colon, paramExpression ] );
return result === null ? null : [ result[ 0 ], result[ 2 ] ];
}
templateContents = choice( [
function () {
var res = sequence( [
// templates can have placeholders for dynamic
// replacement eg: {{PLURAL:$1|one car|$1 cars}}
// or no placeholders eg:
// {{GRAMMAR:genitive|{{SITENAME}}}
choice( [ templateWithReplacement, templateWithOutReplacement ] ),
nOrMore( 0, templateParam )
] );
return res === null ? null : res[ 0 ].concat( res[ 1 ] );
},
function () {
var res = sequence( [ templateName, nOrMore( 0, templateParam ) ] );
if ( res === null ) {
return null;
}
return [ res[ 0 ] ].concat( res[ 1 ] );
}
] );
openTemplate = makeStringParser( '{{' );
closeTemplate = makeStringParser( '}}' );
function template() {
var result = sequence( [ openTemplate, templateContents, closeTemplate ] );
return result === null ? null : result[ 1 ];
}
expression = choice( [ template, replacement, literal ] );
paramExpression = choice( [ template, replacement, literalWithoutBar ] );
function start() {
var result = nOrMore( 0, expression )();
if ( result === null ) {
return null;
}
return [ 'CONCAT' ].concat( result );
}
result = start();
/*
* For success, the pos must have gotten to the end of the input
* and returned a non-null.
* n.b. This is part of language infrastructure, so we do not throw an
* internationalizable message.
*/
if ( result === null || pos !== message.length ) {
throw new Error( 'Parse error at position ' + pos.toString() + ' in input: ' + message );
}
return result;
}
};
$.extend( $.i18n.parser, new MessageParser() );
}( jQuery ) );

View File

@ -0,0 +1,22 @@
/**
* Bosnian (bosanski) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.bs = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'instrumental': // instrumental
word = 's ' + word;
break;
case 'lokativ': // locative
word = 'o ' + word;
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,22 @@
/**
* Lower Sorbian (Dolnoserbski) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.dsb = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'instrumental': // instrumental
word = 'z ' + word;
break;
case 'lokatiw': // lokatiw
word = 'wo ' + word;
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,49 @@
/**
* Finnish (Suomi) language functions
*
* @author Santhosh Thottingal
*/
( function ( $ ) {
'use strict';
$.i18n.languages.fi = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
// vowel harmony flag
var aou = word.match( /[aou][^äöy]*$/i ),
origWord = word;
if ( word.match( /wiki$/i ) ) {
aou = false;
}
// append i after final consonant
if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) ) {
word += 'i';
}
switch ( form ) {
case 'genitive':
word += 'n';
break;
case 'elative':
word += ( aou ? 'sta' : 'stä' );
break;
case 'partitive':
word += ( aou ? 'a' : 'ä' );
break;
case 'illative':
// Double the last letter and add 'n'
word += word.slice( -1 ) + 'n';
break;
case 'inessive':
word += ( aou ? 'ssa' : 'ssä' );
break;
default:
word = origWord;
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,38 @@
/**
* Irish (Gaeilge) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.ga = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
if ( form === 'ainmlae' ) {
switch ( word ) {
case 'an Domhnach':
word = 'Dé Domhnaigh';
break;
case 'an Luan':
word = 'Dé Luain';
break;
case 'an Mháirt':
word = 'Dé Mháirt';
break;
case 'an Chéadaoin':
word = 'Dé Chéadaoin';
break;
case 'an Déardaoin':
word = 'Déardaoin';
break;
case 'an Aoine':
word = 'Dé hAoine';
break;
case 'an Satharn':
word = 'Dé Sathairn';
break;
}
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,31 @@
/**
* Hebrew (עברית) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.he = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'prefixed':
case 'תחילית': // the same word in Hebrew
// Duplicate prefixed "Waw", but only if it's not already double
if ( word.slice( 0, 1 ) === 'ו' && word.slice( 0, 2 ) !== 'וו' ) {
word = 'ו' + word;
}
// Remove the "He" if prefixed
if ( word.slice( 0, 1 ) === 'ה' ) {
word = word.slice( 1 );
}
// Add a hyphen (maqaf) before numbers and non-Hebrew letters
if ( word.slice( 0, 1 ) < 'א' || word.slice( 0, 1 ) > 'ת' ) {
word = '־' + word;
}
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,21 @@
/**
* Upper Sorbian (Hornjoserbsce) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.hsb = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'instrumental': // instrumental
word = 'z ' + word;
break;
case 'lokatiw': // lokatiw
word = 'wo ' + word;
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,26 @@
/**
* Hungarian language functions
*
* @author Santhosh Thottingal
*/
( function ( $ ) {
'use strict';
$.i18n.languages.hu = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'rol':
word += 'ról';
break;
case 'ba':
word += 'ba';
break;
case 'k':
word += 'k';
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,25 @@
/**
* Armenian (Հայերեն) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.hy = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
if ( form === 'genitive' ) { // սեռական հոլով
if ( word.slice( -1 ) === 'ա' ) {
word = word.slice( 0, -1 ) + 'այի';
} else if ( word.slice( -1 ) === 'ո' ) {
word = word.slice( 0, -1 ) + 'ոյի';
} else if ( word.slice( -4 ) === 'գիրք' ) {
word = word.slice( 0, -4 ) + 'գրքի';
} else {
word = word + 'ի';
}
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,54 @@
/**
* Latin (lingua Latina) language functions
*
* @author Santhosh Thottingal
*/
( function ( $ ) {
'use strict';
$.i18n.languages.la = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'genitive':
// only a few declensions, and even for those mostly the singular only
word = word.replace( /u[ms]$/i, 'i' ); // 2nd declension singular
word = word.replace( /ommunia$/i, 'ommunium' ); // 3rd declension neuter plural (partly)
word = word.replace( /a$/i, 'ae' ); // 1st declension singular
word = word.replace( /libri$/i, 'librorum' ); // 2nd declension plural (partly)
word = word.replace( /nuntii$/i, 'nuntiorum' ); // 2nd declension plural (partly)
word = word.replace( /tio$/i, 'tionis' ); // 3rd declension singular (partly)
word = word.replace( /ns$/i, 'ntis' );
word = word.replace( /as$/i, 'atis' );
word = word.replace( /es$/i, 'ei' ); // 5th declension singular
break;
case 'accusative':
// only a few declensions, and even for those mostly the singular only
word = word.replace( /u[ms]$/i, 'um' ); // 2nd declension singular
word = word.replace( /ommunia$/i, 'am' ); // 3rd declension neuter plural (partly)
word = word.replace( /a$/i, 'ommunia' ); // 1st declension singular
word = word.replace( /libri$/i, 'libros' ); // 2nd declension plural (partly)
word = word.replace( /nuntii$/i, 'nuntios' );// 2nd declension plural (partly)
word = word.replace( /tio$/i, 'tionem' ); // 3rd declension singular (partly)
word = word.replace( /ns$/i, 'ntem' );
word = word.replace( /as$/i, 'atem' );
word = word.replace( /es$/i, 'em' ); // 5th declension singular
break;
case 'ablative':
// only a few declensions, and even for those mostly the singular only
word = word.replace( /u[ms]$/i, 'o' ); // 2nd declension singular
word = word.replace( /ommunia$/i, 'ommunibus' ); // 3rd declension neuter plural (partly)
word = word.replace( /a$/i, 'a' ); // 1st declension singular
word = word.replace( /libri$/i, 'libris' ); // 2nd declension plural (partly)
word = word.replace( /nuntii$/i, 'nuntiis' ); // 2nd declension plural (partly)
word = word.replace( /tio$/i, 'tione' ); // 3rd declension singular (partly)
word = word.replace( /ns$/i, 'nte' );
word = word.replace( /as$/i, 'ate' );
word = word.replace( /es$/i, 'e' ); // 5th declension singular
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,98 @@
/**
* Malayalam language functions
*
* @author Santhosh Thottingal
*/
( function ( $ ) {
'use strict';
$.i18n.languages.ml = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
form = form.toLowerCase();
switch ( form ) {
case 'ഉദ്ദേശിക':
case 'dative':
if ( word.slice( -1 ) === 'ു' ||
word.slice( -1 ) === 'ൂ' ||
word.slice( -1 ) === 'ൗ' ||
word.slice( -1 ) === 'ൌ'
) {
word += 'വിന്';
} else if ( word.slice( -1 ) === '' ) {
word = word.slice( 0, -1 ) + 'ത്തിന്';
} else if ( word.slice( -1 ) === 'ൻ' ) {
// Atomic chillu n. അവൻ -> അവന്
word = word.slice( 0, -1 ) + 'ന്';
} else if ( word.slice( -3 ) === 'ന്\u200d' ) {
// chillu n. അവൻ -> അവന്
word = word.slice( 0, -1 );
} else if ( word.slice( -1 ) === 'ൾ' || word.slice( -3 ) === 'ള്\u200d' ) {
word += 'ക്ക്';
} else if ( word.slice( -1 ) === 'ർ' || word.slice( -3 ) === 'ര്\u200d' ) {
word += 'ക്ക്';
} else if ( word.slice( -1 ) === 'ൽ' ) {
// Atomic chillu ൽ , ഫയൽ -> ഫയലിന്
word = word.slice( 0, -1 ) + 'ലിന്';
} else if ( word.slice( -3 ) === 'ല്\u200d' ) {
// chillu ല്\u200d , ഫയല്\u200d -> ഫയലിന്
word = word.slice( 0, -2 ) + 'ിന്';
} else if ( word.slice( -2 ) === 'ു്' ) {
word = word.slice( 0, -2 ) + 'ിന്';
} else if ( word.slice( -1 ) === '്' ) {
word = word.slice( 0, -1 ) + 'ിന്';
} else {
// കാവ്യ -> കാവ്യയ്ക്ക്, ഹരി -> ഹരിയ്ക്ക്, മല -> മലയ്ക്ക്
word += 'യ്ക്ക്';
}
break;
case 'സംബന്ധിക':
case 'genitive':
if ( word.slice( -1 ) === '' ) {
word = word.slice( 0, -1 ) + 'ത്തിന്റെ';
} else if ( word.slice( -2 ) === 'ു്' ) {
word = word.slice( 0, -2 ) + 'ിന്റെ';
} else if ( word.slice( -1 ) === '്' ) {
word = word.slice( 0, -1 ) + 'ിന്റെ';
} else if ( word.slice( -1 ) === 'ു' ||
word.slice( -1 ) === 'ൂ' ||
word.slice( -1 ) === 'ൗ' ||
word.slice( -1 ) === 'ൌ'
) {
word += 'വിന്റെ';
} else if ( word.slice( -1 ) === 'ൻ' ) {
// Atomic chillu n. അവൻ -> അവന്റെ
word = word.slice( 0, -1 ) + 'ന്റെ';
} else if ( word.slice( -3 ) === 'ന്\u200d' ) {
// chillu n. അവൻ -> അവന്റെ
word = word.slice( 0, -1 ) + 'റെ';
} else if ( word.slice( -3 ) === 'ള്\u200d' ) {
// chillu n. അവൾ -> അവളുടെ
word = word.slice( 0, -2 ) + 'ുടെ';
} else if ( word.slice( -1 ) === 'ൾ' ) {
// Atomic chillu n. അവള്\u200d -> അവളുടെ
word = word.slice( 0, -1 ) + 'ളുടെ';
} else if ( word.slice( -1 ) === 'ൽ' ) {
// Atomic l. മുയല്\u200d -> മുയലിന്റെ
word = word.slice( 0, -1 ) + 'ലിന്റെ';
} else if ( word.slice( -3 ) === 'ല്\u200d' ) {
// chillu l. മുയല്\u200d -> അവളുടെ
word = word.slice( 0, -2 ) + 'ിന്റെ';
} else if ( word.slice( -3 ) === 'ര്\u200d' ) {
// chillu r. അവര്\u200d -> അവരുടെ
word = word.slice( 0, -2 ) + 'ുടെ';
} else if ( word.slice( -1 ) === 'ർ' ) {
// Atomic chillu r. അവർ -> അവരുടെ
word = word.slice( 0, -1 ) + 'രുടെ';
} else {
word += 'യുടെ';
}
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,75 @@
/**
* Ossetian (Ирон) language functions
*
* @author Santhosh Thottingal
*/
( function ( $ ) {
'use strict';
$.i18n.languages.os = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
var endAllative, jot, hyphen, ending;
// Ending for allative case
endAllative = 'мæ';
// Variable for 'j' beetwen vowels
jot = '';
// Variable for "-" for not Ossetic words
hyphen = '';
// Variable for ending
ending = '';
if ( word.match( /тæ$/i ) ) {
// Checking if the $word is in plural form
word = word.slice( 0, -1 );
endAllative = 'æм';
} else if ( word.match( /[аæеёиоыэюя]$/i ) ) {
// Works if word is in singular form.
// Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю,
// я.
jot = 'й';
} else if ( word.match( /у$/i ) ) {
// Checking if word ends on 'у'. 'У' can be either consonant 'W' or
// vowel 'U' in cyrillic Ossetic.
// Examples: {{grammar:genitive|аунеу}} = аунеуы,
// {{grammar:genitive|лæппу}} = лæппуйы.
if ( !word.slice( -2, -1 ).match( /[аæеёиоыэюя]$/i ) ) {
jot = 'й';
}
} else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
hyphen = '-';
}
switch ( form ) {
case 'genitive':
ending = hyphen + jot + 'ы';
break;
case 'dative':
ending = hyphen + jot + 'æн';
break;
case 'allative':
ending = hyphen + endAllative;
break;
case 'ablative':
if ( jot === 'й' ) {
ending = hyphen + jot + 'æ';
} else {
ending = hyphen + jot + 'æй';
}
break;
case 'superessive':
ending = hyphen + jot + 'ыл';
break;
case 'equative':
ending = hyphen + jot + 'ау';
break;
case 'comitative':
ending = hyphen + 'имæ';
break;
}
return word + ending;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,29 @@
/**
* Russian (Русский) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.ru = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
if ( form === 'genitive' ) { // родительный падеж
if ( word.slice( -1 ) === 'ь' ) {
word = word.slice( 0, -1 ) + 'я';
} else if ( word.slice( -2 ) === 'ия' ) {
word = word.slice( 0, -2 ) + 'ии';
} else if ( word.slice( -2 ) === 'ка' ) {
word = word.slice( 0, -2 ) + 'ки';
} else if ( word.slice( -2 ) === 'ти' ) {
word = word.slice( 0, -2 ) + 'тей';
} else if ( word.slice( -2 ) === 'ды' ) {
word = word.slice( 0, -2 ) + 'дов';
} else if ( word.slice( -3 ) === 'ник' ) {
word = word.slice( 0, -3 ) + 'ника';
}
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,26 @@
/**
* Slovenian (Slovenščina) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.sl = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
// locative
case 'mestnik':
word = 'o ' + word;
break;
// instrumental
case 'orodnik':
word = 'z ' + word;
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -0,0 +1,39 @@
/**
* Ukrainian (Українська) language functions
*/
( function ( $ ) {
'use strict';
$.i18n.languages.uk = $.extend( {}, $.i18n.languages[ 'default' ], {
convertGrammar: function ( word, form ) {
switch ( form ) {
case 'genitive': // родовий відмінок
if ( word.slice( -1 ) === 'ь' ) {
word = word.slice( 0, -1 ) + 'я';
} else if ( word.slice( -2 ) === 'ія' ) {
word = word.slice( 0, -2 ) + 'ії';
} else if ( word.slice( -2 ) === 'ка' ) {
word = word.slice( 0, -2 ) + 'ки';
} else if ( word.slice( -2 ) === 'ти' ) {
word = word.slice( 0, -2 ) + 'тей';
} else if ( word.slice( -2 ) === 'ды' ) {
word = word.slice( 0, -2 ) + 'дов';
} else if ( word.slice( -3 ) === 'ник' ) {
word = word.slice( 0, -3 ) + 'ника';
}
break;
case 'accusative': // знахідний відмінок
if ( word.slice( -2 ) === 'ія' ) {
word = word.slice( 0, -2 ) + 'ію';
}
break;
}
return word;
}
} );
}( jQuery ) );

View File

@ -71,6 +71,9 @@
"core-index-import/several-file": "There are several files available. Please select the ones to import.",
"core-index-import/sel-by-extension": "Select by Extension",
"core-index-import/sel-by-regex": "Select by Regex on File Names",
"core-index-import/match-count" : "$1 {{plural:$1|match|matches}}",
"core-index-import/file-count" : "$1 {{plural:$1|file|files}}",
"core-index-import/files-selected" : "$1 of $2 {{plural:$2|file|files}} selected",
"core-index-import/parsing-options": "Configure Parsing Options",
"core-index-import/project-name": "Project&nbsp;name",
"core-index-import/project-tags": "Tags",
@ -170,9 +173,8 @@
"core-dialogs/rows-in-cluster": "# Rows in Cluster",
"core-dialogs/choice-avg-length": "Average Length of Choices",
"core-dialogs/choice-var-length": "Length Variance of Choices",
"core-dialogs/found": "found",
"core-dialogs/filtered-from": "filtered from <b>",
"core-dialogs/from-total": "</b> total",
"core-dialogs/clusters-found": "<b>$1</b> {{plural:$1|cluster|clusters}} found",
"core-dialogs/clusters-filtered": "<b>$1</b> {{plural:$1|cluster|clusters}} filtered from <b>$2</b> total",
"core-dialogs/cluster-descr": "This feature helps you find groups of different cell values that might be alternative representations of the same thing. For example, the two strings \"New York\" and \"new york\" are very likely to refer to the same concept and just have capitalization differences, and \"Gödel\" and \"Godel\" probably refer to the same person.",
"core-dialogs/find-more": "Find out more…",
"core-dialogs/method": "Method&nbsp;",
@ -298,7 +300,8 @@
"core-facets/current-exp": "Current Expression",
"core-facets/facet-choices": "Facet Choices as Tab Separated Values",
"core-facets/loading": "Loading…",
"core-facets/too-many-choices": "choices total, too many to display",
"core-facets/choice-count": "$1 {{plural:$1|choice|choices}}",
"core-facets/too-many-choices": "$1 choices total, too many to display",
"core-facets/set-choice-count": "Set choice count limit",
"core-facets/edit": "edit",
"core-facets/facet-by-count": "Facet by choice counts",

View File

@ -79,6 +79,9 @@
"core-index-import/enter-url": "Indiquer une ou plusieurs adresses web (URLs) pointant vers les données à télécharger :",
"core-index-import/pick-nodes": "Choisir les nœuds de lentrée",
"core-index-import/sel-by-regex": "Filtrer par une expression rationnelle (regex) sur les noms de fichier",
"core-index-import/match-count" : "$1 {{plural:$1|match|matchs}}",
"core-index-import/file-count" : "$1 {{plural:$1|fichier|fichiers}}",
"core-index-import/files-selected" : "$1 {{plural:$1|fichier|fichiers}} sur $2 sélectionnés",
"core-index-import/name": "Nom",
"core-index-import/parsing-options": "Configurer les options pour lanalyse syntaxique",
"core-index-import/data-package": "Data Package (URL JSON)",
@ -153,7 +156,7 @@
"core-dialogs/html-table": "Table HTML",
"core-dialogs/internal-err": "Erreur interne",
"core-dialogs/error-apply-code": "Erreur lors de lapplication du code doption",
"core-dialogs/from-total": "</b> total",
"core-dialogs/clusters-filtered": "<b>$1</b> {{plural:$1|grappe|grappes}} filtrées sur <b>$2</b> au total",
"core-dialogs/out-col-header": "Écrire les entêtes de colonnes",
"core-dialogs/tsv": "Valeurs séparées par des tabulations (TSV)",
"core-dialogs/template-rowt": "Modèle de la ligne",
@ -174,7 +177,7 @@
"core-dialogs/merge": "Fusionner ?",
"core-dialogs/cluster-descr": "Cet outil vous aide à identifier des groupes de cellules ayant des valeurs différentes mais qui peuvent correspondre à des représentations alternatives de la même valeur. Par exemple, les deux chaînes \"New York\" et \"new york\" nont quune différence de casse et font très certainement référence à la même ville. \"Gödel\" et \"Godel\" se réfèrent probablement à la même personne.",
"clustering-keyers/cologne-phonetic": "phonétique de Cologne",
"core-dialogs/found": "trouvé",
"core-dialogs/clusters-found": "<b>$1</b> {{plural:$1|grappe|grappes}} trouvée",
"core-dialogs/starred": "Étoilée",
"core-dialogs/find-more": "En savoir plus…",
"core-dialogs/ngram-size": "Taille des N-grammes",
@ -312,7 +315,8 @@
"core-facets/linear-plot": "Tracé linéaire",
"core-facets/rotated-clock": "Tourné de 45°",
"core-facets/edit-facet-exp": "Éditer lexpression de la facette",
"core-facets/too-many-choices": "choix au total, trop nombreux à afficher",
"core-facets/choice-count": "$1 choix",
"core-facets/too-many-choices": "$1 choix au total, trop nombreux à afficher",
"core-facets/error": "Erreur",
"core-facets/export-plot": "exporter le tracé",
"core-facets/big-dot": "Point de grande taille",

View File

@ -271,8 +271,8 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
this._elmts.resultSummary.html(
(clusters.length === this._clusters.length) ?
("<b>" + this._clusters.length + "</b> cluster" + ((this._clusters.length != 1) ? "s" : "") + " "+$.i18n('core-dialogs/found')) :
("<b>" + clusters.length + "</b> cluster" + ((clusters.length != 1) ? "s" : "") + " "+$.i18n('core-dialogs/filtered-from')+ this._clusters.length +$.i18n('core-dialogs/from-total') )
$.i18n('core-dialogs/clusters-found', this._clusters.length) :
$.i18n('core-dialogs/clusters-filtered', clusters.length, this._clusters.length)
);
} else {

View File

@ -293,7 +293,7 @@ ListFacet.prototype._update = function(resetScroll) {
this._elmts.bodyInnerDiv.empty();
var messageDiv = $('<div>')
.text(this._data.choiceCount + " "+$.i18n('core-facets/too-many-choices'))
.text($.i18n('core-facets/too-many-choices', this._data.choiceCount))
.addClass("facet-body-message")
.appendTo(this._elmts.bodyInnerDiv);
$('<br>').appendTo(messageDiv);
@ -348,7 +348,7 @@ ListFacet.prototype._update = function(resetScroll) {
(this._blankChoice !== null && this._blankChoice.s ? 1 : 0) +
(this._errorChoice !== null && this._errorChoice.s ? 1 : 0);
this._elmts.choiceCountContainer.text(choices.length + " choices");
this._elmts.choiceCountContainer.text($.i18n("core-facets/choice-count", choices.length));
if (selectionCount > 0) {
this._elmts.resetButton.show();
this._elmts.invertButton.show();

View File

@ -200,7 +200,7 @@ Refine.DefaultImportingController.prototype._renderFileSelectionPanelControlPane
var renderExtension = function(extension) {
var tr = table.insertRow(table.rows.length);
$('<td>').text(extension.extension).appendTo(tr);
$('<td>').text(extension.count + (extension.count > 1 ? " files" : " file")).appendTo(tr);
$('<td>').text($.i18n('core-index-import/file-count'), extension.count).appendTo(tr);
$('<button>')
.text($.i18n('core-buttons/select'))
.addClass("button")
@ -260,7 +260,7 @@ Refine.DefaultImportingController.prototype._renderFileSelectionPanelControlPane
} catch (e) {
// Ignore
}
self._fileSelectionPanelElmts.regexSummary.text(count + (count == 1 ? " match" : " matches"));
self._fileSelectionPanelElmts.regexSummary.text($.i18n('core-index-import/match-count'), count);
});
this._fileSelectionPanelElmts.selectRegexButton.unbind().click(function() {
self._fileSelectionPanelElmts.filePanel
@ -317,7 +317,7 @@ Refine.DefaultImportingController.prototype._updateFileSelectionSummary = functi
}
}
this._job.config.fileSelection = fileSelection;
this._fileSelectionPanelElmts.summary.text(fileSelection.length + " of " + files.length + " files selected");
this._fileSelectionPanelElmts.summary.text($.i18n('core-index-import/files-selected', fileSelection.length, files.length));
};
Refine.DefaultImportingController.prototype._commitFileSelection = function() {