Skip to main content
Module

x/i18next/LanguageUtils.js

i18next: learn once - translate everywhere
Go to Latest
File
import baseLogger from './logger.js';import { getCleanedCode } from './utils.js';
function capitalize(string) { return string.charAt(0).toUpperCase() + string.slice(1);}
class LanguageUtil { constructor(options) { this.options = options;
this.supportedLngs = this.options.supportedLngs || false; this.logger = baseLogger.create('languageUtils'); }
getScriptPartFromCode(code) { code = getCleanedCode(code); if (!code || code.indexOf('-') < 0) return null;
const p = code.split('-'); if (p.length === 2) return null; p.pop(); if (p[p.length - 1].toLowerCase() === 'x') return null; return this.formatLanguageCode(p.join('-')); }
getLanguagePartFromCode(code) { code = getCleanedCode(code); if (!code || code.indexOf('-') < 0) return code;
const p = code.split('-'); return this.formatLanguageCode(p[0]); }
formatLanguageCode(code) { // http://www.iana.org/assignments/language-tags/language-tags.xhtml if (typeof code === 'string' && code.indexOf('-') > -1) { const specialCases = ['hans', 'hant', 'latn', 'cyrl', 'cans', 'mong', 'arab']; let p = code.split('-');
if (this.options.lowerCaseLng) { p = p.map((part) => part.toLowerCase()); } else if (p.length === 2) { p[0] = p[0].toLowerCase(); p[1] = p[1].toUpperCase();
if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase()); } else if (p.length === 3) { p[0] = p[0].toLowerCase();
// if length 2 guess it's a country if (p[1].length === 2) p[1] = p[1].toUpperCase(); if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase();
if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase()); if (specialCases.indexOf(p[2].toLowerCase()) > -1) p[2] = capitalize(p[2].toLowerCase()); }
return p.join('-'); }
return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code; }
isSupportedCode(code) { if (this.options.load === 'languageOnly' || this.options.nonExplicitSupportedLngs) { code = this.getLanguagePartFromCode(code); } return ( !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.indexOf(code) > -1 ); }
getBestMatchFromCodes(codes) { if (!codes) return null;
let found;
// pick first supported code or if no restriction pick the first one (highest prio) codes.forEach((code) => { if (found) return; const cleanedLng = this.formatLanguageCode(code); if (!this.options.supportedLngs || this.isSupportedCode(cleanedLng)) found = cleanedLng; });
// if we got no match in supportedLngs yet - check for similar locales // first de-CH --> de // second de-CH --> de-DE if (!found && this.options.supportedLngs) { codes.forEach((code) => { if (found) return;
const lngOnly = this.getLanguagePartFromCode(code); // eslint-disable-next-line no-return-assign if (this.isSupportedCode(lngOnly)) return (found = lngOnly);
// eslint-disable-next-line array-callback-return found = this.options.supportedLngs.find((supportedLng) => { if (supportedLng === lngOnly) return supportedLng; if (supportedLng.indexOf('-') < 0 && lngOnly.indexOf('-') < 0) return; if ( supportedLng.indexOf('-') > 0 && lngOnly.indexOf('-') < 0 && supportedLng.substring(0, supportedLng.indexOf('-')) === lngOnly ) return supportedLng; if (supportedLng.indexOf(lngOnly) === 0 && lngOnly.length > 1) return supportedLng; }); }); } // if nothing found, use fallbackLng if (!found) found = this.getFallbackCodes(this.options.fallbackLng)[0];
return found; }
getFallbackCodes(fallbacks, code) { if (!fallbacks) return []; if (typeof fallbacks === 'function') fallbacks = fallbacks(code); if (typeof fallbacks === 'string') fallbacks = [fallbacks]; if (Object.prototype.toString.apply(fallbacks) === '[object Array]') return fallbacks;
if (!code) return fallbacks.default || [];
// assume we have an object defining fallbacks let found = fallbacks[code]; if (!found) found = fallbacks[this.getScriptPartFromCode(code)]; if (!found) found = fallbacks[this.formatLanguageCode(code)]; if (!found) found = fallbacks[this.getLanguagePartFromCode(code)]; if (!found) found = fallbacks.default;
return found || []; }
toResolveHierarchy(code, fallbackCode) { const fallbackCodes = this.getFallbackCodes( fallbackCode || this.options.fallbackLng || [], code, );
const codes = []; const addCode = (c) => { if (!c) return; if (this.isSupportedCode(c)) { codes.push(c); } else { this.logger.warn(`rejecting language code not found in supportedLngs: ${c}`); } };
if (typeof code === 'string' && (code.indexOf('-') > -1 || code.indexOf('_') > -1)) { if (this.options.load !== 'languageOnly') addCode(this.formatLanguageCode(code)); if (this.options.load !== 'languageOnly' && this.options.load !== 'currentOnly') addCode(this.getScriptPartFromCode(code)); if (this.options.load !== 'currentOnly') addCode(this.getLanguagePartFromCode(code)); } else if (typeof code === 'string') { addCode(this.formatLanguageCode(code)); }
fallbackCodes.forEach((fc) => { if (codes.indexOf(fc) < 0) addCode(this.formatLanguageCode(fc)); });
return codes; }}
export default LanguageUtil;