update to state of the art

This commit is contained in:
s2
2020-10-10 15:18:01 +02:00
parent cf251a170f
commit 4cdcfd167c
1526 changed files with 48132 additions and 7268 deletions

View File

@@ -1,3 +1,21 @@
### 6.0.1
- optimize check for local storage and session storage [222](https://github.com/i18next/i18next-browser-languageDetector/pull/222)
### 6.0.0
- **BREAKING** rename lookupSessionStorage and add it to defaults [221](https://github.com/i18next/i18next-browser-languageDetector/pull/221)
### 5.0.1
- optimize cookie serialization and set sameSite to strict by default, to prepare for browser changes
### 5.0.0
- **BREAKING** needs i18next >= 19.5.0
- let i18next figure out which detected lng is best match
### 4.3.1
- typescript Updated typescript typings for DetectorOptions to align with current options [216](https://github.com/i18next/i18next-browser-languageDetector/pull/216)

View File

@@ -35,9 +35,7 @@ Wiring up:
import i18next from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
i18next
.use(LanguageDetector)
.init(i18nextOptions);
i18next.use(LanguageDetector).init(i18nextOptions);
```
As with all modules you can either pass the constructor function (class) to the i18next.use or a concrete instance.
@@ -53,6 +51,7 @@ As with all modules you can either pass the constructor function (class) to the
lookupQuerystring: 'lng',
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
lookupFromPathIndex: 0,
lookupFromSubdomainIndex: 0,
@@ -67,18 +66,8 @@ As with all modules you can either pass the constructor function (class) to the
// optional htmlTag with lang attribute, the default is:
htmlTag: document.documentElement,
// only detect languages that are in the whitelist
checkWhitelist: true,
// fallback to a similar whitelist language
// Example 1: Browser language is 'es'
// if 'es' is not found in whitelist, first fallback to any whitelist language that starts with 'es-', then fallback to fallbackLng ('es' -> 'es-*' -> fallbackLng)
// Example 2: Browser language is 'es-MX'
// if 'es-MX' is not found in whitelist, first fallback to 'es', then fallback to 'es-*', then fallback to fallbackLng ('es-MX' -> 'es' -> 'es-*' -> fallbackLng)
checkForSimilarInWhitelist: false,
// optional set cookie options, reference:[MDN Set-Cookie docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)
cookieOptions: {path:'/'}
cookieOptions: { path: '/', sameSite: 'strict' }
}
```
@@ -90,26 +79,24 @@ Options can be passed in:
import i18next from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
i18next
.use(LanguageDetector)
.init({
detection: options
});
i18next.use(LanguageDetector).init({
detection: options,
});
```
on construction:
```js
import LanguageDetector from 'i18next-browser-languagedetector';
const languageDetector = new LanguageDetector(null, options);
import LanguageDetector from 'i18next-browser-languagedetector';
const languageDetector = new LanguageDetector(null, options);
```
via calling init:
```js
import LanguageDetector from 'i18next-browser-languagedetector';
const languageDetector = new LanguageDetector();
languageDetector.init(options);
import LanguageDetector from 'i18next-browser-languagedetector';
const languageDetector = new LanguageDetector();
languageDetector.init(options);
```
## Adding own detection functionality
@@ -128,30 +115,26 @@ export default {
cacheUserLanguage(lng, options) {
// options -> are passed in options
// lng -> current language, will be called after init and on changeLanguage
// store it
}
},
};
```
### adding it
```js
import LanguageDetector from 'i18next-browser-languagedetector';
const languageDetector = new LanguageDetector();
languageDetector.addDetector(myDetector);
import LanguageDetector from 'i18next-browser-languagedetector';
const languageDetector = new LanguageDetector();
languageDetector.addDetector(myDetector);
i18next
.use(languageDetector)
.init({
detection: options
});
i18next.use(languageDetector).init({
detection: options,
});
```
Don't forget: You have to add the name of your detector (`myDetectorsName` in this case) to the `order` array in your `options` object. Without that, your detector won't be used. See the [Detector Options section for more](#detector-options).
--------------
---
<h3 align="center">Gold Sponsors</h3>

View File

@@ -19,26 +19,90 @@ function defaults(obj) {
return obj;
}
// eslint-disable-next-line no-control-regex
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
var serializeCookie = function serializeCookie(name, val, options) {
var opt = options || {};
opt.path = opt.path || '/';
var value = encodeURIComponent(val);
var str = name + '=' + value;
if (opt.maxAge > 0) {
var maxAge = opt.maxAge - 0;
if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
str += '; Max-Age=' + Math.floor(maxAge);
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}
str += '; Domain=' + opt.domain;
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}
str += '; Path=' + opt.path;
}
if (opt.expires) {
if (typeof opt.expires.toUTCString !== 'function') {
throw new TypeError('option expires is invalid');
}
str += '; Expires=' + opt.expires.toUTCString();
}
if (opt.httpOnly) str += '; HttpOnly';
if (opt.secure) str += '; Secure';
if (opt.sameSite) {
var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
switch (sameSite) {
case true:
str += '; SameSite=Strict';
break;
case 'lax':
str += '; SameSite=Lax';
break;
case 'strict':
str += '; SameSite=Strict';
break;
case 'none':
str += '; SameSite=None';
break;
default:
throw new TypeError('option sameSite is invalid');
}
}
return str;
};
var cookie = {
create: function create(name, value, minutes, domain) {
var cookieOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
path: '/'
path: '/',
sameSite: 'strict'
};
var expires;
if (minutes) {
var date = new Date();
date.setTime(date.getTime() + minutes * 60 * 1000);
expires = '; expires=' + date.toUTCString();
} else expires = '';
cookieOptions.expires = new Date();
cookieOptions.expires.setTime(cookieOptions.expires.getTime() + minutes * 60 * 1000);
}
domain = domain ? 'domain=' + domain + ';' : '';
cookieOptions = Object.keys(cookieOptions).reduce(function (acc, key) {
return acc + ';' + key.replace(/([A-Z])/g, function ($1) {
return '-' + $1.toLowerCase();
}) + '=' + cookieOptions[key];
}, '');
document.cookie = name + '=' + encodeURIComponent(value) + expires + ';' + domain + cookieOptions;
if (domain) cookieOptions.domain = domain;
document.cookie = serializeCookie(name, encodeURIComponent(value), cookieOptions);
},
read: function read(name) {
var nameEQ = name + '=';
@@ -105,23 +169,29 @@ var querystring = {
}
};
var hasLocalStorageSupport;
var hasLocalStorageSupport = null;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
var localStorageAvailable = function localStorageAvailable() {
if (hasLocalStorageSupport !== null) return hasLocalStorageSupport;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
return hasLocalStorageSupport;
};
var localStorage = {
name: 'localStorage',
lookup: function lookup(options) {
var found;
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
var lng = window.localStorage.getItem(options.lookupLocalStorage);
if (lng) found = lng;
}
@@ -129,38 +199,44 @@ var localStorage = {
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
window.localStorage.setItem(options.lookupLocalStorage, lng);
}
}
};
var hasSessionStorageSupport;
var hasSessionStorageSupport = null;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey$1 = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey$1, 'foo');
window.sessionStorage.removeItem(testKey$1);
} catch (e) {
hasSessionStorageSupport = false;
}
var sessionStorageAvailable = function sessionStorageAvailable() {
if (hasSessionStorageSupport !== null) return hasSessionStorageSupport;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey, 'foo');
window.sessionStorage.removeItem(testKey);
} catch (e) {
hasSessionStorageSupport = false;
}
return hasSessionStorageSupport;
};
var sessionStorage = {
name: 'sessionStorage',
lookup: function lookup(options) {
var found;
if (options.lookupsessionStorage && hasSessionStorageSupport) {
var lng = window.sessionStorage.getItem(options.lookupsessionStorage);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
var lng = window.sessionStorage.getItem(options.lookupSessionStorage);
if (lng) found = lng;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupsessionStorage && hasSessionStorageSupport) {
window.sessionStorage.setItem(options.lookupsessionStorage, lng);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
window.sessionStorage.setItem(options.lookupSessionStorage, lng);
}
}
};
@@ -257,13 +333,12 @@ function getDefaults() {
lookupQuerystring: 'lng',
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
// cache user language
caches: ['localStorage'],
excludeCacheFor: ['cimode'],
//cookieMinutes: 10,
excludeCacheFor: ['cimode'] //cookieMinutes: 10,
//cookieDomain: 'myDomain'
checkWhitelist: true,
checkForSimilarInWhitelist: false
};
}
@@ -286,9 +361,7 @@ function () {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services;
this.options = defaults(options, this.options || {}, getDefaults()); // if checking for similar, user needs to check whitelist
if (this.options.checkForSimilarInWhitelist) this.options.checkWhitelist = true; // backwards compatibility
this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility
if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
this.i18nOptions = i18nOptions;
@@ -321,32 +394,9 @@ function () {
if (lookup) detected = detected.concat(lookup);
}
});
var found;
detected.forEach(function (lng) {
if (found) return;
if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng);
if (!_this.options.checkWhitelist || _this.services.languageUtils.isWhitelisted(cleanedLng)) found = cleanedLng;
if (!found && _this.options.checkForSimilarInWhitelist) {
found = _this.getSimilarInWhitelist(cleanedLng);
}
});
if (!found) {
var fallbacks = this.i18nOptions.fallbackLng;
if (typeof fallbacks === 'string') fallbacks = [fallbacks];
if (!fallbacks) fallbacks = [];
if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
found = fallbacks[0];
} else {
found = fallbacks[0] || fallbacks["default"] && fallbacks["default"][0];
}
}
return found;
return detected.length > 0 ? detected[0] : null; // a little backward compatibility
}
}, {
key: "cacheUserLanguage",
@@ -360,30 +410,6 @@ function () {
if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
});
}
}, {
key: "getSimilarInWhitelist",
value: function getSimilarInWhitelist(cleanedLng) {
var _this3 = this;
if (!this.i18nOptions.whitelist) return;
if (cleanedLng.includes('-')) {
// i.e. es-MX should check if es is in whitelist
var prefix = cleanedLng.split('-')[0];
var cleanedPrefix = this.services.languageUtils.formatLanguageCode(prefix);
if (this.services.languageUtils.isWhitelisted(cleanedPrefix)) return cleanedPrefix; // if reached here, nothing found. continue to search for similar using only prefix
cleanedLng = cleanedPrefix;
} // i.e. 'pt' should return 'pt-BR'. If multiple in whitelist with 'pt-', then use first one in whitelist
var similar = this.i18nOptions.whitelist.find(function (whitelistLng) {
var cleanedWhitelistLng = _this3.services.languageUtils.formatLanguageCode(whitelistLng);
if (cleanedWhitelistLng.startsWith(cleanedLng)) return cleanedWhitelistLng;
});
if (similar) return similar;
}
}]);
return Browser;

