| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662 |
- /**
- * CLDR JavaScript Library v0.4.3
- * http://jquery.com/
- *
- * Copyright 2013 Rafael Xavier de Souza
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2015-08-24T01:00Z
- */
- /*!
- * CLDR JavaScript Library v0.4.3 2015-08-24T01:00Z MIT license © Rafael Xavier
- * http://git.io/h4lmVg
- */
- (function( root, factory ) {
- if ( typeof define === "function" && define.amd ) {
- // AMD.
- define( factory );
- } else if ( typeof module === "object" && typeof module.exports === "object" ) {
- // Node. CommonJS.
- module.exports = factory();
- } else {
- // Global
- root.Cldr = factory();
- }
- }( this, function() {
- var arrayIsArray = Array.isArray || function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Array]";
- };
- var pathNormalize = function( path, attributes ) {
- if ( arrayIsArray( path ) ) {
- path = path.join( "/" );
- }
- if ( typeof path !== "string" ) {
- throw new Error( "invalid path \"" + path + "\"" );
- }
- // 1: Ignore leading slash `/`
- // 2: Ignore leading `cldr/`
- path = path
- .replace( /^\// , "" ) /* 1 */
- .replace( /^cldr\// , "" ); /* 2 */
- // Replace {attribute}'s
- path = path.replace( /{[a-zA-Z]+}/g, function( name ) {
- name = name.replace( /^{([^}]*)}$/, "$1" );
- return attributes[ name ];
- });
- return path.split( "/" );
- };
- var arraySome = function( array, callback ) {
- var i, length;
- if ( array.some ) {
- return array.some( callback );
- }
- for ( i = 0, length = array.length; i < length; i++ ) {
- if ( callback( array[ i ], i, array ) ) {
- return true;
- }
- }
- return false;
- };
- /**
- * Return the maximized language id as defined in
- * http://www.unicode.org/reports/tr35/#Likely_Subtags
- * 1. Canonicalize.
- * 1.1 Make sure the input locale is in canonical form: uses the right
- * separator, and has the right casing.
- * TODO Right casing? What df? It seems languages are lowercase, scripts are
- * Capitalized, territory is uppercase. I am leaving this as an exercise to
- * the user.
- *
- * 1.2 Replace any deprecated subtags with their canonical values using the
- * <alias> data in supplemental metadata. Use the first value in the
- * replacement list, if it exists. Language tag replacements may have multiple
- * parts, such as "sh" ➞ "sr_Latn" or mo" ➞ "ro_MD". In such a case, the
- * original script and/or region are retained if there is one. Thus
- * "sh_Arab_AQ" ➞ "sr_Arab_AQ", not "sr_Latn_AQ".
- * TODO What <alias> data?
- *
- * 1.3 If the tag is grandfathered (see <variable id="$grandfathered"
- * type="choice"> in the supplemental data), then return it.
- * TODO grandfathered?
- *
- * 1.4 Remove the script code 'Zzzz' and the region code 'ZZ' if they occur.
- * 1.5 Get the components of the cleaned-up source tag (languages, scripts,
- * and regions), plus any variants and extensions.
- * 2. Lookup. Lookup each of the following in order, and stop on the first
- * match:
- * 2.1 languages_scripts_regions
- * 2.2 languages_regions
- * 2.3 languages_scripts
- * 2.4 languages
- * 2.5 und_scripts
- * 3. Return
- * 3.1 If there is no match, either return an error value, or the match for
- * "und" (in APIs where a valid language tag is required).
- * 3.2 Otherwise there is a match = languagem_scriptm_regionm
- * 3.3 Let xr = xs if xs is not empty, and xm otherwise.
- * 3.4 Return the language tag composed of languager _ scriptr _ regionr +
- * variants + extensions.
- *
- * @subtags [Array] normalized language id subtags tuple (see init.js).
- */
- var coreLikelySubtags = function( Cldr, cldr, subtags, options ) {
- var match, matchFound,
- language = subtags[ 0 ],
- script = subtags[ 1 ],
- sep = Cldr.localeSep,
- territory = subtags[ 2 ];
- options = options || {};
- // Skip if (language, script, territory) is not empty [3.3]
- if ( language !== "und" && script !== "Zzzz" && territory !== "ZZ" ) {
- return [ language, script, territory ];
- }
- // Skip if no supplemental likelySubtags data is present
- if ( typeof cldr.get( "supplemental/likelySubtags" ) === "undefined" ) {
- return;
- }
- // [2]
- matchFound = arraySome([
- [ language, script, territory ],
- [ language, territory ],
- [ language, script ],
- [ language ],
- [ "und", script ]
- ], function( test ) {
- return match = !(/\b(Zzzz|ZZ)\b/).test( test.join( sep ) ) /* [1.4] */ && cldr.get( [ "supplemental/likelySubtags", test.join( sep ) ] );
- });
- // [3]
- if ( matchFound ) {
- // [3.2 .. 3.4]
- match = match.split( sep );
- return [
- language !== "und" ? language : match[ 0 ],
- script !== "Zzzz" ? script : match[ 1 ],
- territory !== "ZZ" ? territory : match[ 2 ]
- ];
- } else if ( options.force ) {
- // [3.1.2]
- return cldr.get( "supplemental/likelySubtags/und" ).split( sep );
- } else {
- // [3.1.1]
- return;
- }
- };
- /**
- * Given a locale, remove any fields that Add Likely Subtags would add.
- * http://www.unicode.org/reports/tr35/#Likely_Subtags
- * 1. First get max = AddLikelySubtags(inputLocale). If an error is signaled,
- * return it.
- * 2. Remove the variants from max.
- * 3. Then for trial in {language, language _ region, language _ script}. If
- * AddLikelySubtags(trial) = max, then return trial + variants.
- * 4. If you do not get a match, return max + variants.
- *
- * @maxLanguageId [Array] maxLanguageId tuple (see init.js).
- */
- var coreRemoveLikelySubtags = function( Cldr, cldr, maxLanguageId ) {
- var match, matchFound,
- language = maxLanguageId[ 0 ],
- script = maxLanguageId[ 1 ],
- territory = maxLanguageId[ 2 ];
- // [3]
- matchFound = arraySome([
- [ [ language, "Zzzz", "ZZ" ], [ language ] ],
- [ [ language, "Zzzz", territory ], [ language, territory ] ],
- [ [ language, script, "ZZ" ], [ language, script ] ]
- ], function( test ) {
- var result = coreLikelySubtags( Cldr, cldr, test[ 0 ] );
- match = test[ 1 ];
- return result && result[ 0 ] === maxLanguageId[ 0 ] &&
- result[ 1 ] === maxLanguageId[ 1 ] &&
- result[ 2 ] === maxLanguageId[ 2 ];
- });
- // [4]
- return matchFound ? match : maxLanguageId;
- };
- /**
- * subtags( locale )
- *
- * @locale [String]
- */
- var coreSubtags = function( locale ) {
- var aux, unicodeLanguageId,
- subtags = [];
- locale = locale.replace( /_/, "-" );
- // Unicode locale extensions.
- aux = locale.split( "-u-" );
- if ( aux[ 1 ] ) {
- aux[ 1 ] = aux[ 1 ].split( "-t-" );
- locale = aux[ 0 ] + ( aux[ 1 ][ 1 ] ? "-t-" + aux[ 1 ][ 1 ] : "");
- subtags[ 4 /* unicodeLocaleExtensions */ ] = aux[ 1 ][ 0 ];
- }
- // TODO normalize transformed extensions. Currently, skipped.
- // subtags[ x ] = locale.split( "-t-" )[ 1 ];
- unicodeLanguageId = locale.split( "-t-" )[ 0 ];
- // unicode_language_id = "root"
- // | unicode_language_subtag
- // (sep unicode_script_subtag)?
- // (sep unicode_region_subtag)?
- // (sep unicode_variant_subtag)* ;
- //
- // Although unicode_language_subtag = alpha{2,8}, I'm using alpha{2,3}. Because, there's no language on CLDR lengthier than 3.
- aux = unicodeLanguageId.match( /^(([a-z]{2,3})(-([A-Z][a-z]{3}))?(-([A-Z]{2}|[0-9]{3}))?)(-[a-zA-Z0-9]{5,8}|[0-9][a-zA-Z0-9]{3})*$|^(root)$/ );
- if ( aux === null ) {
- return [ "und", "Zzzz", "ZZ" ];
- }
- subtags[ 0 /* language */ ] = aux[ 9 ] /* root */ || aux[ 2 ] || "und";
- subtags[ 1 /* script */ ] = aux[ 4 ] || "Zzzz";
- subtags[ 2 /* territory */ ] = aux[ 6 ] || "ZZ";
- subtags[ 3 /* variant */ ] = aux[ 7 ];
- // 0: language
- // 1: script
- // 2: territory (aka region)
- // 3: variant
- // 4: unicodeLocaleExtensions
- return subtags;
- };
- var arrayForEach = function( array, callback ) {
- var i, length;
- if ( array.forEach ) {
- return array.forEach( callback );
- }
- for ( i = 0, length = array.length; i < length; i++ ) {
- callback( array[ i ], i, array );
- }
- };
- /**
- * bundleLookup( minLanguageId )
- *
- * @Cldr [Cldr class]
- *
- * @cldr [Cldr instance]
- *
- * @minLanguageId [String] requested languageId after applied remove likely subtags.
- */
- var bundleLookup = function( Cldr, cldr, minLanguageId ) {
- var availableBundleMap = Cldr._availableBundleMap,
- availableBundleMapQueue = Cldr._availableBundleMapQueue;
- if ( availableBundleMapQueue.length ) {
- arrayForEach( availableBundleMapQueue, function( bundle ) {
- var existing, maxBundle, minBundle, subtags;
- subtags = coreSubtags( bundle );
- maxBundle = coreLikelySubtags( Cldr, cldr, subtags, { force: true } ) || subtags;
- minBundle = coreRemoveLikelySubtags( Cldr, cldr, maxBundle );
- minBundle = minBundle.join( Cldr.localeSep );
- existing = availableBundleMapQueue[ minBundle ];
- if ( existing && existing.length < bundle.length ) {
- return;
- }
- availableBundleMap[ minBundle ] = bundle;
- });
- Cldr._availableBundleMapQueue = [];
- }
- return availableBundleMap[ minLanguageId ] || null;
- };
- var objectKeys = function( object ) {
- var i,
- result = [];
- if ( Object.keys ) {
- return Object.keys( object );
- }
- for ( i in object ) {
- result.push( i );
- }
- return result;
- };
- var createError = function( code, attributes ) {
- var error, message;
- message = code + ( attributes && JSON ? ": " + JSON.stringify( attributes ) : "" );
- error = new Error( message );
- error.code = code;
- // extend( error, attributes );
- arrayForEach( objectKeys( attributes ), function( attribute ) {
- error[ attribute ] = attributes[ attribute ];
- });
- return error;
- };
- var validate = function( code, check, attributes ) {
- if ( !check ) {
- throw createError( code, attributes );
- }
- };
- var validatePresence = function( value, name ) {
- validate( "E_MISSING_PARAMETER", typeof value !== "undefined", {
- name: name
- });
- };
- var validateType = function( value, name, check, expected ) {
- validate( "E_INVALID_PAR_TYPE", check, {
- expected: expected,
- name: name,
- value: value
- });
- };
- var validateTypePath = function( value, name ) {
- validateType( value, name, typeof value === "string" || arrayIsArray( value ), "String or Array" );
- };
- /**
- * Function inspired by jQuery Core, but reduced to our use case.
- */
- var isPlainObject = function( obj ) {
- return obj !== null && "" + obj === "[object Object]";
- };
- var validateTypePlainObject = function( value, name ) {
- validateType( value, name, typeof value === "undefined" || isPlainObject( value ), "Plain Object" );
- };
- var validateTypeString = function( value, name ) {
- validateType( value, name, typeof value === "string", "a string" );
- };
- // @path: normalized path
- var resourceGet = function( data, path ) {
- var i,
- node = data,
- length = path.length;
- for ( i = 0; i < length - 1; i++ ) {
- node = node[ path[ i ] ];
- if ( !node ) {
- return undefined;
- }
- }
- return node[ path[ i ] ];
- };
- /**
- * setAvailableBundles( Cldr, json )
- *
- * @Cldr [Cldr class]
- *
- * @json resolved/unresolved cldr data.
- *
- * Set available bundles queue based on passed json CLDR data. Considers a bundle as any String at /main/{bundle}.
- */
- var coreSetAvailableBundles = function( Cldr, json ) {
- var bundle,
- availableBundleMapQueue = Cldr._availableBundleMapQueue,
- main = resourceGet( json, [ "main" ] );
- if ( main ) {
- for ( bundle in main ) {
- if ( main.hasOwnProperty( bundle ) && bundle !== "root" ) {
- availableBundleMapQueue.push( bundle );
- }
- }
- }
- };
- var alwaysArray = function( somethingOrArray ) {
- return arrayIsArray( somethingOrArray ) ? somethingOrArray : [ somethingOrArray ];
- };
- var jsonMerge = (function() {
- // Returns new deeply merged JSON.
- //
- // Eg.
- // merge( { a: { b: 1, c: 2 } }, { a: { b: 3, d: 4 } } )
- // -> { a: { b: 3, c: 2, d: 4 } }
- //
- // @arguments JSON's
- //
- var merge = function() {
- var destination = {},
- sources = [].slice.call( arguments, 0 );
- arrayForEach( sources, function( source ) {
- var prop;
- for ( prop in source ) {
- if ( prop in destination && typeof destination[ prop ] === "object" && !arrayIsArray( destination[ prop ] ) ) {
- // Merge Objects
- destination[ prop ] = merge( destination[ prop ], source[ prop ] );
- } else {
- // Set new values
- destination[ prop ] = source[ prop ];
- }
- }
- });
- return destination;
- };
- return merge;
- }());
- /**
- * load( Cldr, source, jsons )
- *
- * @Cldr [Cldr class]
- *
- * @source [Object]
- *
- * @jsons [arguments]
- */
- var coreLoad = function( Cldr, source, jsons ) {
- var i, j, json;
- validatePresence( jsons[ 0 ], "json" );
- // Support arbitrary parameters, e.g., `Cldr.load({...}, {...})`.
- for ( i = 0; i < jsons.length; i++ ) {
- // Support array parameters, e.g., `Cldr.load([{...}, {...}])`.
- json = alwaysArray( jsons[ i ] );
- for ( j = 0; j < json.length; j++ ) {
- validateTypePlainObject( json[ j ], "json" );
- source = jsonMerge( source, json[ j ] );
- coreSetAvailableBundles( Cldr, json[ j ] );
- }
- }
- return source;
- };
- var itemGetResolved = function( Cldr, path, attributes ) {
- // Resolve path
- var normalizedPath = pathNormalize( path, attributes );
- return resourceGet( Cldr._resolved, normalizedPath );
- };
- /**
- * new Cldr()
- */
- var Cldr = function( locale ) {
- this.init( locale );
- };
- // Build optimization hack to avoid duplicating functions across modules.
- Cldr._alwaysArray = alwaysArray;
- Cldr._coreLoad = coreLoad;
- Cldr._createError = createError;
- Cldr._itemGetResolved = itemGetResolved;
- Cldr._jsonMerge = jsonMerge;
- Cldr._pathNormalize = pathNormalize;
- Cldr._resourceGet = resourceGet;
- Cldr._validatePresence = validatePresence;
- Cldr._validateType = validateType;
- Cldr._validateTypePath = validateTypePath;
- Cldr._validateTypePlainObject = validateTypePlainObject;
- Cldr._availableBundleMap = {};
- Cldr._availableBundleMapQueue = [];
- Cldr._resolved = {};
- // Allow user to override locale separator "-" (default) | "_". According to http://www.unicode.org/reports/tr35/#Unicode_language_identifier, both "-" and "_" are valid locale separators (eg. "en_GB", "en-GB"). According to http://unicode.org/cldr/trac/ticket/6786 its usage must be consistent throughout the data set.
- Cldr.localeSep = "-";
- /**
- * Cldr.load( json [, json, ...] )
- *
- * @json [JSON] CLDR data or [Array] Array of @json's.
- *
- * Load resolved cldr data.
- */
- Cldr.load = function() {
- Cldr._resolved = coreLoad( Cldr, Cldr._resolved, arguments );
- };
- /**
- * .init() automatically run on instantiation/construction.
- */
- Cldr.prototype.init = function( locale ) {
- var attributes, language, maxLanguageId, minLanguageId, script, subtags, territory, unicodeLocaleExtensions, variant,
- sep = Cldr.localeSep;
- validatePresence( locale, "locale" );
- validateTypeString( locale, "locale" );
- subtags = coreSubtags( locale );
- unicodeLocaleExtensions = subtags[ 4 ];
- variant = subtags[ 3 ];
- // Normalize locale code.
- // Get (or deduce) the "triple subtags": language, territory (also aliased as region), and script subtags.
- // Get the variant subtags (calendar, collation, currency, etc).
- // refs:
- // - http://www.unicode.org/reports/tr35/#Field_Definitions
- // - http://www.unicode.org/reports/tr35/#Language_and_Locale_IDs
- // - http://www.unicode.org/reports/tr35/#Unicode_locale_identifier
- // When a locale id does not specify a language, or territory (region), or script, they are obtained by Likely Subtags.
- maxLanguageId = coreLikelySubtags( Cldr, this, subtags, { force: true } ) || subtags;
- language = maxLanguageId[ 0 ];
- script = maxLanguageId[ 1 ];
- territory = maxLanguageId[ 2 ];
- minLanguageId = coreRemoveLikelySubtags( Cldr, this, maxLanguageId ).join( sep );
- // Set attributes
- this.attributes = attributes = {
- bundle: bundleLookup( Cldr, this, minLanguageId ),
- // Unicode Language Id
- minlanguageId: minLanguageId,
- maxLanguageId: maxLanguageId.join( sep ),
- // Unicode Language Id Subtabs
- language: language,
- script: script,
- territory: territory,
- region: territory, /* alias */
- variant: variant
- };
- // Unicode locale extensions.
- unicodeLocaleExtensions && ( "-" + unicodeLocaleExtensions ).replace( /-[a-z]{3,8}|(-[a-z]{2})-([a-z]{3,8})/g, function( attribute, key, type ) {
- if ( key ) {
- // Extension is in the `keyword` form.
- attributes[ "u" + key ] = type;
- } else {
- // Extension is in the `attribute` form.
- attributes[ "u" + attribute ] = true;
- }
- });
- this.locale = locale;
- };
- /**
- * .get()
- */
- Cldr.prototype.get = function( path ) {
- validatePresence( path, "path" );
- validateTypePath( path, "path" );
- return itemGetResolved( Cldr, path, this.attributes );
- };
- /**
- * .main()
- */
- Cldr.prototype.main = function( path ) {
- validatePresence( path, "path" );
- validateTypePath( path, "path" );
- validate( "E_MISSING_BUNDLE", this.attributes.bundle !== null, {
- locale: this.locale
- });
- path = alwaysArray( path );
- return this.get( [ "main/{bundle}" ].concat( path ) );
- };
- return Cldr;
- }));
|