Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
Localization for client plugins. (#2621)
Browse files Browse the repository at this point in the history
  • Loading branch information
crspeller committed Apr 9, 2019
1 parent 5fb5135 commit 4c0e537
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 34 deletions.
31 changes: 30 additions & 1 deletion actions/views/root.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as UserActions from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client';

import {ActionTypes} from 'utils/constants';
import en from 'i18n/en.json';

export function loadMeAndConfig() {
return async (dispatch) => {
Expand All @@ -25,9 +26,37 @@ export function loadMeAndConfig() {
};
}

const pluginTranslationSources = {};

export function registerPluginTranslationsSource(pluginId, sourceFunction) {
pluginTranslationSources[pluginId] = sourceFunction;
}

export function unregisterPluginTranslationsSource(pluginId) {
Reflect.deleteProperty(pluginTranslationSources, pluginId);
}

export function loadTranslations(locale, url) {
return (dispatch) => {
Client4.getTranslations(url).then((translations) => {
const translations = {};
Object.values(pluginTranslationSources).forEach((pluginFunc) => {
Object.assign(translations, pluginFunc(locale));
});

// No need to go to the server for EN
if (locale === 'en') {
Object.assign(translations, en);
dispatch({
type: ActionTypes.RECEIVED_TRANSLATIONS,
data: {
locale,
translations,
},
});
return;
}
Client4.getTranslations(url).then((serverTranslations) => {
Object.assign(translations, serverTranslations);
dispatch({
type: ActionTypes.RECEIVED_TRANSLATIONS,
data: {
Expand Down
4 changes: 1 addition & 3 deletions components/intl_provider/intl_provider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ export default class IntlProvider extends React.PureComponent {
// Already loaded
return;
}

const localeInfo = I18n.getLanguageInfo(locale);

if (locale === 'en' || !localeInfo) {
// English is loaded by default and invalid locales fall back to English, so we should never hit this
if (!localeInfo) {
return;
}

Expand Down
6 changes: 3 additions & 3 deletions components/root/root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,13 @@ export default class Root extends React.Component {
/*eslint-enable */

const afterIntl = () => {
initializePlugins();

if (this.props.location.pathname === '/' && this.props.noAccounts) {
this.props.history.push('/signup_user_complete');
}

this.setState({configLoaded: true});
initializePlugins().then(() => {
this.setState({configLoaded: true});
});
};
if (global.Intl) {
afterIntl();
Expand Down
52 changes: 28 additions & 24 deletions plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export async function initializePlugins() {
return;
}

data.forEach((m) => {
loadPlugin(m);
});
await Promise.all(data.map((m) => {
return loadPlugin(m);
}));
}

// getPlugins queries the server for all enabled plugins
Expand All @@ -65,31 +65,35 @@ const loadedPlugins = {};
// loadPlugin fetches the web app bundle described by the given manifest, waits for the bundle to
// load, and then ensures the plugin has been initialized.
export function loadPlugin(manifest) {
// Don't load it again if previously loaded
if (loadedPlugins[manifest.id]) {
return;
}
return new Promise((resolve) => {
// Don't load it again if previously loaded
if (loadedPlugins[manifest.id]) {
resolve();
return;
}

function onLoad() {
initializePlugin(manifest);
console.log('Loaded ' + manifest.id + ' plugin'); //eslint-disable-line no-console
}
function onLoad() {
initializePlugin(manifest);
console.log('Loaded ' + manifest.id + ' plugin'); //eslint-disable-line no-console
resolve();
}

// Backwards compatibility for old plugins
let bundlePath = manifest.webapp.bundle_path;
if (bundlePath.includes('/static/') && !bundlePath.includes('/static/plugins/')) {
bundlePath = bundlePath.replace('/static/', '/static/plugins/');
}
// Backwards compatibility for old plugins
let bundlePath = manifest.webapp.bundle_path;
if (bundlePath.includes('/static/') && !bundlePath.includes('/static/plugins/')) {
bundlePath = bundlePath.replace('/static/', '/static/plugins/');
}

const script = document.createElement('script');
script.id = 'plugin_' + manifest.id;
script.type = 'text/javascript';
script.src = getSiteURL() + bundlePath;
script.onload = onLoad;
console.log('Loading ' + manifest.id + ' plugin'); //eslint-disable-line no-console
document.getElementsByTagName('head')[0].appendChild(script);
const script = document.createElement('script');
script.id = 'plugin_' + manifest.id;
script.type = 'text/javascript';
script.src = getSiteURL() + bundlePath;
script.onload = onLoad;
console.log('Loading ' + manifest.id + ' plugin'); //eslint-disable-line no-console
document.getElementsByTagName('head')[0].appendChild(script);

loadedPlugins[manifest.id] = true;
loadedPlugins[manifest.id] = true;
});
}

// initializePlugin creates a registry specific to the plugin and invokes any initialize function
Expand Down
8 changes: 8 additions & 0 deletions plugins/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {
unregisterPluginReconnectHandler,
} from 'actions/websocket_actions.jsx';

import {
registerPluginTranslationsSource,
} from 'actions/views/root';

import store from 'stores/redux_store.jsx';
import {ActionTypes} from 'utils/constants.jsx';
import {generateId} from 'utils/utils.jsx';
Expand Down Expand Up @@ -359,4 +363,8 @@ export default class PluginRegistry {

return id;
}

registerTranslations(getTranslationsForLocale) {
registerPluginTranslationsSource(this.id, getTranslationsForLocale);
}
}
4 changes: 1 addition & 3 deletions reducers/views/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

import {combineReducers} from 'redux';

import en from 'i18n/en.json';

import {ActionTypes} from 'utils/constants.jsx';

function translations(state = {en}, action) {
function translations(state = {}, action) {
switch (action.type) {
case ActionTypes.RECEIVED_TRANSLATIONS:
return {
Expand Down

0 comments on commit 4c0e537

Please sign in to comment.