diff --git a/packages/kolibri-build/src/webpack.config.base.js b/packages/kolibri-build/src/webpack.config.base.js index e6e4ca82051..d50ceaf43b3 100644 --- a/packages/kolibri-build/src/webpack.config.base.js +++ b/packages/kolibri-build/src/webpack.config.base.js @@ -110,8 +110,7 @@ module.exports = ({ mode = 'development', hot = false, cache = false, transpile new TerserPlugin({ parallel: true, terserOptions: { - mangle: false, - safari10: true, + // Don't specify mangle, as it is true by default. output: { comments: false, }, diff --git a/packages/kolibri-i18n/src/intl_code_gen.js b/packages/kolibri-i18n/src/intl_code_gen.js index 7b4f0586bfc..a61ddaa7798 100644 --- a/packages/kolibri-i18n/src/intl_code_gen.js +++ b/packages/kolibri-i18n/src/intl_code_gen.js @@ -2,6 +2,7 @@ const path = require('path'); const fs = require('fs'); const { writeSourceToFile } = require('kolibri-format'); const logger = require('kolibri-logging'); +const uniqBy = require('lodash/uniqBy'); const logging = logger.getLogger('Kolibri Intl Data'); @@ -49,13 +50,15 @@ module.exports = function (outputDir, languageInfoPath) { * Polyfill files are copied to ./polyfills/ directory to avoid external dependencies. */ `; - const vueIntlHeader = `module.exports = function () { - const data = [];`; + const vueIntlHeader = `module.exports = function (locale) { + switch (locale) {`; function generateVueIntlItems(language) { /* - * Generate entries of this form: - * data.push(require('vue-intl/locale-data/ar.js')); + * Generate entries of this form with lazy loading: + * + * case 'ar': + * return import('vue-intl/locale-data/ar.js'); * * Some Intl codes look like 'ar' and others look like 'bn-bd', so for Vue Intl * we strip off the territory code if it's there. @@ -88,17 +91,26 @@ module.exports = function (outputDir, languageInfoPath) { } } - return `data.push(require('${module_path}'));`; + return ` + case '${vue_intl_code}': + return import('${module_path}');`; } } const vueIntlFooter = ` - return data; + default: + return import('vue-intl/locale-data/en.js'); + } }; `; const vueIntlModule = - commonHeader + vueIntlHeader + languageInfo.map(generateVueIntlItems).join('') + vueIntlFooter; + commonHeader + + vueIntlHeader + + uniqBy(languageInfo, l => l.intl_code.split('-')[0]) + .map(generateVueIntlItems) + .join('') + + vueIntlFooter; const vueIntlModulePath = path.resolve(outputDir, 'vue-intl-locale-data.js'); const intlHeader = `module.exports = function(locale) { @@ -109,14 +121,7 @@ module.exports = function (outputDir, languageInfoPath) { * Generate entries of the form: * * case 'sw-tz': - * return new Promise(function(resolve) { - * require.ensure( - * ['intl/locale-data/jsonp/sw-TZ.js'], - * function(require) { - * resolve(() => require('intl/locale-data/jsonp/sw-TZ.js')); - * } - * ); - * }); + * return import('intl/locale-data/jsonp/sw-TZ.js'); * * Note that not all codes have two parts, e.g. 'en' vs 'es-mx'. */ @@ -174,27 +179,13 @@ module.exports = function (outputDir, languageInfoPath) { return ` case '${language.intl_code}': - return new Promise(function(resolve) { - require.ensure( - ['${module_path}'], - function(require) { - resolve(() => require('${module_path}')); - } - ); - });`; + return import('${module_path}');`; } } const intlFooter = ` default: - return new Promise(function(resolve) { - require.ensure( - ['intl/locale-data/jsonp/en.js'], - function(require) { - resolve(() => require('intl/locale-data/jsonp/en.js')); - } - ); - }); + return import('intl/locale-data/jsonp/en.js'); } }; `; diff --git a/packages/kolibri-jest-config/jest.conf/setup.js b/packages/kolibri-jest-config/jest.conf/setup.js index 99bfd41ec82..6d5729e2cd5 100644 --- a/packages/kolibri-jest-config/jest.conf/setup.js +++ b/packages/kolibri-jest-config/jest.conf/setup.js @@ -56,8 +56,6 @@ Vue.config.silent = true; Vue.config.devtools = false; Vue.config.productionTip = false; -i18nSetup(true); - Object.defineProperty(window, 'scrollTo', { value: () => {}, writable: true }); // Shows better NodeJS unhandled promise rejection errors @@ -76,3 +74,7 @@ global.flushPromises = function flushPromises() { }); }; /* eslint-enable vue/one-component-per-file */ + +module.exports = async function () { + await i18nSetup(true); +}; diff --git a/packages/kolibri-sandbox/babel.config.js b/packages/kolibri-sandbox/babel.config.js index 89fe708ead3..67770a9bb6c 100644 --- a/packages/kolibri-sandbox/babel.config.js +++ b/packages/kolibri-sandbox/babel.config.js @@ -3,7 +3,8 @@ module.exports = { [ '@babel/preset-env', { - useBuiltIns: false, + useBuiltIns: 'usage', + corejs: '3.46', }, ], ], diff --git a/packages/kolibri-sandbox/package.json b/packages/kolibri-sandbox/package.json index 42cee2cda71..aee03aa4375 100644 --- a/packages/kolibri-sandbox/package.json +++ b/packages/kolibri-sandbox/package.json @@ -13,12 +13,18 @@ "author": "Learning Equality", "license": "MIT", "devDependencies": { + "babel-loader": "^10.0.0", + "css-loader": "7.1.2", + "css-minimizer-webpack-plugin": "7.0.2", "eslint-plugin-compat": "^6.0.2", "html-webpack-plugin": "5.6.5", "jquery": "3.5.1", "jszip": "^3.10.1", + "mini-css-extract-plugin": "^2.9.4", "mutationobserver-shim": "^0.3.7", - "purgecss": "^6.0.0" + "purgecss": "^6.0.0", + "terser-webpack-plugin": "^5.3.14", + "webpack": "^5.103.0" }, "dependencies": { "core-js": "3.47", @@ -26,6 +32,7 @@ "iri": "^1.3.1", "is-language-code": "^3.1.0", "iso8601-duration": "^2.1.3", + "lodash": "^4.17.21", "toposort-class": "^1.0.1", "uuid": "^13.0.0" }, diff --git a/packages/kolibri-sandbox/src/iframe.js b/packages/kolibri-sandbox/src/iframe.js index 72961d6708b..b2c4b2895a6 100644 --- a/packages/kolibri-sandbox/src/iframe.js +++ b/packages/kolibri-sandbox/src/iframe.js @@ -1,10 +1,3 @@ -import 'core-js/es/array/includes'; -import 'core-js/es/object/assign'; -import 'core-js/es/object/entries'; -import 'core-js/es/object/values'; -import 'core-js/es/promise'; -import 'core-js/es/string/starts-with'; -import 'core-js/web/url'; import Sandbox from './iframeClient'; const sandbox = new Sandbox(); diff --git a/packages/kolibri-sandbox/src/xAPI/xAPIConstants.js b/packages/kolibri-sandbox/src/xAPI/xAPIConstants.js index 1900d988837..070dbc2faa5 100644 --- a/packages/kolibri-sandbox/src/xAPI/xAPIConstants.js +++ b/packages/kolibri-sandbox/src/xAPI/xAPIConstants.js @@ -2,8 +2,6 @@ * xAPI Constants */ -import 'core-js/features/set'; - export const OBJECT_TYPES = { AGENT: 'Agent', GROUP: 'Group', diff --git a/packages/kolibri-sandbox/src/xAPI/xAPISchema.js b/packages/kolibri-sandbox/src/xAPI/xAPISchema.js index 51e904545f3..e1fd46e7fe6 100644 --- a/packages/kolibri-sandbox/src/xAPI/xAPISchema.js +++ b/packages/kolibri-sandbox/src/xAPI/xAPISchema.js @@ -4,7 +4,6 @@ * For more information, see: * https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md */ -import 'core-js/features/set'; import isArray from 'lodash/isArray'; import isBoolean from 'lodash/isBoolean'; import isFunction from 'lodash/isFunction'; diff --git a/packages/kolibri-sandbox/webpack.config.js b/packages/kolibri-sandbox/webpack.config.js index f713b40e49f..5c8a2c2eaa7 100644 --- a/packages/kolibri-sandbox/webpack.config.js +++ b/packages/kolibri-sandbox/webpack.config.js @@ -1,5 +1,7 @@ const path = require('path'); const fs = require('fs'); +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); function Plugin() {} @@ -30,16 +32,25 @@ module.exports = { entry: path.resolve(__dirname, './src/iframe.js'), output: { filename: 'sandbox-[contenthash].js', - chunkFilename: '[name]-[contenthash].bundle.js', + chunkFilename: 'sandbox-[name]-[contenthash].bundle.js', path: path.resolve(__dirname, '../../kolibri/core/content/static/sandbox'), }, - mode: 'none', + mode: 'production', module: { rules: [ { - test: /\.js$/, + test: /\.(js|mjs)$/, loader: 'babel-loader', - exclude: { and: [/(uuid|core-js)/, { not: [/\.(esm\.js|mjs)$/] }] }, + exclude: [ + // From: https://webpack.js.org/loaders/babel-loader/#exclude-libraries-that-should-not-be-transpiled + // \\ for Windows, / for macOS and Linux + /node_modules[\\/]core-js/, + /node_modules[\\/]webpack[\\/]buildin/, + ], + options: { + // Let babel auto-detect ES vs CommonJS + sourceType: 'unambiguous', + }, }, ], }, @@ -47,6 +58,25 @@ module.exports = { splitChunks: { minChunks: 2, }, + minimizer: [ + new TerserPlugin({ + parallel: true, + terserOptions: { + mangle: { + safari10: true, + }, + safari10: true, + output: { + comments: false, + }, + }, + }), + new CssMinimizerPlugin({ + minimizerOptions: { + preset: ['default', { reduceIdents: false, zindex: false }], + }, + }), + ], }, plugins: [ new Plugin(), diff --git a/packages/kolibri/composables/__tests__/useNav.spec.js b/packages/kolibri/composables/__tests__/useNav.spec.js index 609b9c795ce..e93874159cd 100644 --- a/packages/kolibri/composables/__tests__/useNav.spec.js +++ b/packages/kolibri/composables/__tests__/useNav.spec.js @@ -4,12 +4,12 @@ import { navItems, registerNavItem } from '../useNav'; describe('nav component', () => { afterEach(() => { // Clean up the registered navItems - navItems.pop(); + navItems.value = []; }); it('should not register a navItem that has no nav navItem specific properties defined', () => { const navItem = {}; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); it('should register a navItem that has a valid icon', () => { const navItem = { @@ -17,7 +17,7 @@ describe('nav component', () => { url: 'https://example.com', }; registerNavItem(navItem); - expect(navItems).toHaveLength(1); + expect(navItems.value).toHaveLength(1); }); it('should show not register a navItem that has an invalid icon', () => { const navItem = { @@ -25,7 +25,7 @@ describe('nav component', () => { url: 'https://example.com', }; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); it('should not register a navItem that has a non-string icon', () => { const navItem = { @@ -33,7 +33,7 @@ describe('nav component', () => { icon: 0.1, }; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); it('should register a navItem that has a valid url', () => { const navItem = { @@ -41,14 +41,14 @@ describe('nav component', () => { url: 'https://example.com', }; registerNavItem(navItem); - expect(navItems).toHaveLength(1); + expect(navItems.value).toHaveLength(1); }); it('should not register a navItem that has no url', () => { const navItem = { icon: 'search', }; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); it('should not register a navItem that has a non-string url', () => { const navItem = { @@ -56,7 +56,7 @@ describe('nav component', () => { url: 0.1, }; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); Object.values(UserKinds).forEach(role => { it(`should register a navItem that has a role of ${role}`, () => { @@ -69,7 +69,7 @@ describe('nav component', () => { role, }; registerNavItem(navItem); - expect(navItems).toHaveLength(1); + expect(navItems.value).toHaveLength(1); }); }); it('should not register a navItem that has an unrecognized role', () => { @@ -79,7 +79,7 @@ describe('nav component', () => { role: 'bill', }; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); Object.values(NavComponentSections).forEach(section => { it(`should register a navItem that has a section of ${section}`, () => { @@ -92,7 +92,7 @@ describe('nav component', () => { section, }; registerNavItem(navItem); - expect(navItems).toHaveLength(1); + expect(navItems.value).toHaveLength(1); }); }); it('should not register a navItem that has an unrecognized section', () => { @@ -102,6 +102,6 @@ describe('nav component', () => { section: 'bill', }; registerNavItem(navItem); - expect(navItems).toHaveLength(0); + expect(navItems.value).toHaveLength(0); }); }); diff --git a/packages/kolibri/composables/useNav.js b/packages/kolibri/composables/useNav.js index 63a7e650397..0c5ddfef05a 100644 --- a/packages/kolibri/composables/useNav.js +++ b/packages/kolibri/composables/useNav.js @@ -1,14 +1,16 @@ +import { ref, watch, computed, getCurrentInstance } from 'vue'; import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow'; import { KolibriIcons } from 'kolibri-design-system/lib/KIcon/iconDefinitions'; +import { i18nReady } from 'kolibri/utils/i18n'; import { get } from '@vueuse/core'; import { UserKinds, NavComponentSections } from 'kolibri/constants'; import logger from 'kolibri-logging'; -import { computed, getCurrentInstance } from 'vue'; import { generateNavRoute } from './internal/generateNavRoutes'; const logging = logger.getLogger(__filename); -export const navItems = []; +export const navItems = ref([]); +const _tempNavItems = []; function checkDeclared(property) { return typeof property !== 'undefined' && property !== null; @@ -65,9 +67,13 @@ function validateNavItem(component) { } export const registerNavItem = component => { - if (!navItems.includes(component)) { + if (!i18nReady.value) { + _tempNavItems.push(component); + return; + } + if (!navItems.value.includes(component)) { if (validateNavItem(component)) { - navItems.push(component); + navItems.value = [...navItems.value, component]; } else { logging.error('Component has invalid url, icon, role, section, or routes'); } @@ -76,13 +82,23 @@ export const registerNavItem = component => { } }; +const _watcher = watch(i18nReady, newValue => { + if (newValue) { + for (const component of _tempNavItems) { + registerNavItem(component); + } + _tempNavItems.length = 0; + _watcher(); + } +}); + export default function useNav(store) { store = store || getCurrentInstance().proxy.$store; const route = computed(() => store.state.route); const { windowIsSmall } = useKResponsiveWindow(); const topBarHeight = computed(() => (get(windowIsSmall) ? 56 : 64)); const exportedItems = computed(() => - navItems.map(item => { + navItems.value.map(item => { const output = { ...item, active: window.location.pathname == item.url, diff --git a/packages/kolibri/composables/useUser.js b/packages/kolibri/composables/useUser.js index e22b53e96e6..e4e1641e986 100644 --- a/packages/kolibri/composables/useUser.js +++ b/packages/kolibri/composables/useUser.js @@ -8,7 +8,7 @@ import Lockr from 'lockr'; import urls from 'kolibri/urls'; import store from 'kolibri/store'; import { LoginErrors, ERROR_CONSTANTS, UPDATE_MODAL_DISMISSED, UserKinds } from 'kolibri/constants'; -import { pick } from 'lodash'; +import pick from 'lodash/pick'; // Base session state (migrated from session module) const baseSessionState = { diff --git a/packages/kolibri/utils/i18n.js b/packages/kolibri/utils/i18n.js index 769cb5f368c..68bdad76487 100644 --- a/packages/kolibri/utils/i18n.js +++ b/packages/kolibri/utils/i18n.js @@ -1,5 +1,5 @@ import has from 'lodash/has'; -import Vue from 'vue'; +import Vue, { ref } from 'vue'; import logger from 'kolibri-logging'; import plugin_data from 'kolibri-plugin-data'; import importIntlLocale from './internal/intl-locale-data'; @@ -50,10 +50,10 @@ const logging = logger.getLogger(__filename); const languageGlobals = plugin_data['languageGlobals'] || {}; -let _i18nReady = false; +export const i18nReady = ref(false); function $trWrapper(nameSpace, defaultMessages, formatter, messageId, args) { - if (!_i18nReady) { + if (!i18nReady.value) { throw 'Translator used before i18n is ready'; } if (args) { @@ -208,7 +208,7 @@ export function crossComponentTranslator(Component) { return new Translator(Component.name, Component.$trs); } -function _setUpVueIntl() { +async function _setUpVueIntl() { /** * Use the vue-intl plugin. * @@ -228,12 +228,18 @@ function _setUpVueIntl() { if (languageGlobals.coreLanguageMessages) { Vue.registerMessages(currentLanguage, languageGlobals.coreLanguageMessages); } - importVueIntlLocaleData().forEach(localeData => VueIntl.addLocaleData(localeData)); - _i18nReady = true; + // Load vue-intl locale data asynchronously for current language + // Extract just the language code (e.g., 'en' from 'en-us') for vue-intl + const vueIntlLanguageCode = currentLanguage.split('-')[0]; + const module = await importVueIntlLocaleData(vueIntlLanguageCode); + // import() returns the module directly + const localeData = module.default || module; + VueIntl.addLocaleData(localeData); + i18nReady.value = true; } -export function i18nSetup(skipPolyfill = false) { +export async function i18nSetup(skipPolyfill = false) { /** * Load fonts, app strings, and Intl polyfills **/ @@ -244,38 +250,19 @@ export function i18nSetup(skipPolyfill = false) { // If the browser doesn't support the Intl polyfill, we retrieve that and // the modules need to wait until that happens. - return new Promise((resolve, reject) => { - if (Object.prototype.hasOwnProperty.call(global, 'Intl') || skipPolyfill) { - _setUpVueIntl(); - resolve(); - } else { - Promise.all([ - new Promise(res => { - require.ensure( - ['intl'], - require => { - res(() => require('intl')); - }, - 'intl', - ); - }), - importIntlLocale(currentLanguage), - ]).then( - // eslint-disable-line - ([requireIntl, requireIntlLocaleData]) => { - requireIntl(); // requireIntl must run before requireIntlLocaleData - requireIntlLocaleData(); - _setUpVueIntl(); - resolve(); - }, - error => { - logging.error(error); - logging.error('An error occurred trying to setup Internationalization', error); - reject(); - }, - ); + if (Object.prototype.hasOwnProperty.call(global, 'Intl') || skipPolyfill) { + await _setUpVueIntl(); + } else { + try { + await Promise.all([import('intl'), importIntlLocale(currentLanguage)]); + + await _setUpVueIntl(); + } catch (error) { + logging.error(error); + logging.error('An error occurred trying to setup Internationalization', error); + throw error; } - }); + } } export function localeCompare(str1, str2) { diff --git a/packages/kolibri/utils/internal/intl-locale-data.js b/packages/kolibri/utils/internal/intl-locale-data.js index 007d736e08b..5042c4ff5f4 100644 --- a/packages/kolibri/utils/internal/intl-locale-data.js +++ b/packages/kolibri/utils/internal/intl-locale-data.js @@ -11,208 +11,72 @@ module.exports = function (locale) { switch (locale) { case 'ar': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/ar.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/ar.js')); - }); - }); + return import('intl/locale-data/jsonp/ar.js'); case 'bg-bg': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/bg-BG.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/bg-BG.js')); - }); - }); + return import('intl/locale-data/jsonp/bg-BG.js'); case 'bn-bd': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/bn-BD.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/bn-BD.js')); - }); - }); + return import('intl/locale-data/jsonp/bn-BD.js'); case 'de': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/de.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/de.js')); - }); - }); + return import('intl/locale-data/jsonp/de.js'); case 'el': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/el.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/el.js')); - }); - }); + return import('intl/locale-data/jsonp/el.js'); case 'en': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/en.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/en.js')); - }); - }); + return import('intl/locale-data/jsonp/en.js'); case 'es-es': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/es-ES.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/es-ES.js')); - }); - }); + return import('intl/locale-data/jsonp/es-ES.js'); case 'es-419': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/es-419.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/es-419.js')); - }); - }); + return import('intl/locale-data/jsonp/es-419.js'); case 'fa': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/fa.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/fa.js')); - }); - }); + return import('intl/locale-data/jsonp/fa.js'); case 'fr-fr': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/fr-FR.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/fr-FR.js')); - }); - }); + return import('intl/locale-data/jsonp/fr-FR.js'); case 'ff-cm': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/ff-CM.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/ff-CM.js')); - }); - }); + return import('intl/locale-data/jsonp/ff-CM.js'); case 'gu-in': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/gu-IN.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/gu-IN.js')); - }); - }); + return import('intl/locale-data/jsonp/gu-IN.js'); case 'ha': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/ha.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/ha.js')); - }); - }); + return import('intl/locale-data/jsonp/ha.js'); case 'hi-in': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/hi-IN.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/hi-IN.js')); - }); - }); + return import('intl/locale-data/jsonp/hi-IN.js'); case 'ht': - return new Promise(function (resolve) { - require.ensure(['./polyfills/intl/ht.js'], function (require) { - resolve(() => require('./polyfills/intl/ht.js')); - }); - }); + return import('./polyfills/intl/ht.js'); case 'id': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/id.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/id.js')); - }); - }); + return import('intl/locale-data/jsonp/id.js'); case 'it': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/it.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/it.js')); - }); - }); + return import('intl/locale-data/jsonp/it.js'); case 'ka': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/ka.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/ka.js')); - }); - }); + return import('intl/locale-data/jsonp/ka.js'); case 'km': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/km.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/km.js')); - }); - }); + return import('intl/locale-data/jsonp/km.js'); case 'ko': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/ko.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/ko.js')); - }); - }); + return import('intl/locale-data/jsonp/ko.js'); case 'mr': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/mr.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/mr.js')); - }); - }); + return import('intl/locale-data/jsonp/mr.js'); case 'my': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/my.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/my.js')); - }); - }); + return import('intl/locale-data/jsonp/my.js'); case 'ny': - return new Promise(function (resolve) { - require.ensure(['./polyfills/intl/ny.js'], function (require) { - resolve(() => require('./polyfills/intl/ny.js')); - }); - }); + return import('./polyfills/intl/ny.js'); case 'pa': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/pa.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/pa.js')); - }); - }); + return import('intl/locale-data/jsonp/pa.js'); case 'pt-br': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/pt-BR.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/pt-BR.js')); - }); - }); + return import('intl/locale-data/jsonp/pt-BR.js'); case 'pt-mz': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/pt-MZ.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/pt-MZ.js')); - }); - }); + return import('intl/locale-data/jsonp/pt-MZ.js'); case 'sw-tz': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/sw-TZ.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/sw-TZ.js')); - }); - }); + return import('intl/locale-data/jsonp/sw-TZ.js'); case 'te': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/te.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/te.js')); - }); - }); + return import('intl/locale-data/jsonp/te.js'); case 'uk': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/uk.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/uk.js')); - }); - }); + return import('intl/locale-data/jsonp/uk.js'); case 'ur-pk': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/ur-PK.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/ur-PK.js')); - }); - }); + return import('intl/locale-data/jsonp/ur-PK.js'); case 'vi': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/vi.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/vi.js')); - }); - }); + return import('intl/locale-data/jsonp/vi.js'); case 'yo': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/yo.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/yo.js')); - }); - }); + return import('intl/locale-data/jsonp/yo.js'); case 'zh-hans': - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/zh-Hans.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/zh-Hans.js')); - }); - }); + return import('intl/locale-data/jsonp/zh-Hans.js'); default: - return new Promise(function (resolve) { - require.ensure(['intl/locale-data/jsonp/en.js'], function (require) { - resolve(() => require('intl/locale-data/jsonp/en.js')); - }); - }); + return import('intl/locale-data/jsonp/en.js'); } }; diff --git a/packages/kolibri/utils/internal/vue-intl-locale-data.js b/packages/kolibri/utils/internal/vue-intl-locale-data.js index 24417bee1e0..9fea2a70441 100644 --- a/packages/kolibri/utils/internal/vue-intl-locale-data.js +++ b/packages/kolibri/utils/internal/vue-intl-locale-data.js @@ -8,40 +8,71 @@ * * Polyfill files are copied to ./polyfills/ directory to avoid external dependencies. */ -module.exports = function () { - const data = []; - data.push(require('vue-intl/locale-data/ar.js')); - data.push(require('vue-intl/locale-data/bg.js')); - data.push(require('vue-intl/locale-data/bn.js')); - data.push(require('vue-intl/locale-data/de.js')); - data.push(require('vue-intl/locale-data/el.js')); - data.push(require('vue-intl/locale-data/en.js')); - data.push(require('vue-intl/locale-data/es.js')); - data.push(require('vue-intl/locale-data/es.js')); - data.push(require('vue-intl/locale-data/fa.js')); - data.push(require('vue-intl/locale-data/fr.js')); - data.push(require('vue-intl/locale-data/ff.js')); - data.push(require('vue-intl/locale-data/gu.js')); - data.push(require('vue-intl/locale-data/ha.js')); - data.push(require('vue-intl/locale-data/hi.js')); - data.push(require('./polyfills/vue-intl/ht.js')); - data.push(require('vue-intl/locale-data/id.js')); - data.push(require('vue-intl/locale-data/it.js')); - data.push(require('vue-intl/locale-data/ka.js')); - data.push(require('vue-intl/locale-data/km.js')); - data.push(require('vue-intl/locale-data/ko.js')); - data.push(require('vue-intl/locale-data/mr.js')); - data.push(require('vue-intl/locale-data/my.js')); - data.push(require('vue-intl/locale-data/ny.js')); - data.push(require('vue-intl/locale-data/pa.js')); - data.push(require('vue-intl/locale-data/pt.js')); - data.push(require('vue-intl/locale-data/pt.js')); - data.push(require('vue-intl/locale-data/sw.js')); - data.push(require('vue-intl/locale-data/te.js')); - data.push(require('vue-intl/locale-data/uk.js')); - data.push(require('vue-intl/locale-data/ur.js')); - data.push(require('vue-intl/locale-data/vi.js')); - data.push(require('vue-intl/locale-data/yo.js')); - data.push(require('vue-intl/locale-data/zh.js')); - return data; +module.exports = function (locale) { + switch (locale) { + case 'ar': + return import('vue-intl/locale-data/ar.js'); + case 'bg': + return import('vue-intl/locale-data/bg.js'); + case 'bn': + return import('vue-intl/locale-data/bn.js'); + case 'de': + return import('vue-intl/locale-data/de.js'); + case 'el': + return import('vue-intl/locale-data/el.js'); + case 'en': + return import('vue-intl/locale-data/en.js'); + case 'es': + return import('vue-intl/locale-data/es.js'); + case 'fa': + return import('vue-intl/locale-data/fa.js'); + case 'fr': + return import('vue-intl/locale-data/fr.js'); + case 'ff': + return import('vue-intl/locale-data/ff.js'); + case 'gu': + return import('vue-intl/locale-data/gu.js'); + case 'ha': + return import('vue-intl/locale-data/ha.js'); + case 'hi': + return import('vue-intl/locale-data/hi.js'); + case 'ht': + return import('./polyfills/vue-intl/ht.js'); + case 'id': + return import('vue-intl/locale-data/id.js'); + case 'it': + return import('vue-intl/locale-data/it.js'); + case 'ka': + return import('vue-intl/locale-data/ka.js'); + case 'km': + return import('vue-intl/locale-data/km.js'); + case 'ko': + return import('vue-intl/locale-data/ko.js'); + case 'mr': + return import('vue-intl/locale-data/mr.js'); + case 'my': + return import('vue-intl/locale-data/my.js'); + case 'ny': + return import('vue-intl/locale-data/ny.js'); + case 'pa': + return import('vue-intl/locale-data/pa.js'); + case 'pt': + return import('vue-intl/locale-data/pt.js'); + case 'sw': + return import('vue-intl/locale-data/sw.js'); + case 'te': + return import('vue-intl/locale-data/te.js'); + case 'uk': + return import('vue-intl/locale-data/uk.js'); + case 'ur': + return import('vue-intl/locale-data/ur.js'); + case 'vi': + return import('vue-intl/locale-data/vi.js'); + case 'yo': + return import('vue-intl/locale-data/yo.js'); + case 'zh': + return import('vue-intl/locale-data/zh.js'); + default: + return import('vue-intl/locale-data/en.js'); + } };