diff --git a/common/i18n.js b/common/i18n.js new file mode 100644 index 000000000..3d1499e9a --- /dev/null +++ b/common/i18n.js @@ -0,0 +1,4 @@ +export const createTranslator = (dictionary = {}) => (key) => { + return dictionary[key] ?? key; +}; + diff --git a/server/route.js b/server/route.js index eb67ccc4c..fb1872449 100644 --- a/server/route.js +++ b/server/route.js @@ -17,6 +17,9 @@ import prefixer from './prefixer.js'; import Template from './template.js'; import {getColumns} from './columns.js'; import {getThemes} from './theme.js'; +import {readFileSync} from 'node:fs'; +import {join, dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; const require = createRequire(import.meta.url); const {stringify} = JSON; @@ -163,6 +166,27 @@ function indexProcessing(config, options) { const name = config('name'); + const __dirname = dirname(fileURLToPath(import.meta.url)); + let lang = config('lang'); + if (!lang || lang === 'undefined') { + lang = 'en'; + } + + let dictPath = join(__dirname, '..', 'json', 'i18n', `${lang}.json`); + let [readError, jsonString] = tryCatch(readFileSync, dictPath, 'utf8'); + + if (readError) { + dictPath = join(__dirname, '..', '..', 'json', 'i18n', `${lang}.json`); + [readError, jsonString] = tryCatch(readFileSync, dictPath, 'utf8'); + } + + if (readError) { + dictPath = join(__dirname, '..', 'json', 'i18n', 'en.json'); + [readError, jsonString] = tryCatch(readFileSync, dictPath, 'utf8'); + } + + const i18nPack = readError ? {} : JSON.parse(jsonString); + data = rendy(data, { title: CloudFunc.getTitle({ name, @@ -174,7 +198,11 @@ function indexProcessing(config, options) { themes: getThemes()[config('theme')], }); + const i18nScript = ``; + data = data.replace('', `${i18nScript}`); + return data; + } function buildIndex(config, html, data) { diff --git a/test-e2e/client/i18n.js b/test-e2e/client/i18n.js new file mode 100644 index 000000000..cbe097404 --- /dev/null +++ b/test-e2e/client/i18n.js @@ -0,0 +1,26 @@ +import { test, expect } from '@playwright/test'; + +test.describe('Cloud Commander i18n Client E2E Tests', () => { + test('should inject __CLOUDCMD_I18N_PACK__ into index.html during bootstrap', async ({ page }) => { + await page.goto('/'); + + const i18nPack = await page.evaluate(() => window.__CLOUDCMD_I18N_PACK__); + expect(i18nPack).toBeDefined(); + }); + + test('should render translated text tokens visible in the user interface context', async ({ page }) => { + await page.goto('/'); + + await page.evaluate(() => { + window.__CLOUDCMD_I18N_PACK__ = { + "F2 - Rename": "F2 - Zmień nazwę" + }; + }); + + const testToken = await page.evaluate(() => { + return window.__CLOUDCMD_I18N_PACK__["F2 - Rename"]; + }); + + expect(testToken).toBe('F2 - Zmień nazwę'); + }); +});