繁体   English   中英

如何使用来自 Node.js/Express/EJS 网站的一些 JS 脚本的 i18n JSON 翻译,这些脚本只能在客户端运行?

[英]How to use i18n JSON translations from some JS scripts that are to be ran only client-side, from a Node.js / Express / EJS website?

这是我的问题,

我正在使用i18n来管理在 Node.js、Express 和 EJS 上制作的网站的所有内容的翻译。 i18n 在服务器端使用 json 文件。 我已经更新了我需要的所有页面,除了一个。

我的客户端习惯于在每个页面上从页脚调用一个 js 文件。 该文件非常密集,仅在客户端运行。

由于时间限制,我们不希望重构此代码。

如何从仅在客户端运行的脚本中使用我的 json 翻译文件服务器端?

我想制作一个专用的 api 服务来从客户端调用并获取所有翻译,但它似乎很重。

或者我想使用 Node.js 手动编写,在我的 js 文件的末尾运行客户端,当它们更新时翻译 JSON 文件。 但这将意味着数千行,确实我必须忘记为这种情况编写完美干净的代码,但是,好吧......

在继续之前,我非常感谢您在这方面的帮助。 我很想重构,但由于一些棘手的原因,它现在可能不是最好的。

谢谢,祝大家有美好的一天。 :)

我最后做了什么:

我在 /assets 中创建了一个目录来存储所有翻译 json 文件。

如果在测试或开发环境中,在每次请求时,我都会检查这些文件是否在 /locales json 文件之前或之后更新。

/server.js

const { watchAssetsTrads } = require("./middleware/clientSideTrads");
const notInProd = env === "test" || env === "dev";
if (notInProd) app.use((req, res, next) => watchAssetsTrads(next));

我需要改进下一个文件,因为我在这里了解到我是如何管理我的承诺的,尽管它很有效。

/middlewares/clientSideTrads.js

const debug = require("debug")("trads");
const fs = require('fs');
const lodash = require('lodash');
const path = require('path');

const locales = path.join(__dirname, '../locales/');
const assetsTrads = path.join(__dirname, '../assets/trads');

const getFilesNamesFrom = path => {
  return new Promise((resolve, reject) => {
    fs.readdir(path, (err, files) => {
      if (err) return reject(err);
      return resolve(files.filter(e => e !== ".DS_Store"));
    });
  });
};

const read = jsonPath => {
  return new Promise((resolve, reject) => {
    fs.readFile(jsonPath, (err, data) => {
      if (err) return reject(err);
      return resolve(JSON.parse(data));
    });
  });
};

const update = (jsonPath, newJson) => {
  return new Promise((resolve, reject) => {
    fs.writeFile(jsonPath, JSON.stringify(newJson), err => {
      if (err) return reject(err);
      return resolve();
    });
  });
};

const getLastUpdateTime = filePath => {
  return new Promise((resolve, reject) => {
    fs.stat(filePath, (err, stats) => {
      if (err) return reject(err);
      return resolve(stats.mtime);
    });
  });
};

const updateAssetsTrads = async (localesTradPath, assetsTradPath) => {
  const localesTrad = await read(localesTradPath);
  const selectedKeys = lodash.pickBy(localesTrad, function(value, key) {
    if ((/^clientside/u).test(key)) return true;
    return false;
  });
  await update(assetsTradPath, selectedKeys);
  return null;
};

const watchAssetsTrads = async next => {
  debug('Checking asset trads');
  const files = await getFilesNamesFrom(locales);
  files.forEach(async file => {
    try {
      const localesTradPath = path.join(locales, file);
      const assetsTradPath = path.join(assetsTrads, file);
      const lastUpdate = await getLastUpdateTime(localesTradPath);
      const lastMerge = await getLastUpdateTime(assetsTradPath);
      if (lastUpdate > lastMerge) {
        updateAssetsTrads(localesTradPath, assetsTradPath);
        debug('File updated');
      }
    }
    catch (err) {
      return debug(err);
    }
    return null;
  });
  return next();
};

module.exports = {
  watchAssetsTrads
};

使用 i18n,我通过 cookie 管理翻译。 正如我所提到的,我需要使用包含在页脚所有页面中的脚本文件。 在那里,我已经导入了这个:

获取当前语言.js

const getCookie = () => {
  const cookies = document.cookie.split('; ');
  const myCookie = cookies.filter(c => (/^my-cookie/u).test(c));
  if (typeof myCookie[0] == 'undefined') return 'fr';
  const cookieSplitted = myCookie[0].split('=');
  const currentLanguage = cookieSplitted[1];
  return currentLanguage;
};

const getCurrentLanguage = () => {
  const currentLanguage = getCookie();
  return currentLanguage;
};

export { getCurrentLanguage };

然后,我获得所有翻译并返回当前语言客户端可用的翻译(我意识到我只需要获得一个翻译文件,即将改进)。

getTrads.js

const createTradsObjFrom = async (languages, tradsPaths) => {
  try {
    const obj = {};
    for (const [index, lang] of languages.entries()) {
      const path = tradsPaths[index];
      obj[lang] = {
        json: await $.getJSON(path)
      };
    }
    return obj;
  }
  catch (err) {
    throw new Error("some error");
  }
};

const getTrads = currentLanguage => {
  return new Promise((resolve, reject) => {
    const tradsDir = "/assets/trads/";
    const languages = [
      "de",
      "en",
      "es",
      "fr",
      "it",
      "nl",
      "ru"
    ];
    const tradsPaths = languages.map(e => tradsDir + e + '.json');
    createTradsObjFrom(languages, tradsPaths)
    .then(trads => resolve(trads[currentLanguage].json))
    .catch(err => reject(err));
  });
};

export { getTrads };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM