PageSourceSearch

https://web.rosknroll.fi/rosknroll/js/globalize/cldr.js

js rosknroll.fi collected 2026-09-26 03:00:27 UTC 17,683 bytes, 662 lines download raw bytes

vendor: 8,098 bytes, lines 1-271
1/**
2 * CLDR JavaScript Library v0.4.3
3 * http://jquery.com/
4 *
5 * Copyright 2013 Rafael Xavier de Souza
6 * Released under the MIT license
7 * http://jquery.org/license
8 *
9 * Date: 2015-08-24T01:00Z
10 */
11/*!
12 * CLDR JavaScript Library v0.4.3 2015-08-24T01:00Z MIT license © Rafael Xavier
13 * http://git.io/h4lmVg
14 */
15(function( root, factory ) {
16
17	if ( typeof define === "function" && define.amd ) {
18		// AMD.
19		define( factory );
20	} else if ( typeof module === "object" && typeof module.exports === "object" ) {
21		// Node. CommonJS.
22		module.exports = factory();
23	} else {
24		// Global
25		root.Cldr = factory();
26	}
27
28}( this, function() {
29
30
31	var arrayIsArray = Array.isArray || function( obj ) {
32		return Object.prototype.toString.call( obj ) === "[object Array]";
33	};
34
35
36
37
38	var pathNormalize = function( path, attributes ) {
39		if ( arrayIsArray( path ) ) {
40			path = path.join( "/" );
41		}
42		if ( typeof path !== "string" ) {
43			throw new Error( "invalid path \"" + path + "\"" );
44		}
45		// 1: Ignore leading slash `/`
46		// 2: Ignore leading `cldr/`
47		path = path
48			.replace( /^\// , "" ) /* 1 */
49			.replace( /^cldr\// , "" ); /* 2 */
50
51		// Replace {attribute}'s
52		path = path.replace( /{[a-zA-Z]+}/g, function( name ) {
53			name = name.replace( /^{([^}]*)}$/, "$1" );
54			return attributes[ name ];
55		});
56
57		return path.split( "/" );
58	};
59
60
61
62
63	var arraySome = function( array, callback ) {
64		var i, length;
65		if ( array.some ) {
66			return array.some( callback );
67		}
68		for ( i = 0, length = array.length; i < length; i++ ) {
69			if ( callback( array[ i ], i, array ) ) {
70				return true;
71			}
72		}
73		return false;
74	};
75
76
77
78
79	/**
80	 * Return the maximized language id as defined in
81	 * http://www.unicode.org/reports/tr35/#Likely_Subtags
82	 * 1. Canonicalize.
83	 * 1.1 Make sure the input locale is in canonical form: uses the right
84	 * separator, and has the right casing.
85	 * TODO Right casing? What df? It seems languages are lowercase, scripts are
86	 * Capitalized, territory is uppercase. I am leaving this as an exercise to
87	 * the user.
88	 *
89	 * 1.2 Replace any deprecated subtags with their canonical values using the
90	 * <alias> data in supplemental metadata. Use the first value in the
91	 * replacement list, if it exists. Language tag replacements may have multiple
92	 * parts, such as "sh" ➞ "sr_Latn" or mo" ➞ "ro_MD". In such a case, the
93	 * original script and/or region are retained if there is one. Thus
94	 * "sh_Arab_AQ" ➞ "sr_Arab_AQ", not "sr_Latn_AQ".
95	 * TODO What <alias> data?
96	 *
97	 * 1.3 If the tag is grandfathered (see <variable id="$grandfathered"
98	 * type="choice"> in the supplemental data), then return it.
99	 * TODO grandfathered?
100	 *
101	 * 1.4 Remove the script code 'Zzzz' and the region code 'ZZ' if they occur.
102	 * 1.5 Get the components of the cleaned-up source tag (languages, scripts,
103	 * and regions), plus any variants and extensions.
104	 * 2. Lookup. Lookup each of the following in order, and stop on the first
105	 * match:
106	 * 2.1 languages_scripts_regions
107	 * 2.2 languages_regions
108	 * 2.3 languages_scripts
109	 * 2.4 languages
110	 * 2.5 und_scripts
111	 * 3. Return
112	 * 3.1 If there is no match, either return an error value, or the match for
113	 * "und" (in APIs where a valid language tag is required).
114	 * 3.2 Otherwise there is a match = languagem_scriptm_regionm
115	 * 3.3 Let xr = xs if xs is not empty, and xm otherwise.
116	 * 3.4 Return the language tag composed of languager _ scriptr _ regionr +
117	 * variants + extensions.
118	 *
119	 * @subtags [Array] normalized language id subtags tuple (see init.js).
120	 */
121	var coreLikelySubtags = function( Cldr, cldr, subtags, options ) {
122		var match, matchFound,
123			language = subtags[ 0 ],
124			script = subtags[ 1 ],
125			sep = Cldr.localeSep,
126			territory = subtags[ 2 ];
127		options = options || {};
128
129		// Skip if (language, script, territory) is not empty [3.3]
130		if ( language !== "und" && script !== "Zzzz" && territory !== "ZZ" ) {
131			return [ language, script, territory ];
132		}
133
134		// Skip if no supplemental likelySubtags data is present
135		if ( typeof cldr.get( "supplemental/likelySubtags" ) === "undefined" ) {
136			return;
137		}
138
139		// [2]
140		matchFound = arraySome([
141			[ language, script, territory ],
142			[ language, territory ],
143			[ language, script ],
144			[ language ],
145			[ "und", script ]
146		], function( test ) {
147			return match = !(/\b(Zzzz|ZZ)\b/).test( test.join( sep ) ) /* [1.4] */ && cldr.get( [ "supplemental/likelySubtags", test.join( sep ) ] );
148		});
149
150		// [3]
151		if ( matchFound ) {
152			// [3.2 .. 3.4]
153			match = match.split( sep );
154			return [
155				language !== "und" ? language : match[ 0 ],
156				script !== "Zzzz" ? script : match[ 1 ],
157				territory !== "ZZ" ? territory : match[ 2 ]
158			];
159		} else if ( options.force ) {
160			// [3.1.2]
161			return cldr.get( "supplemental/likelySubtags/und" ).split( sep );
162		} else {
163			// [3.1.1]
164			return;
165		}
166	};
167
168
169
170	/**
171	 * Given a locale, remove any fields that Add Likely Subtags would add.
172	 * http://www.unicode.org/reports/tr35/#Likely_Subtags
173	 * 1. First get max = AddLikelySubtags(inputLocale). If an error is signaled,
174	 * return it.
175	 * 2. Remove the variants from max.
176	 * 3. Then for trial in {language, language _ region, language _ script}. If
177	 * AddLikelySubtags(trial) = max, then return trial + variants.
178	 * 4. If you do not get a match, return max + variants.
179	 * 
180	 * @maxLanguageId [Array] maxLanguageId tuple (see init.js).
181	 */
182	var coreRemoveLikelySubtags = function( Cldr, cldr, maxLanguageId ) {
183		var match, matchFound,
184			language = maxLanguageId[ 0 ],
185			script = maxLanguageId[ 1 ],
186			territory = maxLanguageId[ 2 ];
187
188		// [3]
189		matchFound = arraySome([
190			[ [ language, "Zzzz", "ZZ" ], [ language ] ],
191			[ [ language, "Zzzz", territory ], [ language, territory ] ],
192			[ [ language, script, "ZZ" ], [ language, script ] ]
193		], function( test ) {
194			var result = coreLikelySubtags( Cldr, cldr, test[ 0 ] );
195			match = test[ 1 ];
196			return result && result[ 0 ] === maxLanguageId[ 0 ] &&
197				result[ 1 ] === maxLanguageId[ 1 ] &&
198				result[ 2 ] === maxLanguageId[ 2 ];
199		});
200
201		// [4]
202		return matchFound ?  match : maxLanguageId;
203	};
204
205
206
207
208	/**
209	 * subtags( locale )
210	 *
211	 * @locale [String]
212	 */
213	var coreSubtags = function( locale ) {
214		var aux, unicodeLanguageId,
215			subtags = [];
216
217		locale = locale.replace( /_/, "-" );
218
219		// Unicode locale extensions.
220		aux = locale.split( "-u-" );
221		if ( aux[ 1 ] ) {
222			aux[ 1 ] = aux[ 1 ].split( "-t-" );
223			locale = aux[ 0 ] + ( aux[ 1 ][ 1 ] ? "-t-" + aux[ 1 ][ 1 ] : "");
224			subtags[ 4 /* unicodeLocaleExtensions */ ] = aux[ 1 ][ 0 ];
225		}
226
227		// TODO normalize transformed extensions. Currently, skipped.
228		// subtags[ x ] = locale.split( "-t-" )[ 1 ];
229		unicodeLanguageId = locale.split( "-t-" )[ 0 ];
230
231		// unicode_language_id = "root"
232		//   | unicode_language_subtag         
233		//     (sep unicode_script_subtag)? 
234		//     (sep unicode_region_subtag)?
235		//     (sep unicode_variant_subtag)* ;
236		//
237		// Although unicode_language_subtag = alpha{2,8}, I'm using alpha{2,3}. Because, there's no language on CLDR lengthier than 3.
238		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)$/ );
239		if ( aux === null ) {
240			return [ "und", "Zzzz", "ZZ" ];
241		}
242		subtags[ 0 /* language */ ] = aux[ 9 ] /* root */ || aux[ 2 ] || "und";
243		subtags[ 1 /* script */ ] = aux[ 4 ] || "Zzzz";
244		subtags[ 2 /* territory */ ] = aux[ 6 ] || "ZZ";
245		subtags[ 3 /* variant */ ] = aux[ 7 ];
246
247		// 0: language
248		// 1: script
249		// 2: territory (aka region)
250		// 3: variant
251		// 4: unicodeLocaleExtensions
252		return subtags;
253	};
254
255
256
257
258	var arrayForEach = function( array, callback ) {
259		var i, length;
260		if ( array.forEach ) {
261			return array.forEach( callback );
262		}
263		for ( i = 0, length = array.length; i < length; i++ ) {
264			callback( array[ i ], i, array );
265		}
266	};
267
268
269
270
271	/**
272	 * bundleLookup( minLanguageId )
273	 *
274	 * @Cldr [Cldr class]
275	 *
276	 * @cldr [Cldr instance]
277	 *
278	 * @minLanguageId [String] requested languageId after applied remove likely subtags.
279	 */
280	var bundleLookup = function( Cldr, cldr, minLanguageId ) {
281		var availableBundleMap = Cldr._availableBundleMap,
282			availableBundleMapQueue = Cldr._availableBundleMapQueue;
283
284		if ( availableBundleMapQueue.length ) {
285			arrayForEach( availableBundleMapQueue, function( bundle ) {
286				var existing, maxBundle, minBundle, subtags;
287				subtags = coreSubtags( bundle );
288				maxBundle = coreLikelySubtags( Cldr, cldr, subtags, { force: true } ) || subtags;
289				minBundle = coreRemoveLikelySubtags( Cldr, cldr, maxBundle );
290				minBundle = minBundle.join( Cldr.localeSep );
291				existing = availableBundleMapQueue[ minBundle ];
292				if ( existing && existing.length < bundle.length ) {
293					return;
294				}
295				availableBundleMap[ minBundle ] = bundle;
296			});
297			Cldr._availableBundleMapQueue = [];
298		}
299
300		return availableBundleMap[ minLanguageId ] || null;
301	};
302
303
304
305
306	var objectKeys = function( object ) {
307		var i,
308			result = [];
309
310		if ( Object.keys ) {
311			return Object.keys( object );
312		}
313
314		for ( i in object ) {
315			result.push( i );
316		}
317
318		return result;
319	};
320
321
322
323
324	var createError = function( code, attributes ) {
325		var error, message;
326
327		message = code + ( attributes && JSON ? ": " + JSON.stringify( attributes ) : "" );
328		error = new Error( message );
329		error.code = code;
330
331		// extend( error, attributes );
332		arrayForEach( objectKeys( attributes ), function( attribute ) {
333			error[ attribute ] = attributes[ attribute ];
334		});
335
336		return error;
337	};
338
339
340
341
342	var validate = function( code, check, attributes ) {
343		if ( !check ) {
344			throw createError( code, attributes );
345		}
346	};
347
348
349
350
351	var validatePresence = function( value, name ) {
352		validate( "E_MISSING_PARAMETER", typeof value !== "undefined", {
353			name: name
354		});
355	};
356
357
358
359
360	var validateType = function( value, name, check, expected ) {
361		validate( "E_INVALID_PAR_TYPE", check, {
362			expected: expected,
363			name: name,
364			value: value
365		});
366	};
367
368
369
370
371	var validateTypePath = function( value, name ) {
372		validateType( value, name, typeof value === "string" || arrayIsArray( value ), "String or Array" );
373	};
374
375
376
377
378	/**
379	 * Function inspired by jQuery Core, but reduced to our use case.
380	 */
381	var isPlainObject = function( obj ) {
382		return obj !== null && "" + obj === "[object Object]";
383	};
384
385
386
387
388	var validateTypePlainObject = function( value, name ) {
389		validateType( value, name, typeof value === "undefined" || isPlainObject( value ), "Plain Object" );
390	};
391
392
393
394
395	var validateTypeString = function( value, name ) {
396		validateType( value, name, typeof value === "string", "a string" );
397	};
398
399
400
401
402	// @path: normalized path
403	var resourceGet = function( data, path ) {
404		var i,
405			node = data,
406			length = path.length;
407
408		for ( i = 0; i < length - 1; i++ ) {
409			node = node[ path[ i ] ];
410			if ( !node ) {
411				return undefined;
412			}
413		}
414		return node[ path[ i ] ];
415	};
416
417
418
419
420	/**
421	 * setAvailableBundles( Cldr, json )
422	 *
423	 * @Cldr [Cldr class]
424	 *
425	 * @json resolved/unresolved cldr data.
426	 *
427	 * Set available bundles queue based on passed json CLDR data. Considers a bundle as any String at /main/{bundle}.
428	 */
429	var coreSetAvailableBundles = function( Cldr, json ) {
430		var bundle,
431			availableBundleMapQueue = Cldr._availableBundleMapQueue,
432			main = resourceGet( json, [ "main" ] );
433
434		if ( main ) {
435			for ( bundle in main ) {
436				if ( main.hasOwnProperty( bundle ) && bundle !== "root" ) {
437					availableBundleMapQueue.push( bundle );
438				}
439			}
440		}
441	};
442
443
444
445	var alwaysArray = function( somethingOrArray ) {
446		return arrayIsArray( somethingOrArray ) ?  somethingOrArray : [ somethingOrArray ];
447	};
448
449
450	var jsonMerge = (function() {
451
452	// Returns new deeply merged JSON.
453	//
454	// Eg.
455	// merge( { a: { b: 1, c: 2 } }, { a: { b: 3, d: 4 } } )
456	// -> { a: { b: 3, c: 2, d: 4 } }
457	//
458	// @arguments JSON's
459	// 
460	var merge = function() {
461		var destination = {},
462			sources = [].slice.call( arguments, 0 );
463		arrayForEach( sources, function( source ) {
464			var prop;
465			for ( prop in source ) {
466				if ( prop in destination && typeof destination[ prop ] === "object" && !arrayIsArray( destination[ prop ] ) ) {
467
468					// Merge Objects
469					destination[ prop ] = merge( destination[ prop ], source[ prop ] );
470
471				} else {
472
473					// Set new values
474					destination[ prop ] = source[ prop ];
475
476				}
477			}
478		});
479		return destination;
480	};
481
482	return merge;
483
484}());
485
486
487	/**
488	 * load( Cldr, source, jsons )
489	 *
490	 * @Cldr [Cldr class]
491	 *
492	 * @source [Object]
493	 *
494	 * @jsons [arguments]
495	 */
496	var coreLoad = function( Cldr, source, jsons ) {
497		var i, j, json;
498
499		validatePresence( jsons[ 0 ], "json" );
500
501		// Support arbitrary parameters, e.g., `Cldr.load({...}, {...})`.
502		for ( i = 0; i < jsons.length; i++ ) {
503
504			// Support array parameters, e.g., `Cldr.load([{...}, {...}])`.
505			json = alwaysArray( jsons[ i ] );
506
507			for ( j = 0; j < json.length; j++ ) {
508				validateTypePlainObject( json[ j ], "json" );
509				source = jsonMerge( source, json[ j ] );
510				coreSetAvailableBundles( Cldr, json[ j ] );
511			}
512		}
513
514		return source;
515	};
516
517
518
519	var itemGetResolved = function( Cldr, path, attributes ) {
520		// Resolve path
521		var normalizedPath = pathNormalize( path, attributes );
522
523		return resourceGet( Cldr._resolved, normalizedPath );
524	};
525
526
527
528
529	/**
530	 * new Cldr()
531	 */
532	var Cldr = function( locale ) {
533		this.init( locale );
534	};
535
536	// Build optimization hack to avoid duplicating functions across modules.
537	Cldr._alwaysArray = alwaysArray;
538	Cldr._coreLoad = coreLoad;
539	Cldr._createError = createError;
540	Cldr._itemGetResolved = itemGetResolved;
541	Cldr._jsonMerge = jsonMerge;
542	Cldr._pathNormalize = pathNormalize;
543	Cldr._resourceGet = resourceGet;
544	Cldr._validatePresence = validatePresence;
545	Cldr._validateType = validateType;
546	Cldr._validateTypePath = validateTypePath;
547	Cldr._validateTypePlainObject = validateTypePlainObject;
548
549	Cldr._availableBundleMap = {};
550	Cldr._availableBundleMapQueue = [];
551	Cldr._resolved = {};
552
553	// 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.
554	Cldr.localeSep = "-";
555
556	/**
557	 * Cldr.load( json [, json, ...] )
558	 *
559	 * @json [JSON] CLDR data or [Array] Array of @json's.
560	 *
561	 * Load resolved cldr data.
562	 */
563	Cldr.load = function() {
564		Cldr._resolved = coreLoad( Cldr, Cldr._resolved, arguments );
565	};
566
567	/**
568	 * .init() automatically run on instantiation/construction.
569	 */
570	Cldr.prototype.init = function( locale ) {
571		var attributes, language, maxLanguageId, minLanguageId, script, subtags, territory, unicodeLocaleExtensions, variant,
572			sep = Cldr.localeSep;
573
574		validatePresence( locale, "locale" );
575		validateTypeString( locale, "locale" );
576
577		subtags = coreSubtags( locale );
578
579		unicodeLocaleExtensions = subtags[ 4 ];
580		variant = subtags[ 3 ];
581
582		// Normalize locale code.
583		// Get (or deduce) the "triple subtags": language, territory (also aliased as region), and script subtags.
584		// Get the variant subtags (calendar, collation, currency, etc).
585		// refs:
586		// - http://www.unicode.org/reports/tr35/#Field_Definitions
587		// - http://www.unicode.org/reports/tr35/#Language_and_Locale_IDs
588		// - http://www.unicode.org/reports/tr35/#Unicode_locale_identifier
589
590		// When a locale id does not specify a language, or territory (region), or script, they are obtained by Likely Subtags.
591		maxLanguageId = coreLikelySubtags( Cldr, this, subtags, { force: true } ) || subtags;
592		language = maxLanguageId[ 0 ];
593		script = maxLanguageId[ 1 ];
594		territory = maxLanguageId[ 2 ];
595
596		minLanguageId = coreRemoveLikelySubtags( Cldr, this, maxLanguageId ).join( sep );
597
598		// Set attributes
599		this.attributes = attributes = {
vendor: 1,349 bytes, lines 600-662
600			bundle: bundleLookup( Cldr, this, minLanguageId ),
601
602			// Unicode Language Id
603			minlanguageId: minLanguageId,
604			maxLanguageId: maxLanguageId.join( sep ),
605
606			// Unicode Language Id Subtabs
607			language: language,
608			script: script,
609			territory: territory,
610			region: territory, /* alias */
611			variant: variant
612		};
613
614		// Unicode locale extensions.
615		unicodeLocaleExtensions && ( "-" + unicodeLocaleExtensions ).replace( /-[a-z]{3,8}|(-[a-z]{2})-([a-z]{3,8})/g, function( attribute, key, type ) {
616
617			if ( key ) {
618
619				// Extension is in the `keyword` form.
620				attributes[ "u" + key ] = type;
621			} else {
622
623				// Extension is in the `attribute` form.
624				attributes[ "u" + attribute ] = true;
625			}
626		});
627
628		this.locale = locale;
629	};
630
631	/**
632	 * .get()
633	 */
634	Cldr.prototype.get = function( path ) {
635
636		validatePresence( path, "path" );
637		validateTypePath( path, "path" );
638
639		return itemGetResolved( Cldr, path, this.attributes );
640	};
641
642	/**
643	 * .main()
644	 */
645	Cldr.prototype.main = function( path ) {
646		validatePresence( path, "path" );
647		validateTypePath( path, "path" );
648
649		validate( "E_MISSING_BUNDLE", this.attributes.bundle !== null, {
650			locale: this.locale
651		});
652
653		path = alwaysArray( path );
654		return this.get( [ "main/{bundle}" ].concat( path ) );
655	};
656
657	return Cldr;
658
659
660
661
662}));

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.