mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-15 16:06:41 +03:00
fa041d776d
Resolves #5222. It also opens the way for improving the compliance with [RFC 5646](https://datatracker.ietf.org/doc/html/rfc5646) in the future.
241 lines
7.7 KiB
JavaScript
241 lines
7.7 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
describe('LanguageUtils', () => {
|
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
|
|
describe('areLocaleCompatible', () => {
|
|
it('works for language', () => {
|
|
expect(LanguageUtils.areLocaleCompatible('en', 'en')).toBeTruthy();
|
|
expect(LanguageUtils.areLocaleCompatible('en', 'fr')).toBeFalsy();
|
|
});
|
|
|
|
it('works for language and region', () => {
|
|
expect(LanguageUtils.areLocaleCompatible('en-US', 'en-US')).toBeTruthy();
|
|
expect(LanguageUtils.areLocaleCompatible('en-US', 'en-CA')).toBeFalsy();
|
|
});
|
|
|
|
it('ignores dialect', () => {
|
|
expect(LanguageUtils.areLocaleCompatible(
|
|
'en-US-tx', 'en-US-wa')).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('areLanguageCompatible', () => {
|
|
it('works for language', () => {
|
|
expect(LanguageUtils.areLanguageCompatible('en', 'en')).toBeTruthy();
|
|
expect(LanguageUtils.areLanguageCompatible('en', 'fr')).toBeFalsy();
|
|
});
|
|
|
|
it('works for language and region', () => {
|
|
expect(LanguageUtils.areLanguageCompatible(
|
|
'en-US', 'en-US')).toBeTruthy();
|
|
expect(LanguageUtils.areLanguageCompatible(
|
|
'en-US', 'en-CA')).toBeTruthy();
|
|
expect(LanguageUtils.areLanguageCompatible('en-CA', 'fr-CA')).toBeFalsy();
|
|
});
|
|
|
|
it('works for dialects', () => {
|
|
expect(LanguageUtils.areLanguageCompatible(
|
|
'en-US-tx', 'en-US-wa')).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('isSiblingOf', () => {
|
|
it('accepts self', () => {
|
|
expect(LanguageUtils.isSiblingOf('en-US', 'en-US')).toBeTruthy();
|
|
});
|
|
|
|
it('rejects other languages', () => {
|
|
expect(LanguageUtils.isSiblingOf('en-CA', 'fr-CA')).toBeFalsy();
|
|
});
|
|
|
|
it('requires region', () => {
|
|
expect(LanguageUtils.isSiblingOf('en', 'en')).toBeFalsy();
|
|
expect(LanguageUtils.isSiblingOf('en-US', 'en')).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('isParentOf', () => {
|
|
it('rejects self', () => {
|
|
expect(LanguageUtils.isParentOf('en', 'en')).toBeFalsy();
|
|
});
|
|
|
|
it('rejects other languages', () => {
|
|
expect(LanguageUtils.isParentOf('en', 'fr')).toBeFalsy();
|
|
});
|
|
|
|
it('requires region', () => {
|
|
expect(LanguageUtils.isParentOf('en', 'en-US')).toBeTruthy();
|
|
expect(LanguageUtils.isParentOf('en', 'en-CA')).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('findClosestLocale', () => {
|
|
it('returns null when nothing is found', () => {
|
|
const options = ['fr', 'en', 'es'];
|
|
const empty = [];
|
|
|
|
expect(LanguageUtils.findClosestLocale('zh', options)).toBe(null);
|
|
expect(LanguageUtils.findClosestLocale('zh', empty)).toBe(null);
|
|
});
|
|
|
|
it('finds locale compatible matches', () => {
|
|
const options = ['fr', 'en', 'en-US', 'es'];
|
|
|
|
expect(LanguageUtils.findClosestLocale('en', options)).toBe('en');
|
|
expect(LanguageUtils.findClosestLocale('en-US', options)).toBe('en-US');
|
|
});
|
|
|
|
it('find language matches', () => {
|
|
const options = ['en', 'fr', 'en-CA'];
|
|
// Should pick 'en' over 'en-CA'.
|
|
expect(LanguageUtils.findClosestLocale('en-US', options)).toBe('en');
|
|
});
|
|
|
|
it('finds language compatible matches', () => {
|
|
const options = ['en-CA', 'en-US'];
|
|
|
|
// Should return the first one that is language-compatible.
|
|
expect(LanguageUtils.findClosestLocale('en-UK', options)).toBe('en-CA');
|
|
});
|
|
});
|
|
|
|
describe('normalize', () => {
|
|
it('standardizes base language', () => {
|
|
expect(LanguageUtils.normalize('eng')).toBe('en');
|
|
expect(LanguageUtils.normalize('ENG')).toBe('en');
|
|
expect(LanguageUtils.normalize('EN')).toBe('en');
|
|
});
|
|
|
|
it('standardizes region', () => {
|
|
expect(LanguageUtils.normalize('en-US')).toBe('en-US');
|
|
expect(LanguageUtils.normalize('en-us')).toBe('en-US');
|
|
});
|
|
|
|
it('ignores unknown base languages', () => {
|
|
expect(LanguageUtils.normalize('elvish')).toBe('elvish');
|
|
expect(LanguageUtils.normalize(
|
|
'elvish-woodland')).toBe('elvish-WOODLAND');
|
|
});
|
|
|
|
it('supports private use tag', () => {
|
|
expect(LanguageUtils.normalize('eng-us-x-1')).toBe('en-US-x-1');
|
|
expect(LanguageUtils.normalize('eng-x-1')).toBe('en-x-1');
|
|
expect(LanguageUtils.normalize(
|
|
'elvish-woodland-x-1')).toBe('elvish-WOODLAND-x-1');
|
|
});
|
|
});
|
|
|
|
describe('getLocaleForText', () => {
|
|
const notNormalEnglish = 'eng';
|
|
const english = 'en';
|
|
|
|
it('normalizes language', () => {
|
|
const stream = makeTextStream(notNormalEnglish);
|
|
expect(LanguageUtils.getLocaleForText(stream)).toBe(english);
|
|
});
|
|
|
|
/**
|
|
* @param {string} language
|
|
* @return {shaka.extern.Stream}
|
|
*/
|
|
function makeTextStream(language) {
|
|
const sparse = {
|
|
type: shaka.util.ManifestParserUtils.ContentType.TEXT,
|
|
language: language,
|
|
};
|
|
|
|
return /** @type {shaka.extern.Stream} */ (sparse);
|
|
}
|
|
});
|
|
|
|
describe('getLocaleForVariant', () => {
|
|
const notNormalEnglish = 'eng';
|
|
const english = 'en';
|
|
const french = 'fr';
|
|
|
|
it('normalizes language from variant', () => {
|
|
const variant = makeVariant(notNormalEnglish, '', '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('normalizes language from audio', () => {
|
|
const variant = makeVariant('', notNormalEnglish, '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('normalizes language from video', () => {
|
|
const variant = makeVariant('', '', notNormalEnglish);
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('gets language when only in variant', () => {
|
|
const variant = makeVariant(english, '', '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('gets language when only in audio stream', () => {
|
|
const variant = makeVariant('', english, '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('gets language when only in video stream', () => {
|
|
const variant = makeVariant('', '', english);
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('prefers variant over audio', () => {
|
|
const variant = makeVariant(english, french, '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('prefers variant over audio', () => {
|
|
const variant = makeVariant(english, french, '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('prefers variant over video', () => {
|
|
const variant = makeVariant(english, '', french);
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('prefers audio over video', () => {
|
|
const variant = makeVariant('', english, french);
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe(english);
|
|
});
|
|
|
|
it('falls back to und', () => {
|
|
const variant = makeVariant('', '', '');
|
|
expect(LanguageUtils.getLocaleForVariant(variant)).toBe('und');
|
|
});
|
|
|
|
/**
|
|
* @param {string} variantLanguage
|
|
* @param {string} audioLanguage
|
|
* @param {string} videoLanguage
|
|
* @return {shaka.extern.Variant}
|
|
*/
|
|
function makeVariant(variantLanguage, audioLanguage, videoLanguage) {
|
|
// This returns a subset of the fields that would be in a variant.
|
|
// However, we know that we are only operating on the language fields
|
|
// so we are going to be lazy and only set them.
|
|
const sparse = {
|
|
language: variantLanguage,
|
|
audio: {
|
|
language: audioLanguage,
|
|
},
|
|
video: {
|
|
language: videoLanguage,
|
|
},
|
|
};
|
|
|
|
// Cast the sparse object to a variant to make closure happy.
|
|
return /** @type {shaka.extern.Variant} */ (sparse);
|
|
}
|
|
});
|
|
});
|