diff --git a/Resources.php b/Resources.php
index 5e80ac5d..53200577 100644
--- a/Resources.php
+++ b/Resources.php
@@ -129,6 +129,7 @@ $wgResourceModules['ext.uls.webfonts.repository'] = array(
$wgResourceModules['jquery.i18n'] = array(
'scripts' => array(
'lib/jquery.i18n/jquery.i18n.js',
+ 'lib/jquery.i18n/jquery.i18n.messages.js',
'lib/jquery.i18n/jquery.i18n.parser.js',
'lib/jquery.i18n/jquery.i18n.emitter.js',
'lib/jquery.i18n/jquery.i18n.language.js',
diff --git a/lib/jquery.i18n/jquery.i18n.js b/lib/jquery.i18n/jquery.i18n.js
index 7c20f119..34ed7d4a 100644
--- a/lib/jquery.i18n/jquery.i18n.js
+++ b/lib/jquery.i18n/jquery.i18n.js
@@ -16,13 +16,13 @@
( function ( $ ) {
'use strict';
- var nav,
+ var nav, I18N,
slice = Array.prototype.slice;
/**
* @constructor
* @param {Object} options
*/
- var I18N = function ( options ) {
+ I18N = function ( options ) {
// Load defaults
this.options = $.extend( {}, I18N.defaults, options );
@@ -43,13 +43,13 @@
var i18n;
i18n = this;
- i18n.messageStore.init( i18n.locale );
// Set locale of String environment
String.locale = i18n.locale;
// Override String.localeString method
String.prototype.toLocaleString = function () {
- var localeParts, messageLocation, localePartIndex, value, locale, fallbackIndex;
+ var localeParts, localePartIndex, value, locale, fallbackIndex,
+ _locale, message;
value = this.valueOf();
locale = i18n.locale;
@@ -62,24 +62,11 @@
localePartIndex = localeParts.length;
do {
- var _locale = localeParts.slice( 0, localePartIndex ).join( '-' );
-
- if ( i18n.options.messageLocationResolver ) {
- messageLocation = i18n.options.messageLocationResolver( _locale, value );
-
- if ( messageLocation &&
- ( !i18n.messageStore.isLoaded( _locale ,messageLocation ) )
- ) {
- i18n.messageStore.load( messageLocation, _locale );
- }
- }
-
- var message = i18n.messageStore.get( _locale, value );
-
+ _locale = localeParts.slice( 0, localePartIndex ).join( '-' );
+ message = i18n.messageStore.get( _locale, value );
if ( message ) {
return message;
}
-
localePartIndex--;
} while ( localePartIndex );
@@ -89,7 +76,7 @@
locale = ( $.i18n.fallbacks[i18n.locale] && $.i18n.fallbacks[i18n.locale][fallbackIndex] ) ||
i18n.options.fallbackLocale;
- i18n.log( 'Trying fallback locale for ' + i18n.locale + ': ' + locale );
+ $.i18n.log( 'Trying fallback locale for ' + i18n.locale + ': ' + locale );
fallbackIndex++;
}
@@ -122,17 +109,12 @@
* null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
- * @param {String|Object|null} data
+ * @param {String|Object} source
* @param {String} locale Language tag
+ * @returns {jQuery.Promise}
*/
- load: function ( data, locale ) {
- this.messageStore.load( data, locale );
- },
-
- log: function ( /* arguments */ ) {
- if ( window.console && $.i18n.debug ) {
- window.console.log.apply( window.console, arguments );
- }
+ load: function ( source, locale ) {
+ return this.messageStore.load( source, locale );
},
/**
@@ -204,18 +186,16 @@
var i18n = $.data( document, 'i18n' );
String.locale = i18n.locale;
if ( !i18n ) {
- i18n = new I18N( );
+ i18n = new I18N();
$.data( document, 'i18n', i18n );
}
- return this.each( function () {
- var $this = $( this );
- if ( $this.data( 'i18n' ) ) {
- var messageKey = $this.data( 'i18n' ),
- message = messageKey.toLocaleString();
- if ( message !== '' ) {
- $this.text( message );
- }
+ return this.each( function () {
+ var $this = $( this ),
+ messageKey = $this.data( 'i18n' );
+
+ if ( messageKey ) {
+ $this.text( i18n.parse( messageKey ) );
} else {
$this.find( '[data-i18n]' ).i18n();
}
@@ -247,19 +227,19 @@
};
$.i18n.debug = false;
-
+ $.i18n.log = function ( /* arguments */ ) {
+ if ( window.console && $.i18n.debug ) {
+ window.console.log.apply( window.console, arguments );
+ }
+ };
/* Static members */
I18N.defaults = {
locale: String.locale,
fallbackLocale: 'en',
parser: $.i18n.parser,
- messageStore: $.i18n.messageStore,
- /* messageLocationResolver - should be a function taking language code as argument and
- * returning absolute or relative path to the localization file
- */
- messageLocationResolver: null
+ messageStore: $.i18n.messageStore
};
// Expose constructor
- $.I18N = I18N;
+ $.i18n.constructor = I18N;
}( jQuery ) );
diff --git a/lib/jquery.i18n/jquery.i18n.messages.js b/lib/jquery.i18n/jquery.i18n.messages.js
index f14602da..80b3c528 100644
--- a/lib/jquery.i18n/jquery.i18n.messages.js
+++ b/lib/jquery.i18n/jquery.i18n.messages.js
@@ -1,5 +1,5 @@
/**
- * jQuery Internationalization library Message loading , parsing, retrieving utilities
+ * jQuery Internationalization library - Message Store
*
* Copyright (C) 2012 Santhosh Thottingal
*
@@ -18,44 +18,20 @@
var MessageStore = function () {
this.messages = {};
this.sources = {};
- this.locale = String.locale;
};
+ /**
+ * See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
+ */
MessageStore.prototype = {
- /**
- * See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
- *
- * @param locale
- */
- init: function ( locale ) {
- var messageStore = this;
-
- messageStore.locale = locale;
- messageStore.log( 'initializing for ' + locale );
-
- $( 'link' ).each( function ( index, element ) {
- var $link = $( element ),
- rel = ( $link.attr( 'rel' ) || '' ).toLowerCase().split( /\s+/ );
-
- if ( $.inArray( 'localizations', rel ) !== -1 ) {
- // multiple localizations
- messageStore.load( $link.attr( 'href' ) );
- } else if ( $.inArray( 'localization', rel ) !== -1 ) {
- // single localization
- messageStore.queue( ( $link.attr( 'hreflang' ) || '' ).toLowerCase(),
- $link.attr( 'href' ) );
- }
- } );
- },
-
/**
* General message loading API This can take a URL string for
* the json formatted messages.
* load('path/to/all_localizations.json');
*
* This can also load a localization file for a locale
- * load('path/to/de-messages.json', 'de' );
+ * load( 'path/to/de-messages.json', 'de' );
*
* A data object containing message key- message translation mappings
* can also be passed Eg:
@@ -65,168 +41,54 @@
* null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
- * @param {String|Object|null} data
+ * @param {String|Object} source
* @param {String} locale Language tag
+ * @return {jQuery.Promise}
*/
- load: function ( data, locale ) {
+ load: function ( source, locale ) {
var key = null,
- messageStore = this,
- hasOwn = Object.prototype.hasOwnProperty;
+ deferred = null,
+ deferreds = [],
+ messageStore = this;
- if ( !data ) {
- // reset all localizations
- messageStore.log( 'Resetting for locale ' + locale );
- messageStore.messages = {};
-
- return;
- }
-
- if ( typeof data === 'string' ) {
+ if ( typeof source === 'string' ) {
// This is a URL to the messages file.
- messageStore.log( 'Loading messages from: ' + data );
+ $.i18n.log( 'Loading messages from: ' + source );
+ deferred = jsonMessageLoader( source )
+ .done( function ( localization ) {
+ messageStore.set( locale, localization );
+ } );
- messageStore.jsonMessageLoader( data ).done( function ( localization, textStatus ) {
- messageStore.load( localization, locale );
- messageStore.queue( locale, data );
- messageStore.markLoaded( locale, data );
- } );
+ return deferred.promise();
+ }
+
+ if ( locale ) {
+ // source is an key-value pair of messages for given locale
+ messageStore.set( locale, source );
+
+ return $.Deferred().resolve();
} else {
- // Data is either a group of messages for {locale},
- // or a group of languages with groups of messages inside.
- for ( key in data ) {
- if ( hasOwn.call( data, key ) ) {
- if ( locale ) {
-
- // Lazy-init the object
- if ( !messageStore.messages[locale] ) {
- messageStore.messages[locale] = {};
- }
-
- // Update message object keys,
- // don't overwrite the entire object.
- messageStore.messages[locale][key] = data[key];
-
- messageStore.log(
- '[' + locale + '][' + key + '] : ' + data[key]
- );
-
- // No {locale} given, assume data is a group of languages,
- // call this function again for each langauge.
- } else {
- messageStore.load( data[key], key );
- }
+ // source is a key-value pair of locales and their source
+ for ( key in source ) {
+ if ( Object.prototype.hasOwnProperty.call( source, key ) ) {
+ locale = key;
+ // No {locale} given, assume data is a group of languages,
+ // call this function again for each language.
+ deferreds.push( messageStore.load( source[key], locale ) );
}
}
+ return $.when.apply( $, deferreds );
}
- },
- log: function ( /* arguments */ ) {
- if ( window.console && $.i18n.debug ) {
- window.console.log.apply( window.console, arguments );
- }
},
/**
- * Mark a message Location for a locale loaded
- *
+ * Set messages
* @param locale
- * @param messageLocation
+ * @param messages
*/
- markLoaded: function ( locale, messageLocation ) {
- var i,
- queue = this.sources[locale];
-
- if ( !queue ) {
- this.queue( locale, messageLocation );
- queue = this.sources[locale];
- }
-
- this.sources[locale] = this.sources[locale] || [];
-
- for ( i = 0; i < queue.length; i++ ) {
- if ( queue[i].source.url === messageLocation ) {
- queue[i].source.loaded = true;
-
- return;
- }
- }
- },
-
- /**
- * Register the message location for a locale, will be loaded when required
- *
- * @param locale
- * @param messageLocation
- */
- queue: function ( locale, messageLocation ) {
- var i,
- queue = this.sources[locale];
-
- this.sources[locale] = this.sources[locale] || [];
-
- if ( queue ) {
- for ( i = 0; i < queue.length; i++ ) {
- if ( queue[i].source.url === messageLocation ) {
- return;
- }
- }
- }
-
- this.log( 'Source for: ' + locale + ' is ' + messageLocation + ' registered' );
- this.sources[locale].push( {
- source: {
- url: messageLocation,
- loaded: false
- }
- } );
- },
-
- /**
- * Load the messages from the source queue for the locale
- *
- * @param {String} locale
- */
- loadFromQueue: function ( locale ) {
- var i,
- queue = this.sources[locale];
-
- if ( queue ) {
- for ( i = 0; i < queue.length; i++ ) {
- if ( !queue[i].source.loaded ) {
- this.load( queue[i].source.url, locale );
- this.sources[locale][i].source.loaded = true;
- }
- }
- }
- },
-
- isLoaded: function ( locale, messageLocation ) {
- var i,
- sources = this.sources[locale],
- result = false;
-
- if ( sources ) {
- for ( i = 0; i < sources.length; i++ ) {
- if ( sources[i].source.url === messageLocation ) {
- result = true;
- }
- }
- }
-
- return result;
- },
-
- jsonMessageLoader: function ( url ) {
- var messageStore = this;
-
- return $.ajax( {
- url: url,
- dataType: 'json',
- //async: false
- // This is unfortunate.
- } ).fail( function ( jqxhr, settings, exception ) {
- messageStore.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
- } );
+ set: function( locale, messages ) {
+ this.messages[locale] = messages;
},
/**
@@ -236,15 +98,16 @@
* @returns {Boolean}
*/
get: function ( locale, messageKey ) {
- // load locale if not loaded
- if ( !this.messages[locale] ) {
- this.loadFromQueue( locale );
- }
-
return this.messages[locale] && this.messages[locale][messageKey];
}
};
+ function jsonMessageLoader( url ) {
+ return $.getJSON( url ).fail( function ( jqxhr, settings, exception ) {
+ $.i18n.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
+ } );
+ }
+
$.extend( $.i18n.messageStore, new MessageStore() );
}( jQuery, window ) );
diff --git a/lib/jquery.i18n/jquery.i18n.parser.js b/lib/jquery.i18n/jquery.i18n.parser.js
index f26109bd..7dc26e6e 100644
--- a/lib/jquery.i18n/jquery.i18n.parser.js
+++ b/lib/jquery.i18n/jquery.i18n.parser.js
@@ -46,7 +46,11 @@
},
ast: function ( message ) {
- var pos = 0;
+ var pipe, colon, backslash, anyCharacter, dollar, digits, regularLiteral,
+ regularLiteralWithoutBar, regularLiteralWithoutSpace, escapedOrLiteralWithoutBar,
+ escapedOrRegularLiteral, templateContents, templateName, openTemplate,
+ closeTemplate, expression, paramExpression, result,
+ pos = 0;
// Try parsers until one works, if none work return null
function choice ( parserSyntax ) {
@@ -142,15 +146,15 @@
};
}
- 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]/ );
+ pipe = makeStringParser( '|' );
+ colon = makeStringParser( ':' );
+ backslash = makeStringParser( '\\' );
+ anyCharacter = makeRegexParser( /^./ );
+ dollar = makeStringParser( '$' );
+ digits = makeRegexParser( /^\d+/ );
+ regularLiteral = makeRegexParser( /^[^{}\[\]$\\]/ );
+ regularLiteralWithoutBar = makeRegexParser( /^[^{}\[\]$\\|]/ );
+ regularLiteralWithoutSpace = makeRegexParser( /^[^{}\[\]$\s]/ );
// There is a general pattern:
// parse a thing;
@@ -189,8 +193,8 @@
}
choice( [ escapedLiteral, regularLiteralWithoutSpace ] );
- var escapedOrLiteralWithoutBar = choice( [ escapedLiteral, regularLiteralWithoutBar ] );
- var escapedOrRegularLiteral = choice( [ escapedLiteral, regularLiteral ] );
+ escapedOrLiteralWithoutBar = choice( [ escapedLiteral, regularLiteralWithoutBar ] );
+ escapedOrRegularLiteral = choice( [ escapedLiteral, regularLiteral ] );
function replacement () {
var result = sequence( [ dollar, digits ] );
@@ -202,7 +206,7 @@
return [ 'REPLACE', parseInt( result[1], 10 ) - 1 ];
}
- var templateName = transform(
+ templateName = transform(
// see $wgLegalTitleChars
// not allowing : due to the need to catch "PLURAL:$1"
makeRegexParser( /^[ !"$&'()*,.\/0-9;=?@A-Z\^_`a-z~\x80-\xFF+\-]+/ ),
@@ -213,13 +217,14 @@
);
function templateParam () {
- var result = sequence( [ pipe, nOrMore( 0, paramExpression ) ] );
+ var expr,
+ result = sequence( [ pipe, nOrMore( 0, paramExpression ) ] );
if ( result === null ) {
return null;
}
- var expr = result[1];
+ expr = result[1];
// use a "CONCAT" operator if there are multiple nodes,
// otherwise return the first node, raw.
@@ -238,7 +243,7 @@
return result === null ? null : [ result[0], result[2] ];
}
- var templateContents = choice( [
+ templateContents = choice( [
function () {
var res = sequence( [
// templates can have placeholders for dynamic
@@ -262,8 +267,8 @@
}
] );
- var openTemplate = makeStringParser( '{{' );
- var closeTemplate = makeStringParser( '}}' );
+ openTemplate = makeStringParser( '{{' );
+ closeTemplate = makeStringParser( '}}' );
function template () {
var result = sequence( [ openTemplate, templateContents, closeTemplate ] );
@@ -271,8 +276,8 @@
return result === null ? null : result[1];
}
- var expression = choice( [ template, replacement, literal ] );
- var paramExpression = choice( [ template, replacement, literalWithoutBar ] );
+ expression = choice( [ template, replacement, literal ] );
+ paramExpression = choice( [ template, replacement, literalWithoutBar ] );
function start () {
var result = nOrMore( 0, expression )();
@@ -284,7 +289,7 @@
return [ 'CONCAT' ].concat( result );
}
- var result = start();
+ result = start();
/*
* For success, the pos must have gotten to the end of the input
@@ -301,5 +306,4 @@
};
$.extend( $.i18n.parser, new MessageParser() );
-
}( jQuery ) );
diff --git a/resources/js/ext.uls.displaysettings.js b/resources/js/ext.uls.displaysettings.js
index fdc9cd1b..f5389120 100644
--- a/resources/js/ext.uls.displaysettings.js
+++ b/resources/js/ext.uls.displaysettings.js
@@ -316,11 +316,9 @@
* @param {String} language Language code
*/
preview: function ( language ) {
- var displaySettings = this,
- i18n = $.i18n();
+ var displaySettings = this;
- i18n.locale = language;
- i18n.messageStore.load( i18n.locale ).done( function () {
+ mw.uls.loadLocalization( language ).done( function () {
displaySettings.i18n();
} );
},
diff --git a/resources/js/ext.uls.i18n.js b/resources/js/ext.uls.i18n.js
index 5f890c38..0b0c8db9 100644
--- a/resources/js/ext.uls.i18n.js
+++ b/resources/js/ext.uls.i18n.js
@@ -17,54 +17,31 @@
* @licence MIT License
*/
-( function ( $, mw, undefined ) {
+( function ( $, mw ) {
'use strict';
+ mw.uls = mw.uls || {};
+
// jquery.i18n has CLDRPluralRuleParser but MediaWiki also has the same
// parser. Reuse it by aliasing it to window.pluralRuleParser
window.pluralRuleParser = mw.libs.pluralRuleParser;
- /**
- * jquery.i18n message store for MediaWiki
- *
- */
- var MWMessageStore = function () {
- this.messages = {};
- };
+ // JavaScript side i18n initialization
+ $.i18n( {
+ locale: mw.config.get( 'wgUserLanguage' )
+ } );
- MWMessageStore.prototype = {
- init: function () {},
+ mw.uls.loadLocalization = function ( locale ) {
+ var i18n = $.i18n();
- get: function ( locale, messageKey ) {
- return ( this.isLoaded( locale ) && this.messages[locale][messageKey] ) ||
- '<' + messageKey + '>';
- },
-
- set: function( locale, messages ) {
- this.messages[locale] = messages;
- },
-
- isLoaded: function ( locale ) {
- return this.messages[locale];
- },
-
- load: function ( locale ) {
- var store = this,
- deferred = $.Deferred(),
- url = mw.util.wikiScript( 'api' ) + '?action=ulslocalization&language=';
-
- if ( store.isLoaded( locale ) ) {
- return deferred.resolve();
- }
-
- deferred = $.getJSON( url + locale ).done( function ( data ) {
- store.set( locale, data );
- } ).fail( function ( jqxhr, settings, exception ) {
- mw.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
- } );
- return deferred.promise();
+ i18n.locale = locale;
+ if ( i18n.messageStore.messages[locale] ) {
+ return $.Deferred().resolve();
}
+ return i18n.load(
+ mw.util.wikiScript( 'api' ) + '?action=ulslocalization&language=' + locale,
+ locale
+ );
};
- mw.uls = mw.uls || {};
- mw.uls.messageStore = new MWMessageStore();
+
}( jQuery, mediaWiki ) );
diff --git a/resources/js/ext.uls.init.js b/resources/js/ext.uls.init.js
index 90e72858..5be29d5b 100644
--- a/resources/js/ext.uls.init.js
+++ b/resources/js/ext.uls.init.js
@@ -31,7 +31,7 @@
this.$languageFilter.addClass( 'noime' );
};
- var jsonLoader,
+ var jsonLoader = null,
initialized = false,
currentLang = mw.config.get( 'wgUserLanguage' ),
logEventQueue = $.Callbacks( 'memory once' );
@@ -211,14 +211,8 @@
*/
$.uls.data.addLanguage( 'als', { target: 'gsw' } );
- // JavaScript side i18n initialization
- $.i18n( {
- locale: currentLang,
- messageStore: mw.uls.messageStore
- } );
-
if ( !jsonLoader ) {
- jsonLoader = mw.uls.messageStore.load( currentLang );
+ jsonLoader = mw.uls.loadLocalization( currentLang );
} else {
jsonLoader.done( function () {
initialized = true;