i18next.js 65 KB

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