UNPKG

passbolt-styleguide

Version:

Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.

178 lines (161 loc) 5.1 kB
/** * Passbolt ~ Open source password manager for teams * Copyright (c) 2021 Passbolt SA (https://www.passbolt.com) * * Licensed under GNU Affero General Public License version 3 of the or any later version. * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) 2021 Passbolt SA (https://www.passbolt.com) * @license https://opensource.org/licenses/AGPL-3.0 AGPL License * @link https://www.passbolt.com Passbolt(tm) * @since 3.2.0 */ import { createInstance } from "i18next"; import { I18nextProvider } from "react-i18next"; import HttpApi from "i18next-http-backend"; import React, { Component } from "react"; import PropTypes from "prop-types"; /** * The locales default url. * @type {string} */ const DEFAULT_LOCALE_URL = "/locales/{{lng}}/{{ns}}.json"; /** * This component set up the translation process */ class TranslationProvider extends Component { constructor(props) { super(props); this.state = this.defaultState; } /** * Returns the default component state */ get defaultState() { return { i18next: null, // The i18next instance }; } /** * ComponentDidMount * Invoked immediately after component is inserted into the tree * @return {void} */ componentDidMount() { if (this.props.locale) { this.initI18next(); } } /** * Whenever the component has updated in terms of props */ async componentDidUpdate(prevProps) { await this.handleLocaleChange(prevProps); } /** * Check if the locale has changed and update */ async handleLocaleChange(prevProps) { if (this.props.locale !== prevProps?.locale) { this.initI18next(); } } /** * Initialize i18next. * @returns {Promise<void>} */ async initI18next() { const i18next = createInstance(); await i18next // I18next plugin used to load the translations json over http. .use(HttpApi) // init i18next, once done store the i18next instance in the state. .init(this.i18nextOptions, () => this.setState({ i18next, locale: this.props.locale })); } /** * Get the i18next options. * For more information, checkout: https://www.i18next.com/overview/configuration-options * @returns {Object} */ get i18nextOptions() { return { lng: this.props.locale, load: "currentOnly", react: { useSuspense: false, }, backend: { loadPath: (lngs, namespaces) => this.getTranslationPath(lngs, namespaces), }, supportedLngs: this.supportedLocales, fallbackLng: false, ns: ["common"], defaultNS: "common", keySeparator: false, // don't use the dot for separator of nested json object nsSeparator: false, // allowed ':' in key to avoid namespace separator debug: false, }; } /** * Returns true when the component can be rendered */ get isReady() { return this.state.i18next !== null; } /** * Generates the translation file path for i18next with en-GB to en-UK locale mapping. * * i18next no longer supports the non-canonical locale code 'en-UK' and automatically * falls back to the canonical 'en-GB' code. To maintain our existing implementation * which uses 'en-UK' folder structure, this method intercepts the en-GB fallback * and redirects it to our en-UK translation files. * See: https://www.i18next.com/misc/migration-guide#v23.x.x-to-v24.0.0 * * @param {string[]} lngs - Array of language codes from i18next * @param {string[]} namespaces - Array of namespace identifiers * @returns {string} The resolved translation file path with en-GB mapped to en-UK */ getTranslationPath(lngs, namespaces) { const lng = lngs[0]; const ns = namespaces[0]; // i18next is doing a fallback on en-GB we are redirecting to our en-UK folder const actualLng = lng === "en-GB" ? "en-UK" : lng; const basePath = this.props.loadingPath; return basePath.replace("{{lng}}", actualLng).replace("{{ns}}", ns); } /** * Get supported locales. * @returns {string[]} */ get supportedLocales() { const locales = [this.props.locale]; if (locales.includes("en-UK")) { locales.push("en-GB"); //Need to add the locale to support i18next fallback as en-UK is not supported } return locales; } /** * Render the component. * @returns {JSX} */ render() { return ( <> { // Waiting for the i18n initialization to be completed this.isReady && <I18nextProvider i18n={this.state.i18next}>{this.props.children}</I18nextProvider> } </> ); } } TranslationProvider.propTypes = { loadingPath: PropTypes.any, // The way to load translations files children: PropTypes.any, // The children components locale: PropTypes.string, // The locale to use. i.e. en-UK }; TranslationProvider.defaultProps = { loadingPath: DEFAULT_LOCALE_URL, }; export default TranslationProvider;