feat(i18n): Allow label rewrite via advanced branding
This commit is contained in:
parent
df3545d287
commit
f20a50d8a6
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import '../authentication/middleware';
|
||||
import '../base/i18n/middleware';
|
||||
import '../base/devices/middleware';
|
||||
import '../dynamic-branding/middleware';
|
||||
import '../e2ee/middleware';
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that i18next has been initialized.
|
||||
*/
|
||||
export const I18NEXT_INITIALIZED = 'I18NEXT_INITIALIZED';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that language has been changed.
|
||||
*/
|
||||
export const LANGUAGE_CHANGED = 'LANGUAGE_CHANGED';
|
|
@ -1,6 +1,24 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
import i18next from './i18next';
|
||||
|
||||
/**
|
||||
* Changes the main translation bundle.
|
||||
*
|
||||
* @param {string} language - The language e.g. 'en', 'fr'.
|
||||
* @param {string} url - The url of the translation bundle.
|
||||
* @returns {void}
|
||||
*/
|
||||
export async function changeLanguageBundle(language: string, url: string) {
|
||||
const res = await fetch(url);
|
||||
const bundle = await res.json();
|
||||
|
||||
i18next.addResourceBundle(language, 'main', bundle, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a specific React Component in order to enable translations in it.
|
||||
*
|
||||
|
@ -8,7 +26,7 @@ import { withTranslation } from 'react-i18next';
|
|||
* @returns {Component} The React Component which wraps {@link component} and
|
||||
* enables translations in it.
|
||||
*/
|
||||
export function translate(component) {
|
||||
export function translate(component: any) {
|
||||
// Use the default list of namespaces.
|
||||
return withTranslation([ 'main', 'languages', 'countries' ])(component);
|
||||
}
|
||||
|
@ -23,7 +41,7 @@ export function translate(component) {
|
|||
* @returns {ReactElement} A ReactElement which depicts the translated HTML
|
||||
* text.
|
||||
*/
|
||||
export function translateToHTML(t, key, options = {}) {
|
||||
export function translateToHTML(t: Function, key: string, options: Object = {}) {
|
||||
// eslint-disable-next-line react/no-danger
|
||||
return <span dangerouslySetInnerHTML = {{ __html: t(key, options) }} />;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// @flow
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
import COUNTRIES_RESOURCES from 'i18n-iso-countries/langs/en.json';
|
||||
import i18next from 'i18next';
|
||||
import I18nextXHRBackend from 'i18next-xhr-backend';
|
||||
|
@ -7,6 +9,7 @@ import I18nextXHRBackend from 'i18next-xhr-backend';
|
|||
import LANGUAGES_RESOURCES from '../../../../lang/languages.json';
|
||||
import MAIN_RESOURCES from '../../../../lang/main.json';
|
||||
|
||||
import { I18NEXT_INITIALIZED, LANGUAGE_CHANGED } from './actionTypes';
|
||||
import languageDetector from './languageDetector';
|
||||
|
||||
/**
|
||||
|
@ -46,6 +49,8 @@ const options = {
|
|||
load: 'languageOnly',
|
||||
ns: [ 'main', 'languages', 'countries' ],
|
||||
react: {
|
||||
// re-render when a new resource bundle is added
|
||||
bindI18nStore: 'added',
|
||||
useSuspense: false
|
||||
},
|
||||
returnEmptyString: false,
|
||||
|
@ -87,4 +92,15 @@ i18next.addResourceBundle(
|
|||
// since i18next is not yet initialized at that point.
|
||||
require('./BuiltinLanguages');
|
||||
|
||||
// Label change through dynamic branding is available only for web
|
||||
if (typeof APP !== 'undefined') {
|
||||
i18next.on('initialized', () => {
|
||||
APP.store.dispatch({ type: I18NEXT_INITIALIZED });
|
||||
});
|
||||
|
||||
i18next.on('languageChanged', () => {
|
||||
APP.store.dispatch({ type: LANGUAGE_CHANGED });
|
||||
});
|
||||
}
|
||||
|
||||
export default i18next;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { getLogger } from '../logging/functions';
|
||||
|
||||
export default getLogger('features/base/i18n');
|
|
@ -0,0 +1,39 @@
|
|||
// @flow
|
||||
|
||||
import { SET_DYNAMIC_BRANDING_DATA } from '../../dynamic-branding/actionTypes';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
|
||||
import { I18NEXT_INITIALIZED, LANGUAGE_CHANGED } from './actionTypes';
|
||||
import { changeLanguageBundle } from './functions';
|
||||
import i18next from './i18next';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Implements the entry point of the middleware of the feature base/i18n.
|
||||
*
|
||||
* @param {Store} store - The redux store.
|
||||
* @returns {Function}
|
||||
*/
|
||||
MiddlewareRegistry.register(store => next => async action => {
|
||||
switch (action.type) {
|
||||
case I18NEXT_INITIALIZED:
|
||||
case LANGUAGE_CHANGED:
|
||||
case SET_DYNAMIC_BRANDING_DATA: {
|
||||
const { language } = i18next;
|
||||
const { labels } = action.type === SET_DYNAMIC_BRANDING_DATA
|
||||
? action.value
|
||||
: store.getState()['features/dynamic-branding'];
|
||||
|
||||
if (language && labels && labels[language]) {
|
||||
try {
|
||||
await changeLanguageBundle(language, labels[language]);
|
||||
} catch (err) {
|
||||
logger.log('Error setting dynamic language bundle', err);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return next(action);
|
||||
});
|
|
@ -84,6 +84,15 @@ const DEFAULT_STATE = {
|
|||
*/
|
||||
inviteDomain: '',
|
||||
|
||||
/**
|
||||
* An object containing the mapping between the language and url where the translation
|
||||
* bundle is hosted.
|
||||
*
|
||||
* @public
|
||||
* @type {Object}
|
||||
*/
|
||||
labels: null,
|
||||
|
||||
/**
|
||||
* The custom url used when the user clicks the logo.
|
||||
*
|
||||
|
@ -146,6 +155,7 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
|||
defaultBranding,
|
||||
didPageUrl,
|
||||
inviteDomain,
|
||||
labels,
|
||||
logoClickUrl,
|
||||
logoImageUrl,
|
||||
muiBrandedTheme,
|
||||
|
@ -160,6 +170,7 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
|||
defaultBranding,
|
||||
didPageUrl,
|
||||
inviteDomain,
|
||||
labels,
|
||||
logoClickUrl,
|
||||
logoImageUrl,
|
||||
muiBrandedTheme,
|
||||
|
|
Loading…
Reference in New Issue