Skip to content

Commit

Permalink
[FIX] Loading and setting fixes for i18n and RTL (#11363)
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan authored and ggazzo committed Jul 20, 2018
1 parent 96ea55e commit 54c9e16
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 105 deletions.
84 changes: 84 additions & 0 deletions client/startup/i18n.js
@@ -0,0 +1,84 @@
/* globals isRtl */

import moment from 'moment';

const currentLanguage = new ReactiveVar();

Meteor.startup(() => {
TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');
currentLanguage.set(localStorage.getItem('userLanguage'));

const availableLanguages = TAPi18n.getLanguages();

const filterLanguage = language => {
// Fix browsers having all-lowercase language settings eg. pt-br, en-us
const regex = /([a-z]{2})-([a-z]{2})/;
const matches = regex.exec(language);
if (matches) {
return `${ matches[1] }-${ matches[2].toUpperCase() }`;
}

return language;
};

const getBrowserLanguage = () => filterLanguage(window.navigator.userLanguage || window.navigator.language);

const loadMomentLocale = language => new Promise((resolve, reject) => {
if (moment.locales().includes(language.toLowerCase())) {
resolve(language);
return;
}

Meteor.call('loadLocale', language, (error, localeSrc) => {
if (error) {
reject(error);
return;
}

Function(localeSrc).call({ moment });
resolve(language);
});
});

const applyLanguage = (language = 'en') => {
language = filterLanguage(language);

if (!availableLanguages[language]) {
language = language.split('-').shift();
}

if (!language) {
return;
}

document.documentElement.classList[isRtl(language) ? 'add' : 'remove']('rtl');
TAPi18n.setLanguage(language);
loadMomentLocale(language).then(locale => moment.locale(locale), error => console.error(error));
};

const setLanguage = language => {
currentLanguage.set(filterLanguage(language));
localStorage.setItem('userLanguage', currentLanguage.get());
};

window.setLanguage = setLanguage;

window.defaultUserLanguage = () => RocketChat.settings.get('Language') || getBrowserLanguage() || 'en';

Tracker.autorun(() => {
const user = RocketChat.models.Users.findOne(Meteor.userId(), { fields: { username: 1 }});
const userLanguage = user && user.language;

const defaultLanguage = userLanguage || RocketChat.settings.get('Language') || 'en';

if (!currentLanguage.get()) {
setLanguage(defaultLanguage);
}

if (userLanguage && userLanguage !== currentLanguage.get()) {
setLanguage(userLanguage);
}

applyLanguage(currentLanguage.get());
});
});
63 changes: 1 addition & 62 deletions client/startup/startup.js
@@ -1,6 +1,5 @@
/* globals UserPresence, fireGlobalEvent, isRtl */
/* globals UserPresence, fireGlobalEvent */

import moment from 'moment';
import toastr from 'toastr';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css';
Expand All @@ -22,57 +21,6 @@ Meteor.startup(function() {
window.lastMessageWindow = {};
window.lastMessageWindowHistory = {};

TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');

const defaultAppLanguage = () => {
let lng = window.navigator.userLanguage || window.navigator.language || 'en';
// Fix browsers having all-lowercase language settings eg. pt-br, en-us
const re = /([a-z]{2}-)([a-z]{2})/;
if (re.test(lng)) {
lng = lng.replace(re, (match, ...parts) => {
return parts[0] + parts[1].toUpperCase();
});
}
return lng;
};

window.defaultUserLanguage = () => RocketChat.settings.get('Language') || defaultAppLanguage();

const availableLanguages = TAPi18n.getLanguages();
const loadedLanguages = [];

window.setLanguage = function(language) {
if (!language) {
return;
}

if (loadedLanguages.indexOf(language) > -1) {
return;
}

loadedLanguages.push(language);

if (isRtl(language)) {
$('html').addClass('rtl');
} else {
$('html').removeClass('rtl');
}

if (!availableLanguages[language]) {
language = language.split('-').shift();
}

TAPi18n.setLanguage(language);

language = language.toLowerCase();
if (language !== 'en') {
Meteor.call('loadLocale', language, (err, localeFn) => {
Function(localeFn).call({moment});
moment.locale(language);
});
}
};

Tracker.autorun(function(computation) {
if (!Meteor.userId() && !RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
return;
Expand Down Expand Up @@ -114,13 +62,4 @@ Meteor.startup(function() {
fireGlobalEvent('status-changed', status);
}
});

Tracker.autorun(() => {
const userLanguage = Meteor.user() && Meteor.user().language || RocketChat.settings.get('Language') || 'en';

if (loadedLanguages.length === 0 || localStorage.getItem('userLanguage') !== userLanguage) {
localStorage.setItem('userLanguage', userLanguage);
window.setLanguage(userLanguage);
}
});
});
5 changes: 1 addition & 4 deletions packages/rocketchat-ui-account/client/accountPreferences.js
Expand Up @@ -41,11 +41,8 @@ Template.accountPreferences.helpers({
.map(([ key, language ]) => ({ ...language, key: key.toLowerCase() }))
.sort((a, b) => a.key - b.key);

const appLanguageKey = RocketChat.settings.get('Language') || 'en';
const appLanguage = result.filter(({ key }) => key === appLanguageKey.toLowerCase())[0];

result.unshift({
'name': appLanguage ? `Default (${ appLanguage.name })` : 'Default',
'name': 'Default',
'en': 'Default',
'key': ''
});
Expand Down
29 changes: 20 additions & 9 deletions packages/rocketchat-ui-admin/client/admin.js
Expand Up @@ -413,16 +413,27 @@ Template.admin.events({
'click .rc-header__section-button .save'() {
const group = FlowRouter.getParam('group');
const query = { group, changed: true };
const settings = TempSettings.find(query, { fields: { _id: 1, value: 1, editor: 1 }}).fetch();
if (!_.isEmpty(settings)) {
RocketChat.settings.batchSet(settings, function(err) {
if (err) {
return handleError(err);
}
TempSettings.update({ changed: true }, { $unset: { changed: 1 }});
toastr.success(TAPi18n.__('Settings_updated'));
});
const settings = TempSettings.find(query, { fields: { _id: 1, value: 1, editor: 1 }}).fetch() || [];
if (settings.length === 0) {
return;
}

RocketChat.settings.batchSet(settings, (err) => {
if (err) {
return handleError(err);
}

TempSettings.update({ changed: true }, { $unset: { changed: 1 }});

if (settings.some(({ _id }) => _id === 'Language')) {
const lng = Meteor.user().language
|| settings.filter(({ _id }) => _id === 'Language').shift().value
|| 'en';
return TAPi18n._loadLanguage(lng).then(() => toastr.success(TAPi18n.__('Settings_updated', { lng })));
}
toastr.success(TAPi18n.__('Settings_updated'));
});

},
'click .rc-header__section-button .refresh-clients'() {
Meteor.call('refreshClients', function() {
Expand Down
6 changes: 5 additions & 1 deletion packages/rocketchat-ui-login/client/login/footer.html
@@ -1,5 +1,9 @@
<template name='loginFooter'>
<footer>
{{#if LanguageVersion}}<div class="switch-language"><button class="switch-language">{{LanguageVersion}}</button></div>{{/if}}
{{#if languageVersion}}
<div class="switch-language">
<button class="js-switch-language">{{languageVersion}}</button>
</div>
{{/if}}
</footer>
</template>
56 changes: 29 additions & 27 deletions packages/rocketchat-ui-login/client/login/footer.js
@@ -1,35 +1,37 @@
/*globals defaultUserLanguage */
Template.loginFooter.helpers({
LanguageVersion() {
if (Template.instance().languageVersion.get()) {
return TAPi18n.__('Language_Version', {
lng: Template.instance().languageVersion.get()
});
Template.loginFooter.onCreated(function() {
this.suggestedLanguage = new ReactiveVar();

this.suggestAnotherLanguageFor = language => {
const loadAndSetSuggestedLanguage = language => TAPi18n._loadLanguage(language)
.then(() => this.suggestedLanguage.set(language));

const serverLanguage = RocketChat.settings.get('Language');

if (serverLanguage !== language) {
loadAndSetSuggestedLanguage(serverLanguage || 'en');
} else if (!/^en/.test(language)) {
loadAndSetSuggestedLanguage('en');
} else {
this.suggestedLanguage.set(undefined);
}
}
};

const currentLanguage = localStorage.getItem('userLanguage');
this.suggestAnotherLanguageFor(currentLanguage);
});

Template.loginFooter.events({
'click button.switch-language'(e, t) {
const userLanguage = t.languageVersion.get();
localStorage.setItem('userLanguage', userLanguage);
TAPi18n.setLanguage(userLanguage);
moment.locale(userLanguage);
return t.languageVersion.set(userLanguage !== defaultUserLanguage() ? defaultUserLanguage() : 'en');
Template.loginFooter.helpers({
languageVersion() {
const lng = Template.instance().suggestedLanguage.get();
return lng && TAPi18n.__('Language_Version', { lng });
}
});

Template.loginFooter.onCreated(function() {
const self = this;
this.languageVersion = new ReactiveVar;
const userLanguage = localStorage.getItem('userLanguage');
if (userLanguage !== defaultUserLanguage()) {
return TAPi18n._loadLanguage(defaultUserLanguage()).done(function() {
return self.languageVersion.set(defaultUserLanguage());
});
} else if (userLanguage.indexOf('en') !== 0) {
return TAPi18n._loadLanguage('en').done(function() {
return self.languageVersion.set('en');
});
Template.loginFooter.events({
'click button.js-switch-language'(e, t) {
const language = t.suggestedLanguage.get();
window.setLanguage(language);
t.suggestAnotherLanguageFor(language);
return false;
}
});
3 changes: 1 addition & 2 deletions packages/rocketchat-ui-master/client/main.js
@@ -1,4 +1,4 @@
/* globals toolbarSearch, menu, isRtl, fireGlobalEvent, CachedChatSubscription, DynamicCss */
/* globals toolbarSearch, menu, fireGlobalEvent, CachedChatSubscription, DynamicCss */
import Clipboard from 'clipboard';
import s from 'underscore.string';

Expand Down Expand Up @@ -191,7 +191,6 @@ Template.main.events({
});

Template.main.onRendered(function() {
document.body.classList[(isRtl(localStorage.getItem('userLanguage'))? 'add': 'remove')]('rtl');
$('#initial-page-loading').remove();
window.addEventListener('focus', function() {
return Meteor.setTimeout(function() {
Expand Down

0 comments on commit 54c9e16

Please sign in to comment.