import _objectSpread from "@babel/runtime/helpers/objectSpread"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _inherits from "@babel/runtime/helpers/inherits"; import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized"; import * as utils from './utils.js'; import baseLogger from './logger.js'; import EventEmitter from './EventEmitter.js'; function remove(arr, what) { var found = arr.indexOf(what); while (found !== -1) { arr.splice(found, 1); found = arr.indexOf(what); } } var Connector = /*#__PURE__*/ function (_EventEmitter) { _inherits(Connector, _EventEmitter); function Connector(backend, store, services) { var _this; var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; _classCallCheck(this, Connector); _this = _possibleConstructorReturn(this, _getPrototypeOf(Connector).call(this)); EventEmitter.call(_assertThisInitialized(_assertThisInitialized(_this))); // <=IE10 fix (unable to call parent constructor) _this.backend = backend; _this.store = store; _this.languageUtils = services.languageUtils; _this.options = options; _this.logger = baseLogger.create('backendConnector'); _this.state = {}; _this.queue = []; if (_this.backend && _this.backend.init) { _this.backend.init(services, options.backend, options); } return _this; } _createClass(Connector, [{ key: "queueLoad", value: function queueLoad(languages, namespaces, options, callback) { var _this2 = this; // find what needs to be loaded var toLoad = []; var pending = []; var toLoadLanguages = []; var toLoadNamespaces = []; languages.forEach(function (lng) { var hasAllNamespaces = true; namespaces.forEach(function (ns) { var name = "".concat(lng, "|").concat(ns); if (!options.reload && _this2.store.hasResourceBundle(lng, ns)) { _this2.state[name] = 2; // loaded } else if (_this2.state[name] < 0) {// nothing to do for err } else if (_this2.state[name] === 1) { if (pending.indexOf(name) < 0) pending.push(name); } else { _this2.state[name] = 1; // pending hasAllNamespaces = false; if (pending.indexOf(name) < 0) pending.push(name); if (toLoad.indexOf(name) < 0) toLoad.push(name); if (toLoadNamespaces.indexOf(ns) < 0) toLoadNamespaces.push(ns); } }); if (!hasAllNamespaces) toLoadLanguages.push(lng); }); if (toLoad.length || pending.length) { this.queue.push({ pending: pending, loaded: {}, errors: [], callback: callback }); } return { toLoad: toLoad, pending: pending, toLoadLanguages: toLoadLanguages, toLoadNamespaces: toLoadNamespaces }; } }, { key: "loaded", value: function loaded(name, err, data) { var _name$split = name.split('|'), _name$split2 = _slicedToArray(_name$split, 2), lng = _name$split2[0], ns = _name$split2[1]; if (err) this.emit('failedLoading', lng, ns, err); if (data) { this.store.addResourceBundle(lng, ns, data); } // set loaded this.state[name] = err ? -1 : 2; // consolidated loading done in this run - only emit once for a loaded namespace var loaded = {}; // callback if ready this.queue.forEach(function (q) { utils.pushPath(q.loaded, [lng], ns); remove(q.pending, name); if (err) q.errors.push(err); if (q.pending.length === 0 && !q.done) { // only do once per loaded -> this.emit('loaded', q.loaded); Object.keys(q.loaded).forEach(function (l) { if (!loaded[l]) loaded[l] = []; if (q.loaded[l].length) { q.loaded[l].forEach(function (ns) { if (loaded[l].indexOf(ns) < 0) loaded[l].push(ns); }); } }); /* eslint no-param-reassign: 0 */ q.done = true; if (q.errors.length) { q.callback(q.errors); } else { q.callback(); } } }); // emit consolidated loaded event this.emit('loaded', loaded); // remove done load requests this.queue = this.queue.filter(function (q) { return !q.done; }); } }, { key: "read", value: function read(lng, ns, fcName) { var _this3 = this; var tried = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; var wait = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 250; var callback = arguments.length > 5 ? arguments[5] : undefined; if (!lng.length) return callback(null, {}); // noting to load return this.backend[fcName](lng, ns, function (err, data) { if (err && data /* = retryFlag */ && tried < 5) { setTimeout(function () { _this3.read.call(_this3, lng, ns, fcName, tried + 1, wait * 2, callback); }, wait); return; } callback(err, data); }); } /* eslint consistent-return: 0 */ }, { key: "prepareLoading", value: function prepareLoading(languages, namespaces) { var _this4 = this; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var callback = arguments.length > 3 ? arguments[3] : undefined; if (!this.backend) { this.logger.warn('No backend was added via i18next.use. Will not load resources.'); return callback && callback(); } if (typeof languages === 'string') languages = this.languageUtils.toResolveHierarchy(languages); if (typeof namespaces === 'string') namespaces = [namespaces]; var toLoad = this.queueLoad(languages, namespaces, options, callback); if (!toLoad.toLoad.length) { if (!toLoad.pending.length) callback(); // nothing to load and no pendings...callback now return null; // pendings will trigger callback } toLoad.toLoad.forEach(function (name) { _this4.loadOne(name); }); } }, { key: "load", value: function load(languages, namespaces, callback) { this.prepareLoading(languages, namespaces, {}, callback); } }, { key: "reload", value: function reload(languages, namespaces, callback) { this.prepareLoading(languages, namespaces, { reload: true }, callback); } }, { key: "loadOne", value: function loadOne(name) { var _this5 = this; var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var _name$split3 = name.split('|'), _name$split4 = _slicedToArray(_name$split3, 2), lng = _name$split4[0], ns = _name$split4[1]; this.read(lng, ns, 'read', null, null, function (err, data) { if (err) _this5.logger.warn("".concat(prefix, "loading namespace ").concat(ns, " for language ").concat(lng, " failed"), err); if (!err && data) _this5.logger.log("".concat(prefix, "loaded namespace ").concat(ns, " for language ").concat(lng), data); _this5.loaded(name, err, data); }); } }, { key: "saveMissing", value: function saveMissing(languages, namespace, key, fallbackValue, isUpdate) { var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; if (this.backend && this.backend.create) { this.backend.create(languages, namespace, key, fallbackValue, null /* unused callback */ , _objectSpread({}, options, { isUpdate: isUpdate })); } // write to store to avoid resending if (!languages || !languages[0]) return; this.store.addResource(languages[0], namespace, key, fallbackValue); } }]); return Connector; }(EventEmitter); export default Connector;