You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2227 lines
70 KiB

2 years ago
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3. typeof define === 'function' && define.amd ? define(factory) :
  4. (global.i18next = factory());
  5. }(this, (function () { 'use strict';
  6. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  7. return typeof obj;
  8. } : function (obj) {
  9. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  10. };
  11. var asyncGenerator = function () {
  12. function AwaitValue(value) {
  13. this.value = value;
  14. }
  15. function AsyncGenerator(gen) {
  16. var front, back;
  17. function send(key, arg) {
  18. return new Promise(function (resolve, reject) {
  19. var request = {
  20. key: key,
  21. arg: arg,
  22. resolve: resolve,
  23. reject: reject,
  24. next: null
  25. };
  26. if (back) {
  27. back = back.next = request;
  28. } else {
  29. front = back = request;
  30. resume(key, arg);
  31. }
  32. });
  33. }
  34. function resume(key, arg) {
  35. try {
  36. var result = gen[key](arg);
  37. var value = result.value;
  38. if (value instanceof AwaitValue) {
  39. Promise.resolve(value.value).then(function (arg) {
  40. resume("next", arg);
  41. }, function (arg) {
  42. resume("throw", arg);
  43. });
  44. } else {
  45. settle(result.done ? "return" : "normal", result.value);
  46. }
  47. } catch (err) {
  48. settle("throw", err);
  49. }
  50. }
  51. function settle(type, value) {
  52. switch (type) {
  53. case "return":
  54. front.resolve({
  55. value: value,
  56. done: true
  57. });
  58. break;
  59. case "throw":
  60. front.reject(value);
  61. break;
  62. default:
  63. front.resolve({
  64. value: value,
  65. done: false
  66. });
  67. break;
  68. }
  69. front = front.next;
  70. if (front) {
  71. resume(front.key, front.arg);
  72. } else {
  73. back = null;
  74. }
  75. }
  76. this._invoke = send;
  77. if (typeof gen.return !== "function") {
  78. this.return = undefined;
  79. }
  80. }
  81. if (typeof Symbol === "function" && Symbol.asyncIterator) {
  82. AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
  83. return this;
  84. };
  85. }
  86. AsyncGenerator.prototype.next = function (arg) {
  87. return this._invoke("next", arg);
  88. };
  89. AsyncGenerator.prototype.throw = function (arg) {
  90. return this._invoke("throw", arg);
  91. };
  92. AsyncGenerator.prototype.return = function (arg) {
  93. return this._invoke("return", arg);
  94. };
  95. return {
  96. wrap: function (fn) {
  97. return function () {
  98. return new AsyncGenerator(fn.apply(this, arguments));
  99. };
  100. },
  101. await: function (value) {
  102. return new AwaitValue(value);
  103. }
  104. };
  105. }();
  106. var classCallCheck = function (instance, Constructor) {
  107. if (!(instance instanceof Constructor)) {
  108. throw new TypeError("Cannot call a class as a function");
  109. }
  110. };
  111. var _extends = Object.assign || function (target) {
  112. for (var i = 1; i < arguments.length; i++) {
  113. var source = arguments[i];
  114. for (var key in source) {
  115. if (Object.prototype.hasOwnProperty.call(source, key)) {
  116. target[key] = source[key];
  117. }
  118. }
  119. }
  120. return target;
  121. };
  122. var get = function get(object, property, receiver) {
  123. if (object === null) object = Function.prototype;
  124. var desc = Object.getOwnPropertyDescriptor(object, property);
  125. if (desc === undefined) {
  126. var parent = Object.getPrototypeOf(object);
  127. if (parent === null) {
  128. return undefined;
  129. } else {
  130. return get(parent, property, receiver);
  131. }
  132. } else if ("value" in desc) {
  133. return desc.value;
  134. } else {
  135. var getter = desc.get;
  136. if (getter === undefined) {
  137. return undefined;
  138. }
  139. return getter.call(receiver);
  140. }
  141. };
  142. var inherits = function (subClass, superClass) {
  143. if (typeof superClass !== "function" && superClass !== null) {
  144. throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  145. }
  146. subClass.prototype = Object.create(superClass && superClass.prototype, {
  147. constructor: {
  148. value: subClass,
  149. enumerable: false,
  150. writable: true,
  151. configurable: true
  152. }
  153. });
  154. if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  155. };
  156. var possibleConstructorReturn = function (self, call) {
  157. if (!self) {
  158. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  159. }
  160. return call && (typeof call === "object" || typeof call === "function") ? call : self;
  161. };
  162. var set = function set(object, property, value, receiver) {
  163. var desc = Object.getOwnPropertyDescriptor(object, property);
  164. if (desc === undefined) {
  165. var parent = Object.getPrototypeOf(object);
  166. if (parent !== null) {
  167. set(parent, property, value, receiver);
  168. }
  169. } else if ("value" in desc && desc.writable) {
  170. desc.value = value;
  171. } else {
  172. var setter = desc.set;
  173. if (setter !== undefined) {
  174. setter.call(receiver, value);
  175. }
  176. }
  177. return value;
  178. };
  179. var slicedToArray = function () {
  180. function sliceIterator(arr, i) {
  181. var _arr = [];
  182. var _n = true;
  183. var _d = false;
  184. var _e = undefined;
  185. try {
  186. for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
  187. _arr.push(_s.value);
  188. if (i && _arr.length === i) break;
  189. }
  190. } catch (err) {
  191. _d = true;
  192. _e = err;
  193. } finally {
  194. try {
  195. if (!_n && _i["return"]) _i["return"]();
  196. } finally {
  197. if (_d) throw _e;
  198. }
  199. }
  200. return _arr;
  201. }
  202. return function (arr, i) {
  203. if (Array.isArray(arr)) {
  204. return arr;
  205. } else if (Symbol.iterator in Object(arr)) {
  206. return sliceIterator(arr, i);
  207. } else {
  208. throw new TypeError("Invalid attempt to destructure non-iterable instance");
  209. }
  210. };
  211. }();
  212. var consoleLogger = {
  213. type: 'logger',
  214. log: function log(args) {
  215. this._output('log', args);
  216. },
  217. warn: function warn(args) {
  218. this._output('warn', args);
  219. },
  220. error: function error(args) {
  221. this._output('error', args);
  222. },
  223. _output: function _output(type, args) {
  224. if (console && console[type]) console[type].apply(console, Array.prototype.slice.call(args));
  225. }
  226. };
  227. var Logger = function () {
  228. function Logger(concreteLogger) {
  229. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  230. classCallCheck(this, Logger);
  231. this.init(concreteLogger, options);
  232. }
  233. Logger.prototype.init = function init(concreteLogger) {
  234. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  235. this.prefix = options.prefix || 'i18next:';
  236. this.logger = concreteLogger || consoleLogger;
  237. this.options = options;
  238. this.debug = options.debug === false ? false : true;
  239. };
  240. Logger.prototype.setDebug = function setDebug(bool) {
  241. this.debug = bool;
  242. };
  243. Logger.prototype.log = function log() {
  244. this.forward(arguments, 'log', '', true);
  245. };
  246. Logger.prototype.warn = function warn() {
  247. this.forward(arguments, 'warn', '', true);
  248. };
  249. Logger.prototype.error = function error() {
  250. this.forward(arguments, 'error', '');
  251. };
  252. Logger.prototype.deprecate = function deprecate() {
  253. this.forward(arguments, 'warn', 'WARNING DEPRECATED: ', true);
  254. };
  255. Logger.prototype.forward = function forward(args, lvl, prefix, debugOnly) {
  256. if (debugOnly && !this.debug) return;
  257. if (typeof args[0] === 'string') args[0] = prefix + this.prefix + ' ' + args[0];
  258. this.logger[lvl](args);
  259. };
  260. Logger.prototype.create = function create(moduleName) {
  261. var sub = new Logger(this.logger, _extends({ prefix: this.prefix + ':' + moduleName + ':' }, this.options));
  262. return sub;
  263. };
  264. // createInstance(options = {}) {
  265. // return new Logger(options, callback);
  266. // }
  267. return Logger;
  268. }();
  269. var baseLogger = new Logger();
  270. var EventEmitter = function () {
  271. function EventEmitter() {
  272. classCallCheck(this, EventEmitter);
  273. this.observers = {};
  274. }
  275. EventEmitter.prototype.on = function on(events, listener) {
  276. var _this = this;
  277. events.split(' ').forEach(function (event) {
  278. _this.observers[event] = _this.observers[event] || [];
  279. _this.observers[event].push(listener);
  280. });
  281. };
  282. EventEmitter.prototype.off = function off(event, listener) {
  283. var _this2 = this;
  284. if (!this.observers[event]) {
  285. return;
  286. }
  287. this.observers[event].forEach(function () {
  288. if (!listener) {
  289. delete _this2.observers[event];
  290. } else {
  291. var index = _this2.observers[event].indexOf(listener);
  292. if (index > -1) {
  293. _this2.observers[event].splice(index, 1);
  294. }
  295. }
  296. });
  297. };
  298. EventEmitter.prototype.emit = function emit(event) {
  299. for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  300. args[_key - 1] = arguments[_key];
  301. }
  302. if (this.observers[event]) {
  303. this.observers[event].forEach(function (observer) {
  304. observer.apply(undefined, args);
  305. });
  306. }
  307. if (this.observers['*']) {
  308. this.observers['*'].forEach(function (observer) {
  309. var _ref;
  310. observer.apply(observer, (_ref = [event]).concat.apply(_ref, args));
  311. });
  312. }
  313. };
  314. return EventEmitter;
  315. }();
  316. function makeString(object) {
  317. if (object == null) return '';
  318. return '' + object;
  319. }
  320. function copy(a, s, t) {
  321. a.forEach(function (m) {
  322. if (s[m]) t[m] = s[m];
  323. });
  324. }
  325. function getLastOfPath(object, path, Empty) {
  326. function cleanKey(key) {
  327. return key && key.indexOf('###') > -1 ? key.replace(/###/g, '.') : key;
  328. }
  329. var stack = typeof path !== 'string' ? [].concat(path) : path.split('.');
  330. while (stack.length > 1) {
  331. if (!object) return {};
  332. var key = cleanKey(stack.shift());
  333. if (!object[key] && Empty) object[key] = new Empty();
  334. object = object[key];
  335. }
  336. if (!object) return {};
  337. return {
  338. obj: object,
  339. k: cleanKey(stack.shift())
  340. };
  341. }
  342. function setPath(object, path, newValue) {
  343. var _getLastOfPath = getLastOfPath(object, path, Object),
  344. obj = _getLastOfPath.obj,
  345. k = _getLastOfPath.k;
  346. obj[k] = newValue;
  347. }
  348. function pushPath(object, path, newValue, concat) {
  349. var _getLastOfPath2 = getLastOfPath(object, path, Object),
  350. obj = _getLastOfPath2.obj,
  351. k = _getLastOfPath2.k;
  352. obj[k] = obj[k] || [];
  353. if (concat) obj[k] = obj[k].concat(newValue);
  354. if (!concat) obj[k].push(newValue);
  355. }
  356. function getPath(object, path) {
  357. var _getLastOfPath3 = getLastOfPath(object, path),
  358. obj = _getLastOfPath3.obj,
  359. k = _getLastOfPath3.k;
  360. if (!obj) return undefined;
  361. return obj[k];
  362. }
  363. function deepExtend(target, source, overwrite) {
  364. for (var prop in source) {
  365. if (prop in target) {
  366. // If we reached a leaf string in target or source then replace with source or skip depending on the 'overwrite' switch
  367. if (typeof target[prop] === 'string' || target[prop] instanceof String || typeof source[prop] === 'string' || source[prop] instanceof String) {
  368. if (overwrite) target[prop] = source[prop];
  369. } else {
  370. deepExtend(target[prop], source[prop], overwrite);
  371. }
  372. } else {
  373. target[prop] = source[prop];
  374. }
  375. }return target;
  376. }
  377. function regexEscape(str) {
  378. return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
  379. }
  380. /* eslint-disable */
  381. var _entityMap = {
  382. "&": "&amp;",
  383. "<": "&lt;",
  384. ">": "&gt;",
  385. '"': '&quot;',
  386. "'": '&#39;',
  387. "/": '&#x2F;'
  388. };
  389. /* eslint-enable */
  390. function escape(data) {
  391. if (typeof data === 'string') {
  392. return data.replace(/[&<>"'\/]/g, function (s) {
  393. return _entityMap[s];
  394. });
  395. } else {
  396. return data;
  397. }
  398. }
  399. var ResourceStore = function (_EventEmitter) {
  400. inherits(ResourceStore, _EventEmitter);
  401. function ResourceStore() {
  402. var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  403. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { ns: ['translation'], defaultNS: 'translation' };
  404. classCallCheck(this, ResourceStore);
  405. var _this = possibleConstructorReturn(this, _EventEmitter.call(this));
  406. _this.data = data;
  407. _this.options = options;
  408. return _this;
  409. }
  410. ResourceStore.prototype.addNamespaces = function addNamespaces(ns) {
  411. if (this.options.ns.indexOf(ns) < 0) {
  412. this.options.ns.push(ns);
  413. }
  414. };
  415. ResourceStore.prototype.removeNamespaces = function removeNamespaces(ns) {
  416. var index = this.options.ns.indexOf(ns);
  417. if (index > -1) {
  418. this.options.ns.splice(index, 1);
  419. }
  420. };
  421. ResourceStore.prototype.getResource = function getResource(lng, ns, key) {
  422. var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  423. var keySeparator = options.keySeparator || this.options.keySeparator;
  424. if (keySeparator === undefined) keySeparator = '.';
  425. var path = [lng, ns];
  426. if (key && typeof key !== 'string') path = path.concat(key);
  427. if (key && typeof key === 'string') path = path.concat(keySeparator ? key.split(keySeparator) : key);
  428. if (lng.indexOf('.') > -1) {
  429. path = lng.split('.');
  430. }
  431. return getPath(this.data, path);
  432. };
  433. ResourceStore.prototype.addResource = function addResource(lng, ns, key, value) {
  434. var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : { silent: false };
  435. var keySeparator = this.options.keySeparator;
  436. if (keySeparator === undefined) keySeparator = '.';
  437. var path = [lng, ns];
  438. if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
  439. if (lng.indexOf('.') > -1) {
  440. path = lng.split('.');
  441. value = ns;
  442. ns = path[1];
  443. }
  444. this.addNamespaces(ns);
  445. setPath(this.data, path, value);
  446. if (!options.silent) this.emit('added', lng, ns, key, value);
  447. };
  448. ResourceStore.prototype.addResources = function addResources(lng, ns, resources) {
  449. for (var m in resources) {
  450. if (typeof resources[m] === 'string') this.addResource(lng, ns, m, resources[m], { silent: true });
  451. }
  452. this.emit('added', lng, ns, resources);
  453. };
  454. ResourceStore.prototype.addResourceBundle = function addResourceBundle(lng, ns, resources, deep, overwrite) {
  455. var path = [lng, ns];
  456. if (lng.indexOf('.') > -1) {
  457. path = lng.split('.');
  458. deep = resources;
  459. resources = ns;
  460. ns = path[1];
  461. }
  462. this.addNamespaces(ns);
  463. var pack = getPath(this.data, path) || {};
  464. if (deep) {
  465. deepExtend(pack, resources, overwrite);
  466. } else {
  467. pack = _extends({}, pack, resources);
  468. }
  469. setPath(this.data, path, pack);
  470. this.emit('added', lng, ns, resources);
  471. };
  472. ResourceStore.prototype.removeResourceBundle = function removeResourceBundle(lng, ns) {
  473. if (this.hasResourceBundle(lng, ns)) {
  474. delete this.data[lng][ns];
  475. }
  476. this.removeNamespaces(ns);
  477. this.emit('removed', lng, ns);
  478. };
  479. ResourceStore.prototype.hasResourceBundle = function hasResourceBundle(lng, ns) {
  480. return this.getResource(lng, ns) !== undefined;
  481. };
  482. ResourceStore.prototype.getResourceBundle = function getResourceBundle(lng, ns) {
  483. if (!ns) ns = this.options.defaultNS;
  484. // TODO: COMPATIBILITY remove extend in v2.1.0
  485. if (this.options.compatibilityAPI === 'v1') return _extends({}, this.getResource(lng, ns));
  486. return this.getResource(lng, ns);
  487. };
  488. ResourceStore.prototype.toJSON = function toJSON() {
  489. return this.data;
  490. };
  491. return ResourceStore;
  492. }(EventEmitter);
  493. var postProcessor = {
  494. processors: {},
  495. addPostProcessor: function addPostProcessor(module) {
  496. this.processors[module.name] = module;
  497. },
  498. handle: function handle(processors, value, key, options, translator) {
  499. var _this = this;
  500. processors.forEach(function (processor) {
  501. if (_this.processors[processor]) value = _this.processors[processor].process(value, key, options, translator);
  502. });
  503. return value;
  504. }
  505. };
  506. function convertInterpolation(options) {
  507. options.interpolation = {
  508. unescapeSuffix: 'HTML'
  509. };
  510. options.interpolation.prefix = options.interpolationPrefix || '__';
  511. options.interpolation.suffix = options.interpolationSuffix || '__';
  512. options.interpolation.escapeValue = options.escapeInterpolation || false;
  513. options.interpolation.nestingPrefix = options.reusePrefix || '$t(';
  514. options.interpolation.nestingSuffix = options.reuseSuffix || ')';
  515. return options;
  516. }
  517. function convertAPIOptions(options) {
  518. if (options.resStore) options.resources = options.resStore;
  519. if (options.ns && options.ns.defaultNs) {
  520. options.defaultNS = options.ns.defaultNs;
  521. options.ns = options.ns.namespaces;
  522. } else {
  523. options.defaultNS = options.ns || 'translation';
  524. }
  525. if (options.fallbackToDefaultNS && options.defaultNS) options.fallbackNS = options.defaultNS;
  526. options.saveMissing = options.sendMissing;
  527. options.saveMissingTo = options.sendMissingTo || 'current';
  528. options.returnNull = options.fallbackOnNull ? false : true;
  529. options.returnEmptyString = options.fallbackOnEmpty ? false : true;
  530. options.returnObjects = options.returnObjectTrees;
  531. options.joinArrays = '\n';
  532. options.returnedObjectHandler = options.objectTreeKeyHandler;
  533. options.parseMissingKeyHandler = options.parseMissingKey;
  534. options.appendNamespaceToMissingKey = true;
  535. options.nsSeparator = options.nsseparator;
  536. options.keySeparator = options.keyseparator;
  537. if (options.shortcutFunction === 'sprintf') {
  538. options.overloadTranslationOptionHandler = function (args) {
  539. var values = [];
  540. for (var i = 1; i < args.length; i++) {
  541. values.push(args[i]);
  542. }
  543. return {
  544. postProcess: 'sprintf',
  545. sprintf: values
  546. };
  547. };
  548. }
  549. options.whitelist = options.lngWhitelist;
  550. options.preload = options.preload;
  551. if (options.load === 'current') options.load = 'currentOnly';
  552. if (options.load === 'unspecific') options.load = 'languageOnly';
  553. // backend
  554. options.backend = options.backend || {};
  555. options.backend.loadPath = options.resGetPath || 'locales/__lng__/__ns__.json';
  556. options.backend.addPath = options.resPostPath || 'locales/add/__lng__/__ns__';
  557. options.backend.allowMultiLoading = options.dynamicLoad;
  558. // cache
  559. options.cache = options.cache || {};
  560. options.cache.prefix = 'res_';
  561. options.cache.expirationTime = 7 * 24 * 60 * 60 * 1000;
  562. options.cache.enabled = options.useLocalStorage ? true : false;
  563. options = convertInterpolation(options);
  564. if (options.defaultVariables) options.interpolation.defaultVariables = options.defaultVariables;
  565. // TODO: deprecation
  566. // if (options.getAsync === false) throw deprecation error
  567. return options;
  568. }
  569. function convertJSONOptions(options) {
  570. options = convertInterpolation(options);
  571. options.joinArrays = '\n';
  572. return options;
  573. }
  574. function convertTOptions(options) {
  575. if (options.interpolationPrefix || options.interpolationSuffix || options.escapeInterpolation) {
  576. options = convertInterpolation(options);
  577. }
  578. options.nsSeparator = options.nsseparator;
  579. options.keySeparator = options.keyseparator;
  580. options.returnObjects = options.returnObjectTrees;
  581. return options;
  582. }
  583. function appendBackwardsAPI(i18n) {
  584. i18n.lng = function () {
  585. baseLogger.deprecate('i18next.lng() can be replaced by i18next.language for detected language or i18next.languages for languages ordered by translation lookup.');
  586. return i18n.services.languageUtils.toResolveHierarchy(i18n.language)[0];
  587. };
  588. i18n.preload = function (lngs, cb) {
  589. baseLogger.deprecate('i18next.preload() can be replaced with i18next.loadLanguages()');
  590. i18n.loadLanguages(lngs, cb);
  591. };
  592. i18n.setLng = function (lng, options, callback) {
  593. baseLogger.deprecate('i18next.setLng() can be replaced with i18next.changeLanguage() or i18next.getFixedT() to get a translation function with fixed language or namespace.');
  594. if (typeof options === 'function') {
  595. callback = options;
  596. options = {};
  597. }
  598. if (!options) options = {};
  599. if (options.fixLng === true) {
  600. if (callback) return callback(null, i18n.getFixedT(lng));
  601. }
  602. i18n.changeLanguage(lng, callback);
  603. };
  604. i18n.addPostProcessor = function (name, fc) {
  605. baseLogger.deprecate('i18next.addPostProcessor() can be replaced by i18next.use({ type: \'postProcessor\', name: \'name\', process: fc })');
  606. i18n.use({
  607. type: 'postProcessor',
  608. name: name,
  609. process: fc
  610. });
  611. };
  612. }
  613. var Translator = function (_EventEmitter) {
  614. inherits(Translator, _EventEmitter);
  615. function Translator(services) {
  616. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  617. classCallCheck(this, Translator);
  618. var _this = possibleConstructorReturn(this, _EventEmitter.call(this));
  619. copy(['resourceStore', 'languageUtils', 'pluralResolver', 'interpolator', 'backendConnector'], services, _this);
  620. _this.options = options;
  621. _this.logger = baseLogger.create('translator');
  622. return _this;
  623. }
  624. Translator.prototype.changeLanguage = function changeLanguage(lng) {
  625. if (lng) this.language = lng;
  626. };
  627. Translator.prototype.exists = function exists(key) {
  628. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { interpolation: {} };
  629. if (this.options.compatibilityAPI === 'v1') {
  630. options = convertTOptions(options);
  631. }
  632. return this.resolve(key, options) !== undefined;
  633. };
  634. Translator.prototype.extractFromKey = function extractFromKey(key, options) {
  635. var nsSeparator = options.nsSeparator || this.options.nsSeparator;
  636. if (nsSeparator === undefined) nsSeparator = ':';
  637. var namespaces = options.ns || this.options.defaultNS;
  638. if (nsSeparator && key.indexOf(nsSeparator) > -1) {
  639. var parts = key.split(nsSeparator);
  640. namespaces = parts[0];
  641. key = parts[1];
  642. }
  643. if (typeof namespaces === 'string') namespaces = [namespaces];
  644. return {
  645. key: key,
  646. namespaces: namespaces
  647. };
  648. };
  649. Translator.prototype.translate = function translate(keys) {
  650. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  651. if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== 'object') {
  652. options = this.options.overloadTranslationOptionHandler(arguments);
  653. } else if (this.options.compatibilityAPI === 'v1') {
  654. options = convertTOptions(options);
  655. }
  656. // non valid keys handling
  657. if (keys === undefined || keys === null || keys === '') return '';
  658. if (typeof keys === 'number') keys = String(keys);
  659. if (typeof keys === 'string') keys = [keys];
  660. // return key on CIMode
  661. var lng = options.lng || this.language;
  662. if (lng && lng.toLowerCase() === 'cimode') return keys[keys.length - 1];
  663. // separators
  664. var keySeparator = options.keySeparator || this.options.keySeparator || '.';
  665. // get namespace(s)
  666. var _extractFromKey = this.extractFromKey(keys[keys.length - 1], options),
  667. key = _extractFromKey.key,
  668. namespaces = _extractFromKey.namespaces;
  669. var namespace = namespaces[namespaces.length - 1];
  670. // resolve from store
  671. var res = this.resolve(keys, options);
  672. var resType = Object.prototype.toString.apply(res);
  673. var noObject = ['[object Number]', '[object Function]', '[object RegExp]'];
  674. var joinArrays = options.joinArrays !== undefined ? options.joinArrays : this.options.joinArrays;
  675. // object
  676. if (res && typeof res !== 'string' && noObject.indexOf(resType) < 0 && !(joinArrays && resType === '[object Array]')) {
  677. if (!options.returnObjects && !this.options.returnObjects) {
  678. this.logger.warn('accessing an object - but returnObjects options is not enabled!');
  679. return this.options.returnedObjectHandler ? this.options.returnedObjectHandler(key, res, options) : 'key \'' + key + ' (' + this.language + ')\' returned an object instead of string.';
  680. }
  681. var copy$$1 = resType === '[object Array]' ? [] : {}; // apply child translation on a copy
  682. for (var m in res) {
  683. copy$$1[m] = this.translate('' + key + keySeparator + m, _extends({ joinArrays: false, ns: namespaces }, options));
  684. }
  685. res = copy$$1;
  686. }
  687. // array special treatment
  688. else if (joinArrays && resType === '[object Array]') {
  689. res = res.join(joinArrays);
  690. if (res) res = this.extendTranslation(res, key, options);
  691. }
  692. // string, empty or null
  693. else {
  694. var usedDefault = false,
  695. usedKey = false;
  696. // fallback value
  697. if (!this.isValidLookup(res) && options.defaultValue !== undefined) {
  698. usedDefault = true;
  699. res = options.defaultValue;
  700. }
  701. if (!this.isValidLookup(res)) {
  702. usedKey = true;
  703. res = key;
  704. }
  705. // save missing
  706. if (usedKey || usedDefault) {
  707. this.logger.log('missingKey', lng, namespace, key, res);
  708. var lngs = [];
  709. var fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, options.lng || this.language);
  710. if (this.options.saveMissingTo === 'fallback' && fallbackLngs && fallbackLngs[0]) {
  711. for (var i = 0; i < fallbackLngs.length; i++) {
  712. lngs.push(fallbackLngs[i]);
  713. }
  714. } else if (this.options.saveMissingTo === 'all') {
  715. lngs = this.languageUtils.toResolveHierarchy(options.lng || this.language);
  716. } else {
  717. //(this.options.saveMissingTo === 'current' || (this.options.saveMissingTo === 'fallback' && this.options.fallbackLng[0] === false) ) {
  718. lngs.push(options.lng || this.language);
  719. }
  720. if (this.options.saveMissing) {
  721. if (this.options.missingKeyHandler) {
  722. this.options.missingKeyHandler(lngs, namespace, key, res);
  723. } else if (this.backendConnector && this.backendConnector.saveMissing) {
  724. this.backendConnector.saveMissing(lngs, namespace, key, res);
  725. }
  726. }
  727. this.emit('missingKey', lngs, namespace, key, res);
  728. }
  729. // extend
  730. res = this.extendTranslation(res, key, options);
  731. // append namespace if still key
  732. if (usedKey && res === key && this.options.appendNamespaceToMissingKey) res = namespace + ':' + key;
  733. // parseMissingKeyHandler
  734. if (usedKey && this.options.parseMissingKeyHandler) res = this.options.parseMissingKeyHandler(res);
  735. }
  736. // return
  737. return res;
  738. };
  739. Translator.prototype.extendTranslation = function extendTranslation(res, key, options) {
  740. var _this2 = this;
  741. if (options.interpolation) this.interpolator.init(_extends({}, options, { interpolation: _extends({}, this.options.interpolation, options.interpolation) }));
  742. // interpolate
  743. var data = options.replace && typeof options.replace !== 'string' ? options.replace : options;
  744. if (this.options.interpolation.defaultVariables) data = _extends({}, this.options.interpolation.defaultVariables, data);
  745. res = this.interpolator.interpolate(res, data, this.language);
  746. // nesting
  747. res = this.interpolator.nest(res, function () {
  748. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  749. args[_key] = arguments[_key];
  750. }
  751. return _this2.translate.apply(_this2, args);
  752. }, options);
  753. if (options.interpolation) this.interpolator.reset();
  754. // post process
  755. var postProcess = options.postProcess || this.options.postProcess;
  756. var postProcessorNames = typeof postProcess === 'string' ? [postProcess] : postProcess;
  757. if (res !== undefined && postProcessorNames && postProcessorNames.length && options.applyPostProcessor !== false) {
  758. res = postProcessor.handle(postProcessorNames, res, key, options, this);
  759. }
  760. return res;
  761. };
  762. Translator.prototype.resolve = function resolve(keys) {
  763. var _this3 = this;
  764. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  765. var found = void 0;
  766. if (typeof keys === 'string') keys = [keys];
  767. // forEach possible key
  768. keys.forEach(function (k) {
  769. if (_this3.isValidLookup(found)) return;
  770. var _extractFromKey2 = _this3.extractFromKey(k, options),
  771. key = _extractFromKey2.key,
  772. namespaces = _extractFromKey2.namespaces;
  773. if (_this3.options.fallbackNS) namespaces = namespaces.concat(_this3.options.fallbackNS);
  774. var needsPluralHandling = options.count !== undefined && typeof options.count !== 'string';
  775. var needsContextHandling = options.context !== undefined && typeof options.context === 'string' && options.context !== '';
  776. var codes = options.lngs ? options.lngs : _this3.languageUtils.toResolveHierarchy(options.lng || _this3.language);
  777. namespaces.forEach(function (ns) {
  778. if (_this3.isValidLookup(found)) return;
  779. codes.forEach(function (code) {
  780. if (_this3.isValidLookup(found)) return;
  781. var finalKey = key;
  782. var finalKeys = [finalKey];
  783. var pluralSuffix = void 0;
  784. if (needsPluralHandling) pluralSuffix = _this3.pluralResolver.getSuffix(code, options.count);
  785. // fallback for plural if context not found
  786. if (needsPluralHandling && needsContextHandling) finalKeys.push(finalKey + pluralSuffix);
  787. // get key for context if needed
  788. if (needsContextHandling) finalKeys.push(finalKey += '' + _this3.options.contextSeparator + options.context);
  789. // get key for plural if needed
  790. if (needsPluralHandling) finalKeys.push(finalKey += pluralSuffix);
  791. // iterate over finalKeys starting with most specific pluralkey (-> contextkey only) -> singularkey only
  792. var possibleKey = void 0;
  793. while (possibleKey = finalKeys.pop()) {
  794. if (_this3.isValidLookup(found)) continue;
  795. found = _this3.getResource(code, ns, possibleKey, options);
  796. }
  797. });
  798. });
  799. });
  800. return found;
  801. };
  802. Translator.prototype.isValidLookup = function isValidLookup(res) {
  803. return res !== undefined && !(!this.options.returnNull && res === null) && !(!this.options.returnEmptyString && res === '');
  804. };
  805. Translator.prototype.getResource = function getResource(code, ns, key) {
  806. var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  807. return this.resourceStore.getResource(code, ns, key, options);
  808. };
  809. return Translator;
  810. }(EventEmitter);
  811. function capitalize(string) {
  812. return string.charAt(0).toUpperCase() + string.slice(1);
  813. }
  814. var LanguageUtil = function () {
  815. function LanguageUtil(options) {
  816. classCallCheck(this, LanguageUtil);
  817. this.options = options;
  818. this.whitelist = this.options.whitelist || false;
  819. this.logger = baseLogger.create('languageUtils');
  820. }
  821. LanguageUtil.prototype.getLanguagePartFromCode = function getLanguagePartFromCode(code) {
  822. if (code.indexOf('-') < 0) return code;
  823. var specialCases = ['NB-NO', 'NN-NO', 'nb-NO', 'nn-NO', 'nb-no', 'nn-no'];
  824. var p = code.split('-');
  825. return this.formatLanguageCode(specialCases.indexOf(code) > -1 ? p[1].toLowerCase() : p[0]);
  826. };
  827. LanguageUtil.prototype.getScriptPartFromCode = function getScriptPartFromCode(code) {
  828. if (code.indexOf('-') < 0) return null;
  829. var p = code.split('-');
  830. if (p.length === 2) return null;
  831. p.pop();
  832. return this.formatLanguageCode(p.join('-'));
  833. };
  834. LanguageUtil.prototype.getLanguagePartFromCode = function getLanguagePartFromCode(code) {
  835. if (code.indexOf('-') < 0) return code;
  836. var specialCases = ['NB-NO', 'NN-NO', 'nb-NO', 'nn-NO', 'nb-no', 'nn-no'];
  837. var p = code.split('-');
  838. return this.formatLanguageCode(specialCases.indexOf(code) > -1 ? p[1].toLowerCase() : p[0]);
  839. };
  840. LanguageUtil.prototype.formatLanguageCode = function formatLanguageCode(code) {
  841. // http://www.iana.org/assignments/language-tags/language-tags.xhtml
  842. if (typeof code === 'string' && code.indexOf('-') > -1) {
  843. var specialCases = ['hans', 'hant', 'latn', 'cyrl', 'cans', 'mong', 'arab'];
  844. var p = code.split('-');
  845. if (this.options.lowerCaseLng) {
  846. p = p.map(function (part) {
  847. return part.toLowerCase();
  848. });
  849. } else if (p.length === 2) {
  850. p[0] = p[0].toLowerCase();
  851. p[1] = p[1].toUpperCase();
  852. if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase());
  853. } else if (p.length === 3) {
  854. p[0] = p[0].toLowerCase();
  855. // if lenght 2 guess it's a country
  856. if (p[1].length === 2) p[1] = p[1].toUpperCase();
  857. if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase();
  858. if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase());
  859. if (specialCases.indexOf(p[2].toLowerCase()) > -1) p[2] = capitalize(p[2].toLowerCase());
  860. }
  861. return p.join('-');
  862. } else {
  863. return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code;
  864. }
  865. };
  866. LanguageUtil.prototype.isWhitelisted = function isWhitelisted(code, exactMatch) {
  867. if (this.options.load === 'languageOnly' || this.options.nonExplicitWhitelist && !exactMatch) {
  868. code = this.getLanguagePartFromCode(code);
  869. }
  870. return !this.whitelist || !this.whitelist.length || this.whitelist.indexOf(code) > -1 ? true : false;
  871. };
  872. LanguageUtil.prototype.getFallbackCodes = function getFallbackCodes(fallbacks, code) {
  873. if (!fallbacks) return [];
  874. if (typeof fallbacks === 'string') fallbacks = [fallbacks];
  875. if (Object.prototype.toString.apply(fallbacks) === '[object Array]') return fallbacks;
  876. // asume we have an object defining fallbacks
  877. var found = fallbacks[code];
  878. if (!found) found = fallbacks[this.getScriptPartFromCode(code)];
  879. if (!found) found = fallbacks[this.formatLanguageCode(code)];
  880. if (!found) found = fallbacks.default;
  881. return found || [];
  882. };
  883. LanguageUtil.prototype.toResolveHierarchy = function toResolveHierarchy(code, fallbackCode) {
  884. var _this = this;
  885. var fallbackCodes = this.getFallbackCodes(fallbackCode || this.options.fallbackLng || [], code);
  886. var codes = [];
  887. var addCode = function addCode(code) {
  888. var exactMatch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  889. if (!code) return;
  890. if (_this.isWhitelisted(code, exactMatch)) {
  891. codes.push(code);
  892. } else {
  893. _this.logger.warn('rejecting non-whitelisted language code: ' + code);
  894. }
  895. };
  896. if (typeof code === 'string' && code.indexOf('-') > -1) {
  897. if (this.options.load !== 'languageOnly') addCode(this.formatLanguageCode(code), true);
  898. if (this.options.load !== 'languageOnly' && this.options.load !== 'currentOnly') addCode(this.getScriptPartFromCode(code), true);
  899. if (this.options.load !== 'currentOnly') addCode(this.getLanguagePartFromCode(code));
  900. } else if (typeof code === 'string') {
  901. addCode(this.formatLanguageCode(code));
  902. }
  903. fallbackCodes.forEach(function (fc) {
  904. if (codes.indexOf(fc) < 0) addCode(_this.formatLanguageCode(fc));
  905. });
  906. return codes;
  907. };
  908. return LanguageUtil;
  909. }();
  910. // definition http://translate.sourceforge.net/wiki/l10n/pluralforms
  911. /* eslint-disable */
  912. var sets = [{ lngs: ['ach', 'ak', 'am', 'arn', 'br', 'fil', 'gun', 'ln', 'mfe', 'mg', 'mi', 'oc', 'tg', 'ti', 'tr', 'uz', 'wa'], nr: [1, 2], fc: 1 }, { lngs: ['af', 'an', 'ast', 'az', 'bg', 'bn', 'ca', 'da', 'de', 'dev', 'el', 'en', 'eo', 'es', 'es_ar', 'et', 'eu', 'fi', 'fo', 'fur', 'fy', 'gl', 'gu', 'ha', 'he', 'hi', 'hu', 'hy', 'ia', 'it', 'kn', 'ku', 'lb', 'mai', 'ml', 'mn', 'mr', 'nah', 'nap', 'nb', 'ne', 'nl', 'nn', 'no', 'nso', 'pa', 'pap', 'pms', 'ps', 'pt', 'pt_br', 'rm', 'sco', 'se', 'si', 'so', 'son', 'sq', 'sv', 'sw', 'ta', 'te', 'tk', 'ur', 'yo'], nr: [1, 2], fc: 2 }, { lngs: ['ay', 'bo', 'cgg', 'fa', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky', 'lo', 'ms', 'sah', 'su', 'th', 'tt', 'ug', 'vi', 'wo', 'zh'], nr: [1], fc: 3 }, { lngs: ['be', 'bs', 'dz', 'hr', 'ru', 'sr', 'uk'], nr: [1, 2, 5], fc: 4 }, { lngs: ['ar'], nr: [0, 1, 2, 3, 11, 100], fc: 5 }, { lngs: ['cs', 'sk'], nr: [1, 2, 5], fc: 6 }, { lngs: ['csb', 'pl'], nr: [1, 2, 5], fc: 7 }, { lngs: ['cy'], nr: [1, 2, 3, 8], fc: 8 }, { lngs: ['fr'], nr: [1, 2], fc: 9 }, { lngs: ['ga'], nr: [1, 2, 3, 7, 11], fc: 10 }, { lngs: ['gd'], nr: [1, 2, 3, 20], fc: 11 }, { lngs: ['is'], nr: [1, 2], fc: 12 }, { lngs: ['jv'], nr: [0, 1], fc: 13 }, { lngs: ['kw'], nr: [1, 2, 3, 4], fc: 14 }, { lngs: ['lt'], nr: [1, 2, 10], fc: 15 }, { lngs: ['lv'], nr: [1, 2, 0], fc: 16 }, { lngs: ['mk'], nr: [1, 2], fc: 17 }, { lngs: ['mnk'], nr: [0, 1, 2], fc: 18 }, { lngs: ['mt'], nr: [1, 2, 11, 20], fc: 19 }, { lngs: ['or'], nr: [2, 1], fc: 2 }, { lngs: ['ro'], nr: [1, 2, 20], fc: 20 }, { lngs: ['sl'], nr: [5, 1, 2, 3], fc: 21 }];
  913. var _rulesPluralsTypes = {
  914. 1: function _(n) {
  915. return Number(n > 1);
  916. },
  917. 2: function _(n) {
  918. return Number(n != 1);
  919. },
  920. 3: function _(n) {
  921. return 0;
  922. },
  923. 4: function _(n) {
  924. return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
  925. },
  926. 5: function _(n) {
  927. return Number(n === 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5);
  928. },
  929. 6: function _(n) {
  930. return Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2);
  931. },
  932. 7: function _(n) {
  933. return Number(n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
  934. },
  935. 8: function _(n) {
  936. return Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3);
  937. },
  938. 9: function _(n) {
  939. return Number(n >= 2);
  940. },
  941. 10: function _(n) {
  942. return Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4);
  943. },
  944. 11: function _(n) {
  945. return Number(n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3);
  946. },
  947. 12: function _(n) {
  948. return Number(n % 10 != 1 || n % 100 == 11);
  949. },
  950. 13: function _(n) {
  951. return Number(n !== 0);
  952. },
  953. 14: function _(n) {
  954. return Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3);
  955. },
  956. 15: function _(n) {
  957. return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
  958. },
  959. 16: function _(n) {
  960. return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2);
  961. },
  962. 17: function _(n) {
  963. return Number(n == 1 || n % 10 == 1 ? 0 : 1);
  964. },
  965. 18: function _(n) {
  966. return Number(n == 0 ? 0 : n == 1 ? 1 : 2);
  967. },
  968. 19: function _(n) {
  969. return Number(n == 1 ? 0 : n === 0 || n % 100 > 1 && n % 100 < 11 ? 1 : n % 100 > 10 && n % 100 < 20 ? 2 : 3);
  970. },
  971. 20: function _(n) {
  972. return Number(n == 1 ? 0 : n === 0 || n % 100 > 0 && n % 100 < 20 ? 1 : 2);
  973. },
  974. 21: function _(n) {
  975. return Number(n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0);
  976. }
  977. };
  978. /* eslint-enable */
  979. function createRules() {
  980. var l,
  981. rules = {};
  982. sets.forEach(function (set$$1) {
  983. set$$1.lngs.forEach(function (l) {
  984. return rules[l] = {
  985. numbers: set$$1.nr,
  986. plurals: _rulesPluralsTypes[set$$1.fc]
  987. };
  988. });
  989. });
  990. return rules;
  991. }
  992. var PluralResolver = function () {
  993. function PluralResolver(languageUtils) {
  994. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  995. classCallCheck(this, PluralResolver);
  996. this.languageUtils = languageUtils;
  997. this.options = options;
  998. this.logger = baseLogger.create('pluralResolver');
  999. this.rules = createRules();
  1000. }
  1001. PluralResolver.prototype.addRule = function addRule(lng, obj) {
  1002. this.rules[lng] = obj;
  1003. };
  1004. PluralResolver.prototype.getRule = function getRule(code) {
  1005. return this.rules[this.languageUtils.getLanguagePartFromCode(code)];
  1006. };
  1007. PluralResolver.prototype.needsPlural = function needsPlural(code) {
  1008. var rule = this.getRule(code);
  1009. return rule && rule.numbers.length <= 1 ? false : true;
  1010. };
  1011. PluralResolver.prototype.getSuffix = function getSuffix(code, count) {
  1012. var _this = this;
  1013. var rule = this.getRule(code);
  1014. if (rule) {
  1015. var _ret = function () {
  1016. if (rule.numbers.length === 1) return {
  1017. v: ''
  1018. }; // only singular
  1019. var idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count));
  1020. var suffix = rule.numbers[idx];
  1021. // special treatment for lngs only having singular and plural
  1022. if (rule.numbers.length === 2 && rule.numbers[0] === 1) {
  1023. if (suffix === 2) {
  1024. suffix = 'plural';
  1025. } else if (suffix === 1) {
  1026. suffix = '';
  1027. }
  1028. }
  1029. var returnSuffix = function returnSuffix() {
  1030. return _this.options.prepend && suffix.toString() ? _this.options.prepend + suffix.toString() : suffix.toString();
  1031. };
  1032. // COMPATIBILITY JSON
  1033. // v1
  1034. if (_this.options.compatibilityJSON === 'v1') {
  1035. if (suffix === 1) return {
  1036. v: ''
  1037. };
  1038. if (typeof suffix === 'number') return {
  1039. v: '_plural_' + suffix.toString()
  1040. };
  1041. return {
  1042. v: returnSuffix()
  1043. };
  1044. }
  1045. // v2
  1046. else if (_this.options.compatibilityJSON === 'v2' || rule.numbers.length === 2 && rule.numbers[0] === 1) {
  1047. return {
  1048. v: returnSuffix()
  1049. };
  1050. }
  1051. // v3 - gettext index
  1052. else if (rule.numbers.length === 2 && rule.numbers[0] === 1) {
  1053. return {
  1054. v: returnSuffix()
  1055. };
  1056. }
  1057. return {
  1058. v: _this.options.prepend && idx.toString() ? _this.options.prepend + idx.toString() : idx.toString()
  1059. };
  1060. }();
  1061. if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
  1062. } else {
  1063. this.logger.warn('no plural rule found for: ' + code);
  1064. return '';
  1065. }
  1066. };
  1067. return PluralResolver;
  1068. }();
  1069. var Interpolator = function () {
  1070. function Interpolator() {
  1071. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1072. classCallCheck(this, Interpolator);
  1073. this.logger = baseLogger.create('interpolator');
  1074. this.init(options, true);
  1075. }
  1076. Interpolator.prototype.init = function init() {
  1077. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1078. var reset = arguments[1];
  1079. if (reset) {
  1080. this.options = options;
  1081. this.format = options.interpolation && options.interpolation.format || function (value) {
  1082. return value;
  1083. };
  1084. this.escape = options.interpolation && options.interpolation.escape || escape;
  1085. }
  1086. if (!options.interpolation) options.interpolation = { escapeValue: true };
  1087. var iOpts = options.interpolation;
  1088. this.escapeValue = iOpts.escapeValue !== undefined ? iOpts.escapeValue : true;
  1089. this.prefix = iOpts.prefix ? regexEscape(iOpts.prefix) : iOpts.prefixEscaped || '{{';
  1090. this.suffix = iOpts.suffix ? regexEscape(iOpts.suffix) : iOpts.suffixEscaped || '}}';
  1091. this.formatSeparator = iOpts.formatSeparator ? regexEscape(iOpts.formatSeparator) : iOpts.formatSeparator || ',';
  1092. this.unescapePrefix = iOpts.unescapeSuffix ? '' : iOpts.unescapePrefix || '-';
  1093. this.unescapeSuffix = this.unescapePrefix ? '' : iOpts.unescapeSuffix || '';
  1094. this.nestingPrefix = iOpts.nestingPrefix ? regexEscape(iOpts.nestingPrefix) : iOpts.nestingPrefixEscaped || regexEscape('$t(');
  1095. this.nestingSuffix = iOpts.nestingSuffix ? regexEscape(iOpts.nestingSuffix) : iOpts.nestingSuffixEscaped || regexEscape(')');
  1096. // the regexp
  1097. this.resetRegExp();
  1098. };
  1099. Interpolator.prototype.reset = function reset() {
  1100. if (this.options) this.init(this.options);
  1101. };
  1102. Interpolator.prototype.resetRegExp = function resetRegExp() {
  1103. // the regexp
  1104. var regexpStr = this.prefix + '(.+?)' + this.suffix;
  1105. this.regexp = new RegExp(regexpStr, 'g');
  1106. var regexpUnescapeStr = this.prefix + this.unescapePrefix + '(.+?)' + this.unescapeSuffix + this.suffix;
  1107. this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g');
  1108. var nestingRegexpStr = this.nestingPrefix + '(.+?)' + this.nestingSuffix;
  1109. this.nestingRegexp = new RegExp(nestingRegexpStr, 'g');
  1110. };
  1111. Interpolator.prototype.interpolate = function interpolate(str, data, lng) {
  1112. var _this = this;
  1113. var match = void 0,
  1114. value = void 0;
  1115. function regexSafe(val) {
  1116. return val.replace(/\$/g, '$$$$');
  1117. }
  1118. var handleFormat = function handleFormat(key) {
  1119. if (key.indexOf(_this.formatSeparator) < 0) return getPath(data, key);
  1120. var p = key.split(_this.formatSeparator);
  1121. var k = p.shift().trim();
  1122. var f = p.join(_this.formatSeparator).trim();
  1123. return _this.format(getPath(data, k), f, lng);
  1124. };
  1125. this.resetRegExp();
  1126. // unescape if has unescapePrefix/Suffix
  1127. while (match = this.regexpUnescape.exec(str)) {
  1128. var _value = handleFormat(match[1].trim());
  1129. str = str.replace(match[0], _value);
  1130. this.regexpUnescape.lastIndex = 0;
  1131. }
  1132. // regular escape on demand
  1133. while (match = this.regexp.exec(str)) {
  1134. value = handleFormat(match[1].trim());
  1135. if (typeof value !== 'string') value = makeString(value);
  1136. if (!value) {
  1137. this.logger.warn('missed to pass in variable ' + match[1] + ' for interpolating ' + str);
  1138. value = '';
  1139. }
  1140. value = this.escapeValue ? regexSafe(this.escape(value)) : regexSafe(value);
  1141. str = str.replace(match[0], value);
  1142. this.regexp.lastIndex = 0;
  1143. }
  1144. return str;
  1145. };
  1146. Interpolator.prototype.nest = function nest(str, fc) {
  1147. var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  1148. var match = void 0,
  1149. value = void 0;
  1150. var clonedOptions = JSON.parse(JSON.stringify(options));
  1151. clonedOptions.applyPostProcessor = false; // avoid post processing on nested lookup
  1152. function regexSafe(val) {
  1153. return val.replace(/\$/g, '$$$$');
  1154. }
  1155. // if value is something like "myKey": "lorem $(anotherKey, { "count": {{aValueInOptions}} })"
  1156. function handleHasOptions(key) {
  1157. if (key.indexOf(',') < 0) return key;
  1158. var p = key.split(',');
  1159. key = p.shift();
  1160. var optionsString = p.join(',');
  1161. optionsString = this.interpolate(optionsString, clonedOptions);
  1162. optionsString = optionsString.replace(/'/g, '"');
  1163. try {
  1164. clonedOptions = JSON.parse(optionsString);
  1165. } catch (e) {
  1166. this.logger.error('failed parsing options string in nesting for key ' + key, e);
  1167. }
  1168. return key;
  1169. }
  1170. // regular escape on demand
  1171. while (match = this.nestingRegexp.exec(str)) {
  1172. value = fc(handleHasOptions.call(this, match[1].trim()), clonedOptions);
  1173. if (typeof value !== 'string') value = makeString(value);
  1174. if (!value) {
  1175. this.logger.warn('missed to pass in variable ' + match[1] + ' for interpolating ' + str);
  1176. value = '';
  1177. }
  1178. value = this.escapeValue ? regexSafe(escape(value)) : regexSafe(value);
  1179. str = str.replace(match[0], value);
  1180. this.regexp.lastIndex = 0;
  1181. }
  1182. return str;
  1183. };
  1184. return Interpolator;
  1185. }();
  1186. function remove(arr, what) {
  1187. var found = arr.indexOf(what);
  1188. while (found !== -1) {
  1189. arr.splice(found, 1);
  1190. found = arr.indexOf(what);
  1191. }
  1192. }
  1193. var Connector = function (_EventEmitter) {
  1194. inherits(Connector, _EventEmitter);
  1195. function Connector(backend, store, services) {
  1196. var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  1197. classCallCheck(this, Connector);
  1198. var _this = possibleConstructorReturn(this, _EventEmitter.call(this));
  1199. _this.backend = backend;
  1200. _this.store = store;
  1201. _this.services = services;
  1202. _this.options = options;
  1203. _this.logger = baseLogger.create('backendConnector');
  1204. _this.state = {};
  1205. _this.queue = [];
  1206. _this.backend && _this.backend.init && _this.backend.init(services, options.backend, options);
  1207. return _this;
  1208. }
  1209. Connector.prototype.queueLoad = function queueLoad(languages, namespaces, callback) {
  1210. var _this2 = this;
  1211. // find what needs to be loaded
  1212. var toLoad = [],
  1213. pending = [],
  1214. toLoadLanguages = [],
  1215. toLoadNamespaces = [];
  1216. languages.forEach(function (lng) {
  1217. var hasAllNamespaces = true;
  1218. namespaces.forEach(function (ns) {
  1219. var name = lng + '|' + ns;
  1220. if (_this2.store.hasResourceBundle(lng, ns)) {
  1221. _this2.state[name] = 2; // loaded
  1222. } else if (_this2.state[name] < 0) {
  1223. // nothing to do for err
  1224. } else if (_this2.state[name] === 1) {
  1225. if (pending.indexOf(name) < 0) pending.push(name);
  1226. } else {
  1227. _this2.state[name] = 1; // pending
  1228. hasAllNamespaces = false;
  1229. if (pending.indexOf(name) < 0) pending.push(name);
  1230. if (toLoad.indexOf(name) < 0) toLoad.push(name);
  1231. if (toLoadNamespaces.indexOf(ns) < 0) toLoadNamespaces.push(ns);
  1232. }
  1233. });
  1234. if (!hasAllNamespaces) toLoadLanguages.push(lng);
  1235. });
  1236. if (toLoad.length || pending.length) {
  1237. this.queue.push({
  1238. pending: pending,
  1239. loaded: {},
  1240. errors: [],
  1241. callback: callback
  1242. });
  1243. }
  1244. return {
  1245. toLoad: toLoad,
  1246. pending: pending,
  1247. toLoadLanguages: toLoadLanguages,
  1248. toLoadNamespaces: toLoadNamespaces
  1249. };
  1250. };
  1251. Connector.prototype.loaded = function loaded(name, err, data) {
  1252. var _this3 = this;
  1253. var _name$split = name.split('|'),
  1254. _name$split2 = slicedToArray(_name$split, 2),
  1255. lng = _name$split2[0],
  1256. ns = _name$split2[1];
  1257. if (err) this.emit('failedLoading', lng, ns, err);
  1258. if (data) {
  1259. this.store.addResourceBundle(lng, ns, data);
  1260. }
  1261. // set loaded
  1262. this.state[name] = err ? -1 : 2;
  1263. // callback if ready
  1264. this.queue.forEach(function (q) {
  1265. pushPath(q.loaded, [lng], ns);
  1266. remove(q.pending, name);
  1267. if (err) q.errors.push(err);
  1268. if (q.pending.length === 0 && !q.done) {
  1269. q.errors.length ? q.callback(q.errors) : q.callback();
  1270. _this3.emit('loaded', q.loaded);
  1271. q.done = true;
  1272. }
  1273. });
  1274. // remove done load requests
  1275. this.queue = this.queue.filter(function (q) {
  1276. return !q.done;
  1277. });
  1278. };
  1279. Connector.prototype.read = function read(lng, ns, fcName, tried, wait, callback) {
  1280. var _this4 = this;
  1281. if (!tried) tried = 0;
  1282. if (!wait) wait = 250;
  1283. if (!lng.length) return callback(null, {}); // noting to load
  1284. this.backend[fcName](lng, ns, function (err, data) {
  1285. if (err && data /* = retryFlag */ && tried < 5) {
  1286. setTimeout(function () {
  1287. _this4.read.call(_this4, lng, ns, fcName, ++tried, wait * 2, callback);
  1288. }, wait);
  1289. return;
  1290. }
  1291. callback(err, data);
  1292. });
  1293. };
  1294. Connector.prototype.load = function load(languages, namespaces, callback) {
  1295. var _this5 = this;
  1296. if (!this.backend) {
  1297. this.logger.warn('No backend was added via i18next.use. Will not load resources.');
  1298. return callback && callback();
  1299. }
  1300. var options = _extends({}, this.backend.options, this.options.backend);
  1301. if (typeof languages === 'string') languages = this.services.languageUtils.toResolveHierarchy(languages);
  1302. if (typeof namespaces === 'string') namespaces = [namespaces];
  1303. var toLoad = this.queueLoad(languages, namespaces, callback);
  1304. if (!toLoad.toLoad.length) {
  1305. if (!toLoad.pending.length) callback(); // nothing to load and no pendings...callback now
  1306. return; // pendings will trigger callback
  1307. }
  1308. // load with multi-load
  1309. if (options.allowMultiLoading && this.backend.readMulti) {
  1310. this.read(toLoad.toLoadLanguages, toLoad.toLoadNamespaces, 'readMulti', null, null, function (err, data) {
  1311. if (err) _this5.logger.warn('loading namespaces ' + toLoad.toLoadNamespaces.join(', ') + ' for languages ' + toLoad.toLoadLanguages.join(', ') + ' via multiloading failed', err);
  1312. if (!err && data) _this5.logger.log('loaded namespaces ' + toLoad.toLoadNamespaces.join(', ') + ' for languages ' + toLoad.toLoadLanguages.join(', ') + ' via multiloading', data);
  1313. toLoad.toLoad.forEach(function (name) {
  1314. var _name$split3 = name.split('|'),
  1315. _name$split4 = slicedToArray(_name$split3, 2),
  1316. l = _name$split4[0],
  1317. n = _name$split4[1];
  1318. var bundle = getPath(data, [l, n]);
  1319. if (bundle) {
  1320. _this5.loaded(name, err, bundle);
  1321. } else {
  1322. var _err = 'loading namespace ' + n + ' for language ' + l + ' via multiloading failed';
  1323. _this5.loaded(name, _err);
  1324. _this5.logger.error(_err);
  1325. }
  1326. });
  1327. });
  1328. }
  1329. // load one by one
  1330. else {
  1331. (function () {
  1332. var readOne = function readOne(name) {
  1333. var _this6 = this;
  1334. var _name$split5 = name.split('|'),
  1335. _name$split6 = slicedToArray(_name$split5, 2),
  1336. lng = _name$split6[0],
  1337. ns = _name$split6[1];
  1338. this.read(lng, ns, 'read', null, null, function (err, data) {
  1339. if (err) _this6.logger.warn('loading namespace ' + ns + ' for language ' + lng + ' failed', err);
  1340. if (!err && data) _this6.logger.log('loaded namespace ' + ns + ' for language ' + lng, data);
  1341. _this6.loaded(name, err, data);
  1342. });
  1343. };
  1344. toLoad.toLoad.forEach(function (name) {
  1345. readOne.call(_this5, name);
  1346. });
  1347. })();
  1348. }
  1349. };
  1350. Connector.prototype.reload = function reload(languages, namespaces) {
  1351. var _this7 = this;
  1352. if (!this.backend) {
  1353. this.logger.warn('No backend was added via i18next.use. Will not load resources.');
  1354. }
  1355. var options = _extends({}, this.backend.options, this.options.backend);
  1356. if (typeof languages === 'string') languages = this.services.languageUtils.toResolveHierarchy(languages);
  1357. if (typeof namespaces === 'string') namespaces = [namespaces];
  1358. // load with multi-load
  1359. if (options.allowMultiLoading && this.backend.readMulti) {
  1360. this.read(languages, namespaces, 'readMulti', null, null, function (err, data) {
  1361. if (err) _this7.logger.warn('reloading namespaces ' + namespaces.join(', ') + ' for languages ' + languages.join(', ') + ' via multiloading failed', err);
  1362. if (!err && data) _this7.logger.log('reloaded namespaces ' + namespaces.join(', ') + ' for languages ' + languages.join(', ') + ' via multiloading', data);
  1363. languages.forEach(function (l) {
  1364. namespaces.forEach(function (n) {
  1365. var bundle = getPath(data, [l, n]);
  1366. if (bundle) {
  1367. _this7.loaded(l + '|' + n, err, bundle);
  1368. } else {
  1369. var _err2 = 'reloading namespace ' + n + ' for language ' + l + ' via multiloading failed';
  1370. _this7.loaded(l + '|' + n, _err2);
  1371. _this7.logger.error(_err2);
  1372. }
  1373. });
  1374. });
  1375. });
  1376. }
  1377. // load one by one
  1378. else {
  1379. (function () {
  1380. var readOne = function readOne(name) {
  1381. var _this8 = this;
  1382. var _name$split7 = name.split('|'),
  1383. _name$split8 = slicedToArray(_name$split7, 2),
  1384. lng = _name$split8[0],
  1385. ns = _name$split8[1];
  1386. this.read(lng, ns, 'read', null, null, function (err, data) {
  1387. if (err) _this8.logger.warn('reloading namespace ' + ns + ' for language ' + lng + ' failed', err);
  1388. if (!err && data) _this8.logger.log('reloaded namespace ' + ns + ' for language ' + lng, data);
  1389. _this8.loaded(name, err, data);
  1390. });
  1391. };
  1392. languages.forEach(function (l) {
  1393. namespaces.forEach(function (n) {
  1394. readOne.call(_this7, l + '|' + n);
  1395. });
  1396. });
  1397. })();
  1398. }
  1399. };
  1400. Connector.prototype.saveMissing = function saveMissing(languages, namespace, key, fallbackValue) {
  1401. if (this.backend && this.backend.create) this.backend.create(languages, namespace, key, fallbackValue);
  1402. // write to store to avoid resending
  1403. if (!languages || !languages[0]) return;
  1404. this.store.addResource(languages[0], namespace, key, fallbackValue);
  1405. };
  1406. return Connector;
  1407. }(EventEmitter);
  1408. var Connector$1 = function (_EventEmitter) {
  1409. inherits(Connector, _EventEmitter);
  1410. function Connector(cache, store, services) {
  1411. var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  1412. classCallCheck(this, Connector);
  1413. var _this = possibleConstructorReturn(this, _EventEmitter.call(this));
  1414. _this.cache = cache;
  1415. _this.store = store;
  1416. _this.services = services;
  1417. _this.options = options;
  1418. _this.logger = baseLogger.create('cacheConnector');
  1419. _this.cache && _this.cache.init && _this.cache.init(services, options.cache, options);
  1420. return _this;
  1421. }
  1422. Connector.prototype.load = function load(languages, namespaces, callback) {
  1423. var _this2 = this;
  1424. if (!this.cache) return callback && callback();
  1425. var options = _extends({}, this.cache.options, this.options.cache);
  1426. if (typeof languages === 'string') languages = this.services.languageUtils.toResolveHierarchy(languages);
  1427. if (typeof namespaces === 'string') namespaces = [namespaces];
  1428. if (options.enabled) {
  1429. this.cache.load(languages, function (err, data) {
  1430. if (err) _this2.logger.error('loading languages ' + languages.join(', ') + ' from cache failed', err);
  1431. if (data) {
  1432. for (var l in data) {
  1433. for (var n in data[l]) {
  1434. if (n === 'i18nStamp') continue;
  1435. var bundle = data[l][n];
  1436. if (bundle) _this2.store.addResourceBundle(l, n, bundle);
  1437. }
  1438. }
  1439. }
  1440. if (callback) callback();
  1441. });
  1442. } else {
  1443. if (callback) callback();
  1444. }
  1445. };
  1446. Connector.prototype.save = function save() {
  1447. if (this.cache && this.options.cache && this.options.cache.enabled) this.cache.save(this.store.data);
  1448. };
  1449. return Connector;
  1450. }(EventEmitter);
  1451. function get$1() {
  1452. return {
  1453. debug: false,
  1454. initImmediate: true,
  1455. ns: ['translation'],
  1456. defaultNS: ['translation'],
  1457. fallbackLng: ['dev'],
  1458. fallbackNS: false, // string or array of namespaces
  1459. whitelist: false, // array with whitelisted languages
  1460. nonExplicitWhitelist: false,
  1461. load: 'all', // | currentOnly | languageOnly
  1462. preload: false, // array with preload languages
  1463. keySeparator: '.',
  1464. nsSeparator: ':',
  1465. pluralSeparator: '_',
  1466. contextSeparator: '_',
  1467. saveMissing: false, // enable to send missing values
  1468. saveMissingTo: 'fallback', // 'current' || 'all'
  1469. missingKeyHandler: false, // function(lng, ns, key, fallbackValue) -> override if prefer on handling
  1470. postProcess: false, // string or array of postProcessor names
  1471. returnNull: true, // allows null value as valid translation
  1472. returnEmptyString: true, // allows empty string value as valid translation
  1473. returnObjects: false,
  1474. joinArrays: false, // or string to join array
  1475. returnedObjectHandler: function returnedObjectHandler() {}, // function(key, value, options) triggered if key returns object but returnObjects is set to false
  1476. parseMissingKeyHandler: false, // function(key) parsed a key that was not found in t() before returning
  1477. appendNamespaceToMissingKey: false,
  1478. overloadTranslationOptionHandler: function overloadTranslationOptionHandler(args) {
  1479. return { defaultValue: args[1] };
  1480. },
  1481. interpolation: {
  1482. escapeValue: true,
  1483. format: function format(value, _format, lng) {
  1484. return value;
  1485. },
  1486. prefix: '{{',
  1487. suffix: '}}',
  1488. formatSeparator: ',',
  1489. // prefixEscaped: '{{',
  1490. // suffixEscaped: '}}',
  1491. // unescapeSuffix: '',
  1492. unescapePrefix: '-',
  1493. nestingPrefix: '$t(',
  1494. nestingSuffix: ')',
  1495. // nestingPrefixEscaped: '$t(',
  1496. // nestingSuffixEscaped: ')',
  1497. defaultVariables: undefined // object that can have values to interpolate on - extends passed in interpolation data
  1498. }
  1499. };
  1500. }
  1501. function transformOptions(options) {
  1502. // create namespace object if namespace is passed in as string
  1503. if (typeof options.ns === 'string') options.ns = [options.ns];
  1504. if (typeof options.fallbackLng === 'string') options.fallbackLng = [options.fallbackLng];
  1505. if (typeof options.fallbackNS === 'string') options.fallbackNS = [options.fallbackNS];
  1506. // extend whitelist with cimode
  1507. if (options.whitelist && options.whitelist.indexOf('cimode') < 0) options.whitelist.push('cimode');
  1508. return options;
  1509. }
  1510. function noop() {}
  1511. var I18n = function (_EventEmitter) {
  1512. inherits(I18n, _EventEmitter);
  1513. function I18n() {
  1514. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1515. var callback = arguments[1];
  1516. classCallCheck(this, I18n);
  1517. var _this = possibleConstructorReturn(this, _EventEmitter.call(this));
  1518. _this.options = transformOptions(options);
  1519. _this.services = {};
  1520. _this.logger = baseLogger;
  1521. _this.modules = {};
  1522. if (callback && !_this.isInitialized) _this.init(options, callback);
  1523. return _this;
  1524. }
  1525. I18n.prototype.init = function init(options, callback) {
  1526. var _this2 = this;
  1527. if (typeof options === 'function') {
  1528. callback = options;
  1529. options = {};
  1530. }
  1531. if (!options) options = {};
  1532. if (options.compatibilityAPI === 'v1') {
  1533. this.options = _extends({}, get$1(), transformOptions(convertAPIOptions(options)), {});
  1534. } else if (options.compatibilityJSON === 'v1') {
  1535. this.options = _extends({}, get$1(), transformOptions(convertJSONOptions(options)), {});
  1536. } else {
  1537. this.options = _extends({}, get$1(), this.options, transformOptions(options));
  1538. }
  1539. if (!callback) callback = noop;
  1540. function createClassOnDemand(ClassOrObject) {
  1541. if (!ClassOrObject) return;
  1542. if (typeof ClassOrObject === 'function') return new ClassOrObject();
  1543. return ClassOrObject;
  1544. }
  1545. // init services
  1546. if (!this.options.isClone) {
  1547. if (this.modules.logger) {
  1548. baseLogger.init(createClassOnDemand(this.modules.logger), this.options);
  1549. } else {
  1550. baseLogger.init(null, this.options);
  1551. }
  1552. var lu = new LanguageUtil(this.options);
  1553. this.store = new ResourceStore(this.options.resources, this.options);
  1554. var s = this.services;
  1555. s.logger = baseLogger;
  1556. s.resourceStore = this.store;
  1557. s.resourceStore.on('added removed', function (lng, ns) {
  1558. s.cacheConnector.save();
  1559. });
  1560. s.languageUtils = lu;
  1561. s.pluralResolver = new PluralResolver(lu, { prepend: this.options.pluralSeparator, compatibilityJSON: this.options.compatibilityJSON });
  1562. s.interpolator = new Interpolator(this.options);
  1563. s.backendConnector = new Connector(createClassOnDemand(this.modules.backend), s.resourceStore, s, this.options);
  1564. // pipe events from backendConnector
  1565. s.backendConnector.on('*', function (event) {
  1566. for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  1567. args[_key - 1] = arguments[_key];
  1568. }
  1569. _this2.emit.apply(_this2, [event].concat(args));
  1570. });
  1571. s.backendConnector.on('loaded', function (loaded) {
  1572. s.cacheConnector.save();
  1573. });
  1574. s.cacheConnector = new Connector$1(createClassOnDemand(this.modules.cache), s.resourceStore, s, this.options);
  1575. // pipe events from backendConnector
  1576. s.cacheConnector.on('*', function (event) {
  1577. for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  1578. args[_key2 - 1] = arguments[_key2];
  1579. }
  1580. _this2.emit.apply(_this2, [event].concat(args));
  1581. });
  1582. if (this.modules.languageDetector) {
  1583. s.languageDetector = createClassOnDemand(this.modules.languageDetector);
  1584. s.languageDetector.init(s, this.options.detection, this.options);
  1585. }
  1586. this.translator = new Translator(this.services, this.options);
  1587. // pipe events from translator
  1588. this.translator.on('*', function (event) {
  1589. for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
  1590. args[_key3 - 1] = arguments[_key3];
  1591. }
  1592. _this2.emit.apply(_this2, [event].concat(args));
  1593. });
  1594. }
  1595. // append api
  1596. var storeApi = ['getResource', 'addResource', 'addResources', 'addResourceBundle', 'removeResourceBundle', 'hasResourceBundle', 'getResourceBundle'];
  1597. storeApi.forEach(function (fcName) {
  1598. _this2[fcName] = function () {
  1599. return this.store[fcName].apply(this.store, arguments);
  1600. };
  1601. });
  1602. // TODO: COMPATIBILITY remove this
  1603. if (this.options.compatibilityAPI === 'v1') appendBackwardsAPI(this);
  1604. var load = function load() {
  1605. _this2.changeLanguage(_this2.options.lng, function (err, t) {
  1606. _this2.emit('initialized', _this2.options);
  1607. _this2.logger.log('initialized', _this2.options);
  1608. callback(err, t);
  1609. });
  1610. };
  1611. if (this.options.resources || !this.options.initImmediate) {
  1612. load();
  1613. } else {
  1614. setTimeout(load, 0);
  1615. }
  1616. return this;
  1617. };
  1618. I18n.prototype.loadResources = function loadResources(callback) {
  1619. var _this3 = this;
  1620. if (!callback) callback = noop;
  1621. if (!this.options.resources) {
  1622. var _ret = function () {
  1623. if (_this3.language && _this3.language.toLowerCase() === 'cimode') return {
  1624. v: callback()
  1625. }; // avoid loading resources for cimode
  1626. var toLoad = [];
  1627. var append = function append(lng) {
  1628. var lngs = _this3.services.languageUtils.toResolveHierarchy(lng);
  1629. lngs.forEach(function (l) {
  1630. if (toLoad.indexOf(l) < 0) toLoad.push(l);
  1631. });
  1632. };
  1633. append(_this3.language);
  1634. if (_this3.options.preload) {
  1635. _this3.options.preload.forEach(function (l) {
  1636. append(l);
  1637. });
  1638. }
  1639. _this3.services.cacheConnector.load(toLoad, _this3.options.ns, function () {
  1640. _this3.services.backendConnector.load(toLoad, _this3.options.ns, callback);
  1641. });
  1642. }();
  1643. if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
  1644. } else {
  1645. callback(null);
  1646. }
  1647. };
  1648. I18n.prototype.reloadResources = function reloadResources(lngs, ns) {
  1649. if (!lngs) lngs = this.languages;
  1650. if (!ns) ns = this.options.ns;
  1651. this.services.backendConnector.reload(lngs, ns);
  1652. };
  1653. I18n.prototype.use = function use(module) {
  1654. if (module.type === 'backend') {
  1655. this.modules.backend = module;
  1656. }
  1657. if (module.type === 'cache') {
  1658. this.modules.cache = module;
  1659. }
  1660. if (module.type === 'logger' || module.log && module.warn && module.warn) {
  1661. this.modules.logger = module;
  1662. }
  1663. if (module.type === 'languageDetector') {
  1664. this.modules.languageDetector = module;
  1665. }
  1666. if (module.type === 'postProcessor') {
  1667. postProcessor.addPostProcessor(module);
  1668. }
  1669. return this;
  1670. };
  1671. I18n.prototype.changeLanguage = function changeLanguage(lng, callback) {
  1672. var _this4 = this;
  1673. var done = function done(err) {
  1674. if (lng) {
  1675. _this4.emit('languageChanged', lng);
  1676. _this4.logger.log('languageChanged', lng);
  1677. }
  1678. if (callback) callback(err, function () {
  1679. for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
  1680. args[_key4] = arguments[_key4];
  1681. }
  1682. return _this4.t.apply(_this4, args);
  1683. });
  1684. };
  1685. if (!lng && this.services.languageDetector) lng = this.services.languageDetector.detect();
  1686. if (lng) {
  1687. this.language = lng;
  1688. this.languages = this.services.languageUtils.toResolveHierarchy(lng);
  1689. this.translator.changeLanguage(lng);
  1690. if (this.services.languageDetector) this.services.languageDetector.cacheUserLanguage(lng);
  1691. }
  1692. this.loadResources(function (err) {
  1693. done(err);
  1694. });
  1695. };
  1696. I18n.prototype.getFixedT = function getFixedT(lng, ns) {
  1697. var _this5 = this;
  1698. var fixedT = function fixedT(key) {
  1699. var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1700. var options = _extends({}, opts);
  1701. options.lng = options.lng || fixedT.lng;
  1702. options.ns = options.ns || fixedT.ns;
  1703. return _this5.t(key, options);
  1704. };
  1705. fixedT.lng = lng;
  1706. fixedT.ns = ns;
  1707. return fixedT;
  1708. };
  1709. I18n.prototype.t = function t() {
  1710. return this.translator && this.translator.translate.apply(this.translator, arguments);
  1711. };
  1712. I18n.prototype.exists = function exists() {
  1713. return this.translator && this.translator.exists.apply(this.translator, arguments);
  1714. };
  1715. I18n.prototype.setDefaultNamespace = function setDefaultNamespace(ns) {
  1716. this.options.defaultNS = ns;
  1717. };
  1718. I18n.prototype.loadNamespaces = function loadNamespaces(ns, callback) {
  1719. var _this6 = this;
  1720. if (!this.options.ns) return callback && callback();
  1721. if (typeof ns === 'string') ns = [ns];
  1722. ns.forEach(function (n) {
  1723. if (_this6.options.ns.indexOf(n) < 0) _this6.options.ns.push(n);
  1724. });
  1725. this.loadResources(callback);
  1726. };
  1727. I18n.prototype.loadLanguages = function loadLanguages(lngs, callback) {
  1728. if (typeof lngs === 'string') lngs = [lngs];
  1729. var preloaded = this.options.preload || [];
  1730. var newLngs = lngs.filter(function (lng) {
  1731. return preloaded.indexOf(lng) < 0;
  1732. });
  1733. // Exit early if all given languages are already preloaded
  1734. if (!newLngs.length) return callback();
  1735. this.options.preload = preloaded.concat(newLngs);
  1736. this.loadResources(callback);
  1737. };
  1738. I18n.prototype.dir = function dir(lng) {
  1739. if (!lng) lng = this.language;
  1740. if (!lng) return 'rtl';
  1741. var rtlLngs = ['ar', 'shu', 'sqr', 'ssh', 'xaa', 'yhd', 'yud', 'aao', 'abh', 'abv', 'acm', 'acq', 'acw', 'acx', 'acy', 'adf', 'ads', 'aeb', 'aec', 'afb', 'ajp', 'apc', 'apd', 'arb', 'arq', 'ars', 'ary', 'arz', 'auz', 'avl', 'ayh', 'ayl', 'ayn', 'ayp', 'bbz', 'pga', 'he', 'iw', 'ps', 'pbt', 'pbu', 'pst', 'prp', 'prd', 'ur', 'ydd', 'yds', 'yih', 'ji', 'yi', 'hbo', 'men', 'xmn', 'fa', 'jpr', 'peo', 'pes', 'prs', 'dv', 'sam'];
  1742. return rtlLngs.indexOf(this.services.languageUtils.getLanguagePartFromCode(lng)) >= 0 ? 'rtl' : 'ltr';
  1743. };
  1744. I18n.prototype.createInstance = function createInstance() {
  1745. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1746. var callback = arguments[1];
  1747. return new I18n(options, callback);
  1748. };
  1749. I18n.prototype.cloneInstance = function cloneInstance() {
  1750. var _this7 = this;
  1751. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1752. var callback = arguments[1];
  1753. var clone = new I18n(_extends({}, options, this.options, { isClone: true }), callback);
  1754. var membersToCopy = ['store', 'services', 'language'];
  1755. membersToCopy.forEach(function (m) {
  1756. clone[m] = _this7[m];
  1757. });
  1758. clone.translator = new Translator(clone.services, clone.options);
  1759. clone.translator.on('*', function (event) {
  1760. for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
  1761. args[_key5 - 1] = arguments[_key5];
  1762. }
  1763. clone.emit.apply(clone, [event].concat(args));
  1764. });
  1765. return clone;
  1766. };
  1767. return I18n;
  1768. }(EventEmitter);
  1769. var i18next$1 = new I18n();
  1770. return i18next$1;
  1771. })));