UNPKG

12.9 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 typeof define === 'function' && define.amd ? define(factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.i18nextBrowserLanguageDetector = factory());
5}(this, (function () { 'use strict';
6
7 function _classCallCheck(instance, Constructor) {
8 if (!(instance instanceof Constructor)) {
9 throw new TypeError("Cannot call a class as a function");
10 }
11 }
12
13 function _defineProperties(target, props) {
14 for (var i = 0; i < props.length; i++) {
15 var descriptor = props[i];
16 descriptor.enumerable = descriptor.enumerable || false;
17 descriptor.configurable = true;
18 if ("value" in descriptor) descriptor.writable = true;
19 Object.defineProperty(target, descriptor.key, descriptor);
20 }
21 }
22
23 function _createClass(Constructor, protoProps, staticProps) {
24 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
25 if (staticProps) _defineProperties(Constructor, staticProps);
26 return Constructor;
27 }
28
29 var arr = [];
30 var each = arr.forEach;
31 var slice = arr.slice;
32 function defaults(obj) {
33 each.call(slice.call(arguments, 1), function (source) {
34 if (source) {
35 for (var prop in source) {
36 if (obj[prop] === undefined) obj[prop] = source[prop];
37 }
38 }
39 });
40 return obj;
41 }
42
43 // eslint-disable-next-line no-control-regex
44 var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
45
46 var serializeCookie = function serializeCookie(name, val, options) {
47 var opt = options || {};
48 opt.path = opt.path || '/';
49 var value = encodeURIComponent(val);
50 var str = name + '=' + value;
51
52 if (opt.maxAge > 0) {
53 var maxAge = opt.maxAge - 0;
54 if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
55 str += '; Max-Age=' + Math.floor(maxAge);
56 }
57
58 if (opt.domain) {
59 if (!fieldContentRegExp.test(opt.domain)) {
60 throw new TypeError('option domain is invalid');
61 }
62
63 str += '; Domain=' + opt.domain;
64 }
65
66 if (opt.path) {
67 if (!fieldContentRegExp.test(opt.path)) {
68 throw new TypeError('option path is invalid');
69 }
70
71 str += '; Path=' + opt.path;
72 }
73
74 if (opt.expires) {
75 if (typeof opt.expires.toUTCString !== 'function') {
76 throw new TypeError('option expires is invalid');
77 }
78
79 str += '; Expires=' + opt.expires.toUTCString();
80 }
81
82 if (opt.httpOnly) str += '; HttpOnly';
83 if (opt.secure) str += '; Secure';
84
85 if (opt.sameSite) {
86 var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
87
88 switch (sameSite) {
89 case true:
90 str += '; SameSite=Strict';
91 break;
92
93 case 'lax':
94 str += '; SameSite=Lax';
95 break;
96
97 case 'strict':
98 str += '; SameSite=Strict';
99 break;
100
101 case 'none':
102 str += '; SameSite=None';
103 break;
104
105 default:
106 throw new TypeError('option sameSite is invalid');
107 }
108 }
109
110 return str;
111 };
112
113 var cookie = {
114 create: function create(name, value, minutes, domain) {
115 var cookieOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
116 path: '/',
117 sameSite: 'strict'
118 };
119
120 if (minutes) {
121 cookieOptions.expires = new Date();
122 cookieOptions.expires.setTime(cookieOptions.expires.getTime() + minutes * 60 * 1000);
123 }
124
125 if (domain) cookieOptions.domain = domain;
126 document.cookie = serializeCookie(name, encodeURIComponent(value), cookieOptions);
127 },
128 read: function read(name) {
129 var nameEQ = name + '=';
130 var ca = document.cookie.split(';');
131
132 for (var i = 0; i < ca.length; i++) {
133 var c = ca[i];
134
135 while (c.charAt(0) === ' ') {
136 c = c.substring(1, c.length);
137 }
138
139 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
140 }
141
142 return null;
143 },
144 remove: function remove(name) {
145 this.create(name, '', -1);
146 }
147 };
148 var cookie$1 = {
149 name: 'cookie',
150 lookup: function lookup(options) {
151 var found;
152
153 if (options.lookupCookie && typeof document !== 'undefined') {
154 var c = cookie.read(options.lookupCookie);
155 if (c) found = c;
156 }
157
158 return found;
159 },
160 cacheUserLanguage: function cacheUserLanguage(lng, options) {
161 if (options.lookupCookie && typeof document !== 'undefined') {
162 cookie.create(options.lookupCookie, lng, options.cookieMinutes, options.cookieDomain, options.cookieOptions);
163 }
164 }
165 };
166
167 var querystring = {
168 name: 'querystring',
169 lookup: function lookup(options) {
170 var found;
171
172 if (typeof window !== 'undefined') {
173 var query = window.location.search.substring(1);
174 var params = query.split('&');
175
176 for (var i = 0; i < params.length; i++) {
177 var pos = params[i].indexOf('=');
178
179 if (pos > 0) {
180 var key = params[i].substring(0, pos);
181
182 if (key === options.lookupQuerystring) {
183 found = params[i].substring(pos + 1);
184 }
185 }
186 }
187 }
188
189 return found;
190 }
191 };
192
193 var hasLocalStorageSupport = null;
194
195 var localStorageAvailable = function localStorageAvailable() {
196 if (hasLocalStorageSupport !== null) return hasLocalStorageSupport;
197
198 try {
199 hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
200 var testKey = 'i18next.translate.boo';
201 window.localStorage.setItem(testKey, 'foo');
202 window.localStorage.removeItem(testKey);
203 } catch (e) {
204 hasLocalStorageSupport = false;
205 }
206
207 return hasLocalStorageSupport;
208 };
209
210 var localStorage = {
211 name: 'localStorage',
212 lookup: function lookup(options) {
213 var found;
214
215 if (options.lookupLocalStorage && localStorageAvailable()) {
216 var lng = window.localStorage.getItem(options.lookupLocalStorage);
217 if (lng) found = lng;
218 }
219
220 return found;
221 },
222 cacheUserLanguage: function cacheUserLanguage(lng, options) {
223 if (options.lookupLocalStorage && localStorageAvailable()) {
224 window.localStorage.setItem(options.lookupLocalStorage, lng);
225 }
226 }
227 };
228
229 var hasSessionStorageSupport = null;
230
231 var sessionStorageAvailable = function sessionStorageAvailable() {
232 if (hasSessionStorageSupport !== null) return hasSessionStorageSupport;
233
234 try {
235 hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
236 var testKey = 'i18next.translate.boo';
237 window.sessionStorage.setItem(testKey, 'foo');
238 window.sessionStorage.removeItem(testKey);
239 } catch (e) {
240 hasSessionStorageSupport = false;
241 }
242
243 return hasSessionStorageSupport;
244 };
245
246 var sessionStorage = {
247 name: 'sessionStorage',
248 lookup: function lookup(options) {
249 var found;
250
251 if (options.lookupSessionStorage && sessionStorageAvailable()) {
252 var lng = window.sessionStorage.getItem(options.lookupSessionStorage);
253 if (lng) found = lng;
254 }
255
256 return found;
257 },
258 cacheUserLanguage: function cacheUserLanguage(lng, options) {
259 if (options.lookupSessionStorage && sessionStorageAvailable()) {
260 window.sessionStorage.setItem(options.lookupSessionStorage, lng);
261 }
262 }
263 };
264
265 var navigator$1 = {
266 name: 'navigator',
267 lookup: function lookup(options) {
268 var found = [];
269
270 if (typeof navigator !== 'undefined') {
271 if (navigator.languages) {
272 // chrome only; not an array, so can't use .push.apply instead of iterating
273 for (var i = 0; i < navigator.languages.length; i++) {
274 found.push(navigator.languages[i]);
275 }
276 }
277
278 if (navigator.userLanguage) {
279 found.push(navigator.userLanguage);
280 }
281
282 if (navigator.language) {
283 found.push(navigator.language);
284 }
285 }
286
287 return found.length > 0 ? found : undefined;
288 }
289 };
290
291 var htmlTag = {
292 name: 'htmlTag',
293 lookup: function lookup(options) {
294 var found;
295 var htmlTag = options.htmlTag || (typeof document !== 'undefined' ? document.documentElement : null);
296
297 if (htmlTag && typeof htmlTag.getAttribute === 'function') {
298 found = htmlTag.getAttribute('lang');
299 }
300
301 return found;
302 }
303 };
304
305 var path = {
306 name: 'path',
307 lookup: function lookup(options) {
308 var found;
309
310 if (typeof window !== 'undefined') {
311 var language = window.location.pathname.match(/\/([a-zA-Z-]*)/g);
312
313 if (language instanceof Array) {
314 if (typeof options.lookupFromPathIndex === 'number') {
315 if (typeof language[options.lookupFromPathIndex] !== 'string') {
316 return undefined;
317 }
318
319 found = language[options.lookupFromPathIndex].replace('/', '');
320 } else {
321 found = language[0].replace('/', '');
322 }
323 }
324 }
325
326 return found;
327 }
328 };
329
330 var subdomain = {
331 name: 'subdomain',
332 lookup: function lookup(options) {
333 var found;
334
335 if (typeof window !== 'undefined') {
336 var language = window.location.href.match(/(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/gi);
337
338 if (language instanceof Array) {
339 if (typeof options.lookupFromSubdomainIndex === 'number') {
340 found = language[options.lookupFromSubdomainIndex].replace('http://', '').replace('https://', '').replace('.', '');
341 } else {
342 found = language[0].replace('http://', '').replace('https://', '').replace('.', '');
343 }
344 }
345 }
346
347 return found;
348 }
349 };
350
351 function getDefaults() {
352 return {
353 order: ['querystring', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag'],
354 lookupQuerystring: 'lng',
355 lookupCookie: 'i18next',
356 lookupLocalStorage: 'i18nextLng',
357 lookupSessionStorage: 'i18nextLng',
358 // cache user language
359 caches: ['localStorage'],
360 excludeCacheFor: ['cimode'] //cookieMinutes: 10,
361 //cookieDomain: 'myDomain'
362
363 };
364 }
365
366 var Browser =
367 /*#__PURE__*/
368 function () {
369 function Browser(services) {
370 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
371
372 _classCallCheck(this, Browser);
373
374 this.type = 'languageDetector';
375 this.detectors = {};
376 this.init(services, options);
377 }
378
379 _createClass(Browser, [{
380 key: "init",
381 value: function init(services) {
382 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
383 var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
384 this.services = services;
385 this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility
386
387 if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
388 this.i18nOptions = i18nOptions;
389 this.addDetector(cookie$1);
390 this.addDetector(querystring);
391 this.addDetector(localStorage);
392 this.addDetector(sessionStorage);
393 this.addDetector(navigator$1);
394 this.addDetector(htmlTag);
395 this.addDetector(path);
396 this.addDetector(subdomain);
397 }
398 }, {
399 key: "addDetector",
400 value: function addDetector(detector) {
401 this.detectors[detector.name] = detector;
402 }
403 }, {
404 key: "detect",
405 value: function detect(detectionOrder) {
406 var _this = this;
407
408 if (!detectionOrder) detectionOrder = this.options.order;
409 var detected = [];
410 detectionOrder.forEach(function (detectorName) {
411 if (_this.detectors[detectorName]) {
412 var lookup = _this.detectors[detectorName].lookup(_this.options);
413
414 if (lookup && typeof lookup === 'string') lookup = [lookup];
415 if (lookup) detected = detected.concat(lookup);
416 }
417 });
418 if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
419
420 return detected.length > 0 ? detected[0] : null; // a little backward compatibility
421 }
422 }, {
423 key: "cacheUserLanguage",
424 value: function cacheUserLanguage(lng, caches) {
425 var _this2 = this;
426
427 if (!caches) caches = this.options.caches;
428 if (!caches) return;
429 if (this.options.excludeCacheFor && this.options.excludeCacheFor.indexOf(lng) > -1) return;
430 caches.forEach(function (cacheName) {
431 if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
432 });
433 }
434 }]);
435
436 return Browser;
437 }();
438
439 Browser.type = 'languageDetector';
440
441 return Browser;
442
443})));