+ * load('path/to/de-messages.json', 'de' );
+ *
+ * A data object containing message key- message translation mappings can also be passed Eg:
+ *
+ * load( { 'hello' : 'Hello' }, optionalLocale );
+ * If the data argument is
+ * null/undefined/false, all cached messages for the i18n instance will get reset.
+ *
+ * @param {String|Object|null} data
+ * @param {String} locale Language tag
+ */
+ load: function ( data, locale ) {
+ var that = this;
+ var hasOwn = Object.prototype.hasOwnProperty;
+ if ( !data ) {
+ // reset all localizations
+ this.log( "Resetting for locale" + locale );
+ that.messages = {};
+ return;
+ }
+ var dataType = typeof data;
+ if ( locale && this.locale !== locale ) {
+ // queue loading locale if not needed
+ if ( ! ( locale in this.sources ) ) {
+ this.sources[locale] = [];
+ }
+ this.log( "Queueing: " + locale + " Current locale " + this.locale );
+ this.sources[locale].push( data );
+ return;
+ }
+ if ( arguments.length > 0 && dataType !== "number" ) {
+ if ( dataType === "string" ) {
+ // This is a URL to the messages file.
+ this.log( "Loading messages from: " + data );
+ this.jsonMessageLoader( data ).done( function ( localization, textStatus ) {
+ that.load( localization, locale );
+ delete that.sources[locale];
+ } );
+ } else {
+ // data is Object
+ // Extend current localizations instead of completely
+ // overwriting them
+ var localization = data;
+ for ( var messageKey in localization ) {
+ if ( !hasOwn.call( localization, messageKey ) ) {
+ continue;
+ }
+ var messageKeyType = typeof messageKey;
+ if ( messageKeyType === "string" && locale ) {
+ that.log( "[" + locale + "][" + messageKey + "] : "
+ + localization[messageKey] );
+ that.messages[locale] = that.messages[locale] || [];
+ that.messages[locale][messageKey] = localization[messageKey];
+ } else {
+ var passedLocale = messageKey;
+ this.log( "Loading locale: " + passedLocale );
+ that.load( localization[passedLocale], passedLocale );
+ }
+ }
+ }
+ }
+ },
+
+ log: function (/* arguments */) {
+ var hasConsole = window.console !== undefined;
+ if ( hasConsole && $.i18n.debug ) {
+ window.console.log.apply( window.console, arguments );
+ }
+ },
+
+ /**
+ * Load the messages from the source queue for the locale
+ *
+ * @param {String} locale
+ */
+ loadFromQueue: function ( locale ) {
+ var that = this;
+ var queue = that.sources[locale];
+ for ( var i = 0; i < queue.length; i++ ) {
+ that.load( queue[i], locale );
+ }
+ delete that.sources[locale];
+ },
+
+ jsonMessageLoader: function ( url ) {
+ var that = this;
+ return $.ajax( {
+ url: url,
+ dataType: "json",
+ async: false
+ // that is unfortunate
+ } ).fail( function ( jqxhr, settings, exception ) {
+ that.log( "Error in loading messages from " + url + " Exception: " + exception );
+ } );
+ },
+
+ /**
+ *
+ * @param locale
+ * @param messageKey
+ * @returns {Boolean}
+ */
+ get: function ( locale, messageKey ) {
+ // load locale if not loaded
+ if ( this.sources[locale] ) {
+ // We need to switch to this locale
+ this.locale = locale;
+ this.loadFromQueue( locale );
+ }
+ return this.messages[locale] && this.messages[locale][messageKey];
+ }
+ };
+
+ $.extend( $.i18n.messageStore, new MessageStore() );
+
+}( jQuery, window ) );
+
+/**
+ * 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 ( $, undefined ) {
+ $.i18n = $.i18n || {};
+ $.i18n.fallbacks = {
+ "ab": ["ru"],
+ "ace": ["id"],
+ "aln": ["sq"],
+ "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 ) );
+
+/**
+ * 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";
+
+ var MessageParser = function ( options ) {
+ this.options = $.extend( {}, $.i18n.parser.defaults, options );
+ this.language = $.i18n.languages[$.i18n().locale];
+ 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 pos = 0;
+
+ // Try parsers until one works, if none work return null
+ function choice ( parserSyntax ) {
+ return function () {
+ for ( var i = 0; i < parserSyntax.length; i++) {
+ var 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 originalPos = pos;
+ var result = [];
+ for ( var i = 0; i < parserSyntax.length; i++) {
+ var 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;
+ var result = [];
+ var 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.substr( pos, len ) === s ) {
+ result = s;
+ pos += len;
+ }
+ return result;
+ };
+ }
+
+ function makeRegexParser ( regex ) {
+ return function () {
+ var matches = message.substr( pos ).match( regex );
+ if ( matches === null ) {
+ return null;
+ }
+ pos += matches[0].length;
+ return matches[0];
+ };
+ }
+
+ var pipe = makeStringParser( '|' );
+ var colon = makeStringParser( ':' );
+ var backslash = makeStringParser( "\\" );
+ var anyCharacter = makeRegexParser( /^./ );
+ var dollar = makeStringParser( '$' );
+ var digits = makeRegexParser( /^\d+/ );
+ var regularLiteral = makeRegexParser( /^[^{}\[\]$\\]/ );
+ var regularLiteralWithoutBar = makeRegexParser( /^[^{}\[\]$\\|]/ );
+ var regularLiteralWithoutSpace = makeRegexParser( /^[^{}\[\]$\s]/ );
+
+ // There is a general pattern -- parse a thing, if that 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" without spaces, in space-delimited
+ // situations
+ function literalWithoutSpace () {
+ var result = nOrMore( 1, escapedOrLiteralWithoutSpace )();
+ return result === null ? null : result.join( '' );
+ }
+
+ // 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];
+ }
+
+ var escapedOrLiteralWithoutSpace = choice( [ escapedLiteral, regularLiteralWithoutSpace ] );
+ var escapedOrLiteralWithoutBar = choice( [ escapedLiteral, regularLiteralWithoutBar ] );
+ var escapedOrRegularLiteral = choice( [ escapedLiteral, regularLiteral ] );
+
+ function replacement () {
+ var result = sequence( [ dollar, digits ] );
+ if ( result === null ) {
+ return null;
+ }
+ return [ 'REPLACE', parseInt( result[1], 10 ) - 1 ];
+ }
+
+ var 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 result = sequence( [ pipe, nOrMore( 0, paramExpression ) ] );
+ if ( result === null ) {
+ return null;
+ }
+ var 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] ];
+ }
+
+ var 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] );
+ } ] );
+
+ var openTemplate = makeStringParser( '{{' );
+
+ var closeTemplate = makeStringParser( '}}' );
+
+ function template () {
+ var result = sequence( [ openTemplate, templateContents, closeTemplate ] );
+ return result === null ? null : result[1];
+ }
+
+ var expression = choice( [ template, replacement, literal ] );
+ var paramExpression = choice( [ template, replacement, literalWithoutBar ] );
+
+ function start () {
+ var result = nOrMore( 0, expression )();
+
+ if ( result === null ) {
+ return null;
+ }
+
+ return [ "CONCAT" ].concat( result );
+ }
+
+ var result = start();
+ return result;
+ }
+
+ };
+
+ $.extend( $.i18n.parser, new MessageParser() );
+
+}( jQuery ) );
+
+/**
+ * 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";
+
+ var MessageParserEmitter = function () {
+ this.language = $.i18n.languages[$.i18n().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}
+ * 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 = null;
+ var that = this;
+
+ switch (typeof node) {
+ case 'string':
+ case 'number':
+ ret = node;
+ break;
+ case 'object':
+ // node is an array of nodes
+ var subnodes = $.map( node.slice( 1 ), function ( n ) {
+ return that.emit( n, replacements );
+ } );
+ var operation = node[0].toLowerCase();
+ if ( typeof that[operation] === 'function' ) {
+ ret = that[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}
+ * of one element, integer, n >= 0
+ * @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}
+ * of nodes, [ {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 ) );
+ var 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}
+ * of nodes, [ {String}, {String}, {String} , {String} ]
+ * @return {String} selected gender form according to current language
+ */
+ gender: function ( nodes ) {
+ var gender = nodes[0];
+ var 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}
+ * of nodes [{Grammar case eg: genitive}, {String word}]
+ * @return {String} selected grammatical form according to current
+ * language
+ */
+ grammar: function ( nodes ) {
+ var form = nodes[0];
+ var word = nodes[1];
+ return word && form && this.language.convertGrammar( word, form );
+ }
+ };
+
+ $.extend( $.i18n.parser.emitter, new MessageParserEmitter() );
+
+}( jQuery ) );
+/* global pluralRuleParser */
+( function ( $ ) {
+ "use strict";
+ var language = {
+
+ // CLDR plural rules generated using
+ // http://i18ndata.appspot.com/cldr/tags/unconfirmed/supplemental/plurals?action=browse&depth=-1
+ // and compressed
+ pluralRules: {
+ gv: {
+ one: "n mod 10 in 1..2 or n mod 20 is 0"
+ },
+ gu: {
+ one: "n is 1"
+ },
+ rof: {
+ one: "n is 1"
+ },
+ ga: {
+ few: "n in 3..6",
+ many: "n in 7..10",
+ two: "n is 2",
+ one: "n is 1"
+ },
+ gl: {
+ one: "n is 1"
+ },
+ lg: {
+ one: "n is 1"
+ },
+ lb: {
+ one: "n is 1"
+ },
+ xog: {
+ one: "n is 1"
+ },
+ ln: {
+ one: "n in 0..1"
+ },
+ lo: "",
+ brx: {
+ one: "n is 1"
+ },
+ tr: "",
+ ts: {
+ one: "n is 1"
+ },
+ tn: {
+ one: "n is 1"
+ },
+ to: "",
+ lt: {
+ few: "n mod 10 in 2..9 and n mod 100 not in 11..19",
+ one: "n mod 10 is 1 and n mod 100 not in 11..19"
+ },
+ tk: {
+ one: "n is 1"
+ },
+ th: "",
+ ksb: {
+ one: "n is 1"
+ },
+ te: {
+ one: "n is 1"
+ },
+ ksh: {
+ zero: "n is 0",
+ one: "n is 1"
+ },
+ fil: {
+ one: "n in 0..1"
+ },
+ haw: {
+ one: "n is 1"
+ },
+ kcg: {
+ one: "n is 1"
+ },
+ ssy: {
+ one: "n is 1"
+ },
+ yo: "",
+ de: {
+ one: "n is 1"
+ },
+ ko: "",
+ da: {
+ one: "n is 1"
+ },
+ dz: "",
+ dv: {
+ one: "n is 1"
+ },
+ guw: {
+ one: "n in 0..1"
+ },
+ shi: {
+ few: "n in 2..10",
+ one: "n within 0..1"
+ },
+ el: {
+ one: "n is 1"
+ },
+ eo: {
+ one: "n is 1"
+ },
+ en: {
+ one: "n is 1"
+ },
+ ses: "",
+ teo: {
+ one: "n is 1"
+ },
+ ee: {
+ one: "n is 1"
+ },
+ kde: "",
+ fr: {
+ one: "n within 0..2 and n is not 2"
+ },
+ eu: {
+ one: "n is 1"
+ },
+ et: {
+ one: "n is 1"
+ },
+ es: {
+ one: "n is 1"
+ },
+ seh: {
+ one: "n is 1"
+ },
+ ru: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ kl: {
+ one: "n is 1"
+ },
+ sms: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ smn: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ smj: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ smi: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ fy: {
+ one: "n is 1"
+ },
+ rm: {
+ one: "n is 1"
+ },
+ ro: {
+ few: "n is 0 OR n is not 1 AND n mod 100 in 1..19",
+ one: "n is 1"
+ },
+ bn: {
+ one: "n is 1"
+ },
+ sma: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ be: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ bg: {
+ one: "n is 1"
+ },
+ ms: "",
+ wa: {
+ one: "n in 0..1"
+ },
+ ps: {
+ one: "n is 1"
+ },
+ wo: "",
+ bm: "",
+ jv: "",
+ bo: "",
+ bh: {
+ one: "n in 0..1"
+ },
+ kea: "",
+ asa: {
+ one: "n is 1"
+ },
+ cgg: {
+ one: "n is 1"
+ },
+ br: {
+ few: "n mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99",
+ many: "n mod 1000000 is 0 and n is not 0",
+ two: "n mod 10 is 2 and n mod 100 not in 12,72,92",
+ one: "n mod 10 is 1 and n mod 100 not in 11,71,91"
+ },
+ bs: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ ja: "",
+ om: {
+ one: "n is 1"
+ },
+ fa: "",
+ vun: {
+ one: "n is 1"
+ },
+ or: {
+ one: "n is 1"
+ },
+ xh: {
+ one: "n is 1"
+ },
+ nso: {
+ one: "n in 0..1"
+ },
+ ca: {
+ one: "n is 1"
+ },
+ cy: {
+ few: "n is 3",
+ zero: "n is 0",
+ many: "n is 6",
+ two: "n is 2",
+ one: "n is 1"
+ },
+ cs: {
+ few: "n in 2..4",
+ one: "n is 1"
+ },
+ zh: "",
+ lv: {
+ zero: "n is 0",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ pt: {
+ one: "n is 1"
+ },
+ wae: {
+ one: "n is 1"
+ },
+ tl: {
+ one: "n in 0..1"
+ },
+ chr: {
+ one: "n is 1"
+ },
+ pa: {
+ one: "n is 1"
+ },
+ ak: {
+ one: "n in 0..1"
+ },
+ pl: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n is not 1 and n mod 10 in 0..1 or n mod 10 in 5..9 or n mod 100 in 12..14",
+ one: "n is 1"
+ },
+ hr: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ am: {
+ one: "n in 0..1"
+ },
+ ti: {
+ one: "n in 0..1"
+ },
+ hu: "",
+ hi: {
+ one: "n in 0..1"
+ },
+ jmc: {
+ one: "n is 1"
+ },
+ ha: {
+ one: "n is 1"
+ },
+ he: {
+ one: "n is 1"
+ },
+ mg: {
+ one: "n in 0..1"
+ },
+ fur: {
+ one: "n is 1"
+ },
+ bem: {
+ one: "n is 1"
+ },
+ ml: {
+ one: "n is 1"
+ },
+ mo: {
+ few: "n is 0 OR n is not 1 AND n mod 100 in 1..19",
+ one: "n is 1"
+ },
+ mn: {
+ one: "n is 1"
+ },
+ mk: {
+ one: "n mod 10 is 1 and n is not 11"
+ },
+ ur: {
+ one: "n is 1"
+ },
+ bez: {
+ one: "n is 1"
+ },
+ mt: {
+ few: "n is 0 or n mod 100 in 2..10",
+ many: "n mod 100 in 11..19",
+ one: "n is 1"
+ },
+ uk: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ mr: {
+ one: "n is 1"
+ },
+ ta: {
+ one: "n is 1"
+ },
+ my: "",
+ sah: "",
+ ve: {
+ one: "n is 1"
+ },
+ af: {
+ one: "n is 1"
+ },
+ vi: "",
+ is: {
+ one: "n is 1"
+ },
+ iu: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ it: {
+ one: "n is 1"
+ },
+ kn: "",
+ ii: "",
+ ar: {
+ few: "n mod 100 in 3..10",
+ zero: "n is 0",
+ many: "n mod 100 in 11..99",
+ two: "n is 2",
+ one: "n is 1"
+ },
+ zu: {
+ one: "n is 1"
+ },
+ saq: {
+ one: "n is 1"
+ },
+ az: "",
+ tzm: {
+ one: "n in 0..1 or n in 11..99"
+ },
+ id: "",
+ ig: "",
+ pap: {
+ one: "n is 1"
+ },
+ nl: {
+ one: "n is 1"
+ },
+ nn: {
+ one: "n is 1"
+ },
+ no: {
+ one: "n is 1"
+ },
+ nah: {
+ one: "n is 1"
+ },
+ nd: {
+ one: "n is 1"
+ },
+ ne: {
+ one: "n is 1"
+ },
+ ny: {
+ one: "n is 1"
+ },
+ naq: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ nyn: {
+ one: "n is 1"
+ },
+ kw: {
+ two: "n is 2",
+ one: "n is 1"
+ },
+ nr: {
+ one: "n is 1"
+ },
+ tig: {
+ one: "n is 1"
+ },
+ kab: {
+ one: "n within 0..2 and n is not 2"
+ },
+ mas: {
+ one: "n is 1"
+ },
+ rwk: {
+ one: "n is 1"
+ },
+ kaj: {
+ one: "n is 1"
+ },
+ lag: {
+ zero: "n is 0",
+ one: "n within 0..2 and n is not 0 and n is not 2"
+ },
+ syr: {
+ one: "n is 1"
+ },
+ kk: {
+ one: "n is 1"
+ },
+ ff: {
+ one: "n within 0..2 and n is not 2"
+ },
+ fi: {
+ one: "n is 1"
+ },
+ fo: {
+ one: "n is 1"
+ },
+ ka: "",
+ gsw: {
+ one: "n is 1"
+ },
+ ckb: {
+ one: "n is 1"
+ },
+ ss: {
+ one: "n is 1"
+ },
+ sr: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ sq: {
+ one: "n is 1"
+ },
+ sw: {
+ one: "n is 1"
+ },
+ sv: {
+ one: "n is 1"
+ },
+ km: "",
+ st: {
+ one: "n is 1"
+ },
+ sk: {
+ few: "n in 2..4",
+ one: "n is 1"
+ },
+ sh: {
+ few: "n mod 10 in 2..4 and n mod 100 not in 12..14",
+ many: "n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14",
+ one: "n mod 10 is 1 and n mod 100 is not 11"
+ },
+ so: {
+ one: "n is 1"
+ },
+ sn: {
+ one: "n is 1"
+ },
+ ku: {
+ one: "n is 1"
+ },
+ sl: {
+ few: "n mod 100 in 3..4",
+ two: "n mod 100 is 2",
+ one: "n mod 100 is 1"
+ },
+ sg: "",
+ nb: {
+ one: "n is 1"
+ },
+ se: {
+ two: "n is 2",
+ one: "n is 1"
+ }
+ },
+
+ /**
+ * Plural form transformations, needed for some languages.
+ *
+ * @param count
+ * integer Non-localized quantifier
+ * @param forms
+ * array List of plural forms
+ * @return string Correct form for quantifier in this language
+ */
+ convertPlural: function ( count, forms ) {
+ var pluralFormIndex = 0;
+ if ( !forms || forms.length === 0 ) {
+ return '';
+ }
+ var pluralRules = this.pluralRules[$.i18n().locale];
+ if ( !pluralRules ) {
+ // default fallback.
+ return ( count === 1 ) ? forms[0] : forms[1];
+ }
+ pluralFormIndex = this.getPluralForm( count, pluralRules );
+ pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
+ return forms[pluralFormIndex];
+ },
+
+ /**
+ * For the number, get the plural for index
+ *
+ * @param number
+ * @param pluralRules
+ * @return plural form index
+ */
+ getPluralForm: function ( number, pluralRules ) {
+ var pluralForms = [ 'zero', 'one', 'two', 'few', 'many', 'other' ];
+ var pluralFormIndex = 0;
+ for ( var i = 0; i < pluralForms.length; i++) {
+ if ( pluralRules[pluralForms[i]] ) {
+ if ( pluralRuleParser( pluralRules[pluralForms[i]], number ) ) {
+ return pluralFormIndex;
+ }
+ pluralFormIndex++;
+ }
+ }
+ return pluralFormIndex;
+ },
+
+ /**
+ * Converts a number using digitTransformTable.
+ *
+ * @param {num}
+ * number Value to be converted
+ * @param {boolean}
+ * integer Convert the return value to an integer
+ */
+ 'convertNumber': function ( num, integer ) {
+ // Set the target Transform table:
+ var transformTable = this.digitTransformTable( $.i18n().locale ), numberString = ''
+ + num, convertedNumber = '';
+ if ( !transformTable ) {
+ return num;
+ }
+ // Check if the "restore" to Latin number flag is set:
+ if ( integer ) {
+ if ( parseFloat( num, 10 ) === num ) {
+ return num;
+ }
+ var tmp = [];
+ for ( var item in transformTable) {
+ tmp[transformTable[item]] = item;
+ }
+ transformTable = tmp;
+ }
+ for ( var i = 0; i < numberString.length; i++) {
+ if ( transformTable[numberString[i]] ) {
+ convertedNumber += transformTable[numberString[i]];
+ } else {
+ convertedNumber += numberString[i];
+ }
+ }
+
+ return integer ? parseFloat( convertedNumber, 10 ) : convertedNumber;
+ },
+
+ /**
+ * Grammatical transformations, needed for inflected languages.
+ * Invoked by putting {{grammar:form|word}} in a message.
+ * forms can be computed dynamically by overriding this method per language
+ *
+ * @param word {String}
+ * @param form {String}
+ * @return {String}
+ */
+ convertGrammar: function ( word, form ) {
+ return word + form;
+ },
+
+ /**
+ * Provides an alternative text depending on specified gender. Usage
+ * {{gender:[gender|user object]|masculine|feminine|neutral}}. If second
+ * or third parameter are not specified, masculine is used.
+ *
+ * These details may be overriden per language.
+ *
+ * @param gender
+ * string male, female, or anything else for neutral.
+ * @param forms
+ * array List of gender forms
+ *
+ * @return string
+ */
+ 'gender': function ( gender, forms ) {
+ if ( !forms || forms.length === 0 ) {
+ return '';
+ }
+ while (forms.length < 2) {
+ forms.push( forms[forms.length - 1] );
+ }
+ if ( gender === 'male' ) {
+ return forms[0];
+ }
+ if ( gender === 'female' ) {
+ return forms[1];
+ }
+ return ( forms.length === 3 ) ? forms[2] : forms[0];
+ },
+
+ /**
+ * Get the digit transform table for the given language
+ * See http://cldr.unicode.org/translation/numbering-systems
+ * @param language
+ * @returns Array of digits in the passed language representation
+ */
+ digitTransformTable: function ( language ) {
+ var tables = {
+ ar: "۰۱۲۳۴۵۶۷۸۹",
+ ml: "൦൧൨൩൪൫൬൭൮൯",
+ kn: "೦೧೨೩೪೫೬೭೮೯",
+ lo: "໐໑໒໓໔໕໖໗໘໙",
+ or: "୦୧୨୩୪୫୬୭୮୯",
+ kh: "០១២៣៤៥៦៧៨៩",
+ pa: "੦੧੨੩੪੫੬੭੮੯",
+ gu: "૦૧૨૩૪૫૬૭૮૯",
+ hi: "०१२३४५६७८९",
+ my: "၀၁၂၃၄၅၆၇၈၉",
+ ta: "௦௧௨௩௪௫௬௭௮௯",
+ te: "౦౧౨౩౪౫౬౭౮౯",
+ th: "๐๑๒๓๔๕๖๗๘๙", //FIXME use iso 639 codes
+ bo: "༠༡༢༣༤༥༦༧༨༩" //FIXME use iso 639 codes
+ };
+ if ( !tables[language] ) {
+ return null;
+ }
+ return tables[language].split( "" );
+ }
+ };
+
+ $.extend( $.i18n.languages, {
+ 'default': language
+ } );
+
+}( jQuery ) );
+
+/**
+ * Bosnian (bosanski) language functions
+ */
+( function ( $ ) {
+ "use strict";
+ var bosanski = $.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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'bs': bosanski
+ } );
+}( jQuery ) );
+
+/**
+ * Lower Sorbian (Dolnoserbski) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var 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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'dsb': dsb
+ } );
+}( jQuery ) );
+
+/**
+ * Finnish (Suomi) language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ "use strict";
+ var finnish = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ // vowel harmony flag
+ var aou = word.match( /[aou][^äöy]*$/i );
+ var 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.substr( word.length - 1 ) + 'n';
+ break;
+ case 'inessive':
+ word += ( aou ? 'ssa' : 'ssä' );
+ break;
+ default:
+ word = origWord;
+ break;
+ }
+ return word;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'fi': finnish
+ } );
+}( jQuery ) );
+
+/**
+ * Irish (Gaeilge) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var 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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'ga': ga
+ } );
+}( jQuery ) );
+
+/**
+ * Hebrew (עברית) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var hebrew = $.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.substr( 0, 1 ) === "ו" && word.substr( 0, 2 ) !== "וו" ) {
+ word = "ו" + word;
+ }
+
+ // Remove the "He" if prefixed
+ if ( word.substr( 0, 1 ) === "ה" ) {
+ word = word.substr( 1, word.length );
+ }
+
+ // Add a hyphen (maqaf) before numbers and non-Hebrew letters
+ if ( word.substr( 0, 1 ) < "א" || word.substr( 0, 1 ) > "ת" ) {
+ word = "־" + word;
+ }
+ }
+ return word;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'he': hebrew
+ } );
+}( jQuery ) );
+
+/**
+ * Upper Sorbian (Hornjoserbsce) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var 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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'hsb': hsb
+ } );
+}( jQuery ) );
+
+/**
+ * Hungarian language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ "use strict";
+ var 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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'hu': hu
+ } );
+}( jQuery ) );
+
+/**
+ * Armenian (Հայերեն) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var hy = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ if ( form === 'genitive' ) {// սեռական հոլով
+ if ( word.substr( -1 ) === 'ա' ) {
+ word = word.substr( 0, word.length - 1 ) + 'այի';
+ } else if ( word.substr( -1 ) === 'ո' ) {
+ word = word.substr( 0, word.length - 1 ) + 'ոյի';
+ } else if ( word.substr( -4 ) === 'գիրք' ) {
+ word = word.substr( 0, word.length - 4 ) + 'գրքի';
+ } else {
+ word = word + 'ի';
+ }
+ }
+ return word;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'hy': hy
+ } );
+}( jQuery ) );
+
+/**
+ * Latin (lingua Latina) language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ "use strict";
+ var 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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'la': la
+ } );
+}( jQuery ) );
+
+/**
+ * Ossetian (Ирон) language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ "use strict";
+ var os = $.extend( {}, $.i18n.languages['default'],
+ {
+ convertGrammar: function ( word, form ) {
+ // Ending for allative case
+ var end_allative = 'мæ';
+ // Variable for 'j' beetwen vowels
+ var jot = '';
+ // Variable for "-" for not Ossetic words
+ var hyphen = '';
+ // Variable for ending
+ var ending = '';
+ // Checking if the $word is in plural form
+ if ( word.match( /тæ$/i ) ) {
+ word = word.substring( 0, word.length - 1 );
+ end_allative = 'æм';
+ }
+ // Works if word is in singular form.
+ // Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю,
+ // я.
+ else if ( word.match( /[аæеёиоыэюя]$/i ) ) {
+ jot = 'й';
+ }
+ // Checking if word ends on 'у'. 'У' can be either consonant 'W' or
+ // vowel 'U' in cyrillic Ossetic.
+ // Examples: {{grammar:genitive|аунеу}} = аунеуы,
+ // {{grammar:genitive|лæппу}} = лæппуйы.
+ else if ( word.match( /у$/i ) ) {
+ if ( !word.substring( word.length - 2, word.length - 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 + end_allative;
+ 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;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'os': os
+ } );
+}( jQuery ) );
+
+/**
+ * Russian (Русский) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var ru = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ if ( form === 'genitive' ) { // родительный падеж
+ if ( ( word.substr( word.length - 4 ) === 'вики' )
+ || ( word.substr( word.length - 4 ) === 'Вики' ) ) {
+ } else if ( word.substr( word.length - 1 ) === 'ь' ) {
+ word = word.substr( 0, word.length - 1 ) + 'я';
+ } else if ( word.substr( word.length - 2 ) === 'ия' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ии';
+ } else if ( word.substr( word.length - 2 ) === 'ка' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ки';
+ } else if ( word.substr( word.length - 2 ) === 'ти' ) {
+ word = word.substr( 0, word.length - 2 ) + 'тей';
+ } else if ( word.substr( word.length - 2 ) === 'ды' ) {
+ word = word.substr( 0, word.length - 2 ) + 'дов';
+ } else if ( word.substr( word.length - 3 ) === 'ник' ) {
+ word = word.substr( 0, word.length - 3 ) + 'ника';
+ }
+ }
+ return word;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'ru': ru
+ } );
+}( jQuery ) );
+/**
+ * Slovenian (Slovenščina) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var sl = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch (form) {
+ case 'mestnik': // locative
+ word = 'o ' + word;
+ break;
+ case 'orodnik': // instrumental
+ word = 'z ' + word;
+ break;
+ }
+ return word;
+ }
+
+ } );
+ $.extend( $.i18n.languages, {
+ 'sl': sl
+ } );
+}( jQuery ) );
+/**
+ * Ukrainian (Українська) language functions
+ */
+
+( function ( $ ) {
+ "use strict";
+ var uk = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch (form) {
+ case 'genitive': // родовий відмінок
+ if ( ( word.substr( word.length - 4 ) === 'вікі' )
+ || ( word.substr( word.length - 4 ) === 'Вікі' ) ) {
+ } else if ( word.substr( word.length - 1 ) === 'ь' ) {
+ word = word.substr( 0, word.length - 1 ) + 'я';
+ } else if ( word.substr( word.length - 2 ) === 'ія' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ії';
+ } else if ( word.substr( word.length - 2 ) === 'ка' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ки';
+ } else if ( word.substr( word.length - 2 ) === 'ти' ) {
+ word = word.substr( 0, word.length - 2 ) + 'тей';
+ } else if ( word.substr( word.length - 2 ) === 'ды' ) {
+ word = word.substr( 0, word.length - 2 ) + 'дов';
+ } else if ( word.substr( word.length - 3 ) === 'ник' ) {
+ word = word.substr( 0, word.length - 3 ) + 'ника';
+ }
+ break;
+ case 'accusative': // знахідний відмінок
+ if ( ( word.substr( word.length - 4 ) === 'вікі' )
+ || ( word.substr( word.length - 4 ) === 'Вікі' ) ) {
+ } else if ( word.substr( word.length - 2 ) === 'ія' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ію';
+ }
+ break;
+ }
+ return word;
+ }
+ } );
+ $.extend( $.i18n.languages, {
+ 'uk': uk
+ } );
+}( jQuery ) );
+/**
+ * cldrpluralparser.js
+ * A parser engine for CLDR plural rules.
+ *
+ * Copyright 2012 GPLV3+, Santhosh Thottingal
+ *
+ * @version 0.1.0-alpha
+ * @source https://github.com/santhoshtr/CLDRPluralRuleParser
+ * @author Santhosh Thottingal
- * $Spyc = new Spyc;
- * $array = $Spyc->load($file);
- *
- * or:
- *
- * $array = Spyc::YAMLLoad($file);
- *
- * or:
- *
- * $array = spyc_load_file($file);
- *
- * @package Spyc
- */
-class Spyc {
-
- // SETTINGS
-
- const REMPTY = "\0\0\0\0\0";
-
- /**
- * Setting this to true will force YAMLDump to enclose any string value in
- * quotes. False by default.
- *
- * @var bool
- */
- public $setting_dump_force_quotes = false;
-
- /**
- * Setting this to true will forse YAMLLoad to use syck_load function when
- * possible. False by default.
- * @var bool
- */
- public $setting_use_syck_is_possible = false;
-
-
-
- /**#@+
- * @access private
- * @var mixed
- */
- private $_dumpIndent;
- private $_dumpWordWrap;
- private $_containsGroupAnchor = false;
- private $_containsGroupAlias = false;
- private $path;
- private $result;
- private $LiteralPlaceHolder = '___YAML_Literal_Block___';
- private $SavedGroups = array();
- private $indent;
- /**
- * Path modifier that should be applied after adding current element.
- * @var array
- */
- private $delayedPath = array();
-
- /**#@+
- * @access public
- * @var mixed
- */
- public $_nodeId;
-
-/**
- * Load a valid YAML string to Spyc.
- * @param string $input
- * @return array
- */
- public function load ($input) {
- return $this->__loadString($input);
- }
-
- /**
- * Load a valid YAML file to Spyc.
- * @param string $file
- * @return array
- */
- public function loadFile ($file) {
- return $this->__load($file);
- }
-
- /**
- * Load YAML into a PHP array statically
- *
- * The load method, when supplied with a YAML stream (string or file),
- * will do its best to convert YAML in a file into a PHP array. Pretty
- * simple.
- * Usage:
- *
- * $array = Spyc::YAMLLoad('lucky.yaml');
- * print_r($array);
- *
- * @access public
- * @return array
- * @param string $input Path of YAML file or string containing YAML
- */
- public static function YAMLLoad($input) {
- $Spyc = new Spyc;
- return $Spyc->__load($input);
- }
-
- /**
- * Load a string of YAML into a PHP array statically
- *
- * The load method, when supplied with a YAML string, will do its best
- * to convert YAML in a string into a PHP array. Pretty simple.
- *
- * Note: use this function if you don't want files from the file system
- * loaded and processed as YAML. This is of interest to people concerned
- * about security whose input is from a string.
- *
- * Usage:
- *
- * $array = Spyc::YAMLLoadString("---\n0: hello world\n");
- * print_r($array);
- *
- * @access public
- * @return array
- * @param string $input String containing YAML
- */
- public static function YAMLLoadString($input) {
- $Spyc = new Spyc;
- return $Spyc->__loadString($input);
- }
-
- /**
- * Dump YAML from PHP array statically
- *
- * The dump method, when supplied with an array, will do its best
- * to convert the array into friendly YAML. Pretty simple. Feel free to
- * save the returned string as nothing.yaml and pass it around.
- *
- * Oh, and you can decide how big the indent is and what the wordwrap
- * for folding is. Pretty cool -- just pass in 'false' for either if
- * you want to use the default.
- *
- * Indent's default is 2 spaces, wordwrap's default is 40 characters. And
- * you can turn off wordwrap by passing in 0.
- *
- * @access public
- * @return string
- * @param array $array PHP array
- * @param int $indent Pass in false to use the default, which is 2
- * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
- */
- public static function YAMLDump($array,$indent = false,$wordwrap = false) {
- $spyc = new Spyc;
- return $spyc->dump($array,$indent,$wordwrap);
- }
-
-
- /**
- * Dump PHP array to YAML
- *
- * The dump method, when supplied with an array, will do its best
- * to convert the array into friendly YAML. Pretty simple. Feel free to
- * save the returned string as tasteful.yaml and pass it around.
- *
- * Oh, and you can decide how big the indent is and what the wordwrap
- * for folding is. Pretty cool -- just pass in 'false' for either if
- * you want to use the default.
- *
- * Indent's default is 2 spaces, wordwrap's default is 40 characters. And
- * you can turn off wordwrap by passing in 0.
- *
- * @access public
- * @return string
- * @param array $array PHP array
- * @param int $indent Pass in false to use the default, which is 2
- * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
- */
- public function dump($array,$indent = false,$wordwrap = false) {
- // Dumps to some very clean YAML. We'll have to add some more features
- // and options soon. And better support for folding.
-
- // New features and options.
- if ($indent === false or !is_numeric($indent)) {
- $this->_dumpIndent = 2;
- } else {
- $this->_dumpIndent = $indent;
- }
-
- if ($wordwrap === false or !is_numeric($wordwrap)) {
- $this->_dumpWordWrap = 40;
- } else {
- $this->_dumpWordWrap = $wordwrap;
- }
-
- // New YAML document
- $string = "---\n";
-
- // Start at the base of the array and move through it.
- if ($array) {
- $array = (array)$array;
- $previous_key = -1;
- foreach ($array as $key => $value) {
- if (!isset($first_key)) $first_key = $key;
- $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array);
- $previous_key = $key;
- }
- }
- return $string;
- }
-
- /**
- * Attempts to convert a key / value array item to YAML
- * @access private
- * @return string
- * @param $key The name of the key
- * @param $value The value of the item
- * @param $indent The indent of the current node
- */
- private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) {
- if (is_array($value)) {
- if (empty ($value))
- return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array);
- // It has children. What to do?
- // Make it the right kind of item
- $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array);
- // Add the indent
- $indent += $this->_dumpIndent;
- // Yamlize the array
- $string .= $this->_yamlizeArray($value,$indent);
- } elseif (!is_array($value)) {
- // It doesn't have children. Yip.
- $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array);
- }
- return $string;
- }
-
- /**
- * Attempts to convert an array to YAML
- * @access private
- * @return string
- * @param $array The array you want to convert
- * @param $indent The indent of the current level
- */
- private function _yamlizeArray($array,$indent) {
- if (is_array($array)) {
- $string = '';
- $previous_key = -1;
- foreach ($array as $key => $value) {
- if (!isset($first_key)) $first_key = $key;
- $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array);
- $previous_key = $key;
- }
- return $string;
- } else {
- return false;
- }
- }
-
- /**
- * Returns YAML from a key and a value
- * @access private
- * @return string
- * @param $key The name of the key
- * @param $value The value of the item
- * @param $indent The indent of the current node
- */
- private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) {
- // do some folding here, for blocks
- if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false ||
- strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, ' ') !== false ||
- strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 ||
- substr ($value, -1, 1) == ':')
- ) {
- $value = $this->_doLiteralBlock($value,$indent);
- } else {
- $value = $this->_doFolding($value,$indent);
- }
-
- if ($value === array()) $value = '[ ]';
- if (in_array ($value, array ('true', 'TRUE', 'false', 'FALSE', 'y', 'Y', 'n', 'N', 'null', 'NULL'), true)) {
- $value = $this->_doLiteralBlock($value,$indent);
- }
- if (trim ($value) != $value)
- $value = $this->_doLiteralBlock($value,$indent);
-
- if (is_bool($value)) {
- $value = ($value) ? "true" : "false";
- }
-
- if ($value === null) $value = 'null';
- if ($value === "'" . self::REMPTY . "'") $value = null;
-
- $spaces = str_repeat(' ',$indent);
-
- //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) {
- if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) {
- // It's a sequence
- $string = $spaces.'- '.$value."\n";
- } else {
- // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"');
- // It's mapped
- if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; }
- $string = rtrim ($spaces.$key.': '.$value)."\n";
- }
- return $string;
- }
-
- /**
- * Creates a literal block for dumping
- * @access private
- * @return string
- * @param $value
- * @param $indent int The value of the indent
- */
- private function _doLiteralBlock($value,$indent) {
- if ($value === "\n") return '\n';
- if (strpos($value, "\n") === false && strpos($value, "'") === false) {
- return sprintf ("'%s'", $value);
- }
- if (strpos($value, "\n") === false && strpos($value, '"') === false) {
- return sprintf ('"%s"', $value);
- }
- $exploded = explode("\n",$value);
- $newValue = '|';
- $indent += $this->_dumpIndent;
- $spaces = str_repeat(' ',$indent);
- foreach ($exploded as $line) {
- $newValue .= "\n" . $spaces . ($line);
- }
- return $newValue;
- }
-
- /**
- * Folds a string of text, if necessary
- * @access private
- * @return string
- * @param $value The string you wish to fold
- */
- private function _doFolding($value,$indent) {
- // Don't do anything if wordwrap is set to 0
-
- if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) {
- $indent += $this->_dumpIndent;
- $indent = str_repeat(' ',$indent);
- $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
- $value = ">\n".$indent.$wrapped;
- } else {
- if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY)
- $value = '"' . $value . '"';
- }
-
-
- return $value;
- }
-
-// LOADING FUNCTIONS
-
- private function __load($input) {
- $Source = $this->loadFromSource($input);
- return $this->loadWithSource($Source);
- }
-
- private function __loadString($input) {
- $Source = $this->loadFromString($input);
- return $this->loadWithSource($Source);
- }
-
- private function loadWithSource($Source) {
- if (empty ($Source)) return array();
- if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) {
- $array = syck_load (implode ('', $Source));
- return is_array($array) ? $array : array();
- }
-
- $this->path = array();
- $this->result = array();
-
- $cnt = count($Source);
- for ($i = 0; $i < $cnt; $i++) {
- $line = $Source[$i];
-
- $this->indent = strlen($line) - strlen(ltrim($line));
- $tempPath = $this->getParentPathByIndent($this->indent);
- $line = self::stripIndent($line, $this->indent);
- if (self::isComment($line)) continue;
- if (self::isEmpty($line)) continue;
- $this->path = $tempPath;
-
- $literalBlockStyle = self::startsLiteralBlock($line);
- if ($literalBlockStyle) {
- $line = rtrim ($line, $literalBlockStyle . " \n");
- $literalBlock = '';
- $line .= $this->LiteralPlaceHolder;
- $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1]));
- while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) {
- $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent);
- }
- $i--;
- }
-
- while (++$i < $cnt && self::greedilyNeedNextLine($line)) {
- $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t");
- }
- $i--;
-
-
-
- if (strpos ($line, '#')) {
- if (strpos ($line, '"') === false && strpos ($line, "'") === false)
- $line = preg_replace('/\s+#(.+)$/','',$line);
- }
-
- $lineArray = $this->_parseLine($line);
-
- if ($literalBlockStyle)
- $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock);
-
- $this->addArray($lineArray, $this->indent);
-
- foreach ($this->delayedPath as $indent => $delayedPath)
- $this->path[$indent] = $delayedPath;
-
- $this->delayedPath = array();
-
- }
- return $this->result;
- }
-
- private function loadFromSource ($input) {
- if (!empty($input) && strpos($input, "\n") === false && file_exists($input))
- return file($input);
-
- return $this->loadFromString($input);
- }
-
- private function loadFromString ($input) {
- $lines = explode("\n",$input);
- foreach ($lines as $k => $_) {
- $lines[$k] = rtrim ($_, "\r");
- }
- return $lines;
- }
-
- /**
- * Parses YAML code and returns an array for a node
- * @access private
- * @return array
- * @param string $line A line from the YAML file
- */
- private function _parseLine($line) {
- if (!$line) return array();
- $line = trim($line);
- if (!$line) return array();
-
- $array = array();
-
- $group = $this->nodeContainsGroup($line);
- if ($group) {
- $this->addGroup($line, $group);
- $line = $this->stripGroup ($line, $group);
- }
-
- if ($this->startsMappedSequence($line))
- return $this->returnMappedSequence($line);
-
- if ($this->startsMappedValue($line))
- return $this->returnMappedValue($line);
-
- if ($this->isArrayElement($line))
- return $this->returnArrayElement($line);
-
- if ($this->isPlainArray($line))
- return $this->returnPlainArray($line);
-
-
- return $this->returnKeyValuePair($line);
-
- }
-
- /**
- * Finds the type of the passed value, returns the value as the new type.
- * @access private
- * @param string $value
- * @return mixed
- */
- private function _toType($value) {
- if ($value === '') return null;
- $first_character = $value[0];
- $last_character = substr($value, -1, 1);
-
- $is_quoted = false;
- do {
- if (!$value) break;
- if ($first_character != '"' && $first_character != "'") break;
- if ($last_character != '"' && $last_character != "'") break;
- $is_quoted = true;
- } while (0);
-
- if ($is_quoted)
- return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\''));
-
- if (strpos($value, ' #') !== false && !$is_quoted)
- $value = preg_replace('/\s+#(.+)$/','',$value);
-
- if (!$is_quoted) $value = str_replace('\n', "\n", $value);
-
- if ($first_character == '[' && $last_character == ']') {
- // Take out strings sequences and mappings
- $innerValue = trim(substr ($value, 1, -1));
- if ($innerValue === '') return array();
- $explode = $this->_inlineEscape($innerValue);
- // Propagate value array
- $value = array();
- foreach ($explode as $v) {
- $value[] = $this->_toType($v);
- }
- return $value;
- }
-
- if (strpos($value,': ')!==false && $first_character != '{') {
- $array = explode(': ',$value);
- $key = trim($array[0]);
- array_shift($array);
- $value = trim(implode(': ',$array));
- $value = $this->_toType($value);
- return array($key => $value);
- }
-
- if ($first_character == '{' && $last_character == '}') {
- $innerValue = trim(substr ($value, 1, -1));
- if ($innerValue === '') return array();
- // Inline Mapping
- // Take out strings sequences and mappings
- $explode = $this->_inlineEscape($innerValue);
- // Propagate value array
- $array = array();
- foreach ($explode as $v) {
- $SubArr = $this->_toType($v);
- if (empty($SubArr)) continue;
- if (is_array ($SubArr)) {
- $array[key($SubArr)] = $SubArr[key($SubArr)]; continue;
- }
- $array[] = $SubArr;
- }
- return $array;
- }
-
- if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') {
- return null;
- }
-
- if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){
- $intvalue = (int)$value;
- if ($intvalue != PHP_INT_MAX)
- $value = $intvalue;
- return $value;
- }
-
- if (in_array($value,
- array('true', 'on', '+', 'yes', 'y', 'True', 'TRUE', 'On', 'ON', 'YES', 'Yes', 'Y'))) {
- return true;
- }
-
- if (in_array(strtolower($value),
- array('false', 'off', '-', 'no', 'n'))) {
- return false;
- }
-
- if (is_numeric($value)) {
- if ($value === '0') return 0;
- if (rtrim ($value, 0) === $value)
- $value = (float)$value;
- return $value;
- }
-
- return $value;
- }
-
- /**
- * Used in inlines to check for more inlines or quoted strings
- * @access private
- * @return array
- */
- private function _inlineEscape($inline) {
- // There's gotta be a cleaner way to do this...
- // While pure sequences seem to be nesting just fine,
- // pure mappings and mappings with sequences inside can't go very
- // deep. This needs to be fixed.
-
- $seqs = array();
- $maps = array();
- $saved_strings = array();
-
- // Check for strings
- $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
- if (preg_match_all($regex,$inline,$strings)) {
- $saved_strings = $strings[0];
- $inline = preg_replace($regex,'YAMLString',$inline);
- }
- unset($regex);
-
- $i = 0;
- do {
-
- // Check for sequences
- while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) {
- $seqs[] = $matchseqs[0];
- $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1);
- }
-
- // Check for mappings
- while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) {
- $maps[] = $matchmaps[0];
- $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1);
- }
-
- if ($i++ >= 10) break;
-
- } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false);
-
- $explode = explode(', ',$inline);
- $stringi = 0; $i = 0;
-
- while (1) {
-
- // Re-add the sequences
- if (!empty($seqs)) {
- foreach ($explode as $key => $value) {
- if (strpos($value,'YAMLSeq') !== false) {
- foreach ($seqs as $seqk => $seq) {
- $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value);
- $value = $explode[$key];
- }
- }
- }
- }
-
- // Re-add the mappings
- if (!empty($maps)) {
- foreach ($explode as $key => $value) {
- if (strpos($value,'YAMLMap') !== false) {
- foreach ($maps as $mapk => $map) {
- $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value);
- $value = $explode[$key];
- }
- }
- }
- }
-
-
- // Re-add the strings
- if (!empty($saved_strings)) {
- foreach ($explode as $key => $value) {
- while (strpos($value,'YAMLString') !== false) {
- $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1);
- unset($saved_strings[$stringi]);
- ++$stringi;
- $value = $explode[$key];
- }
- }
- }
-
- $finished = true;
- foreach ($explode as $key => $value) {
- if (strpos($value,'YAMLSeq') !== false) {
- $finished = false; break;
- }
- if (strpos($value,'YAMLMap') !== false) {
- $finished = false; break;
- }
- if (strpos($value,'YAMLString') !== false) {
- $finished = false; break;
- }
- }
- if ($finished) break;
-
- $i++;
- if ($i > 10)
- break; // Prevent infinite loops.
- }
-
- return $explode;
- }
-
- private function literalBlockContinues ($line, $lineIndent) {
- if (!trim($line)) return true;
- if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true;
- return false;
- }
-
- private function referenceContentsByAlias ($alias) {
- do {
- if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; }
- $groupPath = $this->SavedGroups[$alias];
- $value = $this->result;
- foreach ($groupPath as $k) {
- $value = $value[$k];
- }
- } while (false);
- return $value;
- }
-
- private function addArrayInline ($array, $indent) {
- $CommonGroupPath = $this->path;
- if (empty ($array)) return false;
-
- foreach ($array as $k => $_) {
- $this->addArray(array($k => $_), $indent);
- $this->path = $CommonGroupPath;
- }
- return true;
- }
-
- private function addArray ($incoming_data, $incoming_indent) {
-
- // print_r ($incoming_data);
-
- if (count ($incoming_data) > 1)
- return $this->addArrayInline ($incoming_data, $incoming_indent);
-
- $key = key ($incoming_data);
- $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null;
- if ($key === '__!YAMLZero') $key = '0';
-
- if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values.
- if ($key || $key === '' || $key === '0') {
- $this->result[$key] = $value;
- } else {
- $this->result[] = $value; end ($this->result); $key = key ($this->result);
- }
- $this->path[$incoming_indent] = $key;
- return;
- }
-
-
-
- $history = array();
- // Unfolding inner array tree.
- $history[] = $_arr = $this->result;
- foreach ($this->path as $k) {
- $history[] = $_arr = $_arr[$k];
- }
-
- if ($this->_containsGroupAlias) {
- $value = $this->referenceContentsByAlias($this->_containsGroupAlias);
- $this->_containsGroupAlias = false;
- }
-
-
- // Adding string or numeric key to the innermost level or $this->arr.
- if (is_string($key) && $key == '<<') {
- if (!is_array ($_arr)) { $_arr = array (); }
-
- $_arr = array_merge ($_arr, $value);
- } elseif ($key || $key === '' || $key === '0') {
- if (!is_array ($_arr))
- $_arr = array ($key=>$value);
- else
- $_arr[$key] = $value;
- } else {
- if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; }
- else { $_arr[] = $value; end ($_arr); $key = key ($_arr); }
- }
-
- $reverse_path = array_reverse($this->path);
- $reverse_history = array_reverse ($history);
- $reverse_history[0] = $_arr;
- $cnt = count($reverse_history) - 1;
- for ($i = 0; $i < $cnt; $i++) {
- $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i];
- }
- $this->result = $reverse_history[$cnt];
-
- $this->path[$incoming_indent] = $key;
-
- if ($this->_containsGroupAnchor) {
- $this->SavedGroups[$this->_containsGroupAnchor] = $this->path;
- if (is_array ($value)) {
- $k = key ($value);
- if (!is_int ($k)) {
- $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k;
- }
- }
- $this->_containsGroupAnchor = false;
- }
-
- }
-
- private static function startsLiteralBlock ($line) {
- $lastChar = substr (trim($line), -1);
- if ($lastChar != '>' && $lastChar != '|') return false;
- if ($lastChar == '|') return $lastChar;
- // HTML tags should not be counted as literal blocks.
- if (preg_match ('#<.*?>$#', $line)) return false;
- return $lastChar;
- }
-
- private static function greedilyNeedNextLine($line) {
- $line = trim ($line);
- if (!strlen($line)) return false;
- if (substr ($line, -1, 1) == ']') return false;
- if ($line[0] == '[') return true;
- if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true;
- return false;
- }
-
- private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) {
- $line = self::stripIndent($line, $indent);
- if ($literalBlockStyle !== '|') {
- $line = self::stripIndent($line);
- }
- $line = rtrim ($line, "\r\n\t ") . "\n";
- if ($literalBlockStyle == '|') {
- return $literalBlock . $line;
- }
- if (strlen($line) == 0)
- return rtrim($literalBlock, ' ') . "\n";
- if ($line == "\n" && $literalBlockStyle == '>') {
- return rtrim ($literalBlock, " \t") . "\n";
- }
- if ($line != "\n")
- $line = trim ($line, "\r\n ") . " ";
- return $literalBlock . $line;
- }
-
- function revertLiteralPlaceHolder ($lineArray, $literalBlock) {
- foreach ($lineArray as $k => $_) {
- if (is_array($_))
- $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock);
- elseif (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder)
- $lineArray[$k] = rtrim ($literalBlock, " \r\n");
- }
- return $lineArray;
- }
-
- private static function stripIndent ($line, $indent = -1) {
- if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line));
- return substr ($line, $indent);
- }
-
- private function getParentPathByIndent ($indent) {
- if ($indent == 0) return array();
- $linePath = $this->path;
- do {
- end($linePath); $lastIndentInParentPath = key($linePath);
- if ($indent <= $lastIndentInParentPath) array_pop ($linePath);
- } while ($indent <= $lastIndentInParentPath);
- return $linePath;
- }
-
-
- private function clearBiggerPathValues ($indent) {
-
-
- if ($indent == 0) $this->path = array();
- if (empty ($this->path)) return true;
-
- foreach ($this->path as $k => $_) {
- if ($k > $indent) unset ($this->path[$k]);
- }
-
- return true;
- }
-
-
- private static function isComment ($line) {
- if (!$line) return false;
- if ($line[0] == '#') return true;
- if (trim($line, " \r\n\t") == '---') return true;
- return false;
- }
-
- private static function isEmpty ($line) {
- return (trim ($line) === '');
- }
-
-
- private function isArrayElement ($line) {
- if (!$line) return false;
- if ($line[0] != '-') return false;
- if (strlen ($line) > 3)
- if (substr($line,0,3) == '---') return false;
-
- return true;
- }
-
- private function isHashElement ($line) {
- return strpos($line, ':');
- }
-
- private function isLiteral ($line) {
- if ($this->isArrayElement($line)) return false;
- if ($this->isHashElement($line)) return false;
- return true;
- }
-
-
- private static function unquote ($value) {
- if (!$value) return $value;
- if (!is_string($value)) return $value;
- if ($value[0] == '\'') return trim ($value, '\'');
- if ($value[0] == '"') return trim ($value, '"');
- return $value;
- }
-
- private function startsMappedSequence ($line) {
- return ($line[0] == '-' && substr ($line, -1, 1) == ':');
- }
-
- private function returnMappedSequence ($line) {
- $array = array();
- $key = self::unquote(trim(substr($line,1,-1)));
- $array[$key] = array();
- $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key);
- return array($array);
- }
-
- private function returnMappedValue ($line) {
- $array = array();
- $key = self::unquote (trim(substr($line,0,-1)));
- $array[$key] = '';
- return $array;
- }
-
- private function startsMappedValue ($line) {
- return (substr ($line, -1, 1) == ':');
- }
-
- private function isPlainArray ($line) {
- return ($line[0] == '[' && substr ($line, -1, 1) == ']');
- }
-
- private function returnPlainArray ($line) {
- return $this->_toType($line);
- }
-
- private function returnKeyValuePair ($line) {
- $array = array();
- $key = '';
- if (strpos ($line, ':')) {
- // It's a key/value pair most likely
- // If the key is in double quotes pull it out
- if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
- $value = trim(str_replace($matches[1],'',$line));
- $key = $matches[2];
- } else {
- // Do some guesswork as to the key and the value
- $explode = explode(':',$line);
- $key = trim($explode[0]);
- array_shift($explode);
- $value = trim(implode(':',$explode));
- }
- // Set the type of the value. Int, string, etc
- $value = $this->_toType($value);
- if ($key === '0') $key = '__!YAMLZero';
- $array[$key] = $value;
- } else {
- $array = array ($line);
- }
- return $array;
-
- }
-
-
- private function returnArrayElement ($line) {
- if (strlen($line) <= 1) return array(array()); // Weird %)
- $array = array();
- $value = trim(substr($line,1));
- $value = $this->_toType($value);
- $array[] = $value;
- return $array;
- }
-
-
- private function nodeContainsGroup ($line) {
- $symbolsForReference = 'A-z0-9_\-';
- if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
- if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
- if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
- if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1];
- if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1];
- if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1];
- return false;
-
- }
-
- private function addGroup ($line, $group) {
- if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1);
- if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1);
- //print_r ($this->path);
- }
-
- private function stripGroup ($line, $group) {
- $line = trim(str_replace($group, '', $line));
- return $line;
- }
-}
-
-// Enable use of Spyc from command line
-// The syntax is the following: php spyc.php spyc.yaml
-
-define ('SPYC_FROM_COMMAND_LINE', false);
-
-do {
- if (!SPYC_FROM_COMMAND_LINE) break;
- if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break;
- if (empty ($_SERVER['PHP_SELF']) || $_SERVER['PHP_SELF'] != 'spyc.php') break;
- $file = $argv[1];
- printf ("Spyc loading file: %s\n", $file);
- print_r (spyc_load_file ($file));
-} while (0);
\ No newline at end of file
diff --git a/lib/jquery.uls/data/ulsdata2json.php b/lib/jquery.uls/data/ulsdata2json.php
deleted file mode 100644
index b11d8297..00000000
--- a/lib/jquery.uls/data/ulsdata2json.php
+++ /dev/null
@@ -1,80 +0,0 @@
-territoryInfo->territory as $territoryRecord ) {
- $territoryAtributes = $territoryRecord->attributes();
- $territoryCodeAttr = $territoryAtributes['type'];
- $territoryCode = "$territoryCodeAttr[0]";
- $parsedLangdb['territories'][$territoryCode] = array();
-
- foreach ( $territoryRecord->languagePopulation as $languageRecord ) {
- $languageAttributes = $languageRecord->attributes();
- $languageCodeAttr = $languageAttributes['type'];
- $parsedLangdb['territories'][$territoryCode][] = "$languageCodeAttr[0]";
- }
-}
-
-print( "Writing JSON langdb...\n" );
-$json = json_encode( $parsedLangdb );
-$js = <<| t |