vendor: 8,402 bytes, lines 1-290
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 ) );
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.