Как использовать переводы i18n JSON из некоторых JS скриптов, которые должны запускаться только на стороне клиента, с веб-сайта Node.js / Express / E JS? - PullRequest
0 голосов
/ 06 января 2020

Вот моя проблема,

Я использую i18n для управления переводами всего контента сайта, сделанного на Node.js, Express и Е JS. i18n использует файлы json на стороне сервера. Я обновил все нужные мне страницы, кроме одной.

У моего клиента на всех страницах вызывается файл js, вызываемый из нижнего колонтитула. Этот файл довольно плотный и запускается только на стороне клиента.

Из-за нехватки времени мы бы предпочли не проводить рефакторинг этого кода.

Как я могу использовать свой json переводить файлы на стороне сервера из сценария, который должен запускаться только на стороне клиента?

Я думал о создании специализированной службы API для вызова со стороны клиента и получения всех переводов, но это кажется довольно тяжелым ,

Или я, хотя и об использовании Node.js для записи вручную, в конце моего js файла работал на стороне клиента, переводил JSON файлы, когда они обновлялись. Но это будет означать тысячи строк, это правда, я должен забыть написать идеально чистый код для этого случая, но, хорошо ...

Прежде чем идти дальше, я очень признателен за вашу помощь в этом. Я бы хотел просто провести рефакторинг, но по некоторым хитрым причинам, это может быть не самым лучшим на данный момент.

Спасибо и хорошего вам дня. :)

1 Ответ

0 голосов
/ 12 января 2020

Что я наконец сделал:

Я создал каталог в / assets для хранения всех файлов перевода json.

При тестировании или разработке, при каждом запросе я проверяю если эти файлы были обновлены до или после / locales json files.

/ server. js

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

I Мне нужно улучшить этот следующий файл, так как я узнал, как плохо справлялся со своими обещаниями, хотя он отлично работает.

/ 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 я управляю переводами через повара ie. Как я уже упоминал, мне нужно было использовать файл сценария, включенный во все страницы нижнего колонтитула. Там я импортировал это:

getCurrentLanguage. 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 };
...