i18next.js 67 KB

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