load('path/to/all_localizations.json');
*
* To load a localization file for a locale:
*
* load('path/to/de-messages.json', 'de' );
*
*
* To load a localization file from a directory:
*
* load('path/to/i18n/directory', 'de' );
*
* The above method has the advantage of fallback resolution.
* ie, it will automatically load the fallback locales for de.
* For most usecases, this is the recommended method.
* It is optional to have trailing slash at end.
*
* A data object containing message key- message translation mappings
* can also be passed. Example:
*
* load( { 'hello' : 'Hello' }, optionalLocale );
*
*
* A source map containing key-value pair of languagename and locations
* can also be passed. Example:
*
* load( {
* bn: 'i18n/bn.json',
* he: 'i18n/he.json',
* en: 'i18n/en.json'
* } )
*
*
* If the data argument is null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
* @param {String|Object} source
* @param {String} locale Language tag
* @returns {jQuery.Promise}
*/
load: function ( source, locale ) {
var fallbackLocales, locIndex, fallbackLocale, sourceMap = {};
if ( !source && !locale ) {
source = 'i18n/' + $.i18n().locale + '.json';
locale = $.i18n().locale;
}
if ( typeof source === 'string' &&
source.split( '.' ).pop() !== 'json'
) {
// Load specified locale then check for fallbacks when directory is specified in load()
sourceMap[locale] = source + '/' + locale + '.json';
fallbackLocales = ( $.i18n.fallbacks[locale] || [] )
.concat( this.options.fallbackLocale );
for ( locIndex in fallbackLocales ) {
fallbackLocale = fallbackLocales[locIndex];
sourceMap[fallbackLocale] = source + '/' + fallbackLocale + '.json';
}
return this.load( sourceMap );
} else {
return this.messageStore.load( source, locale );
}
},
/**
* Does parameter and magic word substitution.
*
* @param {string} key Message key
* @param {Array} parameters Message parameters
* @return {string}
*/
parse: function ( key, parameters ) {
var message = key.toLocaleString();
// FIXME: This changes the state of the I18N object,
// should probably not change the 'this.parser' but just
// pass it to the parser.
this.parser.language = $.i18n.languages[$.i18n().locale] || $.i18n.languages['default'];
if ( message === '' ) {
message = key;
}
return this.parser.parse( message, parameters );
}
};
/**
* Process a message from the $.I18N instance
* for the current document, stored in jQuery.data(document).
*
* @param {string} key Key of the message.
* @param {string} param1 [param...] Variadic list of parameters for {key}.
* @return {string|$.I18N} Parsed message, or if no key was given
* the instance of $.I18N is returned.
*/
$.i18n = function ( key, param1 ) {
var parameters,
i18n = $.data( document, 'i18n' ),
options = typeof key === 'object' && key;
// If the locale option for this call is different then the setup so far,
// update it automatically. This doesn't just change the context for this
// call but for all future call as well.
// If there is no i18n setup yet, don't do this. It will be taken care of
// by the `new I18N` construction below.
// NOTE: It should only change language for this one call.
// Then cache instances of I18N somewhere.
if ( options && options.locale && i18n && i18n.locale !== options.locale ) {
String.locale = i18n.locale = options.locale;
}
if ( !i18n ) {
i18n = new I18N( options );
$.data( document, 'i18n', i18n );
}
if ( typeof key === 'string' ) {
if ( param1 !== undefined ) {
parameters = slice.call( arguments, 1 );
} else {
parameters = [];
}
return i18n.parse( key, parameters );
} else {
// FIXME: remove this feature/bug.
return i18n;
}
};
$.fn.i18n = function () {
var i18n = $.data( document, 'i18n' );
if ( !i18n ) {
i18n = new I18N();
$.data( document, 'i18n', i18n );
}
String.locale = i18n.locale;
return this.each( function () {
var $this = $( this ),
messageKey = $this.data( 'i18n' );
if ( messageKey ) {
$this.text( i18n.parse( messageKey ) );
} else {
$this.find( '[data-i18n]' ).i18n();
}
} );
};
String.locale = String.locale || $( 'html' ).attr( 'lang' );
if ( !String.locale ) {
if ( typeof window.navigator !== undefined ) {
nav = window.navigator;
String.locale = nav.language || nav.userLanguage || '';
} else {
String.locale = '';
}
}
$.i18n.languages = {};
$.i18n.messageStore = $.i18n.messageStore || {};
$.i18n.parser = {
// The default parser only handles variable substitution
parse: function ( message, parameters ) {
return message.replace( /\$(\d+)/g, function ( str, match ) {
var index = parseInt( match, 10 ) - 1;
return parameters[index] !== undefined ? parameters[index] : '$' + match;
} );
},
emitter: {}
};
$.i18n.fallbacks = {};
$.i18n.debug = false;
$.i18n.log = function ( /* arguments */ ) {
if ( window.console && $.i18n.debug ) {
window.console.log.apply( window.console, arguments );
}
};
/* Static members */
I18N.defaults = {
locale: String.locale,
fallbackLocale: 'en',
parser: $.i18n.parser,
messageStore: $.i18n.messageStore
};
// Expose constructor
$.i18n.constructor = I18N;
}( jQuery ) );
================================================
FILE: plugins/web/public/js/jquery.i18n/1.0.4/jquery.i18n.messagestore.js
================================================
/**
* jQuery Internationalization library - Message Store
*
* 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 ( $, window, undefined ) {
'use strict';
var MessageStore = function () {
this.messages = {};
this.sources = {};
};
/**
* See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
*/
MessageStore.prototype = {
/**
* General message loading API This can take a URL string for
* the json formatted messages.
* load('path/to/all_localizations.json');
*
* This can also load a localization file for a locale
* 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} source
* @param {String} locale Language tag
* @return {jQuery.Promise}
*/
load: function ( source, locale ) {
var key = null,
deferred = null,
deferreds = [],
messageStore = this;
if ( typeof source === 'string' ) {
// This is a URL to the messages file.
$.i18n.log( 'Loading messages from: ' + source );
deferred = jsonMessageLoader( source )
.done( function ( localization ) {
messageStore.set( locale, localization );
} );
return deferred.promise();
}
if ( locale ) {
// source is an key-value pair of messages for given locale
messageStore.set( locale, source );
return $.Deferred().resolve();
} else {
// source is a key-value pair of locales and their source
for ( key in source ) {
if ( Object.prototype.hasOwnProperty.call( source, key ) ) {
locale = key;
// No {locale} given, assume data is a group of languages,
// call this function again for each language.
deferreds.push( messageStore.load( source[key], locale ) );
}
}
return $.when.apply( $, deferreds );
}
},
/**
* Set messages to the given locale.
* If locale exists, add messages to the locale.
* @param locale
* @param messages
*/
set: function ( locale, messages ) {
if ( !this.messages[locale] ) {
this.messages[locale] = messages;
} else {
this.messages[locale] = $.extend( this.messages[locale], messages );
}
},
/**
*
* @param locale
* @param messageKey
* @returns {Boolean}
*/
get: function ( locale, messageKey ) {
return this.messages[locale] && this.messages[locale][messageKey];
}
};
function jsonMessageLoader( url ) {
var deferred = $.Deferred();
$.getJSON( url )
.done( deferred.resolve )
.fail( function ( jqxhr, settings, exception ) {
$.i18n.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
// Ignore 404 exception, because we are handling fallabacks explicitly
deferred.resolve();
} );
return deferred.promise();
}
$.extend( $.i18n.messageStore, new MessageStore() );
}( jQuery, window ) );
================================================
FILE: plugins/web/public/js/jquery.i18n.fallbacks.js
================================================
/*!
* jQuery Internationalization library
*
* Copyright (C) 2012 Santhosh Thottingal
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
* choose one license or the other and you don't have to notify anyone which license you are using.
* You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
( function ( $ ) {
'use strict';
$.i18n = $.i18n || {};
$.extend( $.i18n.fallbacks, {
ab: [ 'ru' ],
ace: [ 'id' ],
aln: [ 'sq' ],
// Not so standard - als is supposed to be Tosk Albanian,
// but in Wikipedia it's used for a Germanic language.
als: [ 'gsw', 'de' ],
an: [ 'es' ],
anp: [ 'hi' ],
arn: [ 'es' ],
arz: [ 'ar' ],
av: [ 'ru' ],
ay: [ 'es' ],
ba: [ 'ru' ],
bar: [ 'de' ],
'bat-smg': [ 'sgs', 'lt' ],
bcc: [ 'fa' ],
'be-x-old': [ 'be-tarask' ],
bh: [ 'bho' ],
bjn: [ 'id' ],
bm: [ 'fr' ],
bpy: [ 'bn' ],
bqi: [ 'fa' ],
bug: [ 'id' ],
'cbk-zam': [ 'es' ],
ce: [ 'ru' ],
crh: [ 'crh-latn' ],
'crh-cyrl': [ 'ru' ],
csb: [ 'pl' ],
cv: [ 'ru' ],
'de-at': [ 'de' ],
'de-ch': [ 'de' ],
'de-formal': [ 'de' ],
dsb: [ 'de' ],
dtp: [ 'ms' ],
egl: [ 'it' ],
eml: [ 'it' ],
ff: [ 'fr' ],
fit: [ 'fi' ],
'fiu-vro': [ 'vro', 'et' ],
frc: [ 'fr' ],
frp: [ 'fr' ],
frr: [ 'de' ],
fur: [ 'it' ],
gag: [ 'tr' ],
gan: [ 'gan-hant', 'zh-hant', 'zh-hans' ],
'gan-hans': [ 'zh-hans' ],
'gan-hant': [ 'zh-hant', 'zh-hans' ],
gl: [ 'pt' ],
glk: [ 'fa' ],
gn: [ 'es' ],
gsw: [ 'de' ],
hif: [ 'hif-latn' ],
hsb: [ 'de' ],
ht: [ 'fr' ],
ii: [ 'zh-cn', 'zh-hans' ],
inh: [ 'ru' ],
iu: [ 'ike-cans' ],
jut: [ 'da' ],
jv: [ 'id' ],
kaa: [ 'kk-latn', 'kk-cyrl' ],
kbd: [ 'kbd-cyrl' ],
khw: [ 'ur' ],
kiu: [ 'tr' ],
kk: [ 'kk-cyrl' ],
'kk-arab': [ 'kk-cyrl' ],
'kk-latn': [ 'kk-cyrl' ],
'kk-cn': [ 'kk-arab', 'kk-cyrl' ],
'kk-kz': [ 'kk-cyrl' ],
'kk-tr': [ 'kk-latn', 'kk-cyrl' ],
kl: [ 'da' ],
'ko-kp': [ 'ko' ],
koi: [ 'ru' ],
krc: [ 'ru' ],
ks: [ 'ks-arab' ],
ksh: [ 'de' ],
ku: [ 'ku-latn' ],
'ku-arab': [ 'ckb' ],
kv: [ 'ru' ],
lad: [ 'es' ],
lb: [ 'de' ],
lbe: [ 'ru' ],
lez: [ 'ru' ],
li: [ 'nl' ],
lij: [ 'it' ],
liv: [ 'et' ],
lmo: [ 'it' ],
ln: [ 'fr' ],
ltg: [ 'lv' ],
lzz: [ 'tr' ],
mai: [ 'hi' ],
'map-bms': [ 'jv', 'id' ],
mg: [ 'fr' ],
mhr: [ 'ru' ],
min: [ 'id' ],
mo: [ 'ro' ],
mrj: [ 'ru' ],
mwl: [ 'pt' ],
myv: [ 'ru' ],
mzn: [ 'fa' ],
nah: [ 'es' ],
nap: [ 'it' ],
nds: [ 'de' ],
'nds-nl': [ 'nl' ],
'nl-informal': [ 'nl' ],
no: [ 'nb' ],
os: [ 'ru' ],
pcd: [ 'fr' ],
pdc: [ 'de' ],
pdt: [ 'de' ],
pfl: [ 'de' ],
pms: [ 'it' ],
pt: [ 'pt-br' ],
'pt-br': [ 'pt' ],
qu: [ 'es' ],
qug: [ 'qu', 'es' ],
rgn: [ 'it' ],
rmy: [ 'ro' ],
'roa-rup': [ 'rup' ],
rue: [ 'uk', 'ru' ],
ruq: [ 'ruq-latn', 'ro' ],
'ruq-cyrl': [ 'mk' ],
'ruq-latn': [ 'ro' ],
sa: [ 'hi' ],
sah: [ 'ru' ],
scn: [ 'it' ],
sg: [ 'fr' ],
sgs: [ 'lt' ],
sli: [ 'de' ],
sr: [ 'sr-ec' ],
srn: [ 'nl' ],
stq: [ 'de' ],
su: [ 'id' ],
szl: [ 'pl' ],
tcy: [ 'kn' ],
tg: [ 'tg-cyrl' ],
tt: [ 'tt-cyrl', 'ru' ],
'tt-cyrl': [ 'ru' ],
ty: [ 'fr' ],
udm: [ 'ru' ],
ug: [ 'ug-arab' ],
uk: [ 'ru' ],
vec: [ 'it' ],
vep: [ 'et' ],
vls: [ 'nl' ],
vmf: [ 'de' ],
vot: [ 'fi' ],
vro: [ 'et' ],
wa: [ 'fr' ],
wo: [ 'fr' ],
wuu: [ 'zh-hans' ],
xal: [ 'ru' ],
xmf: [ 'ka' ],
yi: [ 'he' ],
za: [ 'zh-hans' ],
zea: [ 'nl' ],
zh: [ 'zh-hans' ],
'zh-classical': [ 'lzh' ],
'zh-cn': [ 'zh-hans' ],
'zh-hant': [ 'zh-hans' ],
'zh-hk': [ 'zh-hant', 'zh-hans' ],
'zh-min-nan': [ 'nan' ],
'zh-mo': [ 'zh-hk', 'zh-hant', 'zh-hans' ],
'zh-my': [ 'zh-sg', 'zh-hans' ],
'zh-sg': [ 'zh-hans' ],
'zh-tw': [ 'zh-hant', 'zh-hans' ],
'zh-yue': [ 'yue' ]
} );
}( jQuery ) );
================================================
FILE: plugins/web/public/js/jquery.i18n.js
================================================
/*!
* 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 I18N,
slice = Array.prototype.slice;
/**
* @constructor
* @param {Object} options
*/
I18N = function ( options ) {
// Load defaults
this.options = $.extend( {}, I18N.defaults, options );
this.parser = this.options.parser;
this.locale = this.options.locale;
this.messageStore = this.options.messageStore;
this.languages = {};
};
I18N.prototype = {
/**
* Localize a given messageKey to a locale.
* @param {String} messageKey
* @return {String} Localized message
*/
localize: function ( messageKey ) {
var localeParts, localePartIndex, locale, fallbackIndex,
tryingLocale, message;
locale = this.locale;
fallbackIndex = 0;
while ( locale ) {
// Iterate through locales starting at most-specific until
// localization is found. As in fi-Latn-FI, fi-Latn and fi.
localeParts = locale.split( '-' );
localePartIndex = localeParts.length;
do {
tryingLocale = localeParts.slice( 0, localePartIndex ).join( '-' );
message = this.messageStore.get( tryingLocale, messageKey );
if ( message ) {
return message;
}
localePartIndex--;
} while ( localePartIndex );
if ( locale === 'en' ) {
break;
}
locale = ( $.i18n.fallbacks[ this.locale ] &&
$.i18n.fallbacks[ this.locale ][ fallbackIndex ] ) ||
this.options.fallbackLocale;
$.i18n.log( 'Trying fallback locale for ' + this.locale + ': ' + locale + ' (' + messageKey + ')' );
fallbackIndex++;
}
// key not found
return '';
},
/*
* Destroy the i18n instance.
*/
destroy: function () {
$.removeData( document, 'i18n' );
},
/**
* General message loading API This can take a URL string for
* the json formatted messages. Example:
* load('path/to/all_localizations.json');
*
* To load a localization file for a locale:
*
* load('path/to/de-messages.json', 'de' );
*
*
* To load a localization file from a directory:
*
* load('path/to/i18n/directory', 'de' );
*
* The above method has the advantage of fallback resolution.
* ie, it will automatically load the fallback locales for de.
* For most usecases, this is the recommended method.
* It is optional to have trailing slash at end.
*
* A data object containing message key- message translation mappings
* can also be passed. Example:
*
* load( { 'hello' : 'Hello' }, optionalLocale );
*
*
* A source map containing key-value pair of languagename and locations
* can also be passed. Example:
*
* load( {
* bn: 'i18n/bn.json',
* he: 'i18n/he.json',
* en: 'i18n/en.json'
* } )
*
*
* If the data argument is null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
* @param {string|Object} source
* @param {string} locale Language tag
* @return {jQuery.Promise}
*/
load: function ( source, locale ) {
var fallbackLocales, locIndex, fallbackLocale, sourceMap = {};
if ( !source && !locale ) {
source = 'i18n/' + $.i18n().locale + '.json';
locale = $.i18n().locale;
}
if ( typeof source === 'string' &&
// source extension should be json, but can have query params after that.
source.split( '?' )[ 0 ].split( '.' ).pop() !== 'json'
) {
// Load specified locale then check for fallbacks when directory is
// specified in load()
sourceMap[ locale ] = source + '/' + locale + '.json';
fallbackLocales = ( $.i18n.fallbacks[ locale ] || [] )
.concat( this.options.fallbackLocale );
for ( locIndex = 0; locIndex < fallbackLocales.length; locIndex++ ) {
fallbackLocale = fallbackLocales[ locIndex ];
sourceMap[ fallbackLocale ] = source + '/' + fallbackLocale + '.json';
}
return this.load( sourceMap );
} else {
return this.messageStore.load( source, locale );
}
},
/**
* Does parameter and magic word substitution.
*
* @param {string} key Message key
* @param {Array} parameters Message parameters
* @return {string}
*/
parse: function ( key, parameters ) {
var message = this.localize( key );
// FIXME: This changes the state of the I18N object,
// should probably not change the 'this.parser' but just
// pass it to the parser.
this.parser.language = $.i18n.languages[ $.i18n().locale ] || $.i18n.languages[ 'default' ];
if ( message === '' ) {
message = key;
}
return this.parser.parse( message, parameters );
}
};
/**
* Process a message from the $.I18N instance
* for the current document, stored in jQuery.data(document).
*
* @param {string} key Key of the message.
* @param {string} param1 [param...] Variadic list of parameters for {key}.
* @return {string|$.I18N} Parsed message, or if no key was given
* the instance of $.I18N is returned.
*/
$.i18n = function ( key, param1 ) {
var parameters,
i18n = $.data( document, 'i18n' ),
options = typeof key === 'object' && key;
// If the locale option for this call is different then the setup so far,
// update it automatically. This doesn't just change the context for this
// call but for all future call as well.
// If there is no i18n setup yet, don't do this. It will be taken care of
// by the `new I18N` construction below.
// NOTE: It should only change language for this one call.
// Then cache instances of I18N somewhere.
if ( options && options.locale && i18n && i18n.locale !== options.locale ) {
i18n.locale = options.locale;
}
if ( !i18n ) {
i18n = new I18N( options );
$.data( document, 'i18n', i18n );
}
if ( typeof key === 'string' ) {
if ( param1 !== undefined ) {
parameters = slice.call( arguments, 1 );
} else {
parameters = [];
}
return i18n.parse( key, parameters );
} else {
// FIXME: remove this feature/bug.
return i18n;
}
};
$.fn.i18n = function () {
var i18n = $.data( document, 'i18n' );
if ( !i18n ) {
i18n = new I18N();
$.data( document, 'i18n', i18n );
}
return this.each( function () {
var $this = $( this ),
messageKey = $this.data( 'i18n' ),
lBracket, rBracket, type, key;
if ( messageKey ) {
lBracket = messageKey.indexOf( '[' );
rBracket = messageKey.indexOf( ']' );
if ( lBracket !== -1 && rBracket !== -1 && lBracket < rBracket ) {
type = messageKey.slice( lBracket + 1, rBracket );
key = messageKey.slice( rBracket + 1 );
if ( type === 'html' ) {
$this.html( i18n.parse( key ) );
} else {
$this.attr( type, i18n.parse( key ) );
}
} else {
$this.text( i18n.parse( messageKey ) );
}
} else {
$this.find( '[data-i18n]' ).i18n();
}
} );
};
function getDefaultLocale() {
var nav, locale = $( 'html' ).attr( 'lang' );
if ( !locale ) {
if ( typeof window.navigator !== undefined ) {
nav = window.navigator;
locale = nav.language || nav.userLanguage || '';
} else {
locale = '';
}
}
return locale;
}
$.i18n.languages = {};
$.i18n.messageStore = $.i18n.messageStore || {};
$.i18n.parser = {
// The default parser only handles variable substitution
parse: function ( message, parameters ) {
return message.replace( /\$(\d+)/g, function ( str, match ) {
var index = parseInt( match, 10 ) - 1;
return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
} );
},
emitter: {}
};
$.i18n.fallbacks = {};
$.i18n.debug = false;
$.i18n.log = function ( /* arguments */ ) {
if ( window.console && $.i18n.debug ) {
window.console.log.apply( window.console, arguments );
}
};
/* Static members */
I18N.defaults = {
locale: getDefaultLocale(),
fallbackLocale: 'en',
parser: $.i18n.parser,
messageStore: $.i18n.messageStore
};
// Expose constructor
$.i18n.constructor = I18N;
}( jQuery ) );
================================================
FILE: plugins/web/public/js/jquery.i18n.messagestore.js
================================================
/*!
* jQuery Internationalization library - Message Store
*
* 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 MessageStore = function () {
this.messages = {};
this.sources = {};
};
function jsonMessageLoader( url ) {
var deferred = $.Deferred();
$.getJSON( url )
.done( deferred.resolve )
.fail( function ( jqxhr, settings, exception ) {
$.i18n.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
// Ignore 404 exception, because we are handling fallabacks explicitly
deferred.resolve();
} );
return deferred.promise();
}
/**
* See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
*/
MessageStore.prototype = {
/**
* General message loading API This can take a URL string for
* the json formatted messages.
* load('path/to/all_localizations.json');
*
* This can also load a localization file for a locale
* 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} source
* @param {string} locale Language tag
* @return {jQuery.Promise}
*/
load: function ( source, locale ) {
var key = null,
deferred = null,
deferreds = [],
messageStore = this;
if ( typeof source === 'string' ) {
// This is a URL to the messages file.
$.i18n.log( 'Loading messages from: ' + source );
deferred = jsonMessageLoader( source )
.done( function ( localization ) {
messageStore.set( locale, localization );
} );
return deferred.promise();
}
if ( locale ) {
// source is an key-value pair of messages for given locale
messageStore.set( locale, source );
return $.Deferred().resolve();
} else {
// source is a key-value pair of locales and their source
for ( key in source ) {
if ( Object.prototype.hasOwnProperty.call( source, key ) ) {
locale = key;
// No {locale} given, assume data is a group of languages,
// call this function again for each language.
deferreds.push( messageStore.load( source[ key ], locale ) );
}
}
return $.when.apply( $, deferreds );
}
},
/**
* Set messages to the given locale.
* If locale exists, add messages to the locale.
*
* @param {string} locale
* @param {Object} messages
*/
set: function ( locale, messages ) {
if ( !this.messages[ locale ] ) {
this.messages[ locale ] = messages;
} else {
this.messages[ locale ] = $.extend( this.messages[ locale ], messages );
}
},
/**
*
* @param {string} locale
* @param {string} messageKey
* @return {boolean}
*/
get: function ( locale, messageKey ) {
return this.messages[ locale ] && this.messages[ locale ][ messageKey ];
}
};
$.extend( $.i18n.messageStore, new MessageStore() );
}( jQuery ) );
================================================
FILE: plugins/web/public/scss/common.scss
================================================
@import "reset";
.container {
padding: 20px;
max-width: 400px;
margin: auto;
}
.mi_logo {
width: 48px;
height: 48px;
margin: 30px auto;
}
.dear_user {
font-size: 16px;
font-weight: bold;
padding: 10px 0;
}
.help_phone {
padding: 10px 0;
}
.modal {
display: none;
opacity: 0;
position: fixed;
z-index: 999;
left: 0;
top: 0;
height: 100%;
width: 100%;
transition: opacity .5s;
}
.allow_btn {
margin-top: 60px;
}
.modal.visible {
display: block;
opacity: 1;
}
.modal_mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .4;
filter: alpha(opacity=40);
background-color: black;
}
.modal_box {
text-align: center;
position: absolute;
bottom: -30px;
width: 90%;
left: 50%;
box-shadow: 0 1px 8px rgba(128, 128, 128, 0.3);
border: 1px solid #d1d1d1;
border-radius: 10px;
overflow: hidden;
background-color: white;
transition: width .5s ease, height .5s ease;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%, 0);
transform: translate(-50%, -50%, 0);
_top: 0;
_left: 0;
_margin-left: 0;
_margin-top: 0;
max-width: 400px;
}
.modal_body {
margin: 20px;
text-align: left;
}
.modal_footer {
display: flex;
border-top: 1px solid #f8f8f8;
}
.modal_btn {
flex: 1;
padding: 15px 0;
}
.modal_btn_ok {
color: #ff6700;
border-left: 1px solid #f8f8f8;
}
.btn {
margin-bottom: 20px;
text-align: center;
padding: 12px 0;
border-radius: 6px;
}
.btn_ok {
background-color: #ff6700;
color: #fff;
}
.btn_no {
background-color: #fff;
color: #999;
border: 1px solid #d3d3d3;
}
.state {
margin-top: 30px;
img {
width: 100px;
height: 100px;
margin-top: 40px;
}
dd {
font-size: 30px;
margin: 20px 0;
}
}
.device_list {
margin: 20px 0 20px 30px;
list-style-type: disc;
&.gray {
width: 220px;
color: #999;
margin: 40px auto 0 auto;
}
}
.caution {
margin: 30px 0;
.line {
width: 100%;
margin-bottom: -10px;
border-bottom: 1px solid #f0f0f0;
}
.txt {
color: #999;
background-color: #fff;
padding: 5px 10px;
}
}
.tips {
margin: 20px 0;
}
.icon_gter {
width: 10%;
height: 16px;
display: block;
position: relative;
&:after {
content: "";
width: 12px;
height: 12px;
border-width: 1px;
border-style: solid;
border-color: transparent transparent rgba(0, 0, 0, 0.3) rgba(0, 0, 0, 0.3);
-webkit-transform: rotate(-135deg);
transform: rotate(-135deg);
position: absolute;
left: 5px;
top: 4px;
}
}
.icon_lser {
width: 10%;
height: 16px;
display: block;
position: relative;
&:after {
content: "";
width: 12px;
height: 12px;
border-width: 1px;
border-style: solid;
border-color: transparent transparent rgba(0, 0, 0, 0.3) rgba(0, 0, 0, 0.3);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
left: 5px;
top: 4px;
}
}
.active_tips {
text-align: center;
}
.more_tips {
.tips {
height: 60px;
overflow: auto;
}
}
.more_sec_info {
font-size: 12px;
}
.lang-select-list {
height: 20px;
line-height: 20px;
text-align: center;
li {
font-size: 14px;
display: inline-block;
a {
padding: 10px;
color: #999;
&.current {
color: #ef5b00;
}
}
}
}
.outlook_tips {
color: #f66;
font-size: 12px;
padding-bottom: 20px;
display: none;
}
================================================
FILE: plugins/web/public/scss/reset.scss
================================================
* {
margin: 0;
padding: 0;
}
a,
a:hover {
text-decoration: none;
color: #09f;
}
body {
font-size: 14px;
font-family: arial, "Hiragino Sans GB", "Microsoft YaHei", "微軟正黑體", "儷黑 Pro", sans-serif;
color: #000;
background-color: #fff;
}
.tac {
text-align: center;
}
.fl {
float: left;
}
.fr {
float: right
}
ul {
list-style: none;
}
.clearfix {
&:before,
&:after {
content: " ";
display: table;
}
&:after {
clear: both;
}
}
================================================
FILE: plugins/web/templates/activeSync.html
================================================
亲爱的
您的邮箱 正在一台新的设备()上登录,详情如下
您使用的是outlook客户端,用户名和密码会被保存到第三方微软公司的服务器中,存在安全风险,推荐使用手机自带的邮件客户端
如果这不是您本人操作,您的邮箱密码可能已经泄露,请登录到内网帐号中心修改密码并拒绝该请求
如需协助请联系IT部门
已授权设备请登录到内网账号中心中的“手机邮箱”中进行管理
如果该设备不是您的设备,您的密码可能已经泄漏,请登录到内网账号中心修改密码
已拒绝设备请登录到内网账号中心中的“手机邮箱”中进行管理
已经激活的设备数超出了10台的限制,请登录到内网账号中心,在“手机邮箱”中删除不再使用的设备
更多安全知识,请访问小米安全中心