Independent-of-prod quality debt from PENDIENTE.md §2: - test: migrate broken Jest -> meteortesting:mocha. Tests rewritten to chai + Meteor 3 async APIs, moved to test/server/ (server-only). test/server/ 00-setup.test.js re-runs the collection2/accounts init that `meteor test` skips (no server/main.js). New comments method + mediaAnalyzers coverage. Dropped rest.test.js (removed meteor/http; covered by smoke/). 36 passing. - fix: scope FireContainer read by the URL _id on the archive route instead of a selector-less FiresCollection.findOne() (imports/ui/pages/Fires/Fires.js). - feat: rate-limit abusable publications via rateLimitSubscriptions (fireFrom* and comments.forReference 5/1000ms; geo subs 10/1000ms). - perf: append loading=async to the Google Maps loader URL (Gkeys.js). - deps: meteor-accounts-t9n 2.0 -> 2.6 (no gl build -> keep gl->es fallback, documented); add 3 missing gl/common.json keys (0 missing now). - deps: drop jest/babel/enzyme, add chai.
113 lines
3.5 KiB
JavaScript
113 lines
3.5 KiB
JavaScript
/* global Intl */
|
|
import i18n from 'i18next';
|
|
import { Meteor } from 'meteor/meteor';
|
|
import { Tracker } from 'meteor/tracker';
|
|
import { ReactiveVar } from 'meteor/reactive-var';
|
|
import backend from 'i18next-http-backend';
|
|
import LngDetector from 'i18next-browser-languagedetector';
|
|
import { T9n } from 'meteor-accounts-t9n';
|
|
import moment from 'moment';
|
|
import 'moment/locale/es';
|
|
import 'moment/locale/pt';
|
|
import 'moment/locale/gl';
|
|
import i18nOpts from '../common/i18n';
|
|
|
|
// Adapted from: https://github.com/appigram/ryfma-boilerplate/blob/44c1eabfb9928b5623afab36a23997969e5beb02/imports/startup/client/i18n.js
|
|
|
|
const detectorOptions = {
|
|
// order and from where user language should be detected
|
|
order: ['querystring', 'navigator', 'cookie', 'localStorage', 'htmlTag'],
|
|
|
|
// keys or params to lookup language from
|
|
lookupQuerystring: 'lng',
|
|
lookupCookie: 'i18next',
|
|
lookupLocalStorage: 'i18nextLng',
|
|
|
|
// cache user language on
|
|
caches: ['localStorage', 'cookie'],
|
|
excludeCacheFor: ['cimode'] // languages to not persist (cookie, localStorage)
|
|
};
|
|
|
|
export const i18nReady = new ReactiveVar(false);
|
|
|
|
i18nOpts.detection = detectorOptions;
|
|
i18nOpts.react = {
|
|
useSuspense: false, // was `wait: true` pre-react-i18next-10
|
|
defaultTransParent: 'span'
|
|
// https://react.i18next.com/components/i18next-instance.ht
|
|
/* bindI18n: 'languageChanged loaded',
|
|
bindStore: 'added removed',
|
|
nsMode: 'default' */
|
|
};
|
|
|
|
const sendMissing = true; // Meteor.isDevelopment;
|
|
if (sendMissing && Meteor.isDevelopment) {
|
|
i18nOpts.saveMissing = true;
|
|
// Modern signature is (lngs, ns, key, fallbackValue, ...); key/fallback keep
|
|
// the same positions, so we still only need those two.
|
|
i18nOpts.missingKeyHandler = function miss(lngs, ns, key, defaultValue) {
|
|
Meteor.call('utility.saveMissingI18n', key, defaultValue);
|
|
};
|
|
}
|
|
|
|
function setT9(lang) {
|
|
// meteor-accounts-t9n has no Galician build, so use Spanish for gl account
|
|
// error messages (the closest shipped language). See common/i18n.js.
|
|
if (lang === 'gl') {
|
|
T9n.setLanguage('es');
|
|
} else {
|
|
T9n.setLanguage(lang);
|
|
}
|
|
}
|
|
|
|
i18n.use(backend)
|
|
.use(LngDetector)
|
|
.init(i18nOpts, (err, t) => {
|
|
// initialized and ready to
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
console.log(`Language initialized: ${i18n.language}`);
|
|
|
|
// document.title = t('AppName');
|
|
// Accounts translation
|
|
// https://github.com/softwarerero/meteor-accounts-t9n
|
|
setT9(i18n.language);
|
|
// console.log(T9n.get('error.accounts.User not found'));
|
|
moment.locale(i18n.language);
|
|
|
|
i18nReady.set(true);
|
|
|
|
// Cookie consent banner: selaias:cookie-consent (Blaze, dead on Meteor 3)
|
|
// replaced by the React component imports/ui/components/CookieConsent,
|
|
// which reuses the same i18n keys.
|
|
});
|
|
|
|
Meteor.subscribe('userData'); // lang is there
|
|
|
|
i18n.on('languageChanged', (lng) => {
|
|
moment.locale(lng);
|
|
// TODO fix this when gl is translated
|
|
setT9(lng);
|
|
Tracker.autorun((computation) => {
|
|
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}, from previous ${Meteor.user().lang}`);
|
|
// console.log(Meteor.user());
|
|
Meteor.call('users.setLang', lng, (error) => {
|
|
if (error) {
|
|
console.error(error);
|
|
}
|
|
});
|
|
computation.stop(); // not need it again til new lang change
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
export default i18n;
|