UNPKG

@commercetools-frontend/i18n

Version:
755 lines (741 loc) • 25.1 kB
import { useState, useEffect, useCallback } from 'react'; import { reportErrorToSentry } from '@commercetools-frontend/sentry'; import _slicedToArray from '@babel/runtime-corejs3/helpers/esm/slicedToArray'; import _Promise from '@babel/runtime-corejs3/core-js-stable/promise'; import _includesInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/includes'; import moment from 'moment'; import _reduceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/reduce'; import _Object$entries from '@babel/runtime-corejs3/core-js-stable/object/entries'; import _Object$assign from '@babel/runtime-corejs3/core-js-stable/object/assign'; import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with'; import { jsx, Fragment } from '@emotion/react/jsx-runtime'; import { defineMessages } from 'react-intl'; // NOTE: This string will be replaced on build time with the package version. var version = "27.8.0"; /** * Registers a locale as a child of a parent locale if not already registered. * This is needed for regional locales (e.g., 'en-be') that don't have their own * moment locale file but should inherit formatting from a parent (e.g., 'en-gb'). */ function defineLocaleIfNeeded(locale, parentLocale) { var _context; if (!_includesInstanceProperty(_context = moment.locales()).call(_context, locale)) { moment.defineLocale(locale, { parentLocale }); } moment.locale(locale); } async function loadMomentLocales(locale) { const lowercaseLocale = locale.toLowerCase(); switch (lowercaseLocale) { case 'de': await import('moment/dist/locale/de'); break; case 'de-at': await import('moment/dist/locale/de-at'); break; case 'de-be': await import('moment/dist/locale/de'); await defineLocaleIfNeeded('de-be', 'de'); break; case 'de-ch': await import('moment/dist/locale/de-ch'); break; case 'de-de': await import('moment/dist/locale/de'); await defineLocaleIfNeeded('de-de', 'de'); break; case 'de-li': await import('moment/dist/locale/de'); await defineLocaleIfNeeded('de-li', 'de'); break; case 'de-lu': await import('moment/dist/locale/de'); await defineLocaleIfNeeded('de-lu', 'de'); break; case 'en-ag': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ag', 'en-gb'); break; case 'en-ai': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ai', 'en-gb'); break; case 'en-au': await import('moment/dist/locale/en-au'); break; case 'en-bb': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-bb', 'en-gb'); break; case 'en-be': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-be', 'en-gb'); break; case 'en-bi': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-bi', 'en-gb'); break; case 'en-bm': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-bm', 'en-gb'); break; case 'en-bs': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-bs', 'en-gb'); break; case 'en-bw': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-bw', 'en-gb'); break; case 'en-bz': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-bz', 'en-gb'); break; case 'en-ca': await import('moment/dist/locale/en-ca'); break; case 'en-cc': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-cc', 'en-gb'); break; case 'en-ck': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ck', 'en-gb'); break; case 'en-cm': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-cm', 'en-gb'); break; case 'en-cq': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-cq', 'en-gb'); break; case 'en-cx': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-cx', 'en-gb'); break; case 'en-dg': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-dg', 'en-gb'); break; case 'en-dm': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-dm', 'en-gb'); break; case 'en-er': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-er', 'en-gb'); break; case 'en-fj': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-fj', 'en-gb'); break; case 'en-fk': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-fk', 'en-gb'); break; case 'en-gb': await import('moment/dist/locale/en-gb'); break; case 'en-gd': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gd', 'en-gb'); break; case 'en-gg': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gg', 'en-gb'); break; case 'en-gh': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gh', 'en-gb'); break; case 'en-gi': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gi', 'en-gb'); break; case 'en-gm': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gm', 'en-gb'); break; case 'en-gs': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gs', 'en-gb'); break; case 'en-gy': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-gy', 'en-gb'); break; case 'en-hk': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-hk', 'en-gb'); break; case 'en-ie': await import('moment/dist/locale/en-ie'); break; case 'en-im': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-im', 'en-gb'); break; case 'en-in': await import('moment/dist/locale/en-in'); break; case 'en-io': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-io', 'en-gb'); break; case 'en-je': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-je', 'en-gb'); break; case 'en-jm': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-jm', 'en-gb'); break; case 'en-ke': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ke', 'en-gb'); break; case 'en-ki': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ki', 'en-gb'); break; case 'en-kn': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-kn', 'en-gb'); break; case 'en-ky': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ky', 'en-gb'); break; case 'en-lc': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-lc', 'en-gb'); break; case 'en-lr': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-lr', 'en-gb'); break; case 'en-ls': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ls', 'en-gb'); break; case 'en-mg': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-mg', 'en-gb'); break; case 'en-ms': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ms', 'en-gb'); break; case 'en-mt': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-mt', 'en-gb'); break; case 'en-mu': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-mu', 'en-gb'); break; case 'en-mw': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-mw', 'en-gb'); break; case 'en-na': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-na', 'en-gb'); break; case 'en-nf': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-nf', 'en-gb'); break; case 'en-ng': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ng', 'en-gb'); break; case 'en-nr': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-nr', 'en-gb'); break; case 'en-nu': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-nu', 'en-gb'); break; case 'en-nz': await import('moment/dist/locale/en-nz'); break; case 'en-pg': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-pg', 'en-gb'); break; case 'en-ph': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ph', 'en-gb'); break; case 'en-pk': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-pk', 'en-gb'); break; case 'en-pn': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-pn', 'en-gb'); break; case 'en-rw': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-rw', 'en-gb'); break; case 'en-sb': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sb', 'en-gb'); break; case 'en-sc': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sc', 'en-gb'); break; case 'en-sd': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sd', 'en-gb'); break; case 'en-sg': await import('moment/dist/locale/en-sg'); break; case 'en-sh': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sh', 'en-gb'); break; case 'en-sl': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sl', 'en-gb'); break; case 'en-ss': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ss', 'en-gb'); break; case 'en-sx': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sx', 'en-gb'); break; case 'en-sz': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-sz', 'en-gb'); break; case 'en-tc': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-tc', 'en-gb'); break; case 'en-tk': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-tk', 'en-gb'); break; case 'en-to': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-to', 'en-gb'); break; case 'en-tt': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-tt', 'en-gb'); break; case 'en-tv': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-tv', 'en-gb'); break; case 'en-tz': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-tz', 'en-gb'); break; case 'en-ug': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ug', 'en-gb'); break; case 'en-vc': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-vc', 'en-gb'); break; case 'en-vg': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-vg', 'en-gb'); break; case 'en-vu': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-vu', 'en-gb'); break; case 'en-ws': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-ws', 'en-gb'); break; case 'en-za': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-za', 'en-gb'); break; case 'en-zm': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-zm', 'en-gb'); break; case 'en-zw': await import('moment/dist/locale/en-gb'); await defineLocaleIfNeeded('en-zw', 'en-gb'); break; case 'es': await import('moment/dist/locale/es'); break; case 'es-ar': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-ar', 'es'); break; case 'es-bo': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-bo', 'es'); break; case 'es-cl': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-cl', 'es'); break; case 'es-co': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-co', 'es'); break; case 'es-cr': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-cr', 'es'); break; case 'es-cu': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-cu', 'es'); break; case 'es-do': await import('moment/dist/locale/es-do'); break; case 'es-ea': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-ea', 'es'); break; case 'es-ec': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-ec', 'es'); break; case 'es-es': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-es', 'es'); break; case 'es-gq': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-gq', 'es'); break; case 'es-gt': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-gt', 'es'); break; case 'es-hn': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-hn', 'es'); break; case 'es-ic': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-ic', 'es'); break; case 'es-mx': await import('moment/dist/locale/es-mx'); break; case 'es-ni': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-ni', 'es'); break; case 'es-pa': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-pa', 'es'); break; case 'es-pe': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-pe', 'es'); break; case 'es-pr': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-pr', 'es'); break; case 'es-py': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-py', 'es'); break; case 'es-sv': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-sv', 'es'); break; case 'es-uy': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-uy', 'es'); break; case 'es-ve': await import('moment/dist/locale/es'); await defineLocaleIfNeeded('es-ve', 'es'); break; case 'fr-fr': await import('moment/dist/locale/fr'); await defineLocaleIfNeeded('fr-fr', 'fr'); break; case 'pt-br': await import('moment/dist/locale/pt-br'); break; } } const extractLanguageTagFromLocale = locale => _includesInstanceProperty(locale).call(locale, '-') ? locale.split('-')[0] : locale; const isStructuredJson = message => message?.string !== undefined; const parseChunkImport = chunkImport => { var _context; // Prefer loading `default` (for ESM bundles) and // fall back to normal import (for CJS bundles). const contents = chunkImport.default || chunkImport; return _reduceInstanceProperty(_context = _Object$entries(contents)).call(_context, (messages, _ref) => { let _ref2 = _slicedToArray(_ref, 2), messageKey = _ref2[0], messageValue = _ref2[1]; const messageAsString = isStructuredJson(messageValue) ? messageValue.string : messageValue; messages[messageKey] = messageAsString; return messages; }, {}); }; const mergeMessages = function () { for (var _len = arguments.length, messages = new Array(_len), _key = 0; _key < _len; _key++) { messages[_key] = arguments[_key]; } return _Object$assign({}, ...messages); }; const mapLocaleToIntlLocale = locale => { if (_startsWithInstanceProperty(locale).call(locale, 'de')) return 'de'; if (_startsWithInstanceProperty(locale).call(locale, 'es')) return 'es'; if (_startsWithInstanceProperty(locale).call(locale, 'fr')) return 'fr-FR'; if (locale === 'pt-BR') return 'pt-BR'; return 'en'; }; const getUiKitChunkImport = locale => { const intlLocale = mapLocaleToIntlLocale(locale); switch (intlLocale) { case 'de': return import(/* webpackChunkName: "i18n-ui-kit-locale-de" */'@commercetools-uikit/i18n/compiled-data/de.json'); case 'es': return import(/* webpackChunkName: "i18n-ui-kit-locale-es" */'@commercetools-uikit/i18n/compiled-data/es.json'); case 'fr-FR': return import(/* webpackChunkName: "i18n-ui-kit-locale-fr-FR" */'@commercetools-uikit/i18n/compiled-data/fr-FR.json'); case 'pt-BR': return import(/* webpackChunkName: "i18n-ui-kit-locale-pt-BR" */'@commercetools-uikit/i18n/compiled-data/pt-BR.json'); default: return import(/* webpackChunkName: "i18n-ui-kit-locale-en" */'@commercetools-uikit/i18n/compiled-data/en.json'); } }; const getAppKitChunkImport = locale => { const intlLocale = mapLocaleToIntlLocale(locale); switch (intlLocale) { case 'de': return import(/* webpackChunkName: "i18n-app-kit-locale-de" */'./de-138824ef.esm.js'); case 'es': return import(/* webpackChunkName: "i18n-app-kit-locale-es" */'./es-4e419bcb.esm.js'); case 'fr-FR': return import(/* webpackChunkName: "i18n-app-kit-locale-fr-FR" */'./fr-FR-03b4b160.esm.js'); case 'pt-BR': return import(/* webpackChunkName: "i18n-app-kit-locale-pt-BR" */'./pt-BR-29b8e141.esm.js'); default: return import(/* webpackChunkName: "i18n-app-kit-locale-en" */'./en-ca69b165.esm.js'); } }; const getCommunityKitChunkImport = async locale => { const intlLocale = mapLocaleToIntlLocale(locale); switch (intlLocale) { case 'de': return await import(/* webpackChunkName: "i18n-community-kit-locale-de" */'@commercetools-community-kit/i18n/compiled-data/de.json'); case 'es': return await import(/* webpackChunkName: "i18n-community-kit-locale-es" */'@commercetools-community-kit/i18n/compiled-data/es.json'); case 'fr-FR': return await import(/* webpackChunkName: "i18n-community-kit-locale-fr-FR" */'@commercetools-community-kit/i18n/compiled-data/fr-FR.json'); default: return await import(/* webpackChunkName: "i18n-community-kit-locale-en" */'@commercetools-community-kit/i18n/compiled-data/en.json'); } }; // Use default (lazy) so that we will receive one chunk per // locale. https://webpack.js.org/api/module-methods/#import- async function loadI18n(locale) { const _await$Promise$all = await _Promise.all([ // Load moment localizations loadMomentLocales(locale), // Load ui-kit translations getUiKitChunkImport(locale), // Load app-kit translations getAppKitChunkImport(locale), // Load community-kit translations getCommunityKitChunkImport(locale)]), _await$Promise$all2 = _slicedToArray(_await$Promise$all, 4), uiKitChunkImport = _await$Promise$all2[1], appKitChunkImport = _await$Promise$all2[2], communityKitChunkImport = _await$Promise$all2[3]; // Prefer loading `default` (for ESM bundles) and // fall back to normal import (for CJS bundles). return mergeMessages(parseChunkImport(uiKitChunkImport), parseChunkImport(appKitChunkImport), parseChunkImport(communityKitChunkImport)); } const initialState = { isLoading: true, messages: undefined, error: undefined }; // Low level hook to load messages for a specific locale. The loading is async // because it's assumed that the translation files are dynamically imported (code splitted). const useAsyncIntlMessages = _ref => { let locale = _ref.locale, loader = _ref.loader; const _useState = useState(initialState), _useState2 = _slicedToArray(_useState, 2), state = _useState2[0], setState = _useState2[1]; useEffect(() => { let _isUnmounting = false; async function load(_locale) { try { if (!_isUnmounting) { const messages = await loader(_locale); setState({ isLoading: false, messages }); } } catch (error) { if (error instanceof Error) { setState({ isLoading: false, error }); } } } if (locale) load(locale); return () => { _isUnmounting = true; }; }, [locale, loader]); return state; }; const getMessagesForLocale = (data, locale) => { if (!data || !locale) return {}; if (data[locale]) return data[locale]; const fallbackLanguage = extractLanguageTagFromLocale(locale); return data[fallbackLanguage]; }; const useAsyncLocaleData = _ref => { let locale = _ref.locale, applicationMessages = _ref.applicationMessages; const loadApplicationMessages = useCallback(async locale => { if (typeof applicationMessages === 'function') { return await applicationMessages(locale); } return getMessagesForLocale(applicationMessages, locale); }, // NOTE: we assume that the `applicationMessages` argument never changes. // Therefore, we disable the dependency array to not depend on that argument. // This is important, to avoid potential infinite loops. // eslint-disable-next-line react-hooks/exhaustive-deps []); const messagesFromKitResult = useAsyncIntlMessages({ locale, loader: loadI18n }); const applicationMessagesResult = useAsyncIntlMessages({ locale, loader: loadApplicationMessages }); // Merge the loaded messages into one return { isLoading: messagesFromKitResult.isLoading || applicationMessagesResult.isLoading, messages: mergeMessages(messagesFromKitResult.messages ?? {}, applicationMessagesResult.messages ?? {}), error: messagesFromKitResult.error ?? applicationMessagesResult.error }; }; const AsyncLocaleData = props => { const _useAsyncLocaleData = useAsyncLocaleData(props), isLoading = _useAsyncLocaleData.isLoading, messages = _useAsyncLocaleData.messages, error = _useAsyncLocaleData.error; useEffect(() => { if (error) reportErrorToSentry(error, {}); }, [error]); return jsx(Fragment, { children: props.children({ isLoading, locale: isLoading ? undefined : props.locale, messages: error ? undefined : messages }) }); }; // TODO: move it to its own package, so that other people can also use it? // Selection of shared messages, to avoid duplicating translations. // Avoid changing the message id, otherwise you need to translate them again in Transifex. const messages = defineMessages({ cancel: { id: 'AppKit.Shared.cancel', defaultMessage: 'Cancel' }, revert: { id: 'AppKit.Shared.revert', defaultMessage: 'Revert' }, confirm: { id: 'AppKit.Shared.confirm', defaultMessage: 'Confirm' }, save: { id: 'AppKit.Shared.save', defaultMessage: 'Save' }, update: { id: 'AppKit.Shared.update', defaultMessage: 'Update' }, create: { id: 'AppKit.Shared.create', defaultMessage: 'Create' }, delete: { id: 'AppKit.Shared.delete', defaultMessage: 'Delete' }, add: { id: 'AppKit.Shared.add', defaultMessage: 'Add' }, remove: { id: 'AppKit.Shared.remove', defaultMessage: 'Remove' }, close: { id: 'AppKit.Shared.close', defaultMessage: 'Close' }, edit: { id: 'AppKit.Shared.edit', defaultMessage: 'Edit' }, open: { id: 'AppKit.Shared.open', defaultMessage: 'Open' }, activate: { id: 'AppKit.Shared.activate', defaultMessage: 'Activate' }, deactivate: { id: 'AppKit.Shared.deactivate', defaultMessage: 'Deactivate' }, active: { id: 'AppKit.Shared.active', defaultMessage: 'Active' }, inactive: { id: 'AppKit.Shared.inactive', defaultMessage: 'Inactive' }, enable: { id: 'AppKit.Shared.enable', defaultMessage: 'Enable' }, disable: { id: 'AppKit.Shared.disable', defaultMessage: 'Disable' } }); export { AsyncLocaleData, isStructuredJson, mapLocaleToIntlLocale, mergeMessages, parseChunkImport, messages as sharedMessages, useAsyncIntlMessages, useAsyncLocaleData, version };