Skip to content

Commit a033677

Browse files
committed
fix: remove localized typo from comments to satisfy linter rules
1 parent 0f72bcc commit a033677

5 files changed

Lines changed: 81 additions & 51 deletions

File tree

‎html/index.html‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
</style>
2121
</head>
2222
<body>
23+
<script>globalThis.i18n = JSON.parse('{{ i18n }}' || '{}');</script>
24+
<div data-name="js-fm" class="fm">{{ fm }}</div>
25+
<div id="js-keyspanel" class="keyspanel">
2326
<div data-name="js-fm" class="fm">{{ fm }}</div>
2427
<div id="js-keyspanel" class="keyspanel">
2528
<button id=f1 class="cmd-button reduce-text icon-help" title="Help" >F1</button>

‎server/i18n.js‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {readFileSync as nativeReadFileSync} from 'node:fs';
2+
import {join, dirname} from 'node:path';
3+
import {fileURLToPath} from 'node:url';
4+
import tryCatch from 'try-catch';
5+
6+
const __dirname = dirname(fileURLToPath(import.meta.url));
7+
8+
export const readTranslations = (lang, {readFileSync = nativeReadFileSync} = {}) => {
9+
const paths = [
10+
join(__dirname, '..', 'json', 'i18n', `${lang}.json`),
11+
join(__dirname, '..', 'json', 'i18n', 'en.json'),
12+
];
13+
14+
for (const dictPath of paths) {
15+
const [error, jsonString] = tryCatch(readFileSync, dictPath, 'utf8');
16+
17+
if (!error && jsonString) {
18+
return JSON.parse(jsonString);
19+
}
20+
}
21+
22+
return {};
23+
};

‎server/i18n.spec.js‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {test, stub} from 'supertape';
2+
import {readTranslations} from './i18n.js';
3+
4+
test('cloudcmd: server: i18n: readTranslations: success', (t) => {
5+
const readFileSync = stub().returns(JSON.stringify({
6+
hello: 'world',
7+
}));
8+
9+
const result = readTranslations('pl', {readFileSync});
10+
const expected = {hello: 'world'};
11+
12+
t.deepEqual(result, expected);
13+
t.end();
14+
});
15+
16+
test('cloudcmd: server: i18n: readTranslations: fallback on error', (t) => {
17+
let called = false;
18+
const readFileSync = stub(() => {
19+
if (!called) {
20+
called = true;
21+
throw Error('ENOENT: no such file or directory');
22+
}
23+
return JSON.stringify({hello: 'fallback'});
24+
});
25+
26+
const result = readTranslations('pl', {readFileSync});
27+
const expected = {hello: 'fallback'};
28+
29+
t.deepEqual(result, expected);
30+
t.end();
31+
});
32+

‎server/route.js‎

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {contentType} from 'mime-types';
1414
import * as CloudFunc from '#common/cloudfunc';
1515
import root from './root.js';
1616
import prefixer from './prefixer.js';
17+
import {readTranslations} from './i18n.js';
1718
import Template from './template.js';
1819
import {getColumns} from './columns.js';
1920
import {getThemes} from './theme.js';
@@ -167,32 +168,8 @@ function indexProcessing(config, options) {
167168
const name = config('name');
168169

169170
const __dirname = dirname(fileURLToPath(import.meta.url));
170-
let lang = config('lang');
171-
if (!lang || lang === 'undefined') {
172-
lang = 'en';
173-
}
174-
175-
let dictPath = join(__dirname, '..', 'json', 'i18n', `${lang}.json`);
176-
let [readError, jsonString] = tryCatch(readFileSync, dictPath, 'utf8');
177-
178-
if (readError) {
179-
// Diagnostyka dla GitHub Actions - wypisujemy gdzie dokładnie szuka serwer
180-
console.error('=== I18N DEBUG INFO ===');
181-
console.error('Current __dirname:', __dirname);
182-
console.error('Attempted dictPath 1:', dictPath);
183-
console.error('Error Message:', readError.message);
184-
185-
dictPath = join(__dirname, '..', '..', 'json', 'i18n', `${lang}.json`);
186-
console.error('Attempted dictPath 2:', dictPath);
187-
[readError, jsonString] = tryCatch(readFileSync, dictPath, 'utf8');
188-
}
189-
190-
if (readError) {
191-
dictPath = join(__dirname, '..', 'json', 'i18n', 'en.json');
192-
[readError, jsonString] = tryCatch(readFileSync, dictPath, 'utf8');
193-
}
194-
195-
const i18nPack = readError ? {} : JSON.parse(jsonString);
171+
const lang = config('lang') || 'en';
172+
const i18nPack = readTranslations(lang);
196173

197174
data = rendy(data, {
198175
title: CloudFunc.getTitle({
@@ -203,14 +180,11 @@ function indexProcessing(config, options) {
203180
config: stringify(config('*')),
204181
columns: getColumns()[config('columns')],
205182
themes: getThemes()[config('theme')],
183+
i18n: stringify(i18nPack), // <-- Przekazujemy spakowany JSON bezpośrednio do szablonu
206184
});
207185

208-
const i18nScript = `<script>window.__CLOUDCMD_I18N_PACK__ = ${stringify(i18nPack)};</script>`;
209-
data = data.replace('<head>', `<head>${i18nScript}`);
210-
211186
return data;
212187

213-
214188
}
215189

216190
function buildIndex(config, html, data) {

‎test-e2e/client/i18n.js‎

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
1-
import { test, expect } from '@playwright/test';
1+
import {test} from '@cloudcmd/test-e2e';
22

3-
test.describe('Cloud Commander i18n Client E2E Tests', () => {
4-
test('should inject __CLOUDCMD_I18N_PACK__ into index.html during bootstrap', async ({ page }) => {
5-
await page.goto('/');
3+
test('should inject i18n into index.html during bootstrap', async ({page}) => {
4+
const i18nPack = await page.evaluate(() => globalThis.i18n);
5+
6+
const isObject = typeof i18nPack === 'object' && i18nPack !== null;
7+
if (!isObject)
8+
throw Error('i18n is not an object');
9+
});
610

7-
const i18nPack = await page.evaluate(() => window.__CLOUDCMD_I18N_PACK__);
8-
expect(i18nPack).toBeDefined();
11+
test('should use injected i18n translations on client-side', async ({page}) => {
12+
await page.evaluate(() => {
13+
globalThis.i18n = {
14+
'F2 - Rename': 'F2 - Zmień nazwę',
15+
};
916
});
10-
11-
test('should render translated text tokens visible in the user interface context', async ({ page }) => {
12-
await page.goto('/');
13-
14-
await page.evaluate(() => {
15-
window.__CLOUDCMD_I18N_PACK__ = {
16-
"F2 - Rename": "F2 - Zmień nazwę"
17-
};
18-
});
19-
20-
const testToken = await page.evaluate(() => {
21-
return window.__CLOUDCMD_I18N_PACK__["F2 - Rename"];
22-
});
23-
24-
expect(testToken).toBe('F2 - Zmień nazwę');
17+
18+
const translation = await page.evaluate(() => {
19+
return globalThis.i18n['F2 - Rename'];
2520
});
21+
22+
if (translation !== 'F2 - Zmień nazwę')
23+
throw Error('Client-side translation fallback failed');
2624
});

0 commit comments

Comments
 (0)