i18nextBrowserLanguageDetector.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3. typeof define === 'function' && define.amd ? define(factory) :
  4. (global.i18nextBrowserLanguageDetector = factory());
  5. }(this, function () { 'use strict';
  6. var arr = [];
  7. var each = arr.forEach;
  8. var slice = arr.slice;
  9. function defaults(obj) {
  10. each.call(slice.call(arguments, 1), function (source) {
  11. if (source) {
  12. for (var prop in source) {
  13. if (obj[prop] === undefined) obj[prop] = source[prop];
  14. }
  15. }
  16. });
  17. return obj;
  18. }
  19. var cookie = {
  20. create: function create(name, value, minutes, domain) {
  21. var expires = void 0;
  22. if (minutes) {
  23. var date = new Date();
  24. date.setTime(date.getTime() + minutes * 60 * 1000);
  25. expires = '; expires=' + date.toGMTString();
  26. } else expires = '';
  27. domain = domain ? 'domain=' + domain + ';' : '';
  28. document.cookie = name + '=' + value + expires + ';' + domain + 'path=/';
  29. },
  30. read: function read(name) {
  31. var nameEQ = name + '=';
  32. var ca = document.cookie.split(';');
  33. for (var i = 0; i < ca.length; i++) {
  34. var c = ca[i];
  35. while (c.charAt(0) === ' ') {
  36. c = c.substring(1, c.length);
  37. }if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
  38. }
  39. return null;
  40. },
  41. remove: function remove(name) {
  42. this.create(name, '', -1);
  43. }
  44. };
  45. var cookie$1 = {
  46. name: 'cookie',
  47. lookup: function lookup(options) {
  48. var found = void 0;
  49. if (options.lookupCookie && typeof document !== 'undefined') {
  50. var c = cookie.read(options.lookupCookie);
  51. if (c) found = c;
  52. }
  53. return found;
  54. },
  55. cacheUserLanguage: function cacheUserLanguage(lng, options) {
  56. if (options.lookupCookie && typeof document !== 'undefined') {
  57. cookie.create(options.lookupCookie, lng, options.cookieMinutes, options.cookieDomain);
  58. }
  59. }
  60. };
  61. var querystring = {
  62. name: 'querystring',
  63. lookup: function lookup(options) {
  64. var found = void 0;
  65. if (typeof window !== 'undefined') {
  66. var query = window.location.search.substring(1);
  67. var params = query.split('&');
  68. for (var i = 0; i < params.length; i++) {
  69. var pos = params[i].indexOf('=');
  70. if (pos > 0) {
  71. var key = params[i].substring(0, pos);
  72. if (key === options.lookupQuerystring) {
  73. found = params[i].substring(pos + 1);
  74. }
  75. }
  76. }
  77. }
  78. return found;
  79. }
  80. };
  81. var hasLocalStorageSupport = void 0;
  82. try {
  83. hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
  84. var testKey = 'i18next.translate.boo';
  85. window.localStorage.setItem(testKey, 'foo');
  86. window.localStorage.removeItem(testKey);
  87. } catch (e) {
  88. hasLocalStorageSupport = false;
  89. }
  90. var localStorage = {
  91. name: 'localStorage',
  92. lookup: function lookup(options) {
  93. var found = void 0;
  94. if (options.lookupLocalStorage && hasLocalStorageSupport) {
  95. var lng = window.localStorage.getItem(options.lookupLocalStorage);
  96. if (lng) found = lng;
  97. }
  98. return found;
  99. },
  100. cacheUserLanguage: function cacheUserLanguage(lng, options) {
  101. if (options.lookupLocalStorage && hasLocalStorageSupport) {
  102. window.localStorage.setItem(options.lookupLocalStorage, lng);
  103. }
  104. }
  105. };
  106. var navigator$1 = {
  107. name: 'navigator',
  108. lookup: function lookup(options) {
  109. var found = [];
  110. if (typeof navigator !== 'undefined') {
  111. if (navigator.languages) {
  112. // chrome only; not an array, so can't use .push.apply instead of iterating
  113. for (var i = 0; i < navigator.languages.length; i++) {
  114. found.push(navigator.languages[i]);
  115. }
  116. }
  117. if (navigator.userLanguage) {
  118. found.push(navigator.userLanguage);
  119. }
  120. if (navigator.language) {
  121. found.push(navigator.language);
  122. }
  123. }
  124. return found.length > 0 ? found : undefined;
  125. }
  126. };
  127. var htmlTag = {
  128. name: 'htmlTag',
  129. lookup: function lookup(options) {
  130. var found = void 0;
  131. var htmlTag = options.htmlTag || (typeof document !== 'undefined' ? document.documentElement : null);
  132. if (htmlTag && typeof htmlTag.getAttribute === 'function') {
  133. found = htmlTag.getAttribute('lang');
  134. }
  135. return found;
  136. }
  137. };
  138. var path = {
  139. name: 'path',
  140. lookup: function lookup(options) {
  141. var found = void 0;
  142. if (typeof window !== 'undefined') {
  143. var language = window.location.pathname.match(/\/([a-zA-Z-]*)/g);
  144. if (language instanceof Array) {
  145. if (typeof options.lookupFromPathIndex === 'number') {
  146. if (typeof language[options.lookupFromPathIndex] !== 'string') {
  147. return undefined;
  148. }
  149. found = language[options.lookupFromPathIndex].replace('/', '');
  150. } else {
  151. found = language[0].replace('/', '');
  152. }
  153. }
  154. }
  155. return found;
  156. }
  157. };
  158. var subdomain = {
  159. name: 'subdomain',
  160. lookup: function lookup(options) {
  161. var found = void 0;
  162. if (typeof window !== 'undefined') {
  163. var language = window.location.pathname.match(/(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/gi);
  164. if (language instanceof Array) {
  165. if (typeof options.lookupFromSubdomainIndex === 'number') {
  166. found = language[options.lookupFromSubdomainIndex].replace('http://', '').replace('https://', '').replace('.', '');
  167. } else {
  168. found = language[0].replace('http://', '').replace('https://', '').replace('.', '');
  169. }
  170. }
  171. }
  172. return found;
  173. }
  174. };
  175. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  176. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  177. function getDefaults() {
  178. return {
  179. order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'],
  180. lookupQuerystring: 'lng',
  181. lookupCookie: 'i18next',
  182. lookupLocalStorage: 'i18nextLng',
  183. // cache user language
  184. caches: ['localStorage'],
  185. excludeCacheFor: ['cimode']
  186. //cookieMinutes: 10,
  187. //cookieDomain: 'myDomain'
  188. };
  189. }
  190. var Browser = function () {
  191. function Browser(services) {
  192. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  193. _classCallCheck(this, Browser);
  194. this.type = 'languageDetector';
  195. this.detectors = {};
  196. this.init(services, options);
  197. }
  198. _createClass(Browser, [{
  199. key: 'init',
  200. value: function init(services) {
  201. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  202. var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  203. this.services = services;
  204. this.options = defaults(options, this.options || {}, getDefaults());
  205. // backwards compatibility
  206. if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
  207. this.i18nOptions = i18nOptions;
  208. this.addDetector(cookie$1);
  209. this.addDetector(querystring);
  210. this.addDetector(localStorage);
  211. this.addDetector(navigator$1);
  212. this.addDetector(htmlTag);
  213. this.addDetector(path);
  214. this.addDetector(subdomain);
  215. }
  216. }, {
  217. key: 'addDetector',
  218. value: function addDetector(detector) {
  219. this.detectors[detector.name] = detector;
  220. }
  221. }, {
  222. key: 'detect',
  223. value: function detect(detectionOrder) {
  224. var _this = this;
  225. if (!detectionOrder) detectionOrder = this.options.order;
  226. var detected = [];
  227. detectionOrder.forEach(function (detectorName) {
  228. if (_this.detectors[detectorName]) {
  229. var lookup = _this.detectors[detectorName].lookup(_this.options);
  230. if (lookup && typeof lookup === 'string') lookup = [lookup];
  231. if (lookup) detected = detected.concat(lookup);
  232. }
  233. });
  234. var found = void 0;
  235. detected.forEach(function (lng) {
  236. if (found) return;
  237. var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng);
  238. if (_this.services.languageUtils.isWhitelisted(cleanedLng)) found = cleanedLng;
  239. });
  240. if (!found) {
  241. var fallbacks = this.i18nOptions.fallbackLng;
  242. if (typeof fallbacks === 'string') fallbacks = [fallbacks];
  243. if (!fallbacks) fallbacks = [];
  244. if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
  245. found = fallbacks[0];
  246. } else {
  247. found = fallbacks[0] || fallbacks.default && fallbacks.default[0];
  248. }
  249. };
  250. return found;
  251. }
  252. }, {
  253. key: 'cacheUserLanguage',
  254. value: function cacheUserLanguage(lng, caches) {
  255. var _this2 = this;
  256. if (!caches) caches = this.options.caches;
  257. if (!caches) return;
  258. if (this.options.excludeCacheFor && this.options.excludeCacheFor.indexOf(lng) > -1) return;
  259. caches.forEach(function (cacheName) {
  260. if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
  261. });
  262. }
  263. }]);
  264. return Browser;
  265. }();
  266. Browser.type = 'languageDetector';
  267. return Browser;
  268. }));