Skip to content

Commit

Permalink
Server side translation evershopcommerce#305
Browse files Browse the repository at this point in the history
  • Loading branch information
treoden committed Aug 9, 2023
1 parent 514c07c commit de1c0c5
Show file tree
Hide file tree
Showing 18 changed files with 123 additions and 49 deletions.
7 changes: 5 additions & 2 deletions packages/evershop/bin/lib/addDefaultMiddlewareFuncs.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const { pool } = require('@evershop/evershop/src/lib/postgres/connection');
const {
setContextValue
} = require('@evershop/evershop/src/modules/graphql/services/contextHelper');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = exports = {};

Expand Down Expand Up @@ -277,8 +280,8 @@ exports.addDefaultMiddlewareFuncs = function addDefaultMiddlewareFuncs(
response.status(404);
request.currentRoute = routes.find((r) => r.id === 'notFound');
setContextValue(request, 'pageInfo', {
title: 'Not found',
description: 'Not found'
title: translate('Not found'),
description: translate('Not found')
});
next();
} else {
Expand Down
31 changes: 31 additions & 0 deletions packages/evershop/src/lib/locale/translate/translate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const {
loadCsvTranslationFiles
} = require('../../webpack/loaders/loadTranslationFromCsv');

var csvData = undefined;

/**
* This function is used to translate the text form server side, like from middleware. For templating use the _ function
*/
module.exports.translate = function translate(enText, values = {}) {
const translatedText =
csvData[enText] !== undefined ? csvData[enText] : enText;
// Check if the data is null, undefined or empty object
if (!values || Object.keys(values).length === 0) {
return translatedText;
} else {
const template = `${translatedText}`;
return template.replace(/\${(.*?)}/g, (match, key) =>
values[key.trim()] !== undefined ? values[key.trim()] : match
);
}
};

module.exports.loadCsv = async function loadCsv() {
// Only load the csv files once
if (csvData === undefined) {
csvData = await loadCsvTranslationFiles();
} else {
return;
}
};
24 changes: 24 additions & 0 deletions packages/evershop/src/lib/util/readCsvFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const fs = require('fs');
const csv = require('csv-parser');

async function readCsvFile(filePath) {
return new Promise((resolve, reject) => {
const results = {};
fs.createReadStream(filePath)
.pipe(csv({ headers: false }))
.on('data', (data) => {
// Skip the first row (headers)
if (!data[0].startsWith('#')) {
results[data[0]] = data[1];
}
})
.on('end', () => {
resolve(results);
})
.on('error', (err) => {
reject(err);
});
});
}

module.exports.readCsvFile = readCsvFile;
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,22 @@
/* eslint-disable global-require */
module.exports = exports = async function TranslationLoader(c) {
const csvData = await this.getOptions().getTranslateData();
//console.log('csvData', csvData);
// Use regex to find all function call `t()` in the template string
// Use regex to find all function call `_()` in the template string
const regex =
/_\s*\(\s*(?<arg1>["'][^"']*["']|\w+)\s*(?:,\s*(?<arg2>null|\{[\s\S]*?\}|[\w\.]+)\s*)?\)/g;
/_\s*\(\s*(?<arg1>"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*'|\w+)\s*(?:,\s*(?<arg2>null|\{[\s\S]*?\}|"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*'|\w+)\s*)?\)/g;

let result = c;
// Loop through each function call and get the template string
let match;
while ((match = regex.exec(c)) !== null) {
let template = match.groups.arg1;
// Remove the quote from the start and end of the template string
template = template.replace(/^['"]|['"]$/g, '');
template = template.replace(/^["']/, '').replace(/["']$/, '');
const newValue = csvData[template];
// Check if the template is exist in the csvData
if (newValue) {
result = result.replace(match[0], `_("${newValue}",${match[2] || null})`);
}
}

return result;
};
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
const fs = require('fs');
const csv = require('csv-parser');
const { getConfig } = require('../../util/getConfig');
const path = require('path');
const { CONSTANTS } = require('../../helpers');

async function readCsvFile(filePath) {
return new Promise((resolve, reject) => {
const results = {};
fs.createReadStream(filePath)
.pipe(csv({ headers: false }))
.on('data', (data) => {
// Skip the first row (headers)
if (!data[0].startsWith('#')) {
results[data[0]] = data[1];
}
})
.on('end', () => {
resolve(results);
})
.on('error', (err) => {
reject(err);
});
});
}
const { readCsvFile } = require('../../util/readCsvFile');

module.exports.loadCsvTranslationFiles =
async function loadCsvTranslationFiles() {
Expand All @@ -36,7 +16,7 @@ module.exports.loadCsvTranslationFiles =

// Check if path exists
if (!fs.existsSync(folderPath)) {
return [];
return {};
}

const results = {};
Expand Down
7 changes: 7 additions & 0 deletions packages/evershop/src/modules/base/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const {
loadCsv
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = async () => {
await loadCsv();
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');
const { setContextValue } = require('../../../graphql/services/contextHelper');

module.exports = async (request, response, delegate, next) => {
if (response.statusCode !== 404) {
next();
} else {
setContextValue(request, 'pageInfo', {
title: 'Not found',
description: 'Page not found'
title: translate('Not found'),
description: translate('Page not found')
});
next();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');
const {
setContextValue
} = require('@evershop/evershop/src/modules/graphql/services/contextHelper');
Expand Down Expand Up @@ -47,8 +50,8 @@ module.exports = (request, response, delegate, next) => {
// Remove html tags
const keyword = query.keyword;
setContextValue(request, 'pageInfo', {
title: `Search results for "${keyword}"`,
description: `Search results for "${keyword}"`
title: translate('Search results for "${keyword}"', { keyword }),
description: translate('Search results for "${keyword}"', { keyword })
});

filtersFromUrl.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const {
getContextValue
} = require('../../../../graphql/services/contextHelper');
const { getCustomerCart } = require('../../../services/getCustomerCart');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = async (request, response, delegate, next) => {
const cart = await getCustomerCart(
Expand All @@ -19,8 +22,8 @@ module.exports = async (request, response, delegate, next) => {
response.redirect(302, buildUrl('cart'));
} else {
setContextValue(request, 'pageInfo', {
title: 'Checkout',
description: 'Checkout'
title: translate('Checkout'),
description: translate('Checkout')
});
setContextValue(request, 'cart_id', cart.getData('uuid'));
next();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');
const { get } = require('@evershop/evershop/src/lib/util/get');
const { select } = require('@evershop/postgres-query-builder');

Expand Down Expand Up @@ -30,7 +33,7 @@ module.exports = {
if (!rewriteRule) {
return [
{
title: 'Home',
title: translate('Home'),
url: '/'
},
{
Expand All @@ -46,7 +49,7 @@ module.exports = {
// Build the breadrumbs
const breadcrumbs = [
{
title: 'Home',
title: translate('Home'),
url: '/'
}
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const {
getContextValue,
setContextValue
} = require('../../../../graphql/services/contextHelper');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = (request, response, delegate, next) => {
// Check if the user is logged in
Expand All @@ -12,8 +15,8 @@ module.exports = (request, response, delegate, next) => {
response.redirect(buildUrl('homepage'));
} else {
setContextValue(request, 'pageInfo', {
title: 'Account details',
description: 'Account details'
title: translate('Account details'),
description: translate('Account details')
});
next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const {
getContextValue,
setContextValue
} = require('../../../../graphql/services/contextHelper');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = (request, response, delegate, next) => {
// Check if the user is logged in
Expand All @@ -12,8 +15,8 @@ module.exports = (request, response, delegate, next) => {
response.redirect(buildUrl('homepage'));
} else {
setContextValue(request, 'pageInfo', {
title: 'Login',
description: 'Login'
title: translate('Login'),
description: translate('Login')
});
next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const {
getContextValue,
setContextValue
} = require('../../../../graphql/services/contextHelper');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = (request, response, delegate, next) => {
// Check if the user is logged in
Expand All @@ -12,8 +15,8 @@ module.exports = (request, response, delegate, next) => {
response.redirect(buildUrl('homepage'));
} else {
setContextValue(request, 'pageInfo', {
title: 'Create an account',
description: 'Create an account'
title: translate('Create an account'),
description: translate('Create an account')
});
next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const {
getContextValue,
setContextValue
} = require('../../../../graphql/services/contextHelper');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = (request, response, delegate, next) => {
// Check if the user is logged in
Expand All @@ -12,8 +15,8 @@ module.exports = (request, response, delegate, next) => {
response.redirect(buildUrl('homepage'));
} else {
setContextValue(request, 'pageInfo', {
title: 'Reset password',
description: 'Reset password'
title: translate('Reset password'),
description: translate('Reset password')
});
next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const {
getContextValue,
setContextValue
} = require('../../../../graphql/services/contextHelper');
const {
translate
} = require('@evershop/evershop/src/lib/locale/translate/translate');

module.exports = (request, response, delegate, next) => {
// Check if the user is logged in
Expand All @@ -12,8 +15,8 @@ module.exports = (request, response, delegate, next) => {
response.redirect(buildUrl('homepage'));
} else {
setContextValue(request, 'pageInfo', {
title: 'Update password',
description: 'Update password'
title: translate('Update password'),
description: translate('Update password')
});
next();
}
Expand Down
3 changes: 2 additions & 1 deletion translations/zh/catalog.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ Featured collection, 精选合集
SHOP BY, 按类别购买
Sort By, 按类别排序
There is no product to display, 没有产品可显示
${count} products, ${count} 个产品
${count} products, ${count} 个产品
Search results for "${keyword}", 搜索结果为 “${keyword}”
4 changes: 3 additions & 1 deletion translations/zh/general.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ Discount ${discount} For All Orders Over ${price}, 所有超过 ${price} 的订
Please select, 请选择
The page you requested does not exist., 您请求的页面不存在。
Continue shopping, 继续购物
404 Page Not Found, 404 页面未找到
404 Page Not Found, 404 页面未找到
Home, 首页
Not found, 未找到

0 comments on commit de1c0c5

Please sign in to comment.