PageSourceSearch

https://www.kozlovna.eu/templates/smarty/gourmet/scripts/i18.js

js kozlovna.eu collected 2026-10-04 18:45:19 UTC 50,768 bytes, 1,207 lines download raw bytes

1/*!
2 * jQuery Internationalization library
3 *
4 * Copyright (C) 2012 Santhosh Thottingal
5 *
6 * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
7 * anything special to choose one license or the other and you don't have to
8 * notify anyone which license you are using. You are free to use
9 * UniversalLanguageSelector in commercial projects as long as the copyright
10 * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
11 *
12 * @licence GNU General Public Licence 2.0 or later
13 * @licence MIT License
14 */
15
16(function ($) {
17    'use strict';
18
19    var I18N,
20            slice = Array.prototype.slice;
21    /**
22     * @constructor
23     * @param {Object} options
24     */
25    I18N = function (options) {
26        // Load defaults
27        this.options = $.extend({}, I18N.defaults, options);
28
29        this.parser = this.options.parser;
30        this.locale = this.options.locale;
31        this.messageStore = this.options.messageStore;
32        this.languages = {};
33    };
34
35    I18N.prototype = {
36        /**
37         * Localize a given messageKey to a locale.
38         * @param {string} messageKey
39         * @return {string} Localized message
40         */
41        localize: function (messageKey) {
42            var localeParts, localePartIndex, locale, fallbackIndex,
43                    tryingLocale, message;
44
45            locale = this.locale;
46            fallbackIndex = 0;
47
48            while (locale) {
49                // Iterate through locales starting at most-specific until
50                // localization is found. As in fi-Latn-FI, fi-Latn and fi.
51                localeParts = locale.split('-');
52                localePartIndex = localeParts.length;
53
54                do {
55                    tryingLocale = localeParts.slice(0, localePartIndex).join('-');
56                    message = this.messageStore.get(tryingLocale, messageKey);
57
58                    if (message) {
59                        return message;
60                    }
61
62                    localePartIndex--;
63                } while (localePartIndex);
64
65                if (locale === this.options.fallbackLocale) {
66                    break;
67                }
68
69                locale = ($.i18n.fallbacks[ this.locale ] &&
70                        $.i18n.fallbacks[ this.locale ][ fallbackIndex ]) ||
71                        this.options.fallbackLocale;
72                $.i18n.log('Trying fallback locale for ' + this.locale + ': ' + locale + ' (' + messageKey + ')');
73
74                fallbackIndex++;
75            }
76
77            // key not found
78            return '';
79        },
80
81        /*
82         * Destroy the i18n instance.
83         */
84        destroy: function () {
85            $.removeData(document, 'i18n');
86        },
87
88        /**
89         * General message loading API This can take a URL string for
90         * the json formatted messages. Example:
91         * <code>load('path/to/all_localizations.json');</code>
92         *
93         * To load a localization file for a locale:
94         * <code>
95         * load('path/to/de-messages.json', 'de' );
96         * </code>
97         *
98         * To load a localization file from a directory:
99         * <code>
100         * load('path/to/i18n/directory', 'de' );
101         * </code>
102         * The above method has the advantage of fallback resolution.
103         * ie, it will automatically load the fallback locales for de.
104         * For most usecases, this is the recommended method.
105         * It is optional to have trailing slash at end.
106         *
107         * A data object containing message key- message translation mappings
108         * can also be passed. Example:
109         * <code>
110         * load( { 'hello' : 'Hello' }, optionalLocale );
111         * </code>
112         *
113         * A source map containing key-value pair of languagename and locations
114         * can also be passed. Example:
115         * <code>
116         * load( {
117         * bn: 'i18n/bn.json',
118         * he: 'i18n/he.json',
119         * en: 'i18n/en.json'
120         * } )
121         * </code>
122         *
123         * If the data argument is null/undefined/false,
124         * all cached messages for the i18n instance will get reset.
125         *
126         * @param {string|Object} source
127         * @param {string} locale Language tag
128         * @return {jQuery.Promise}
129         */
130        load: function (source, locale) {
131            var fallbackLocales, locIndex, fallbackLocale, sourceMap = {};
132            if (!source && !locale) {
133                source = 'i18n/' + $.i18n().locale + '.json';
134                locale = $.i18n().locale;
135            }
136            if (typeof source === 'string' &&
137                    // source extension should be json, but can have query params after that.
138                    source.split('?')[ 0 ].split('.').pop() !== 'json'
139                    ) {
140                // Load specified locale then check for fallbacks when directory is
141                // specified in load()
142                sourceMap[ locale ] = source + '/' + locale + '.json';
143                fallbackLocales = ($.i18n.fallbacks[ locale ] || [])
144                        .concat(this.options.fallbackLocale);
145                for (locIndex = 0; locIndex < fallbackLocales.length; locIndex++) {
146                    fallbackLocale = fallbackLocales[ locIndex ];
147                    sourceMap[ fallbackLocale ] = source + '/' + fallbackLocale + '.json';
148                }
149                return this.load(sourceMap);
150            } else {
151                return this.messageStore.load(source, locale);
152            }
153
154        },
155
156        /**
157         * Does parameter and magic word substitution.
158         *
159         * @param {string} key Message key
160         * @param {Array} parameters Message parameters
161         * @return {string}
162         */
163        parse: function (key, parameters) {
164            var message = this.localize(key);
165            // FIXME: This changes the state of the I18N object,
166            // should probably not change the 'this.parser' but just
167            // pass it to the parser.
168            this.parser.language = $.i18n.languages[ $.i18n().locale ] || $.i18n.languages[ 'default' ];
169            if (message === '') {
170                message = key;
171            }
172            return this.parser.parse(message, parameters);
173        }
174    };
175
176    /**
177     * Process a message from the $.I18N instance
178     * for the current document, stored in jQuery.data(document).
179     *
180     * @param {string} key Key of the message.
181     * @param {string} param1 [param...] Variadic list of parameters for {key}.
182     * @return {string|$.I18N} Parsed message, or if no key was given
183     * the instance of $.I18N is returned.
184     */
185    $.i18n = function (key, param1) {
186        var parameters,
187                i18n = $.data(document, 'i18n'),
188                options = typeof key === 'object' && key;
189
190        // If the locale option for this call is different then the setup so far,
191        // update it automatically. This doesn't just change the context for this
192        // call but for all future call as well.
193        // If there is no i18n setup yet, don't do this. It will be taken care of
194        // by the `new I18N` construction below.
195        // NOTE: It should only change language for this one call.
196        // Then cache instances of I18N somewhere.
197        if (options && options.locale && i18n && i18n.locale !== options.locale) {
198            i18n.locale = options.locale;
199        }
200
201        if (!i18n) {
202            i18n = new I18N(options);
203            $.data(document, 'i18n', i18n);
204        }
205
206        if (typeof key === 'string') {
207            if (param1 !== undefined) {
208                parameters = slice.call(arguments, 1);
209            } else {
210                parameters = [];
211            }
212
213            return i18n.parse(key, parameters);
214        } else {
215            // FIXME: remove this feature/bug.
216            return i18n;
217        }
218    };
219
220    $.fn.i18n = function () {
221        var i18n = $.data(document, 'i18n');
222
223        if (!i18n) {
224            i18n = new I18N();
225            $.data(document, 'i18n', i18n);
226        }
227
228        return this.each(function () {
229            var $this = $(this),
230                    messageKey = $this.data('i18n'),
231                    lBracket, rBracket, type, key;
232
233            if (messageKey) {
234                lBracket = messageKey.indexOf('[');
235                rBracket = messageKey.indexOf(']');
236                if (lBracket !== -1 && rBracket !== -1 && lBracket < rBracket) {
237                    type = messageKey.slice(lBracket + 1, rBracket);
238                    key = messageKey.slice(rBracket + 1);
239                    if (type === 'html') {
240                        $this.html(i18n.parse(key));
241                    } else {
242                        $this.attr(type, i18n.parse(key));
243                    }
244                } else {
245                    $this.text(i18n.parse(messageKey));
246                }
247            } else {
248                $this.find('[data-i18n]').i18n();
249            }
250        });
251    };
252
253    function getDefaultLocale() {
254        var locale = $('html').attr('lang');
255        if (!locale) {
256            locale = navigator.language || navigator.userLanguage || '';
257        }
258        return locale;
259    }
260
261    $.i18n.languages = {};
262    $.i18n.messageStore = $.i18n.messageStore || {};
263    $.i18n.parser = {
264        // The default parser only handles variable substitution
265        parse: function (message, parameters) {
266            return message.replace(/\$(\d+)/g, function (str, match) {
267                var index = parseInt(match, 10) - 1;
268                return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
269            });
270        },
271        emitter: {}
272    };
273    $.i18n.fallbacks = {};
274    $.i18n.debug = false;
275    $.i18n.log = function ( /* arguments */ ) {
276        if (window.console && $.i18n.debug) {
277            window.console.log.apply(window.console, arguments);
278        }
279    };
280    /* Static members */
281    I18N.defaults = {
282        locale: getDefaultLocale(),
283        fallbackLocale: 'en',
284        parser: $.i18n.parser,
285        messageStore: $.i18n.messageStore
286    };
287
288    // Expose constructor
289    $.i18n.constructor = I18N;
290}(jQuery));
291
292/*!
293 * jQuery Internationalization library - Message Store
294 *
295 * Copyright (C) 2012 Santhosh Thottingal
296 *
297 * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
298 * choose one license or the other and you don't have to notify anyone which license you are using.
299 * You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
300 * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
301 *
302 * @licence GNU General Public Licence 2.0 or later
303 * @licence MIT License
304 */
305
306(function ($) {
307    'use strict';
308
309    var MessageStore = function () {
310        this.messages = {};
311        this.sources = {};
312    };
313
314    function jsonMessageLoader(url) {
315        var deferred = $.Deferred();
316
317        $.getJSON(url)
318                .done(deferred.resolve)
319                .fail(function (jqxhr, settings, exception) {
320                    $.i18n.log('Error in loading messages from ' + url + ' Exception: ' + exception);
321                    // Ignore 404 exception, because we are handling fallabacks explicitly
322                    deferred.resolve();
323                });
324
325        return deferred.promise();
326    }
327
328    /**
329     * See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
330     */
331    MessageStore.prototype = {
332
333        /**
334         * General message loading API This can take a URL string for
335         * the json formatted messages.
336         * <code>load('path/to/all_localizations.json');</code>
337         *
338         * This can also load a localization file for a locale <code>
339         * load( 'path/to/de-messages.json', 'de' );
340         * </code>
341         * A data object containing message key- message translation mappings
342         * can also be passed Eg:
343         * <code>
344         * load( { 'hello' : 'Hello' }, optionalLocale );
345         * </code> If the data argument is
346         * null/undefined/false,
347         * all cached messages for the i18n instance will get reset.
348         *
349         * @param {string|Object} source
350         * @param {string} locale Language tag
351         * @return {jQuery.Promise}
352         */
353        load: function (source, locale) {
354            var key = null,
355                    deferreds = [],
356                    messageStore = this;
357
358            if (typeof source === 'string') {
359                // This is a URL to the messages file.
360                $.i18n.log('Loading messages from: ' + source);
361                return jsonMessageLoader(source)
362                        .then(function (localization) {
363                            return messageStore.load(localization, locale);
364                        });
365            }
366
367            if (locale) {
368                // source is an key-value pair of messages for given locale
369                messageStore.set(locale, source);
370
371                return $.Deferred().resolve();
372            } else {
373                // source is a key-value pair of locales and their source
374                for (key in source) {
375                    if (Object.prototype.hasOwnProperty.call(source, key)) {
376                        locale = key;
377                        // No {locale} given, assume data is a group of languages,
378                        // call this function again for each language.
379                        deferreds.push(messageStore.load(source[ key ], locale));
380                    }
381                }
382                return $.when.apply($, deferreds);
383            }
384
385        },
386
387        /**
388         * Set messages to the given locale.
389         * If locale exists, add messages to the locale.
390         *
391         * @param {string} locale
392         * @param {Object} messages
393         */
394        set: function (locale, messages) {
395            if (!this.messages[ locale ]) {
396                this.messages[ locale ] = messages;
397            } else {
398                this.messages[ locale ] = $.extend(this.messages[ locale ], messages);
399            }
400        },
401
402        /**
403         *
404         * @param {string} locale
405         * @param {string} messageKey
406         * @return {boolean}
407         */
408        get: function (locale, messageKey) {
409            return this.messages[ locale ] && this.messages[ locale ][ messageKey ];
410        }
411    };
412
413    $.extend($.i18n.messageStore, new MessageStore());
414}(jQuery));
415
416/*!
417 * jQuery Internationalization library
418 *
419 * Copyright (C) 2012 Santhosh Thottingal
420 *
421 * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
422 * choose one license or the other and you don't have to notify anyone which license you are using.
423 * You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
424 * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
425 *
426 * @licence GNU General Public Licence 2.0 or later
427 * @licence MIT License
428 */
429(function ($) {
430    'use strict';
431
432    $.i18n = $.i18n || {};
433    $.extend($.i18n.fallbacks, {
434        ab: ['ru'],
435        ace: ['id'],
436        aln: ['sq'],
437        // Not so standard - als is supposed to be Tosk Albanian,
438        // but in Wikipedia it's used for a Germanic language.
439        als: ['gsw', 'de'],
440        an: ['es'],
441        anp: ['hi'],
442        arn: ['es'],
443        arz: ['ar'],
444        av: ['ru'],
445        ay: ['es'],
446        ba: ['ru'],
447        bar: ['de'],
448        'bat-smg': ['sgs', 'lt'],
449        bcc: ['fa'],
450        'be-x-old': ['be-tarask'],
451        bh: ['bho'],
452        bjn: ['id'],
453        bm: ['fr'],
454        bpy: ['bn'],
455        bqi: ['fa'],
456        bug: ['id'],
457        'cbk-zam': ['es'],
458        ce: ['ru'],
459        crh: ['crh-latn'],
460        'crh-cyrl': ['ru'],
461        csb: ['pl'],
462        cv: ['ru'],
463        'de-at': ['de'],
464        'de-ch': ['de'],
465        'de-formal': ['de'],
466        dsb: ['de'],
467        dtp: ['ms'],
468        egl: ['it'],
469        eml: ['it'],
470        ff: ['fr'],
471        fit: ['fi'],
472        'fiu-vro': ['vro', 'et'],
473        frc: ['fr'],
474        frp: ['fr'],
475        frr: ['de'],
476        fur: ['it'],
477        gag: ['tr'],
478        gan: ['gan-hant', 'zh-hant', 'zh-hans'],
479        'gan-hans': ['zh-hans'],
480        'gan-hant': ['zh-hant', 'zh-hans'],
481        gl: ['pt'],
482        glk: ['fa'],
483        gn: ['es'],
484        gsw: ['de'],
485        hif: ['hif-latn'],
486        hsb: ['de'],
487        ht: ['fr'],
488        ii: ['zh-cn', 'zh-hans'],
489        inh: ['ru'],
490        iu: ['ike-cans'],
491        jut: ['da'],
492        jv: ['id'],
493        kaa: ['kk-latn', 'kk-cyrl'],
494        kbd: ['kbd-cyrl'],
495        khw: ['ur'],
496        kiu: ['tr'],
497        kk: ['kk-cyrl'],
498        'kk-arab': ['kk-cyrl'],
499        'kk-latn': ['kk-cyrl'],
500        'kk-cn': ['kk-arab', 'kk-cyrl'],
501        'kk-kz': ['kk-cyrl'],
502        'kk-tr': ['kk-latn', 'kk-cyrl'],
503        kl: ['da'],
504        'ko-kp': ['ko'],
505        koi: ['ru'],
506        krc: ['ru'],
507        ks: ['ks-arab'],
508        ksh: ['de'],
509        ku: ['ku-latn'],
510        'ku-arab': ['ckb'],
511        kv: ['ru'],
512        lad: ['es'],
513        lb: ['de'],
514        lbe: ['ru'],
515        lez: ['ru'],
516        li: ['nl'],
517        lij: ['it'],
518        liv: ['et'],
519        lmo: ['it'],
520        ln: ['fr'],
521        ltg: ['lv'],
522        lzz: ['tr'],
523        mai: ['hi'],
524        'map-bms': ['jv', 'id'],
525        mg: ['fr'],
526        mhr: ['ru'],
527        min: ['id'],
528        mo: ['ro'],
529        mrj: ['ru'],
530        mwl: ['pt'],
531        myv: ['ru'],
532        mzn: ['fa'],
533        nah: ['es'],
534        nap: ['it'],
535        nds: ['de'],
536        'nds-nl': ['nl'],
537        'nl-informal': ['nl'],
538        no: ['nb'],
539        os: ['ru'],
540        pcd: ['fr'],
541        pdc: ['de'],
542        pdt: ['de'],
543        pfl: ['de'],
544        pms: ['it'],
545        pt: ['pt-br'],
546        'pt-br': ['pt'],
547        qu: ['es'],
548        qug: ['qu', 'es'],
549        rgn: ['it'],
550        rmy: ['ro'],
551        'roa-rup': ['rup'],
552        rue: ['uk', 'ru'],
553        ruq: ['ruq-latn', 'ro'],
554        'ruq-cyrl': ['mk'],
555        'ruq-latn': ['ro'],
556        sa: ['hi'],
557        sah: ['ru'],
558        scn: ['it'],
559        sg: ['fr'],
560        sgs: ['lt'],
561        sli: ['de'],
562        sr: ['sr-ec'],
563        srn: ['nl'],
564        stq: ['de'],
565        su: ['id'],
566        szl: ['pl'],
567        tcy: ['kn'],
568        tg: ['tg-cyrl'],
569        tt: ['tt-cyrl', 'ru'],
570        'tt-cyrl': ['ru'],
571        ty: ['fr'],
572        udm: ['ru'],
573        ug: ['ug-arab'],
574        uk: ['ru'],
575        vec: ['it'],
576        vep: ['et'],
577        vls: ['nl'],
578        vmf: ['de'],
579        vot: ['fi'],
580        vro: ['et'],
581        wa: ['fr'],
582        wo: ['fr'],
583        wuu: ['zh-hans'],
584        xal: ['ru'],
585        xmf: ['ka'],
586        yi: ['he'],
587        za: ['zh-hans'],
588        zea: ['nl'],
589        zh: ['zh-hans'],
590        'zh-classical': ['lzh'],
591        'zh-cn': ['zh-hans'],
592        'zh-hant': ['zh-hans'],
593        'zh-hk': ['zh-hant', 'zh-hans'],
594        'zh-min-nan': ['nan'],
595        'zh-mo': ['zh-hk', 'zh-hant', 'zh-hans'],
596        'zh-my': ['zh-sg', 'zh-hans'],
597        'zh-sg': ['zh-hans'],
598        'zh-tw': ['zh-hant', 'zh-hans'],
599        'zh-yue': ['yue']
600    });
601}(jQuery));
602/*!
603 * jQuery Internationalization library
604 *
605 * Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
606 *
607 * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
608 * anything special to choose one license or the other and you don't have to
609 * notify anyone which license you are using. You are free to use
610 * UniversalLanguageSelector in commercial projects as long as the copyright
611 * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
612 *
613 * @licence GNU General Public Licence 2.0 or later
614 * @licence MIT License
615 */
616
617(function ($) {
618    'use strict';
619
620    var MessageParser = function (options) {
621        this.options = $.extend({}, $.i18n.parser.defaults, options);
622        this.language = $.i18n.languages[ String.locale ] || $.i18n.languages[ 'default' ];
623        this.emitter = $.i18n.parser.emitter;
624    };
625
626    MessageParser.prototype = {
627
628        constructor: MessageParser,
629
630        simpleParse: function (message, parameters) {
631            return message.replace(/\$(\d+)/g, function (str, match) {
632                var index = parseInt(match, 10) - 1;
633
634                return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
635            });
636        },
637
638        parse: function (message, replacements) {
639            if (message.indexOf('{{') < 0) {
640                return this.simpleParse(message, replacements);
641            }
642
643            this.emitter.language = $.i18n.languages[ $.i18n().locale ] ||
644                    $.i18n.languages[ 'default' ];
645
646            return this.emitter.emit(this.ast(message), replacements);
647        },
648
649        ast: function (message) {
650            var pipe, colon, backslash, anyCharacter, dollar, digits, regularLiteral,
651                    regularLiteralWithoutBar, regularLiteralWithoutSpace, escapedOrLiteralWithoutBar,
652                    escapedOrRegularLiteral, templateContents, templateName, openTemplate,
653                    closeTemplate, expression, paramExpression, result,
654                    pos = 0;
655
656            // Try parsers until one works, if none work return null
657            function choice(parserSyntax) {
658                return function () {
659                    var i, result;
660
661                    for (i = 0; i < parserSyntax.length; i++) {
662                        result = parserSyntax[ i ]();
663
664                        if (result !== null) {
665                            return result;
666                        }
667                    }
668
669                    return null;
670                };
671            }
672
673            // Try several parserSyntax-es in a row.
674            // All must succeed; otherwise, return null.
675            // This is the only eager one.
676            function sequence(parserSyntax) {
677                var i, res,
678                        originalPos = pos,
679                        result = [];
680
681                for (i = 0; i < parserSyntax.length; i++) {
682                    res = parserSyntax[ i ]();
683
684                    if (res === null) {
685                        pos = originalPos;
686
687                        return null;
688                    }
689
690                    result.push(res);
691                }
692
693                return result;
694            }
695
696            // Run the same parser over and over until it fails.
697            // Must succeed a minimum of n times; otherwise, return null.
698            function nOrMore(n, p) {
699                return function () {
700                    var originalPos = pos,
701                            result = [],
702                            parsed = p();
703
704                    while (parsed !== null) {
705                        result.push(parsed);
706                        parsed = p();
707                    }
708
709                    if (result.length < n) {
710                        pos = originalPos;
711
712                        return null;
713                    }
714
715                    return result;
716                };
717            }
718
719            // Helpers -- just make parserSyntax out of simpler JS builtin types
720
721            function makeStringParser(s) {
722                var len = s.length;
723
724                return function () {
725                    var result = null;
726
727                    if (message.slice(pos, pos + len) === s) {
728                        result = s;
729                        pos += len;
730                    }
731
732                    return result;
733                };
734            }
735
736            function makeRegexParser(regex) {
737                return function () {
738                    var matches = message.slice(pos).match(regex);
739
740                    if (matches === null) {
741                        return null;
742                    }
743
744                    pos += matches[ 0 ].length;
745
746                    return matches[ 0 ];
747                };
748            }
749
750            pipe = makeStringParser('|');
751            colon = makeStringParser(':');
752            backslash = makeStringParser('\\');
753            anyCharacter = makeRegexParser(/^./);
754            dollar = makeStringParser('$');
755            digits = makeRegexParser(/^\d+/);
756            regularLiteral = makeRegexParser(/^[^{}[\]$\\]/);
757            regularLiteralWithoutBar = makeRegexParser(/^[^{}[\]$\\|]/);
758            regularLiteralWithoutSpace = makeRegexParser(/^[^{}[\]$\s]/);
759
760            // There is a general pattern:
761            // parse a thing;
762            // if it worked, apply transform,
763            // otherwise return null.
764            // But using this as a combinator seems to cause problems
765            // when combined with nOrMore().
766            // May be some scoping issue.
767            function transform(p, fn) {
768                return function () {
769                    var result = p();
770
771                    return result === null ? null : fn(result);
772                };
773            }
774
775            // Used to define "literals" within template parameters. The pipe
776            // character is the parameter delimeter, so by default
777            // it is not a literal in the parameter
778            function literalWithoutBar() {
779                var result = nOrMore(1, escapedOrLiteralWithoutBar)();
780
781                return result === null ? null : result.join('');
782            }
783
784            function literal() {
785                var result = nOrMore(1, escapedOrRegularLiteral)();
786
787                return result === null ? null : result.join('');
788            }
789
790            function escapedLiteral() {
791                var result = sequence([backslash, anyCharacter]);
792
793                return result === null ? null : result[ 1 ];
794            }
795
796            choice([escapedLiteral, regularLiteralWithoutSpace]);
797            escapedOrLiteralWithoutBar = choice([escapedLiteral, regularLiteralWithoutBar]);
798            escapedOrRegularLiteral = choice([escapedLiteral, regularLiteral]);
799
800            function replacement() {
801                var result = sequence([dollar, digits]);
802
803                if (result === null) {
804                    return null;
805                }
806
807                return ['REPLACE', parseInt(result[ 1 ], 10) - 1];
808            }
809
810            templateName = transform(
811                    // see $wgLegalTitleChars
812                    // not allowing : due to the need to catch "PLURAL:$1"
813                    makeRegexParser(/^[ !"$&'()*,./0-9;=?@A-Z^_`a-z~\x80-\xFF+-]+/),
814                    function (result) {
815                        return result.toString();
816                    }
817            );
818
819            function templateParam() {
820                var expr,
821                        result = sequence([pipe, nOrMore(0, paramExpression)]);
822
823                if (result === null) {
824                    return null;
825                }
826
827                expr = result[ 1 ];
828
829                // use a "CONCAT" operator if there are multiple nodes,
830                // otherwise return the first node, raw.
831                return expr.length > 1 ? ['CONCAT'].concat(expr) : expr[ 0 ];
832            }
833
834            function templateWithReplacement() {
835                var result = sequence([templateName, colon, replacement]);
836
837                return result === null ? null : [result[ 0 ], result[ 2 ]];
838            }
839
840            function templateWithOutReplacement() {
841                var result = sequence([templateName, colon, paramExpression]);
842
843                return result === null ? null : [result[ 0 ], result[ 2 ]];
844            }
845
846            templateContents = choice([
847                function () {
848                    var res = sequence([
849                        // templates can have placeholders for dynamic
850                        // replacement eg: {{PLURAL:$1|one car|$1 cars}}
851                        // or no placeholders eg:
852                        // {{GRAMMAR:genitive|{{SITENAME}}}
853                        choice([templateWithReplacement, templateWithOutReplacement]),
854                        nOrMore(0, templateParam)
855                    ]);
856
857                    return res === null ? null : res[ 0 ].concat(res[ 1 ]);
858                },
859                function () {
860                    var res = sequence([templateName, nOrMore(0, templateParam)]);
861
862                    if (res === null) {
863                        return null;
864                    }
865
866                    return [res[ 0 ]].concat(res[ 1 ]);
867                }
868            ]);
869
870            openTemplate = makeStringParser('{{');
871            closeTemplate = makeStringParser('}}');
872
873            function template() {
874                var result = sequence([openTemplate, templateContents, closeTemplate]);
875
876                return result === null ? null : result[ 1 ];
877            }
878
879            expression = choice([template, replacement, literal]);
880            paramExpression = choice([template, replacement, literalWithoutBar]);
881
882            function start() {
883                var result = nOrMore(0, expression)();
884
885                if (result === null) {
886                    return null;
887                }
888
889                return ['CONCAT'].concat(result);
890            }
891
892            result = start();
893
894            /*
895             * For success, the pos must have gotten to the end of the input
896             * and returned a non-null.
897             * n.b. This is part of language infrastructure, so we do not throw an
898             * internationalizable message.
899             */
900            if (result === null || pos !== message.length) {
901                throw new Error('Parse error at position ' + pos.toString() + ' in input: ' + message);
902            }
903
904            return result;
905        }
906
907    };
908
909    $.extend($.i18n.parser, new MessageParser());
910}(jQuery));
911
912/*!
913 * jQuery Internationalization library
914 *
915 * Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
916 *
917 * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
918 * anything special to choose one license or the other and you don't have to
919 * notify anyone which license you are using. You are free to use
920 * UniversalLanguageSelector in commercial projects as long as the copyright
921 * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
922 *
923 * @licence GNU General Public Licence 2.0 or later
924 * @licence MIT License
925 */
926
927(function ($) {
928    'use strict';
929
930    var MessageParserEmitter = function () {
931        this.language = $.i18n.languages[ String.locale ] || $.i18n.languages[ 'default' ];
932    };
933
934    MessageParserEmitter.prototype = {
935        constructor: MessageParserEmitter,
936
937        /**
938         * (We put this method definition here, and not in prototype, to make
939         * sure it's not overwritten by any magic.) Walk entire node structure,
940         * applying replacements and template functions when appropriate
941         *
942         * @param {Mixed} node abstract syntax tree (top node or subnode)
943         * @param {Array} replacements for $1, $2, ... $n
944         * @return {Mixed} single-string node or array of nodes suitable for
945         *  jQuery appending.
946         */
947        emit: function (node, replacements) {
948            var ret, subnodes, operation,
949                    messageParserEmitter = this;
950
951            switch (typeof node) {
952                case 'string':
953                case 'number':
954                    ret = node;
955                    break;
956                case 'object':
957                    // node is an array of nodes
958                    subnodes = $.map(node.slice(1), function (n) {
959                        return messageParserEmitter.emit(n, replacements);
960                    });
961
962                    operation = node[ 0 ].toLowerCase();
963
964                    if (typeof messageParserEmitter[ operation ] === 'function') {
965                        ret = messageParserEmitter[ operation ](subnodes, replacements);
966                    } else {
967                        throw new Error('unknown operation "' + operation + '"');
968                    }
969
970                    break;
971                case 'undefined':
972                    // Parsing the empty string (as an entire expression, or as a
973                    // paramExpression in a template) results in undefined
974                    // Perhaps a more clever parser can detect this, and return the
975                    // empty string? Or is that useful information?
976                    // The logical thing is probably to return the empty string here
977                    // when we encounter undefined.
978                    ret = '';
979                    break;
980                default:
981                    throw new Error('unexpected type in AST: ' + typeof node);
982            }
983
984            return ret;
985        },
986
987        /**
988         * Parsing has been applied depth-first we can assume that all nodes
989         * here are single nodes Must return a single node to parents -- a
990         * jQuery with synthetic span However, unwrap any other synthetic spans
991         * in our children and pass them upwards
992         *
993         * @param {Array} nodes Mixed, some single nodes, some arrays of nodes.
994         * @return {string}
995         */
996        concat: function (nodes) {
997            var result = '';
998
999            $.each(nodes, function (i, node) {
1000                // strings, integers, anything else
1001                result += node;
1002            });
1003
1004            return result;
1005        },
1006
1007        /**
1008         * Return escaped replacement of correct index, or string if
1009         * unavailable. Note that we expect the parsed parameter to be
1010         * zero-based. i.e. $1 should have become [ 0 ]. if the specified
1011         * parameter is not found return the same string (e.g. "$99" ->
1012         * parameter 98 -> not found -> return "$99" ) TODO throw error if
1013         * nodes.length > 1 ?
1014         *
1015         * @param {Array} nodes One element, integer, n >= 0
1016         * @param {Array} replacements for $1, $2, ... $n
1017         * @return {string} replacement
1018         */
1019        replace: function (nodes, replacements) {
1020            var index = parseInt(nodes[ 0 ], 10);
1021
1022            if (index < replacements.length) {
1023                // replacement is not a string, don't touch!
1024                return replacements[ index ];
1025            } else {
1026                // index not found, fallback to displaying variable
1027                return '$' + (index + 1);
1028            }
1029        },
1030
1031        /**
1032         * Transform parsed structure into pluralization n.b. The first node may
1033         * be a non-integer (for instance, a string representing an Arabic
1034         * number). So convert it back with the current language's
1035         * convertNumber.
1036         *
1037         * @param {Array} nodes List [ {String|Number}, {String}, {String} ... ]
1038         * @return {string} selected pluralized form according to current
1039         *  language.
1040         */
1041        plural: function (nodes) {
1042            var count = parseFloat(this.language.convertNumber(nodes[ 0 ], 10)),
1043                    forms = nodes.slice(1);
1044
1045            return forms.length ? this.language.convertPlural(count, forms) : '';
1046        },
1047
1048        /**
1049         * Transform parsed structure into gender Usage
1050         * {{gender:gender|masculine|feminine|neutral}}.
1051         *
1052         * @param {Array} nodes List [ {String}, {String}, {String} , {String} ]
1053         * @return {string} selected gender form according to current language
1054         */
1055        gender: function (nodes) {
1056            var gender = nodes[ 0 ],
1057                    forms = nodes.slice(1);
1058
1059            return this.language.gender(gender, forms);
1060        },
1061
1062        /**
1063         * Transform parsed structure into grammar conversion. Invoked by
1064         * putting {{grammar:form|word}} in a message
1065         *
1066         * @param {Array} nodes List [{Grammar case eg: genitive}, {String word}]
1067         * @return {string} selected grammatical form according to current
1068         *  language.
1069         */
1070        grammar: function (nodes) {
1071            var form = nodes[ 0 ],
1072                    word = nodes[ 1 ];
1073
1074            return word && form && this.language.convertGrammar(word, form);
1075        }
1076    };
1077
1078    $.extend($.i18n.parser.emitter, new MessageParserEmitter());
1079}(jQuery));
1080
1081/*!
1082 * BIDI embedding support for jQuery.i18n
1083 *
1084 * Copyright (C) 2015, David Chan
1085 *
1086 * This code is dual licensed GPLv2 or later and MIT. You don't have to do
1087 * anything special to choose one license or the other and you don't have to
1088 * notify anyone which license you are using. You are free to use this code
1089 * in commercial projects as long as the copyright header is left intact.
1090 * See files GPL-LICENSE and MIT-LICENSE for details.
1091 *
1092 * @licence GNU General Public Licence 2.0 or later
1093 * @licence MIT License
1094 */
1095
1096(function ($) {
1097    'use strict';
1098    var strongDirRegExp;
1099
1100    /**
1101     * Matches the first strong directionality codepoint:
1102     * - in group 1 if it is LTR
1103     * - in group 2 if it is RTL
1104     * Does not match if there is no strong directionality codepoint.
1105     *
1106     * Generated by UnicodeJS (see tools/strongDir) from the UCD; see
1107     * https://phabricator.wikimedia.org/diffusion/GUJS/ .
1108     */
1109    // eslint-disable-next-line no-misleading-character-class
1110    strongDirRegExp = new RegExp(
1111            '(?:' +
1112            '(' +
1113            '[\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02b8\u02bb-\u02c1\u02d0\u02d1\u02e0-\u02e4\u02ee\u0370-\u0373\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0482\u048a-\u052f\u0531-\u0556\u0559-\u055f\u0561-\u0587\u0589\u0903-\u0939\u093b\u093d-\u0940\u0949-\u094c\u094e-\u0950\u0958-\u0961\u0964-\u0980\u0982\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd-\u09c0\u09c7\u09c8\u09cb\u09cc\u09ce\u09d7\u09dc\u09dd\u09df-\u09e1\u09e6-\u09f1\u09f4-\u09fa\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3e-\u0a40\u0a59-\u0a5c\u0a5e\u0a66-\u0a6f\u0a72-\u0a74\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0
1113ab9\u0abd-\u0ac0\u0ac9\u0acb\u0acc\u0ad0\u0ae0\u0ae1\u0ae6-\u0af0\u0af9\u0b02\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b3e\u0b40\u0b47\u0b48\u0b4b\u0b4c\u0b57\u0b5c\u0b5d\u0b5f-\u0b61\u0b66-\u0b77\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe\u0bbf\u0bc1\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd0\u0bd7\u0be6-\u0bf2\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c41-\u0c44\u0c58-\u0c5a\u0c60\u0c61\u0c66-\u0c6f\u0c7f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd-\u0cc4\u0cc6-\u0cc8\u0cca\u0ccb\u0cd5\u0cd6\u0cde\u0ce0\u0ce1\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d4e\u0d57\u0d5f-\u0d61\u0d66-\u0d75\u0d79-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dcf-\u0dd1\u0dd8-\u0ddf\u0de6-\u0def\u0df2-\u0df4\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e4f-\u0e5b\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0ed0-\u0ed9\u0edc-\u0edf\u0f00-\u0f17\u0f1a-\u0f34\u0f36\u0f38\u0f3e-\u0f47\u0f49-\u0f6c\u0f7f\u0f85\u0f88-\u0f8c\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce-\u0fda\u1000-\u102c\u1031\u1038\u103b\u103c\u103f-\u1057\u105a-\u105d\u1061-\u1070\u1075-\u1081\u1083\u1084\u1087-\u108c\u108e-\u109c\u109e-\u10c5\u10c7\u10cd\u10d0-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1360-\u137c\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u167f\u1681-\u169a\u16a0-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1735\u1736\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17b6\u17be-\u17c5\u17c7\u17c8\u17d4-\u17da\u17dc\u17e0-\u17e9\u1810-\u1819\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1923-\u1926\u1929-\u192b\u1930\u1931\u1933-\u1938\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19da\u1a00-\u1a16\u1a19\u1a1a\u1a1e-\u1a55\u1a57\u1a61\u1a63\u1a64\u1a6d-\u1a72\u1a80-\u1a89\u1a90-\u1a99\u1aa0-\u1aad\u1b04-\u1b33\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b4b\u1b50-\u1b6a\u1b74-\u1b7c\u1b82-\u1ba1\u1ba6\u1ba7\u1baa\u1bae-\u1be5\u1be7\u1bea-\u1bec\u1bee\u1bf2\u1bf3\u1bfc-\u1c2b\u1c34\u1c35\u1c3b-\u1c49\u1c4d-\u1c7f\u1cc0-\u1cc7\u1cd3\u1ce1\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200e\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u214f\u2160-\u2188\u2336-\u237a\u2395\u249c-\u24e9\u26ac\u2800-\u28ff\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d70\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u302e\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u3190-\u31ba\u31f0-\u321c\u3220-\u324f\u3260-\u327b\u327f-\u32b0\u32c0-\u32cb\u32d0-\u32fe\u3300-\u3376\u337b-\u33dd\u33e0-\u33fe\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua60c\ua610-\ua62b\ua640-\ua66e\ua680-\ua69d\ua6a0-\ua6ef\ua6f2-\ua6f7\ua722-\ua787\ua789-\ua7ad\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua824\ua827\ua830-\ua837\ua840-\ua873\ua880-\ua8c3\ua8ce-\ua8d9\ua8f2-\ua8fd\ua900-\ua925\ua92e-\ua946\ua952\ua953\ua95f-\ua97c\ua983-\ua9b2\ua9b4\ua9b5\ua9ba\ua9bb\ua9bd-\ua9cd\ua9cf-\ua9d9\ua9de-\ua9e4\ua9e6-\ua9fe\uaa00-\uaa28\uaa2f\uaa30\uaa33\uaa34\uaa40-\uaa42\uaa44-\uaa4b\uaa4d\uaa50-\uaa59\uaa5c-\uaa7b\uaa7d-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaaeb\uaaee-\uaaf5\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab65\uab70-\uabe4\uabe6\uabe7\uabe9-\uabec\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\ue000-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]|\ud800[\udc00-\udc0b]|\ud800[\udc0d-\udc26]|\ud800[\udc28-\udc3a]|\ud800\udc3c|\ud800\udc3d|\ud800[\udc3f-\udc4d]|\ud800[\udc50-\udc5d]|\ud800[\udc80-\udcfa]|\ud800\udd00|\ud800\udd02|\ud800[\udd07-\udd33]|\ud800[\udd37-\udd3f]|\ud800[\uddd0-\uddfc]|\ud800[\ude80-\ude9c]|\ud800[\udea0-\uded0]|\ud800[\udf00-\udf23]|\ud800[\udf30-\udf4a]|\ud800[\udf50-\udf75]|\ud800[\udf80-\udf9d]|\ud800[\udf9f-\udfc3]|\ud800[\udfc8-\udfd5]|\ud801[\udc00-\udc9d]|\ud801[\udca0-\udca9]|\ud801[\udd00-\udd27]|\ud801[\udd30-\udd63]|\ud801\udd6f|\ud801[\ude00-\udf36]|\ud801[\udf40-\udf55]|\ud801[\udf60-\udf67]|\ud804\udc00|\ud804[\udc02-\udc37]|\ud804[\udc47-\udc4d]|\ud804[\udc66-\udc6f]|\ud804[\udc82-\udcb2]|\ud804\udcb7|\ud804\udcb8|\ud804[\udcbb-\udcc1]|\ud804[\udcd0-\udce8]|\ud804[\udcf0-\udcf9]|\ud804[\udd03-\udd26]|\ud804\udd2c|\ud804[\udd36-\udd43]|\ud804[\udd50-\udd72]|\ud804[\udd74-\udd76]|\ud804[\udd82-\uddb5]|\ud804[\uddbf-\uddc9]|\ud804\uddcd|\ud804[\uddd0-\udddf]|\ud804[\udde1-\uddf4]|\ud804[\ude00-\ude11]|\ud804[\ude13-\ude2e]|\ud804\ude32|\ud804\ude33|\ud804\ude35|\ud804[\ude38-\ude3d]|\ud804[\ude80-\ude86]|\ud804\ude88|\ud804[\ude8a-\ude8d]|\ud804[\ude8f-\ude9d]|\ud804[\ude9f-\udea9]|\ud804[\udeb0-\udede]|\ud804[\udee0-\udee2]|\ud804[\udef0-\udef9]|\ud804\udf02|\ud804\udf03|\ud804[\udf05-\udf0c]|\ud804\udf0f|\ud804\udf10|\ud804[\udf13-\udf28]|\ud804[\udf2a-\udf30]|\ud804\udf32|\ud804\udf33|\ud804[\udf35-\udf39]|\ud804[\udf3d-\udf3f]|\ud804[\udf41-\udf44]|\ud804\udf47|\ud804\udf48|\ud804[\udf4b-\udf4d]|\ud804\udf50|\ud804\udf57|\ud804[\udf5d-\udf63]|\ud805[\udc80-\udcb2]|\ud805\udcb9|\ud805[\udcbb-\udcbe]|\ud805\udcc1|\ud805[\udcc4-\udcc7]|\ud805[\udcd0-\udcd9]|\ud805[\udd80-\uddb1]|\ud805[\uddb8-\uddbb]|\ud805\uddbe|\ud805[\uddc1-\udddb]|\ud805[\ude00-\ude32]|\ud805\ude3b|\ud805\ude3c|\ud805\ude3e|\ud805[\ude41-\ude44]|\ud805[\ude50-\ude59]|\ud805[\ude80-\udeaa]|\ud805\udeac|\ud805\udeae|\ud805\udeaf|\ud805\udeb6|\ud805[\udec0-\udec9]|\ud805[\udf00-\udf19]|\ud805\udf20|\ud805\udf21|\ud805\udf26|\ud805[\udf30-\udf3f]|\ud806[\udca0-\udcf2]|\ud806\udcff|\ud806[\udec0-\udef8]|\ud808[\udc00-\udf99]|\ud809[\udc00-\udc6e]|\ud809[\udc70-\udc74]|\ud809[\udc80-\udd43]|\ud80c[\udc00-\udfff]|\ud80d[\udc00-\udc2e]|\ud811[\udc00-\ude46]|\ud81a[\udc00-\ude38]|\ud81a[\ude40-\ude5e]|\ud81a[\ude60-\ude69]|\ud81a\ude6e|\ud81a\ude6f|\ud81a[\uded0-\udeed]|\ud81a\udef5|\ud81a[\udf00-\udf2f]|\ud81a[\udf37-\udf45]|\ud81a[\udf50-\udf59]|\ud81a[\udf5b-\udf61]|\ud81a[\udf63-\udf77]|\ud81a[\udf7d-\udf8f]|\ud81b[\udf00-\udf44]|\ud81b[\udf50-\udf7e]|\ud81b[\udf93-\udf9f]|\ud82c\udc00|\ud82c\udc01|\ud82f[\udc00-\udc6a]|\ud82f[\udc70-\udc7c]|\ud82f[\udc80-\udc88]|\ud82f[\udc90-\udc99]|\ud82f\udc9c|\ud82f\udc9f|\ud834[\udc00-\udcf5]|\ud834[\udd00-\udd26]|\ud834[\udd29-\udd66]|\ud834[\udd6a-\udd72]|\ud834\udd83|\ud834\udd84|\ud834[\udd8c-\udda9]|\ud834[\uddae-\udde8]|\ud834[\udf60-\udf71]|\ud835[\udc00-\udc54]|\ud835[\udc56-\udc9c]|\ud835\udc9e|\ud835\udc9f|\ud835\udca2|\ud835\udca5|\ud835\udca6|\ud835[\udca9-\udcac]|\ud835[\udcae-\udcb9]|\ud835\udcbb|\ud835[\udcbd-\udcc3]|\ud835[\udcc5-\udd05]|\ud835[\udd07-\udd0a]|\ud835[\udd0d-\udd14]|\ud835[\udd16-\udd1c]|\ud835[\udd1e-\udd39]|\ud835[\udd3b-\udd3e]|\ud835[\udd40-\udd44]|\ud835\udd46|\ud835[\udd4a-\udd50
1113]|\ud835[\udd52-\udea5]|\ud835[\udea8-\udeda]|\ud835[\udedc-\udf14]|\ud835[\udf16-\udf4e]|\ud835[\udf50-\udf88]|\ud835[\udf8a-\udfc2]|\ud835[\udfc4-\udfcb]|\ud836[\udc00-\uddff]|\ud836[\ude37-\ude3a]|\ud836[\ude6d-\ude74]|\ud836[\ude76-\ude83]|\ud836[\ude85-\ude8b]|\ud83c[\udd10-\udd2e]|\ud83c[\udd30-\udd69]|\ud83c[\udd70-\udd9a]|\ud83c[\udde6-\ude02]|\ud83c[\ude10-\ude3a]|\ud83c[\ude40-\ude48]|\ud83c\ude50|\ud83c\ude51|[\ud840-\ud868][\udc00-\udfff]|\ud869[\udc00-\uded6]|\ud869[\udf00-\udfff]|[\ud86a-\ud86c][\udc00-\udfff]|\ud86d[\udc00-\udf34]|\ud86d[\udf40-\udfff]|\ud86e[\udc00-\udc1d]|\ud86e[\udc20-\udfff]|[\ud86f-\ud872][\udc00-\udfff]|\ud873[\udc00-\udea1]|\ud87e[\udc00-\ude1d]|[\udb80-\udbbe][\udc00-\udfff]|\udbbf[\udc00-\udffd]|[\udbc0-\udbfe][\udc00-\udfff]|\udbff[\udc00-\udffd]' +
1114            ')|(' +
1115            '[\u0590\u05be\u05c0\u05c3\u05c6\u05c8-\u05ff\u07c0-\u07ea\u07f4\u07f5\u07fa-\u0815\u081a\u0824\u0828\u082e-\u0858\u085c-\u089f\u200f\ufb1d\ufb1f-\ufb28\ufb2a-\ufb4f\u0608\u060b\u060d\u061b-\u064a\u066d-\u066f\u0671-\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u0710\u0712-\u072f\u074b-\u07a5\u07b1-\u07bf\u08a0-\u08e2\ufb50-\ufd3d\ufd40-\ufdcf\ufdf0-\ufdfc\ufdfe\ufdff\ufe70-\ufefe]|\ud802[\udc00-\udd1e]|\ud802[\udd20-\ude00]|\ud802\ude04|\ud802[\ude07-\ude0b]|\ud802[\ude10-\ude37]|\ud802[\ude3b-\ude3e]|\ud802[\ude40-\udee4]|\ud802[\udee7-\udf38]|\ud802[\udf40-\udfff]|\ud803[\udc00-\ude5f]|\ud803[\ude7f-\udfff]|\ud83a[\udc00-\udccf]|\ud83a[\udcd7-\udfff]|\ud83b[\udc00-\uddff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\ude00-\udeef]|\ud83b[\udef2-\udeff]' +
1116            ')' +
1117            ')'
1118            );
1119
1120    /**
1121     * Gets directionality of the first strongly directional codepoint
1122     *
1123     * This is the rule the BIDI algorithm uses to determine the directionality of
1124     * paragraphs ( http://unicode.org/reports/tr9/#The_Paragraph_Level ) and
1125     * FSI isolates ( http://unicode.org/reports/tr9/#Explicit_Directional_Isolates ).
1126     *
1127     * TODO: Does not handle BIDI control characters inside the text.
1128     * TODO: Does not handle unallocated characters.
1129     *
1130     * @param {string} text The text from which to extract initial directionality.
1131     * @return {string} Directionality (either 'ltr' or 'rtl')
1132     */
1133    function strongDirFromContent(text) {
1134        var m = text.match(strongDirRegExp);
1135        if (!m) {
1136            return null;
1137        }
1138        if (m[ 2 ] === undefined) {
1139            return 'ltr';
1140        }
1141        return 'rtl';
1142    }
1143
1144    $.extend($.i18n.parser.emitter, {
1145        /**
1146         * Wraps argument with unicode control characters for directionality safety
1147         *
1148         * This solves the problem where directionality-neutral characters at the edge of
1149         * the argument string get interpreted with the wrong directionality from the
1150         * enclosing context, giving renderings that look corrupted like "(Ben_(WMF".
1151         *
1152         * The wrapping is LRE...PDF or RLE...PDF, depending on the detected
1153         * directionality of the argument string, using the BIDI algorithm's own "First
1154         * strong directional codepoint" rule. Essentially, this works round the fact that
1155         * there is no embedding equivalent of U+2068 FSI (isolation with heuristic
1156         * direction inference). The latter is cleaner but still not widely supported.
1157         *
1158         * @param {string[]} nodes The text nodes from which to take the first item.
1159         * @return {string} Wrapped String of content as needed.
1160         */
1161        bidi: function (nodes) {
1162            var dir = strongDirFromContent(nodes[ 0 ]);
1163            if (dir === 'ltr') {
1164                // Wrap in LEFT-TO-RIGHT EMBEDDING ... POP DIRECTIONAL FORMATTING
1165                return '\u202A' + nodes[ 0 ] + '\u202C';
1166            }
1167            if (dir === 'rtl') {
1168                // Wrap in RIGHT-TO-LEFT EMBEDDING ... POP DIRECTIONAL FORMATTING
1169                return '\u202B' + nodes[ 0 ] + '\u202C';
1170            }
1171            // No strong directionality: do not wrap
1172            return nodes[ 0 ];
1173        }
1174    });
1175}(jQuery));
1176
1177
1178
1179function _(str)
1180{
1181    var args = Array.prototype.slice.call(arguments);
1182    var tr =  $.i18n().messageStore.get($.i18n().locale, str);
1183    if (args.length > 1)
1184    {
1185        var args = [].slice.call(args);
1186        args.shift();
1187        if (!tr)
1188        {
1189            return $.i18n.parser.parse(str, args);
1190        }
1191        else
1192        {
1193            return $.i18n.parser.parse(tr, args);
1194        }
1195    } else
1196    {
1197        if (!tr)
1198        {
1199            return str;
1200        }
1201        else
1202        {
1203            return tr;
1204        }
1205    }
1206
1207}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.