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 { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check'; import { check, Match } from 'meteor/check';
import { Accounts } from 'meteor/accounts-base'; import { Accounts } from 'meteor/accounts-base';
import editProfile from './edit-profile'; import editProfile from './edit-profile';
import rateLimit from '../../../modules/rate-limit'; 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({ Meteor.methods({
'users.sendVerificationEmail': function usersSendVerificationEmail() { 'users.sendVerificationEmail': function usersSendVerificationEmail() {
return Accounts.sendVerificationEmail(this.userId); return Accounts.sendVerificationEmail(this.userId);
@ -14,9 +20,9 @@ Meteor.methods({
profile: { profile: {
name: { name: {
first: String, first: String,
last: String, last: String
}, }
}, }
}); });
return editProfile({ userId: this.userId, profile }) return editProfile({ userId: this.userId, profile })
@ -25,13 +31,17 @@ Meteor.methods({
throw new Meteor.Error('500', exception); throw new Meteor.Error('500', exception);
}); });
}, },
'users.setLang': function userLang(lang) {
check(lang, validLangCode);
Meteor.users.update({ _id: this.userId }, { $set: { lang } });
}
}); });
rateLimit({ rateLimit({
methods: [ methods: [
'users.sendVerificationEmail', 'users.sendVerificationEmail',
'users.editProfile', 'users.editProfile'
], ],
limit: 5, limit: 5,
timeRange: 1000, timeRange: 1000
}); });

View file

@ -1,6 +1,7 @@
/* global CookieConsent Intl */ /* global CookieConsent Intl */
import i18n from 'i18next'; import i18n from 'i18next';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import backend from 'i18next-xhr-backend'; import backend from 'i18next-xhr-backend';
import LngDetector from 'i18next-browser-languagedetector'; import LngDetector from 'i18next-browser-languagedetector';
import Cache from 'i18next-localstorage-cache'; import Cache from 'i18next-localstorage-cache';
@ -98,6 +99,22 @@ i18n.use(backend)
i18n.on('languageChanged', (lng) => { i18n.on('languageChanged', (lng) => {
moment.locale(lng); moment.locale(lng);
T9n.setLanguage(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; export default i18n;

View file

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

View file

@ -47,13 +47,17 @@ class Login extends React.Component {
} }
handleSubmit = () => { handleSubmit = () => {
const { history } = this.props; const { history, i18n } = this.props;
Meteor.loginWithPassword(this.emailAddress.value, this.password.value, (error) => { Meteor.loginWithPassword(this.emailAddress.value, this.password.value, (error) => {
if (error) { if (error) {
Bert.alert(T9n.get(`error.accounts.${error.reason}`), 'danger'); Bert.alert(T9n.get(`error.accounts.${error.reason}`), 'danger');
} else { } else {
Bert.alert(this.t('Bienvenid@ de nuevo'), 'success'); 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 = { Login.propTypes = {
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
t: PropTypes.func.isRequired, t: PropTypes.func.isRequired,
i18n: PropTypes.object.isRequired,
location: PropTypes.object location: PropTypes.object
}; };

View file

@ -26,6 +26,7 @@ class Profile extends React.Component {
this.renderOAuthUser = this.renderOAuthUser.bind(this); this.renderOAuthUser = this.renderOAuthUser.bind(this);
this.renderPasswordUser = this.renderPasswordUser.bind(this); this.renderPasswordUser = this.renderPasswordUser.bind(this);
this.renderProfileForm = this.renderProfileForm.bind(this); this.renderProfileForm = this.renderProfileForm.bind(this);
this.onLangSelect = this.onLangSelect.bind(this);
} }
componentDidMount() { 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) { getUserType(user) {
const userToCheck = user; const userToCheck = user;
delete userToCheck.services.resume; delete userToCheck.services.resume;
@ -137,6 +150,8 @@ class Profile extends React.Component {
} }
renderPasswordUser(loading, user) { renderPasswordUser(loading, user) {
const {t, i18n} = this.props;
const langName = { 'en': 'English', 'es': 'Español', 'gl': 'Galego', 'ast': 'Asturianu', 'ca': 'Català' };
return !loading ? (<div> return !loading ? (<div>
<Row> <Row>
<Col xs={6}> <Col xs={6}>
@ -174,6 +189,26 @@ class Profile extends React.Component {
className="form-control" className="form-control"
/> />
</FormGroup> </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> <FormGroup>
<ControlLabel>{this.t("Contraseña actual")}</ControlLabel> <ControlLabel>{this.t("Contraseña actual")}</ControlLabel>
<input <input
@ -221,7 +256,9 @@ class Profile extends React.Component {
Profile.propTypes = { Profile.propTypes = {
loading: PropTypes.bool.isRequired, 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(() => { 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", "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", "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" "Iniciar sesión con Telegram",
"Idioma":
"Idioma"
} }