后端内部化更改语言会话与系统

backend internalization change language session vs system

所以我的后端是用 nodejs 编写的,我正在使用 i18next 进行内部化。我也在前端使用它。前端的语言由域决定。例如es.domain.com 是西班牙语,ja.domain.com 是日语等

在后端,目标是通过域来源确定用户语言,并将响应语言更改为其来源。默认为英语。

我的问题是,

当我更改语言时,它会更改 API 默认语言还是那个请求会话语言? 即,如果用户 1 用日语发出请求需要 5 秒,而用户 2 用英语发出请求后用户 1 需要 1 秒。 user1 会不会意外收到英文回复?

抱歉,如果问题unclear/hard无法理解。请在下方评论,我会尝试改写。

const i18n = require('i18next');

const express     = require('express');
const app         = express();
const port        = 3050;
const bodyParser  = require('body-parser');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(require('express-useragent').express());

// Internationalization
i18n.init({
  resources: langResources,
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false
  }
}); 

// Cors
app.use(function(req, res, next) {

  // HERE's where I'll be detecting and changing the language
  i18n.changeLanguage('ja');
  console.log("i18n.t('test')",i18n.t('test',{count:1}));

  
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, auth-id, auth-token, x-csrf-token, _csrf");
  res.header('Access-Control-Allow-Methods', 'PATCH, POST, GET, DELETE, OPTIONS');
  next();
}); ```

我意识到我可以像这样快速测试一下。

我发送了两个请求。第一个睡眠时间为 5000 毫秒,ja lang,而第二个睡眠时间为 150 毫秒,en lang。

test: async function(req){

      let user = req.query.user;
      let lang = req.query.lang;
      let time = req.query.time;

      // console.log("test 0Ro-> i18n.t('test')",i18n.t('test',{count:1}));

      i18n.changeLanguage(lang);
      console.log("user 1Ro:",user,"lang 1Ro:",lang);
      console.log("test 1Ro-> i18n.t('test')",i18n.t('test',{count:1}));
      await sleep(time)
      console.log("user 2Ro:",user,"lang 2Ro:",lang);
      console.log("test 2Ro-> i18n.t('test')",i18n.t('test',{count:1}));


    },

不幸的是,ja 语言用户以英语返回,这意味着更改语言不会更改会话语言,而是更改 api 语言。

这是问题的答案。但是我仍在寻找解决方案。

编辑:找不到 i18next 解决方案,所以我自己做了一个。如果您想使用它,就在这里。添加 express-session 您的项目。

app.js - 初始化

const {t} = require('./translations/i18n').i18n;

process.env.TZ = "Etc/GMT"

const express     = require('express');
const session     = require('express-session');
const app         = express();
const port        = 3050;
const bodyParser  = require('body-parser');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(require('express-useragent').express());
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

// Cors
app.use(async function(req, res, next) {

  let allowOrigins = [
    '(.*my-domain\.com)',
  ];

  if(Config.Env !== Environments.Production){
    res.header("Access-Control-Allow-Origin", "*");
  }else{
    res.header("Access-Control-Allow-Origin", Config.FrontEnd.Url);
    var origin = req.get('origin');
    console.log("origin",origin);
    for (let i = 0; i < allowOrigins.length; i++) {
      const allowOrigin = allowOrigins[i];
      if(origin.match(allowOrigin)){
        res.header("Access-Control-Allow-Origin", origin);
      }
    }
  }

  // example vars
  let user = req.query.user;
  let lang = req.query.lang;
  let time = req.query.time;

  // set language on session
  req.session.language = lang;


  console.log("user 1Ro:",user,"lang 1Ro:",lang);
  t(req,'test',{count: time});
  await sleep(time);
  console.log("user 2Ro:",user,"lang 2Ro:",lang);
  t(req,'test',{count: time});


  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, auth-id, auth-token, x-csrf-token, _csrf");
  res.header('Access-Control-Allow-Methods', 'PATCH, POST, GET, DELETE, OPTIONS');
  next();
});

all.js - 您的翻译放在这里。

// import translation objects here. then add to tranlations object


const convertToSingularLocale = (messages, locale ) => {
  let singleLocale = Object.assign({}, messages)

  for (let property in singleLocale) {
    if (property === locale) {
      return singleLocale[property]
    } else if (typeof singleLocale[property] === 'object') {
      singleLocale[property] = convertToSingularLocale(singleLocale[property], locale)
    }
  }

  return singleLocale
}

const translations = {
  general: {
    languageAbbreviation: {
      de: "de",
      es: "es",
      en: "en",
      ja: "ja",
      fr: "fr",
      zh: "zh",
    },
  },
  test:{
    en: "TEST {{count}}",
    ja: "テスト {{count}}",
  }
}

const english = convertToSingularLocale(translations, 'en')
const japanese = convertToSingularLocale(translations, 'ja')

const langResources = {
  en: english,
  ja: japanese,
}

const availableLanguages = [
  { name: "English", nativeName:"English", code: "en" },
  { name: "Japanese", nativeName:"日本語", code: "ja" },
]

module.exports = {
  langResources: langResources,
  availableLanguages: availableLanguages,
} 

i18n.js - 简单的翻译器




const defaultLang = "en";
const {langResources} = require('./all');

const translate = (req,str,args) => {
  let validLang = false;
  let lang = req.session.language;
  for (var key in langResources) {
    if(langResources.hasOwnProperty(key)) {
      validLang = true;
      break
    }
  }
  if(!validLang){
    lang = defaultLang;
  }

  const sourceLang = langResources[lang];

  var keys = str.split(".");

  let source = sourceLang;
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    source = source[key];
  }

  let text = source;
  for (var key in args) {
    if(args.hasOwnProperty(key)) {
      text = text.replace("{{"+key+"}}", args[key]);
    }
  }

  return text;
}

const i18n = {
  translate: translate,
  t: translate,
} 

module.exports = {
  i18n: i18n,
}