View File

@@ -15,26 +15,90 @@ function defaults(obj) {
return obj;
}
// eslint-disable-next-line no-control-regex
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
var serializeCookie = function serializeCookie(name, val, options) {
var opt = options || {};
opt.path = opt.path || '/';
var value = encodeURIComponent(val);
var str = name + '=' + value;
if (opt.maxAge > 0) {
var maxAge = opt.maxAge - 0;
if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
str += '; Max-Age=' + Math.floor(maxAge);
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}
str += '; Domain=' + opt.domain;
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}
str += '; Path=' + opt.path;
}
if (opt.expires) {
if (typeof opt.expires.toUTCString !== 'function') {
throw new TypeError('option expires is invalid');
}
str += '; Expires=' + opt.expires.toUTCString();
}
if (opt.httpOnly) str += '; HttpOnly';
if (opt.secure) str += '; Secure';
if (opt.sameSite) {
var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
switch (sameSite) {
case true:
str += '; SameSite=Strict';
break;
case 'lax':
str += '; SameSite=Lax';
break;
case 'strict':
str += '; SameSite=Strict';
break;
case 'none':
str += '; SameSite=None';
break;
default:
throw new TypeError('option sameSite is invalid');
}
}
return str;
};
var cookie = {
create: function create(name, value, minutes, domain) {
var cookieOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
path: '/'
path: '/',
sameSite: 'strict'
};
var expires;
if (minutes) {
var date = new Date();
date.setTime(date.getTime() + minutes * 60 * 1000);
expires = '; expires=' + date.toUTCString();
} else expires = '';
cookieOptions.expires = new Date();
cookieOptions.expires.setTime(cookieOptions.expires.getTime() + minutes * 60 * 1000);
}
domain = domain ? 'domain=' + domain + ';' : '';
cookieOptions = Object.keys(cookieOptions).reduce(function (acc, key) {
return acc + ';' + key.replace(/([A-Z])/g, function ($1) {
return '-' + $1.toLowerCase();
}) + '=' + cookieOptions[key];
}, '');
document.cookie = name + '=' + encodeURIComponent(value) + expires + ';' + domain + cookieOptions;
if (domain) cookieOptions.domain = domain;
document.cookie = serializeCookie(name, encodeURIComponent(value), cookieOptions);
},
read: function read(name) {
var nameEQ = name + '=';
@@ -101,23 +165,29 @@ var querystring = {
}
};
var hasLocalStorageSupport;
var hasLocalStorageSupport = null;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
var localStorageAvailable = function localStorageAvailable() {
if (hasLocalStorageSupport !== null) return hasLocalStorageSupport;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
return hasLocalStorageSupport;
};
var localStorage = {
name: 'localStorage',
lookup: function lookup(options) {
var found;
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
var lng = window.localStorage.getItem(options.lookupLocalStorage);
if (lng) found = lng;
}
@@ -125,38 +195,44 @@ var localStorage = {
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
window.localStorage.setItem(options.lookupLocalStorage, lng);
}
}
};
var hasSessionStorageSupport;
var hasSessionStorageSupport = null;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey$1 = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey$1, 'foo');
window.sessionStorage.removeItem(testKey$1);
} catch (e) {
hasSessionStorageSupport = false;
}
var sessionStorageAvailable = function sessionStorageAvailable() {
if (hasSessionStorageSupport !== null) return hasSessionStorageSupport;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey, 'foo');
window.sessionStorage.removeItem(testKey);
} catch (e) {
hasSessionStorageSupport = false;
}
return hasSessionStorageSupport;
};
var sessionStorage = {
name: 'sessionStorage',
lookup: function lookup(options) {
var found;
if (options.lookupsessionStorage && hasSessionStorageSupport) {
var lng = window.sessionStorage.getItem(options.lookupsessionStorage);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
var lng = window.sessionStorage.getItem(options.lookupSessionStorage);
if (lng) found = lng;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupsessionStorage && hasSessionStorageSupport) {
window.sessionStorage.setItem(options.lookupsessionStorage, lng);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
window.sessionStorage.setItem(options.lookupSessionStorage, lng);
}
}
};
@@ -253,13 +329,12 @@ function getDefaults() {
lookupQuerystring: 'lng',
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
// cache user language
caches: ['localStorage'],
excludeCacheFor: ['cimode'],
//cookieMinutes: 10,
excludeCacheFor: ['cimode'] //cookieMinutes: 10,
//cookieDomain: 'myDomain'
checkWhitelist: true,
checkForSimilarInWhitelist: false
};
}
@@ -282,9 +357,7 @@ function () {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services;
this.options = defaults(options, this.options || {}, getDefaults()); // if checking for similar, user needs to check whitelist
if (this.options.checkForSimilarInWhitelist) this.options.checkWhitelist = true; // backwards compatibility
this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility
if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
this.i18nOptions = i18nOptions;
@@ -317,32 +390,9 @@ function () {
if (lookup) detected = detected.concat(lookup);
}
});
var found;
detected.forEach(function (lng) {
if (found) return;
if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng);
if (!_this.options.checkWhitelist || _this.services.languageUtils.isWhitelisted(cleanedLng)) found = cleanedLng;
if (!found && _this.options.checkForSimilarInWhitelist) {
found = _this.getSimilarInWhitelist(cleanedLng);
}
});
if (!found) {
var fallbacks = this.i18nOptions.fallbackLng;
if (typeof fallbacks === 'string') fallbacks = [fallbacks];
if (!fallbacks) fallbacks = [];
if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
found = fallbacks[0];
} else {
found = fallbacks[0] || fallbacks["default"] && fallbacks["default"][0];
}
}
return found;
return detected.length > 0 ? detected[0] : null; // a little backward compatibility
}
}, {
key: "cacheUserLanguage",
@@ -356,30 +406,6 @@ function () {
if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
});
}
}, {
key: "getSimilarInWhitelist",
value: function getSimilarInWhitelist(cleanedLng) {
var _this3 = this;
if (!this.i18nOptions.whitelist) return;
if (cleanedLng.includes('-')) {
// i.e. es-MX should check if es is in whitelist
var prefix = cleanedLng.split('-')[0];
var cleanedPrefix = this.services.languageUtils.formatLanguageCode(prefix);
if (this.services.languageUtils.isWhitelisted(cleanedPrefix)) return cleanedPrefix; // if reached here, nothing found. continue to search for similar using only prefix
cleanedLng = cleanedPrefix;
} // i.e. 'pt' should return 'pt-BR'. If multiple in whitelist with 'pt-', then use first one in whitelist
var similar = this.i18nOptions.whitelist.find(function (whitelistLng) {
var cleanedWhitelistLng = _this3.services.languageUtils.formatLanguageCode(whitelistLng);
if (cleanedWhitelistLng.startsWith(cleanedLng)) return cleanedWhitelistLng;
});
if (similar) return similar;
}
}]);
return Browser;

