UNPKG

@enact/i18n

Version:

Internationalization support for Enact using iLib

218 lines (210 loc) 9.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.I18n = void 0; var _dispatcher = require("@enact/core/dispatcher"); var _util = require("@enact/core/util"); var _locale = require("../locale"); var _resBundle = require("../src/resBundle"); var _wrapIlibCallback = _interopRequireDefault(require("../src/wrapIlibCallback")); var _getI18nClasses = _interopRequireDefault(require("./getI18nClasses")); var _windowFocus = require("./windowFocus"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } function _toArray(r) { return _arrayWithHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * Manages i18n resource loading. * * @class I18n * @private */ var I18n = exports.I18n = /*#__PURE__*/function () { function I18n(_ref) { var _this = this; var latinLanguageOverrides = _ref.latinLanguageOverrides, nonLatinLanguageOverrides = _ref.nonLatinLanguageOverrides, resources = _ref.resources, _ref$sync = _ref.sync, sync = _ref$sync === void 0 ? true : _ref$sync; _classCallCheck(this, I18n); /** * Called when the `languagechange` event fires. */ this.handleLocaleChange = function () { (0, _windowFocus.onWindowFocus)(_this.updateLocale); }; /** * Updates the locale for the application. * * If `newLocale` is omitted, the locale will be reset to the device's default locale. * * @param {String} newLocale Locale identifier string * * @returns {undefined} * @public */ this.updateLocale = function (newLocale) { _this.loadResources(newLocale); }; this._locale = null; this._ready = sync; this._onLoadResources = function () {}; this.loadResourceJob = null; this.latinLanguageOverrides = latinLanguageOverrides; this.nonLatinLanguageOverrides = nonLatinLanguageOverrides; this.resources = this.normalizeResources(resources); this.sync = sync; } /** * Sets the current locale and load callback. * * Changing the locale will request new resource files for that locale. * * @type {String} * @public */ return _createClass(I18n, [{ key: "setContext", value: function setContext(locale, onLoadResources) { this.loadResourceJob = new _util.Job(onLoadResources); this._onLoadResources = onLoadResources; if (this._locale !== locale) { this._locale = locale; this.loadResources(locale); } } /** * Normalize the structure of the external resources to be an array of resource/onLoad pairs. * * @private */ }, { key: "normalizeResources", value: function normalizeResources(resources) { return Array.isArray(resources) ? resources.map(function (res) { if (!res) return; var fn = res.resource || res; var onLoad = res.onLoad; if (typeof fn !== 'function') return; return { resource: fn, onLoad: onLoad }; }).filter(Boolean) : []; } /** * Adds the `languagechange` event listener and initiates async resource retrieval. * * Should only be called after `window` is available and the DOM is ready. * * @public */ }, { key: "load", value: function load() { this._ready = true; if (typeof window === 'object') { (0, _dispatcher.on)('languagechange', this.handleLocaleChange, window); } // When async, we defer loading resources until DOM is ready if (!this.sync) { this.loadResources(this._locale); } } /** * Cleans up resource retrieval and event listeners. * * @public */ }, { key: "unload", value: function unload() { this._ready = false; this.loadResourceJob.stop(); if (typeof window === 'object') { (0, _dispatcher.off)('languagechange', this.handleLocaleChange, window); } } /** * Loads the resources for the given locale. * * @private */ }, { key: "loadResources", value: function loadResources(spec) { var _this2 = this; if (!this._ready) return; var locale = (0, _locale.updateLocale)(spec); var options = { sync: this.sync, locale: locale }; var rtl = (0, _wrapIlibCallback["default"])(_locale.isRtlLocale, options); var className = (0, _wrapIlibCallback["default"])(_getI18nClasses["default"], _objectSpread(_objectSpread({}, options), {}, { latinLanguageOverrides: this.latinLanguageOverrides, nonLatinLanguageOverrides: this.nonLatinLanguageOverrides })); var bundle = (0, _wrapIlibCallback["default"])(_resBundle.createResBundle, options); if (this.sync) { var state = { className: className, loaded: true, locale: locale, rtl: rtl }; (0, _resBundle.setResBundle)(bundle); this.resources.forEach(function (_ref2) { var resource = _ref2.resource, onLoad = _ref2.onLoad; var result = resource(options); if (onLoad) onLoad(result); }); this._onLoadResources(state); } else { var resources = Promise.all([rtl, className, // move updating into a new method with call to setState bundle].concat(_toConsumableArray(this.resources.map(function (res) { return (0, _wrapIlibCallback["default"])(res.resource, options); })))).then(function (_ref3) { var _ref4 = _toArray(_ref3), rtlResult = _ref4[0], classNameResult = _ref4[1], bundleResult = _ref4[2], userResources = _arrayLikeToArray(_ref4).slice(3); (0, _resBundle.setResBundle)(bundleResult); _this2.resources.forEach(function (_ref5, i) { var onLoad = _ref5.onLoad; return onLoad && onLoad(userResources[i]); }); return { className: classNameResult, loaded: true, locale: locale, rtl: rtlResult }; }); // TODO: Resolve how to handle failed resource requests // .catch(...); this.loadResourceJob.promise(resources); } } }]); }(); var _default = exports["default"] = I18n;