%PDF- %PDF-
Direktori : /home/opti/workflow/node_modules/@ladjs/i18n/lib/ |
Current File : /home/opti/workflow/node_modules/@ladjs/i18n/lib/index.js |
"use strict"; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } const _require = require('path'), extname = _require.extname, resolve = _require.resolve; const Boom = require('@hapi/boom'); const autoBind = require('auto-bind'); const boolean = require('boolean'); const debug = require('debug')('ladjs:i18n'); const i18n = require('i18n'); const locales = require('i18n-locales'); const moment = require('moment'); const titleize = require('titleize'); const _require2 = require('country-language'), getLanguage = _require2.getLanguage; const _require3 = require('lodash'), isEmpty = _require3.isEmpty, sortBy = _require3.sortBy, every = _require3.every, isFunction = _require3.isFunction; const _require4 = require('qs'), stringify = _require4.stringify; // expose global i18n.api = {}; class I18N { constructor(config = {}) { this.config = Object.assign({ phrases: {}, logger: console, directory: resolve('locales'), locales: ['en', 'es', 'zh'], cookie: 'locale', indent: ' ', defaultLocale: 'en', syncFiles: boolean(process.env.I18N_SYNC_FILES || true), autoReload: boolean(process.env.I18N_AUTO_RELOAD || false), updateFiles: boolean(process.env.I18N_UPDATE_FILES || true), api: { __: 't', __n: 'tn', __l: 'tl', __h: 'th', __mf: 'tmf' }, register: i18n.api, lastLocaleField: 'last_locale' }, config); // validate locales against available ones if (!every(this.config.locales, l => locales.includes(l))) throw new Error(`Invalid locales: ${this.config.locales.filter(str => !locales.includes(str)).join(', ')}`); // inherit i18n object Object.assign(this, i18n); // configure i18n this.configure(this.config); autoBind(this); } translate(key, locale) { const phrases = this.config.phrases; // eslint-disable-next-line prefer-rest-params let args = Object.keys(arguments) // eslint-disable-next-line prefer-rest-params .map(key => arguments[key]).slice(2); if (typeof args === 'undefined') args = []; const phrase = phrases[key]; if (typeof phrase !== 'string') throw new Error(`translation key missing: ${key}`); args = [{ phrase, locale }, ...args]; return i18n.api.t(...args); } middleware(ctx, next) { const _this$config = this.config, locales = _this$config.locales, defaultLocale = _this$config.defaultLocale, phrases = _this$config.phrases, cookie = _this$config.cookie; // expose api methods to `ctx.request` and `ctx.state` i18n.init(ctx.request, ctx.state); // expose a helper function to `ctx.state.l` // which prefixes a link/path with the locale ctx.state.l = (path = '') => { return `/${ctx.state.locale}${path}`; }; // override the existing locale detection with our own // in order of priority: // // 1. check the URL, if === `/de` or starts with `/de/` then locale is `de` // 2. check the cookie // 3. check Accept-Language last // // also we need to expose `ctx.pathWithoutLocale` // as the path without locale let locale = locales.find(l => { return `/${l}` === ctx.path || ctx.path.indexOf(`/${l}/`) === 0; }); ctx.pathWithoutLocale = locale ? ctx.path.substring(`/${locale}`.length) : ctx.path; if (ctx.pathWithoutLocale === '') ctx.pathWithoutLocale = '/'; if (!locale) { locale = defaultLocale; if (ctx.cookies.get(cookie) && locales.includes(ctx.cookies.get(cookie))) { locale = ctx.cookies.get(cookie); debug('found locale via cookie using %s', locale); } else if (ctx.request.acceptsLanguages(locales)) { locale = ctx.request.acceptsLanguages(locales); debug('found locale via Accept-Language header using %s', locale); } else { debug('using default locale'); } } // set the locale properly i18n.setLocale([ctx.request, ctx.state], locale); ctx.locale = ctx.request.locale; // if the locale was not available then redirect user if (locale !== ctx.state.locale) { debug('locale was not available redirecting user'); return ctx.redirect(`/${ctx.state.locale}${ctx.pathWithoutLocale}${isEmpty(ctx.query) ? '' : `?${stringify(ctx.query)}`}`); } // available languages for a dropdown menu to change language ctx.state.availableLanguages = sortBy(locales.map(locale => { return { locale, url: `/${locale}${ctx.pathWithoutLocale}${isEmpty(ctx.query) ? '' : `?${stringify(ctx.query)}`}`, name: getLanguage(locale).name[0] }; }), 'name'); // get the name of the current locale's language in native language ctx.state.currentLanguage = titleize(getLanguage(ctx.request.locale).nativeName[0]); // bind `ctx.translate` as a helper func // so you can pass `ctx.translate('SOME_KEY_IN_CONFIG');` and it will lookup // `phrases['SOMETHING']` to get a specific and constant message // and then it will call `t` to translate it to the user's locale ctx.translate = function (...args) { if (typeof args[0] !== 'string' || typeof phrases[args[0]] !== 'string') return ctx.throw(Boom.badRequest('Translation for your locale failed, try again')); args[0] = phrases[args[0]]; return ctx.request.t(...args); }; return next(); } redirect(ctx, next) { var _this = this; return _asyncToGenerator(function* () { debug('attempting to redirect'); // do not redirect static paths if (extname(ctx.path) !== '') return next(); // inspired by nodejs.org language support // <https://github.com/nodejs/nodejs.org/commit/d6cdd942a8fc0fffcf6879eca124295e95991bbc#diff-78c12f5adc1848d13b1c6f07055d996eR59> const locale = ctx.url.split('/')[1].split('?')[0]; const hasLang = _this.config.locales.includes(locale); // if the URL did not have a valid language found // then redirect the user to their detected locale if (!hasLang) { ctx.status = 302; let redirect = `/${ctx.request.locale}${ctx.url}`; if (redirect === `/${ctx.request.locale}/`) redirect = `/${ctx.request.locale}`; if (!isEmpty(ctx.query)) redirect += `?${stringify(ctx.query)}`; debug('no valid locale found in URL, redirecting to %s', redirect); return ctx.redirect(redirect); } debug('found valid language "%s"', locale); // set the cookie for future requests ctx.cookies.set(_this.config.cookie, locale, { // Disable signed cookies in NODE_ENV=test signed: process.env.NODE_ENV !== 'test', expires: moment().add(1, 'year').toDate() }); debug('set cookies for locale "%s"', locale); // if the user is logged in and ctx.isAuthenticated() exists, // then save it as `last_locale` (variable based off lastLocaleField) if (isFunction(ctx.isAuthenticated) && ctx.isAuthenticated()) { ctx.state.user[_this.config.lastLocaleField] = locale; try { yield ctx.state.user.save(); } catch (err) { _this.config.logger.error(err); } } return next(); })(); } } module.exports = I18N;