View File

@@ -40,26 +40,90 @@
return obj;
}
// eslint-disable-next-line no-control-regex
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
var serializeCookie = function serializeCookie(name, val, options) {
var opt = options || {};
opt.path = opt.path || '/';
var value = encodeURIComponent(val);
var str = name + '=' + value;
if (opt.maxAge > 0) {
var maxAge = opt.maxAge - 0;
if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
str += '; Max-Age=' + Math.floor(maxAge);
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}
str += '; Domain=' + opt.domain;
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}
str += '; Path=' + opt.path;
}
if (opt.expires) {
if (typeof opt.expires.toUTCString !== 'function') {
throw new TypeError('option expires is invalid');
}
str += '; Expires=' + opt.expires.toUTCString();
}
if (opt.httpOnly) str += '; HttpOnly';
if (opt.secure) str += '; Secure';
if (opt.sameSite) {
var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
switch (sameSite) {
case true:
str += '; SameSite=Strict';
break;
case 'lax':
str += '; SameSite=Lax';
break;
case 'strict':
str += '; SameSite=Strict';
break;
case 'none':
str += '; SameSite=None';
break;
default:
throw new TypeError('option sameSite is invalid');
}
}
return str;
};
var cookie = {
create: function create(name, value, minutes, domain) {
var cookieOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
path: '/'
path: '/',
sameSite: 'strict'
};
var expires;
if (minutes) {
var date = new Date();
date.setTime(date.getTime() + minutes * 60 * 1000);
expires = '; expires=' + date.toUTCString();
} else expires = '';
cookieOptions.expires = new Date();
cookieOptions.expires.setTime(cookieOptions.expires.getTime() + minutes * 60 * 1000);
}
domain = domain ? 'domain=' + domain + ';' : '';
cookieOptions = Object.keys(cookieOptions).reduce(function (acc, key) {
return acc + ';' + key.replace(/([A-Z])/g, function ($1) {
return '-' + $1.toLowerCase();
}) + '=' + cookieOptions[key];
}, '');
document.cookie = name + '=' + encodeURIComponent(value) + expires + ';' + domain + cookieOptions;
if (domain) cookieOptions.domain = domain;
document.cookie = serializeCookie(name, encodeURIComponent(value), cookieOptions);
},
read: function read(name) {
var nameEQ = name + '=';
@@ -126,23 +190,29 @@
}
};
var hasLocalStorageSupport;
var hasLocalStorageSupport = null;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
var localStorageAvailable = function localStorageAvailable() {
if (hasLocalStorageSupport !== null) return hasLocalStorageSupport;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
return hasLocalStorageSupport;
};
var localStorage = {
name: 'localStorage',
lookup: function lookup(options) {
var found;
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
var lng = window.localStorage.getItem(options.lookupLocalStorage);
if (lng) found = lng;
}
@@ -150,38 +220,44 @@
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
window.localStorage.setItem(options.lookupLocalStorage, lng);
}
}
};
var hasSessionStorageSupport;
var hasSessionStorageSupport = null;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey$1 = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey$1, 'foo');
window.sessionStorage.removeItem(testKey$1);
} catch (e) {
hasSessionStorageSupport = false;
}
var sessionStorageAvailable = function sessionStorageAvailable() {
if (hasSessionStorageSupport !== null) return hasSessionStorageSupport;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey, 'foo');
window.sessionStorage.removeItem(testKey);
} catch (e) {
hasSessionStorageSupport = false;
}
return hasSessionStorageSupport;
};
var sessionStorage = {
name: 'sessionStorage',
lookup: function lookup(options) {
var found;
if (options.lookupsessionStorage && hasSessionStorageSupport) {
var lng = window.sessionStorage.getItem(options.lookupsessionStorage);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
var lng = window.sessionStorage.getItem(options.lookupSessionStorage);
if (lng) found = lng;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupsessionStorage && hasSessionStorageSupport) {
window.sessionStorage.setItem(options.lookupsessionStorage, lng);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
window.sessionStorage.setItem(options.lookupSessionStorage, lng);
}
}
};
@@ -278,13 +354,12 @@
lookupQuerystring: 'lng',
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
// cache user language
caches: ['localStorage'],
excludeCacheFor: ['cimode'],
//cookieMinutes: 10,
excludeCacheFor: ['cimode'] //cookieMinutes: 10,
//cookieDomain: 'myDomain'
checkWhitelist: true,
checkForSimilarInWhitelist: false
};
}
@@ -307,9 +382,7 @@
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services;
this.options = defaults(options, this.options || {}, getDefaults()); // if checking for similar, user needs to check whitelist
if (this.options.checkForSimilarInWhitelist) this.options.checkWhitelist = true; // backwards compatibility
this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility
if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
this.i18nOptions = i18nOptions;
@@ -342,32 +415,9 @@
if (lookup) detected = detected.concat(lookup);
}
});
var found;
detected.forEach(function (lng) {
if (found) return;
if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng);
if (!_this.options.checkWhitelist || _this.services.languageUtils.isWhitelisted(cleanedLng)) found = cleanedLng;
if (!found && _this.options.checkForSimilarInWhitelist) {
found = _this.getSimilarInWhitelist(cleanedLng);
}
});
if (!found) {
var fallbacks = this.i18nOptions.fallbackLng;
if (typeof fallbacks === 'string') fallbacks = [fallbacks];
if (!fallbacks) fallbacks = [];
if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
found = fallbacks[0];
} else {
found = fallbacks[0] || fallbacks["default"] && fallbacks["default"][0];
}
}
return found;
return detected.length > 0 ? detected[0] : null; // a little backward compatibility
}
}, {
key: "cacheUserLanguage",
@@ -381,30 +431,6 @@
if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
});
}
}, {
key: "getSimilarInWhitelist",
value: function getSimilarInWhitelist(cleanedLng) {
var _this3 = this;
if (!this.i18nOptions.whitelist) return;
if (cleanedLng.includes('-')) {
// i.e. es-MX should check if es is in whitelist
var prefix = cleanedLng.split('-')[0];
var cleanedPrefix = this.services.languageUtils.formatLanguageCode(prefix);
if (this.services.languageUtils.isWhitelisted(cleanedPrefix)) return cleanedPrefix; // if reached here, nothing found. continue to search for similar using only prefix
cleanedLng = cleanedPrefix;
} // i.e. 'pt' should return 'pt-BR'. If multiple in whitelist with 'pt-', then use first one in whitelist
var similar = this.i18nOptions.whitelist.find(function (whitelistLng) {
var cleanedWhitelistLng = _this3.services.languageUtils.formatLanguageCode(whitelistLng);
if (cleanedWhitelistLng.startsWith(cleanedLng)) return cleanedWhitelistLng;
});
if (similar) return similar;
}
}]);
return Browser;

