Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const parse = (locales: string | string[] = []): Entry[] => {
let raw: string[];
if (typeof locales === 'string') {
raw = locales.split(TAG_SEP);
} else {
raw = locales.reduce((a: string[], e: string): string[] => {
const tmp = e.split(TAG_SEP);
return a.concat(tmp);
}, []);
}
const result: Entry[] = [];
const len = raw.length;
for (let i = 0; i < len; i++) {
const id = raw[i].trim();
const tag = parseLanguageTag(id);
// Preserve 'und' undefined locale. If we resolve it, adding
// likely subtags will expand it to 'en-Latn-US'.
if (tag.hasLanguage() || tag.hasScript() || tag.hasRegion()) {
result.push(new Entry(id, LanguageResolver.resolve(tag)));
} else {
// Preserve undefined core fields, but include input's extensions
result.push(new Entry(id, new LanguageTag(
undefined, undefined, undefined, undefined, tag.extensions(), tag.privateUse()
)));
}
}
return result;
};
}, []);
}
const result: Entry[] = [];
const len = raw.length;
for (let i = 0; i < len; i++) {
const id = raw[i].trim();
const tag = parseLanguageTag(id);
// Preserve 'und' undefined locale. If we resolve it, adding
// likely subtags will expand it to 'en-Latn-US'.
if (tag.hasLanguage() || tag.hasScript() || tag.hasRegion()) {
result.push(new Entry(id, LanguageResolver.resolve(tag)));
} else {
// Preserve undefined core fields, but include input's extensions
result.push(new Entry(id, new LanguageTag(
undefined, undefined, undefined, undefined, tag.extensions(), tag.privateUse()
)));
}
}
return result;
};
static removeLikelySubtags(real: string | LanguageTag): LanguageTag {
const tag = typeof real === 'string' ? parseLanguageTag(real) : real;
const max = fastTag(tag);
if (max[Tag.LANGUAGE] === Tag.LANGUAGE || max[Tag.SCRIPT] === Tag.SCRIPT || max[Tag.REGION] === Tag.REGION) {
addLikelySubtags(max);
}
const tmp = UNDEFINED.slice(0);
// Using "en-Latn-US" as an example...
// 1. Match "en-Zzzz-ZZ"
tmp[Tag.LANGUAGE] = max[Tag.LANGUAGE];
let match = tmp.slice(0);
addLikelySubtags(match);
if (fastTagEquals(match, max)) {
return returnTag(tag, tmp);
}
// 2. Match "en-Zzzz-US"
const fastTag = (real: LanguageTag): FastTag => {
// Hack to get fast access to internal core fields without exposing them.
const fake = (real as any) as FakeLanguageTag;
// The fast tag is used for indexing purposes. Since a field may be
// undefined, and we don't want to use its string representation of
// the undefined value (e.g. 'und', 'Zzzz', etc), we use the field's
// index number to represent undefined.
const language = fake.core[Tag.LANGUAGE];
const script = fake.core[Tag.SCRIPT];
const region = fake.core[Tag.REGION];
return [
language || Tag.LANGUAGE,
script || Tag.SCRIPT,
region || Tag.REGION
];
};
addLikelySubtags(match);
if (fastTagEquals(match, max)) {
return returnTag(tag, tmp);
}
// 2. Match "en-Zzzz-US"
tmp[Tag.REGION] = max[Tag.REGION];
match = tmp.slice(0);
addLikelySubtags(match);
if (fastTagEquals(match, max)) {
tmp[Tag.LANGUAGE] = max[Tag.LANGUAGE];
return returnTag(tag, tmp);
}
// 3. Match "en-Latn-ZZ"
tmp[Tag.REGION] = Tag.REGION;
tmp[Tag.SCRIPT] = max[Tag.SCRIPT];
match = tmp.slice(0);
addLikelySubtags(match);
if (fastTagEquals(match, max)) {
return returnTag(tag, tmp);
}
// 4. Nothing matched, so return a copy of the original tag.
return returnTag(tag, max);
}
const fastTag = (real: LanguageTag): FastTag => {
// Hack to get fast access to internal core fields without exposing them.
const fake = (real as any) as FakeLanguageTag;
// The fast tag is used for indexing purposes. Since a field may be
// undefined, and we don't want to use its string representation of
// the undefined value (e.g. 'und', 'Zzzz', etc), we use the field's
// index number to represent undefined.
const language = fake.core[Tag.LANGUAGE];
const script = fake.core[Tag.SCRIPT];
const region = fake.core[Tag.REGION];
return [
language || Tag.LANGUAGE,
script || Tag.SCRIPT,
region || Tag.REGION
];
};
const fastTag = (real: LanguageTag): FastTag => {
// Hack to get fast access to internal core fields without exposing them.
const fake = (real as any) as FakeLanguageTag;
// The fast tag is used for indexing purposes. Since a field may be
// undefined, and we don't want to use its string representation of
// the undefined value (e.g. 'und', 'Zzzz', etc), we use the field's
// index number to represent undefined.
const language = fake.core[Tag.LANGUAGE];
const script = fake.core[Tag.SCRIPT];
const region = fake.core[Tag.REGION];
return [
language || Tag.LANGUAGE,
script || Tag.SCRIPT,
region || Tag.REGION
];
};
const returnTag = (real: LanguageTag, fast: FastTag): LanguageTag => {
const language = fast[Tag.LANGUAGE];
const script = fast[Tag.SCRIPT];
const region = fast[Tag.REGION];
return new LanguageTag(
typeof language === 'number' ? undefined : language,
typeof script === 'number' ? undefined : script,
typeof region === 'number' ? undefined : region,
real.variant(),
real.extensions(),
real.privateUse()
);
};
import { parseLanguageTag, LanguageTag } from '@phensley/language-tag';
import { LanguageResolver } from './resolver';
const UNDEFINED = new LanguageTag();
/**
* Wrapper pairing an application's opaque locale identifier with a
* parsed and resolved language tag object.
*
* @alpha
*/
export interface Locale {
/**
* Application's own identifier for the locale, e.g. 'en_US', 'fr-CA', etc.
* We preserve this since applications may use it as a unique key to
* resolve translated messages, and may be forced to use a legacy
* identifier.
*/
readonly id: string;
}
for (let j = 0; j < this.count; j++) {
const supported = this.supported[j];
const distance = getDistance(desired.tag, supported.tag, threshold);
if (bestDistance === U || distance < bestDistance) {
bestDistance = distance;
bestMatch = supported;
bestDesired = desired;
}
}
}
const extensions = bestDesired.tag.extensions();
const privateUse = bestDesired.tag.privateUse();
const { id, tag } = bestMatch === U ? this.default : bestMatch;
const result = new LanguageTag(tag.language(), tag.script(), tag.region(), tag.variant(), extensions, privateUse);
return {
locale: { id, tag: result },
distance: bestMatch === U ? MAX_DISTANCE : bestDistance
};
}
}