yavsc/web/Scripts/cldr.js

668 lines
17 KiB
JavaScript

* MarkdownHelper.cs: implements MarkdownDeep helper from NuGet * uninstdbws.sql: * jquery-2.1.3.js: * jquery-2.1.4.js: * date.js: * mdd_help.htm: * scorediv-latest.js: * jquery-2.1.4.min.js: * jquery-2.1.3.min.js: * plural.js: * number.js: * jquery-2.1.4.min.map: * message.js: * jquery-2.1.3.min.map: * jquery-2.1.3-vsdoc.js: * currency.js: * jquery-2.1.4-vsdoc.js: * globalize.js: * MarkdownDeepLib.min.js: * relative-time.js: * globalize.cultures.js: * globalize.culture.kn.js: * globalize.culture.or.js: * globalize.culture.pa.js: * globalize.culture.pl.js: * globalize.culture.fo.js: * globalize.culture.ps.js: * globalize.culture.fi.js: * globalize.culture.fa.js: * globalize.culture.fr.js: * globalize.culture.nn.js: * globalize.culture.no.js: * globalize.culture.gl.js: * globalize.culture.gd.js: * globalize.culture.ga.js: * globalize.culture.oc.js: * globalize.culture.fy.js: * globalize.culture.eu.js: * globalize.culture.se.js: * globalize.culture.si.js: * globalize.culture.sk.js: * globalize.culture.sl.js: * globalize.culture.sq.js: * globalize.culture.sr.js: * globalize.culture.sv.js: * globalize.culture.sa.js: * globalize.culture.pt.js: * globalize.culture.et.js: * globalize.culture.es.js: * globalize.culture.rm.js: * globalize.culture.ro.js: * globalize.culture.ru.js: * globalize.culture.rw.js: * globalize.culture.gu.js: * globalize.culture.kk.js: * globalize.culture.ka.js: * globalize.culture.mk.js: * globalize.culture.ja.js: * globalize.culture.iu.js: * globalize.culture.ml.js: * globalize.culture.mn.js: * globalize.culture.mi.js: * globalize.culture.ky.js: * globalize.culture.lo.js: * globalize.culture.ko.js: * globalize.culture.lt.js: * globalize.culture.lv.js: * globalize.culture.km.js: * globalize.culture.kl.js: * globalize.culture.it.js: * globalize.culture.nb.js: * globalize.culture.hr.js: * globalize.culture.ne.js: * globalize.culture.hi.js: * globalize.culture.he.js: * globalize.culture.ha.js: * globalize.culture.nl.js: * globalize.culture.hu.js: * globalize.culture.mr.js: * globalize.culture.is.js: * globalize.culture.ii.js: * globalize.culture.ig.js: * globalize.culture.ms.js: * globalize.culture.id.js: * globalize.culture.hy.js: * globalize.culture.mt.js: * globalize.culture.sw.js: * globalize.culture.bs.js: * globalize.culture.tt.js: * globalize.culture.lb.js: * globalize.culture.ug.js: * globalize.culture.br.js: * globalize.culture.bo.js: * globalize.culture.uk.js: * globalize.culture.ca.js: * globalize.culture.tk.js: * globalize.culture.da.js: * globalize.culture.cy.js: * globalize.culture.tn.js: * globalize.culture.cs.js: * globalize.culture.co.js: * globalize.culture.tr.js: * globalize.culture.bn.js: * globalize.culture.as.js: * globalize.culture.yo.js: * globalize.culture.ar.js: * globalize.culture.zh.js: * globalize.culture.zu.js: * globalize.culture.am.js: * globalize.culture.af.js: * globalize.culture.xh.js: * globalize.culture.ur.js: * globalize.culture.bg.js: * globalize.culture.uz.js: * globalize.culture.be.js: * globalize.culture.ba.js: * globalize.culture.vi.js: * globalize.culture.az.js: * globalize.culture.wo.js: * globalize.culture.dv.js: * globalize.culture.te.js: * globalize.culture.de.js: * globalize.culture.tg.js: * globalize.culture.ta.js: * globalize.culture.el.js: * globalize.culture.th.js: * globalize.culture.arn.js: * globalize.culture.gsw.js: * globalize.culture.nso.js: * globalize.culture.sah.js: * globalize.culture.syr.js: * globalize.culture.tzm.js: * globalize.culture.kok.js: * globalize.culture.dsb.js: * globalize.culture.moh.js: * globalize.culture.sms.js: * globalize.culture.smn.js: * globalize.culture.smj.js: * globalize.culture.sma.js: * globalize.culture.hsb.js: * globalize.culture.quz.js: * globalize.culture.fil.js: * globalize.culture.qut.js: * globalize.culture.prs.js: * globalize.culture.mn-MN.js: * globalize.culture.rm-CH.js: * globalize.culture.ta-IN.js: * globalize.culture.ml-IN.js: * globalize.culture.zh-CN.js: * globalize.culture.zh-HK.js: * globalize.culture.tn-ZA.js: * globalize.culture.ms-BN.js: * globalize.culture.ro-RO.js: * globalize.culture.sq-AL.js: * globalize.culture.mr-IN.js: * globalize.culture.yo-NG.js: * globalize.culture.pt-PT.js: * globalize.culture.sa-IN.js: * globalize.culture.zh-MO.js: * globalize.culture.am-ET.js: * globalize.culture.lt-LT.js: * globalize.culture.tk-TM.js: * globalize.culture.sw-KE.js: * globalize.culture.af-ZA.js: * globalize.culture.lo-LA.js: * globalize.culture.lv-LV.js: * globalize.culture.mk-MK.js: * globalize.culture.zh-SG.js: * globalize.culture.zh-TW.js: * globalize.culture.sv-FI.js: * globalize.culture.mi-NZ.js: * globalize.culture.zu-ZA.js: * globalize.culture.sv-SE.js: * globalize.culture.xh-ZA.js: * globalize.culture.uk-UA.js: * globalize.culture.se-SE.js: * globalize.culture.nn-NO.js: * globalize.culture.si-LK.js: * globalize.culture.nl-NL.js: * globalize.culture.ur-PK.js: * globalize.culture.pl-PL.js: * globalize.culture.or-IN.js: * globalize.culture.tt-RU.js: * globalize.culture.pa-IN.js: * globalize.culture.ug-CN.js: * globalize.culture.rw-RW.js: * globalize.culture.se-FI.js: * globalize.culture.se-NO.js: * globalize.culture.nl-BE.js: * globalize.culture.ru-RU.js: * globalize.culture.mt-MT.js: * globalize.culture.th-TH.js: * globalize.culture.wo-SN.js: * globalize.culture.pt-BR.js: * globalize.culture.ms-MY.js: * globalize.culture.vi-VN.js: * globalize.culture.te-IN.js: * globalize.culture.sk-SK.js: * globalize.culture.ne-NP.js: * globalize.culture.tr-TR.js: * globalize.culture.sl-SI.js: * globalize.culture.ps-AF.js: * globalize.culture.nb-NO.js: * globalize.culture.oc-FR.js: * globalize.culture.en-JM.js: * globalize.culture.en-MY.js: * globalize.culture.en-NZ.js: * globalize.culture.en-PH.js: * globalize.culture.en-SG.js: * globalize.culture.en-TT.js: * globalize.culture.en-US.js: * globalize.culture.en-IN.js: * globalize.culture.dv-MV.js: * globalize.culture.el-GR.js: * globalize.culture.en-AU.js: * globalize.culture.en-BZ.js: * globalize.culture.en-CA.js: * globalize.culture.en-GB.js: * globalize.culture.en-IE.js: * globalize.culture.en-ZA.js: * globalize.culture.es-ES.js: * globalize.culture.es-GT.js: * globalize.culture.es-HN.js: * globalize.culture.es-MX.js: * globalize.culture.es-NI.js: * globalize.culture.es-PA.js: * globalize.culture.es-PE.js: * globalize.culture.es-EC.js: * globalize.culture.en-ZW.js: * globalize.culture.es-AR.js: * globalize.culture.es-BO.js: * globalize.culture.es-CL.js: * globalize.culture.es-CO.js: * globalize.culture.es-CR.js: * globalize.culture.es-DO.js: * globalize.culture.de-LU.js: * globalize.culture.ar-OM.js: * globalize.culture.ar-QA.js: * globalize.culture.ar-SA.js: * globalize.culture.ar-SY.js: * globalize.culture.ar-TN.js: * globalize.culture.ar-YE.js: * globalize.culture.as-IN.js: * globalize.culture.ar-MA.js: * globalize.culture.ar-DZ.js: * globalize.culture.ar-EG.js: * globalize.culture.ar-IQ.js: * globalize.culture.ar-JO.js: * globalize.culture.ar-KW.js: * globalize.culture.ar-LB.js: * globalize.culture.ar-LY.js: * globalize.culture.ba-RU.js: * globalize.culture.cs-CZ.js: * globalize.culture.cy-GB.js: * globalize.culture.da-DK.js: * globalize.culture.de-AT.js: * globalize.culture.de-CH.js: * globalize.culture.de-DE.js: * globalize.culture.de-LI.js: * globalize.culture.co-FR.js: * globalize.culture.be-BY.js: * globalize.culture.bg-BG.js: * globalize.culture.bn-BD.js: * globalize.culture.bn-IN.js: * globalize.culture.bo-CN.js: * globalize.culture.br-FR.js: * globalize.culture.ca-ES.js: * globalize.culture.es-PR.js: * globalize.culture.hi-IN.js: * globalize.culture.hr-BA.js: * globalize.culture.hr-HR.js: * globalize.culture.hu-HU.js: * globalize.culture.hy-AM.js: * globalize.culture.id-ID.js: * globalize.culture.he-IL.js: * globalize.culture.fy-NL.js: * globalize.culture.ga-IE.js: * globalize.culture.gd-GB.js: * globalize.culture.gl-ES.js: * globalize.culture.gu-IN.js: * globalize.culture.ka-GE.js: * globalize.culture.ig-NG.js: * globalize.culture.km-KH.js: * globalize.culture.kn-IN.js: * globalize.culture.ar-BH.js: * globalize.culture.ko-KR.js: * globalize.culture.ky-KG.js: * globalize.culture.lb-LU.js: * globalize.culture.kl-GL.js: * globalize.culture.ii-CN.js: * globalize.culture.is-IS.js: * globalize.culture.it-CH.js: * globalize.culture.it-IT.js: * globalize.culture.ja-JP.js: * globalize.culture.ar-AE.js: * globalize.culture.kk-KZ.js: * globalize.culture.fr-MC.js: * globalize.culture.fr-LU.js: * globalize.culture.fr-FR.js: * globalize.culture.fa-IR.js: * globalize.culture.fr-CH.js: * globalize.culture.et-EE.js: * globalize.culture.fi-FI.js: * globalize.culture.fo-FO.js: * globalize.culture.fr-BE.js: * globalize.culture.fr-CA.js: * globalize.culture.eu-ES.js: * globalize.culture.es-US.js: * globalize.culture.es-PY.js: * globalize.culture.es-UY.js: * globalize.culture.es-VE.js: * globalize.culture.es-SV.js: * globalize.culture.sma-SE.js: * globalize.culture.hsb-DE.js: * globalize.culture.prs-AF.js: * globalize.culture.sma-NO.js: * globalize.culture.qut-GT.js: * globalize.culture.moh-CA.js: * globalize.culture.zh-CHT.js: * globalize.culture.quz-BO.js: * globalize.culture.fil-PH.js: * globalize.culture.zh-CHS.js: * globalize.culture.smj-NO.js: * globalize.culture.gsw-FR.js: * globalize.culture.nso-ZA.js: * globalize.culture.sms-FI.js: * globalize.culture.quz-PE.js: * globalize.culture.sah-RU.js: * globalize.culture.kok-IN.js: * globalize.culture.syr-SY.js: * globalize.culture.smj-SE.js: * globalize.culture.arn-CL.js: * globalize.culture.dsb-DE.js: * globalize.culture.quz-EC.js: * globalize.culture.smn-FI.js: * globalize.culture.en-029.js: * globalize.culture.uz-Latn.js: * globalize.culture.tg-Cyrl.js: * globalize.culture.iu-Cans.js: * globalize.culture.mn-Mong.js: * globalize.culture.az-Latn.js: * globalize.culture.az-Cyrl.js: * globalize.culture.sr-Cyrl.js: * globalize.culture.mn-Cyrl.js: * globalize.culture.bs-Cyrl.js: * globalize.culture.iu-Latn.js: * globalize.culture.ha-Latn.js: * globalize.culture.sr-Latn.js: * globalize.culture.zh-Hant.js: * globalize.culture.bs-Latn.js: * globalize.culture.uz-Cyrl.js: * globalize.culture.zh-Hans.js: * globalize.culture.tzm-Latn.js: * globalize.culture.iu-Latn-CA.js: * globalize.culture.sr-Latn-RS.js: * globalize.culture.sr-Latn-ME.js: * globalize.culture.sr-Latn-CS.js: * globalize.culture.sr-Latn-BA.js: * globalize.culture.sr-Cyrl-RS.js: * globalize.culture.sr-Cyrl-ME.js: * globalize.culture.sr-Cyrl-CS.js: * globalize.culture.sr-Cyrl-BA.js: * globalize.culture.ha-Latn-NG.js: * globalize.culture.mn-Mong-CN.js: * globalize.culture.az-Cyrl-AZ.js: * globalize.culture.az-Latn-AZ.js: * globalize.culture.uz-Latn-UZ.js: * globalize.culture.uz-Cyrl-UZ.js: * globalize.culture.iu-Cans-CA.js: * globalize.culture.bs-Cyrl-BA.js: * globalize.culture.bs-Latn-BA.js: * globalize.culture.tg-Cyrl-TJ.js: * globalize.culture.tzm-Latn-DZ.js: Package update * cldr.js: * globalize.js: * event.js: * unresolved.js: * supplemental.js: * adds Localisation purpose dependency * mdd_styles.css: * mdd_gripper.png: * mdd_toolbar.png: * mdd_ajax_loader.gif: * mdd_modal_background.png: Adds Markdown editor resources * CalendarController.cs: Refactoring : moved Notification and MessagesWithPayLoad into the Google data model (YavscModel) * BlogsController.cs: * Removes input validation, in order to process some Markdown values. * Makes the "Edit" Method the one that do the inital post (makes the "Post" method obsolete) * App.master: * jQuery version updated to 2.1.4 * style.css: Sets a non null padding to the body of html pages. * Edit.aspx: Passes from BBCodes to Markdown at edition time, adds the Markdown editor. * UserPost.aspx: Now displays Markdown content * Web.config: * Modifies the "Thanks" configuration * Removes useless addembly bindings * * Web.csproj: * packages.config: Package updates * instdbws.sql: Adds a GCM registration id in the user's profile data. * LoginModel.cs: Allows numbers in passords and logins * YavscModel.csproj: GCM refactorisation * Post.aspx: Replaced by Edit.aspx
9 years ago
/**
* CLDR JavaScript Library v0.4.1
* http://jquery.com/
*
* Copyright 2013 Rafael Xavier de Souza
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2015-02-25T13:51Z
*/
/*!
* CLDR JavaScript Library v0.4.1 2015-02-25T13:51Z 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 && arrayIsArray( destination[ prop ] ) ) {
// Concat Arrays
destination[ prop ] = destination[ prop ].concat( source[ prop ] );
} else if ( prop in destination && typeof destination[ prop ] === "object" ) {
// 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;
}));