Added user lang setting

This commit is contained in:
vjrj 2018-01-09 12:05:36 +01:00
parent fc56bd3273
commit 97c47c5d1d
7 changed files with 90 additions and 21 deletions

View file

@ -1,9 +1,15 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { check, Match } from 'meteor/check';
import { Accounts } from 'meteor/accounts-base';
import editProfile from './edit-profile';
import rateLimit from '../../../modules/rate-limit';
const validLangCode = Match.Where((lang) => {
check(lang, String);
const regexp = /^[a-z]{2,3}(?:-[A-Z]{2,3}(?:-[a-zA-Z]{4})?)?$/;
return regexp.test(lang);
});
Meteor.methods({
'users.sendVerificationEmail': function usersSendVerificationEmail() {
return Accounts.sendVerificationEmail(this.userId);
@ -14,24 +20,28 @@ Meteor.methods({
profile: {
name: {
first: String,
last: String,
},
},
last: String
}
}
});
return editProfile({ userId: this.userId, profile })
.then(response => response)
.catch((exception) => {
throw new Meteor.Error('500', exception);
});
.then(response => response)
.catch((exception) => {
throw new Meteor.Error('500', exception);
});
},
'users.setLang': function userLang(lang) {
check(lang, validLangCode);
Meteor.users.update({ _id: this.userId }, { $set: { lang } });
}
});
rateLimit({
methods: [
'users.sendVerificationEmail',
'users.editProfile',
'users.editProfile'
],
limit: 5,
timeRange: 1000,
timeRange: 1000
});

View file

@ -1,6 +1,7 @@
/* global CookieConsent Intl */
import i18n from 'i18next';
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import backend from 'i18next-xhr-backend';
import LngDetector from 'i18next-browser-languagedetector';
import Cache from 'i18next-localstorage-cache';
@ -98,6 +99,22 @@ i18n.use(backend)
i18n.on('languageChanged', (lng) => {
moment.locale(lng);
T9n.setLanguage(lng);
Tracker.autorun(() => {
if (Meteor.userId()) {
// logged
if (Meteor.user() && (typeof Meteor.user().lang === 'undefined' ||
Meteor.user().lang !== lng)
) {
// Set the autodetected/changed lang
console.log(`Setting the autodetected lang ${lng}`);
Meteor.call('users.setLang', lng, (error) => {
if (error) {
console.error(error);
}
});
}
}
});
});
export default i18n;

View file

@ -20,14 +20,8 @@ const shouldDebug = (forceDebug && !Meteor.isProduction);
const i18nOpts = {
backend: backOpts,
lng: 'es',
// fallbackLng: 'es',
fallbackLng: {
'en-US': ['en'],
'en-GB': ['en'],
'pt-BR': ['pt'],
default: ['es']
},
// lng: 'es',
fallbackLng: ['es', 'en'],
interpolation: {
escapeValue: false, // not needed for react!!
formatSeparator: ',',

View file

@ -47,13 +47,17 @@ class Login extends React.Component {
}
handleSubmit = () => {
const { history } = this.props;
const { history, i18n } = this.props;
Meteor.loginWithPassword(this.emailAddress.value, this.password.value, (error) => {
if (error) {
Bert.alert(T9n.get(`error.accounts.${error.reason}`), 'danger');
} else {
Bert.alert(this.t('Bienvenid@ de nuevo'), 'success');
const userLang = Meteor.user().lang
if (typeof userLang === 'string' && i18n.language !== userLang) {
i18n.changeLanguage(userLang);
}
}
});
}
@ -111,6 +115,7 @@ class Login extends React.Component {
Login.propTypes = {
history: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
i18n: PropTypes.object.isRequired,
location: PropTypes.object
};

View file

@ -26,6 +26,7 @@ class Profile extends React.Component {
this.renderOAuthUser = this.renderOAuthUser.bind(this);
this.renderPasswordUser = this.renderPasswordUser.bind(this);
this.renderProfileForm = this.renderProfileForm.bind(this);
this.onLangSelect = this.onLangSelect.bind(this);
}
componentDidMount() {
@ -78,6 +79,18 @@ class Profile extends React.Component {
});
}
onLangSelect(lang) {
// console.log(lang);
Meteor.call('users.setLang', lang, (error) => {
if (error) {
console.error(error);
} else {
this.props.i18n.changeLanguage(lang);
// Bert.alert(this.t("¡Perfíl actualizado!"), 'success');
}
});
}
getUserType(user) {
const userToCheck = user;
delete userToCheck.services.resume;
@ -137,6 +150,8 @@ class Profile extends React.Component {
}
renderPasswordUser(loading, user) {
const {t, i18n} = this.props;
const langName = { 'en': 'English', 'es': 'Español', 'gl': 'Galego', 'ast': 'Asturianu', 'ca': 'Català' };
return !loading ? (<div>
<Row>
<Col xs={6}>
@ -174,6 +189,26 @@ class Profile extends React.Component {
className="form-control"
/>
</FormGroup>
<FormGroup>
<ControlLabel>{this.t("Idioma")}</ControlLabel>
<div className="btn-group">
<button className="btn btn-secondary btn-sm dropdown-toggle lang-selector" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{langName[i18n.language]}
</button>
<div className="dropdown-menu">
{i18n.languages.map(lang => (
<button
className="dropdown-item"
onClick={() => this.onLangSelect(lang)}
key={lang}
type="button">
{langName[lang]}
</button>
))
}
</div>
</div>
</FormGroup>
<FormGroup>
<ControlLabel>{this.t("Contraseña actual")}</ControlLabel>
<input
@ -221,7 +256,9 @@ class Profile extends React.Component {
Profile.propTypes = {
loading: PropTypes.bool.isRequired,
user: PropTypes.object.isRequired
user: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
i18n: PropTypes.object.isRequired
};
export default translate([], { wait: true })(createContainer(() => {

View file

@ -44,3 +44,7 @@
}
}
}
.lang-selector {
margin: 10px 0 0 0;
}

View file

@ -183,5 +183,7 @@
"Política de Privacidad": "Política de Privacidad",
"No estás suscrito a fuegos en ninguna zona": "No estás suscrito a fuegos en ninguna zona",
"Iniciar sesión con Telegram":
"Iniciar sesión con Telegram"
"Iniciar sesión con Telegram",
"Idioma":
"Idioma"
}