如何使用来自 Node.js / Express / EJS 网站的一些 JS 脚本中的 i18n JSON t运行 版本,这些脚本仅 运行 客户端?
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 t运行slation 文件服务器端的脚本,该脚本将 运行 仅在客户端?
我虽然想制作一个专用的 api 服务来从客户端调用并获取所有 t运行 选项,但它看起来很重。
或者我虽然使用 Node.js 手动编写,但在我的 js 文件 运行 客户端的末尾,t运行slations 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 管理翻译。正如我提到的,我需要使用包含在页脚上所有页面中的脚本文件。在那里,我导入了这个:
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 };
然后,我得到所有的翻译和return当前语言客户端可用的一个(我意识到我只需要一个翻译文件,以后会改进)。
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 };
这是我的问题,
我正在使用 i18n 来管理在 Node.js、Express 和 EJS 上制作的网站所有内容的翻译运行。 i18n 在服务器端使用 json 文件。我已经更新了所有需要更新的页面,只有一个页面除外。
我的客户端习惯于在每个页面的页脚调用一个js文件。此文件非常密集,运行 仅在客户端。
由于时间限制,我们不希望重构此代码。
我如何使用我的 json t运行slation 文件服务器端的脚本,该脚本将 运行 仅在客户端?
我虽然想制作一个专用的 api 服务来从客户端调用并获取所有 t运行 选项,但它看起来很重。
或者我虽然使用 Node.js 手动编写,但在我的 js 文件 运行 客户端的末尾,t运行slations 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 管理翻译。正如我提到的,我需要使用包含在页脚上所有页面中的脚本文件。在那里,我导入了这个:
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 };
然后,我得到所有的翻译和return当前语言客户端可用的一个(我意识到我只需要一个翻译文件,以后会改进)。
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 };