Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Loading and setting fixes for i18n and RTL #11363

Merged
merged 18 commits into from
Jul 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions client/startup/i18n.js
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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