File diff suppressed because one or more lines are too long

View File

@@ -40,26 +40,90 @@
return obj;
}
// eslint-disable-next-line no-control-regex
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
var serializeCookie = function serializeCookie(name, val, options) {
var opt = options || {};
opt.path = opt.path || '/';
var value = encodeURIComponent(val);
var str = name + '=' + value;
if (opt.maxAge > 0) {
var maxAge = opt.maxAge - 0;
if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
str += '; Max-Age=' + Math.floor(maxAge);
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}
str += '; Domain=' + opt.domain;
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}
str += '; Path=' + opt.path;
}
if (opt.expires) {
if (typeof opt.expires.toUTCString !== 'function') {
throw new TypeError('option expires is invalid');
}
str += '; Expires=' + opt.expires.toUTCString();
}
if (opt.httpOnly) str += '; HttpOnly';
if (opt.secure) str += '; Secure';
if (opt.sameSite) {
var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
switch (sameSite) {
case true:
str += '; SameSite=Strict';
break;
case 'lax':
str += '; SameSite=Lax';
break;
case 'strict':
str += '; SameSite=Strict';
break;
case 'none':
str += '; SameSite=None';
break;
default:
throw new TypeError('option sameSite is invalid');
}
}
return str;
};
var cookie = {
create: function create(name, value, minutes, domain) {
var cookieOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
path: '/'
path: '/',
sameSite: 'strict'
};
var expires;
if (minutes) {
var date = new Date();
date.setTime(date.getTime() + minutes * 60 * 1000);
expires = '; expires=' + date.toUTCString();
} else expires = '';
cookieOptions.expires = new Date();
cookieOptions.expires.setTime(cookieOptions.expires.getTime() + minutes * 60 * 1000);
}
domain = domain ? 'domain=' + domain + ';' : '';
cookieOptions = Object.keys(cookieOptions).reduce(function (acc, key) {
return acc + ';' + key.replace(/([A-Z])/g, function ($1) {
return '-' + $1.toLowerCase();
}) + '=' + cookieOptions[key];
}, '');
document.cookie = name + '=' + encodeURIComponent(value) + expires + ';' + domain + cookieOptions;
if (domain) cookieOptions.domain = domain;
document.cookie = serializeCookie(name, encodeURIComponent(value), cookieOptions);
},
read: function read(name) {
var nameEQ = name + '=';
@@ -126,23 +190,29 @@
}
};
var hasLocalStorageSupport;
var hasLocalStorageSupport = null;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
var localStorageAvailable = function localStorageAvailable() {
if (hasLocalStorageSupport !== null) return hasLocalStorageSupport;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
return hasLocalStorageSupport;
};
var localStorage = {
name: 'localStorage',
lookup: function lookup(options) {
var found;
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
var lng = window.localStorage.getItem(options.lookupLocalStorage);
if (lng) found = lng;
}
@@ -150,38 +220,44 @@
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupLocalStorage && hasLocalStorageSupport) {
if (options.lookupLocalStorage && localStorageAvailable()) {
window.localStorage.setItem(options.lookupLocalStorage, lng);
}
}
};
var hasSessionStorageSupport;
var hasSessionStorageSupport = null;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey$1 = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey$1, 'foo');
window.sessionStorage.removeItem(testKey$1);
} catch (e) {
hasSessionStorageSupport = false;
}
var sessionStorageAvailable = function sessionStorageAvailable() {
if (hasSessionStorageSupport !== null) return hasSessionStorageSupport;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey, 'foo');
window.sessionStorage.removeItem(testKey);
} catch (e) {
hasSessionStorageSupport = false;
}
return hasSessionStorageSupport;
};
var sessionStorage = {
name: 'sessionStorage',
lookup: function lookup(options) {
var found;
if (options.lookupsessionStorage && hasSessionStorageSupport) {
var lng = window.sessionStorage.getItem(options.lookupsessionStorage);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
var lng = window.sessionStorage.getItem(options.lookupSessionStorage);
if (lng) found = lng;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupsessionStorage && hasSessionStorageSupport) {
window.sessionStorage.setItem(options.lookupsessionStorage, lng);
if (options.lookupSessionStorage && sessionStorageAvailable()) {
window.sessionStorage.setItem(options.lookupSessionStorage, lng);
}
}
};
@@ -278,13 +354,12 @@
lookupQuerystring: 'lng',
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
// cache user language
caches: ['localStorage'],
excludeCacheFor: ['cimode'],
//cookieMinutes: 10,
excludeCacheFor: ['cimode'] //cookieMinutes: 10,
//cookieDomain: 'myDomain'
checkWhitelist: true,
checkForSimilarInWhitelist: false
};
}
@@ -307,9 +382,7 @@
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services;
this.options = defaults(options, this.options || {}, getDefaults()); // if checking for similar, user needs to check whitelist
if (this.options.checkForSimilarInWhitelist) this.options.checkWhitelist = true; // backwards compatibility
this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility
if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
this.i18nOptions = i18nOptions;
@@ -342,32 +415,9 @@
if (lookup) detected = detected.concat(lookup);
}
});
var found;
detected.forEach(function (lng) {
if (found) return;
if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng);
if (!_this.options.checkWhitelist || _this.services.languageUtils.isWhitelisted(cleanedLng)) found = cleanedLng;
if (!found && _this.options.checkForSimilarInWhitelist) {
found = _this.getSimilarInWhitelist(cleanedLng);
}
});
if (!found) {
var fallbacks = this.i18nOptions.fallbackLng;
if (typeof fallbacks === 'string') fallbacks = [fallbacks];
if (!fallbacks) fallbacks = [];
if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
found = fallbacks[0];
} else {
found = fallbacks[0] || fallbacks["default"] && fallbacks["default"][0];
}
}
return found;
return detected.length > 0 ? detected[0] : null; // a little backward compatibility
}
}, {
key: "cacheUserLanguage",
@@ -381,30 +431,6 @@
if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
});
}
}, {
key: "getSimilarInWhitelist",
value: function getSimilarInWhitelist(cleanedLng) {
var _this3 = this;
if (!this.i18nOptions.whitelist) return;
if (cleanedLng.includes('-')) {
// i.e. es-MX should check if es is in whitelist
var prefix = cleanedLng.split('-')[0];
var cleanedPrefix = this.services.languageUtils.formatLanguageCode(prefix);
if (this.services.languageUtils.isWhitelisted(cleanedPrefix)) return cleanedPrefix; // if reached here, nothing found. continue to search for similar using only prefix
cleanedLng = cleanedPrefix;
} // i.e. 'pt' should return 'pt-BR'. If multiple in whitelist with 'pt-', then use first one in whitelist
var similar = this.i18nOptions.whitelist.find(function (whitelistLng) {
var cleanedWhitelistLng = _this3.services.languageUtils.formatLanguageCode(whitelistLng);
if (cleanedWhitelistLng.startsWith(cleanedLng)) return cleanedWhitelistLng;
});
if (similar) return similar;
}
}]);
return Browser;

File diff suppressed because one or more lines are too long

View File

@@ -1,22 +1,6 @@
import * as i18next from 'i18next';
interface DetectorOptions {
/**
* only detect languages that are in the whitelist
* @default true
*/
checkWhitelist?: boolean;
/**
* fallback to a similar whitelist language
* Example 1: Browser language is 'es'
* if 'es' is not found in whitelist, first fallback to any whitelist language that starts with 'es-', then fallback to fallbackLng ('es' -> 'es-*' -> fallbackLng)
* Example 2: Browser language is 'es-MX'
* if 'es-MX' is not found in whitelist, first fallback to 'es', then fallback to 'es-*', then fallback to fallbackLng ('es-MX' -> 'es' -> 'es-*' -> fallbackLng)
* @default false
*/
checkForSimilarInWhitelist?: boolean;
/**
* order and from where user language should be detected
*/
@@ -29,6 +13,7 @@ interface DetectorOptions {
*/
lookupQuerystring?: string;
lookupCookie?: string;
lookupSessionStorage?: string;
lookupLocalStorage?: string;
lookupFromPathIndex?: number;
lookupFromSubdomainIndex?: number;

View File

@@ -1,27 +1,27 @@
{
"_from": "i18next-browser-languagedetector@4.3.1",
"_id": "i18next-browser-languagedetector@4.3.1",
"_from": "i18next-browser-languagedetector@latest",
"_id": "i18next-browser-languagedetector@6.0.1",
"_inBundle": false,
"_integrity": "sha512-KIToAzf8zwWvacgnRwJp63ase26o24AuNUlfNVJ5YZAFmdGhsJpmFClxXPuk9rv1FMI4lnc8zLSqgZPEZMrW4g==",
"_integrity": "sha512-3H+OsNQn3FciomUU0d4zPFHsvJv4X66lBelXk9hnIDYDsveIgT7dWZ3/VvcSlpKk9lvCK770blRZ/CwHMXZqWw==",
"_location": "/i18next-browser-languagedetector",
"_phantomChildren": {},
"_requested": {
"type": "version",
"type": "tag",
"registry": true,
"raw": "i18next-browser-languagedetector@4.3.1",
"raw": "i18next-browser-languagedetector@latest",
"name": "i18next-browser-languagedetector",
"escapedName": "i18next-browser-languagedetector",
"rawSpec": "4.3.1",
"rawSpec": "latest",
"saveSpec": null,
"fetchSpec": "4.3.1"
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-4.3.1.tgz",
"_shasum": "005d2db6204b0a4af5f01c7987f5ccaf4ef97da5",
"_spec": "i18next-browser-languagedetector@4.3.1",
"_resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.0.1.tgz",
"_shasum": "83654bc87302be2a6a5a75146ffea97b4ca268cf",
"_spec": "i18next-browser-languagedetector@latest",
"_where": "D:\\Projects\\vanillajs-seed",
"author": {
"name": "Jan Mühlemann",
@@ -88,5 +88,5 @@
"test:typescript:noninterop": "tslint --project tsconfig.nonEsModuleInterop.json"
},
"types": "./index.d.ts",
"version": "4.3.1"
"version": "6.0.1"
}