mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
i18n: fix review findings and polish ru/es strings
Fixes the 51 P0–P2 findings from the full review of the i18n branch and the issues found while checking every new string on screen in ru and es. - Translate errors and statuses that still reached ru/es in English: feed and tile errors, provider statuses, the ALPR chip, the traffic mode chip, voice plan step labels, fire feed values, receiver bands, scene save reasons and the Cesium attribution link. - Show preset city names in the UI language (src/ui/placeNames.js); data and everything sent to the model stay English. - Share layer names between the layer panel, HUD and voice card (src/ui/layerNames.js). - Keep long ru/es strings whole: voice card error lines, analyst titles, the voice tier status, the Nepal evidence button, the ALPR retry chip. English layout is unchanged. - Ask before a language switch drops unsaved work. - Catalog fixes: glossary terms (пуск, пресет), gender agreement and consistent "peticiones" in es, fewer calques in both languages. - Fix English text that was itself wrong (e.g. "Exit cockpit to fly to a weather", raw tool ids in voice plan steps). Catalogs: es/ru 2535 messages each, complete. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
8029747b7e
commit
00704ddc89
212 files changed
+9871
-909
No files matched your search
@@ -0,0 +1,134 @@
|
||||
// K-25: a refused key save reads in the panel's language. The server sends a
|
||||
// `code` (and `params`) beside its English `error`; the panel builds the
|
||||
// sentence through t(), so English stays the server's own text and es/ru get
|
||||
// the catalog's.
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
admitKeySetupRequest,
|
||||
KEY_SETUP_UPDATE_LIMIT,
|
||||
validateKeySetupUpdates,
|
||||
} from './keySetupCore.mjs';
|
||||
import { collectKeyUpdates, saveRefusalText } from './keySetup.js';
|
||||
import { setLocale } from './i18n/index.js';
|
||||
import { extractMessages } from '../scripts/i18n.mjs';
|
||||
|
||||
const local = {
|
||||
method: 'POST',
|
||||
remoteAddress: '127.0.0.1',
|
||||
hostHeader: 'localhost:4173',
|
||||
origin: 'http://localhost:4173',
|
||||
contentType: 'application/json',
|
||||
};
|
||||
|
||||
// Every refusal the core can return, plus the ones only the endpoint sends
|
||||
// (server/standalone/key-setup.js), with the English the server writes.
|
||||
const refusals = () => [
|
||||
validateKeySetupUpdates(
|
||||
collectKeyUpdates([{ envVar: 'OPENAI_API_KEY', value: '"sk-abc123"' }]),
|
||||
),
|
||||
validateKeySetupUpdates(
|
||||
collectKeyUpdates([{ envVar: 'OPENAI_API_KEY', value: 'sk abc123' }]),
|
||||
),
|
||||
validateKeySetupUpdates({ OPENAI_API_KEY: 'x'.repeat(600) }),
|
||||
validateKeySetupUpdates({ OPENAI_API_KEY: ' ' }),
|
||||
validateKeySetupUpdates({ OPENAI_API_KEY: 42 }),
|
||||
validateKeySetupUpdates({ PATH: '/usr/bin' }),
|
||||
validateKeySetupUpdates({}),
|
||||
validateKeySetupUpdates([]),
|
||||
validateKeySetupUpdates(
|
||||
Object.fromEntries(
|
||||
Array.from({ length: KEY_SETUP_UPDATE_LIMIT + 1 }, (_, i) => [
|
||||
`K${i}`,
|
||||
'v',
|
||||
]),
|
||||
),
|
||||
),
|
||||
admitKeySetupRequest({ ...local, proxyHeaders: { 'x-forwarded-for': '1' } }),
|
||||
admitKeySetupRequest({
|
||||
...local,
|
||||
env: { PINOKIO_SHARE_CLOUDFLARE: 'true' },
|
||||
}),
|
||||
admitKeySetupRequest({ ...local, remoteAddress: '192.168.1.20' }),
|
||||
admitKeySetupRequest({ ...local, hostHeader: 'workstation.local:4173' }),
|
||||
admitKeySetupRequest({ ...local, origin: undefined }),
|
||||
admitKeySetupRequest({ ...local, origin: 'not a url' }),
|
||||
admitKeySetupRequest({ ...local, origin: 'https://evil.example' }),
|
||||
admitKeySetupRequest({ ...local, contentType: 'text/plain' }),
|
||||
{ error: 'Method not allowed', code: 'method' },
|
||||
{ error: 'Request too large', code: 'too-large' },
|
||||
{ error: 'Invalid JSON', code: 'invalid-json' },
|
||||
{
|
||||
error:
|
||||
'OPENAI_API_KEY is configured outside Provider Settings and can only be changed where it was set',
|
||||
code: 'external',
|
||||
params: { name: 'OPENAI_API_KEY' },
|
||||
},
|
||||
{
|
||||
error:
|
||||
'The key was not saved: could not restrict the credential file to your account; nothing was saved',
|
||||
code: 'harden-failed',
|
||||
},
|
||||
{
|
||||
error:
|
||||
'The key was not saved: the existing configuration could not be read, so nothing was changed',
|
||||
code: 'store-unreadable',
|
||||
},
|
||||
{
|
||||
error: 'Could not write the env-file store',
|
||||
code: 'write-failed',
|
||||
params: { store: 'env-file' },
|
||||
},
|
||||
];
|
||||
|
||||
test('every refusal carries a code', () => {
|
||||
for (const refusal of refusals()) {
|
||||
assert.equal(refusal.ok ?? false, false);
|
||||
assert.equal(typeof refusal.code, 'string', refusal.error);
|
||||
}
|
||||
});
|
||||
|
||||
test('in English the panel shows exactly the server sentence', () => {
|
||||
setLocale('en');
|
||||
for (const refusal of refusals())
|
||||
assert.equal(saveRefusalText(refusal, 400), refusal.error);
|
||||
});
|
||||
|
||||
test('an unknown code or a bare error falls back as before', () => {
|
||||
setLocale('en');
|
||||
assert.equal(
|
||||
saveRefusalText({ error: 'Something new', code: 'new' }, 400),
|
||||
'Something new',
|
||||
);
|
||||
assert.equal(saveRefusalText({}, 502), 'Save failed (502).');
|
||||
});
|
||||
|
||||
test('the refusal sentences are catalog messages', () => {
|
||||
const messages = extractMessages();
|
||||
setLocale('en');
|
||||
for (const refusal of refusals()) {
|
||||
const pattern = saveRefusalText(
|
||||
{
|
||||
code: refusal.code,
|
||||
params: { name: '{name}', limit: '{limit}', store: '{store}' },
|
||||
},
|
||||
400,
|
||||
);
|
||||
assert.ok(messages.has(pattern), pattern);
|
||||
}
|
||||
});
|
||||
|
||||
for (const locale of ['es', 'ru']) {
|
||||
test(`${locale}: a refused save reads in the panel language`, () => {
|
||||
setLocale(locale);
|
||||
try {
|
||||
for (const refusal of refusals()) {
|
||||
const text = saveRefusalText(refusal, 400);
|
||||
assert.notEqual(text, refusal.error, `${locale}: ${refusal.error}`);
|
||||
if (refusal.params?.name) assert.ok(text.includes(refusal.params.name));
|
||||
}
|
||||
} finally {
|
||||
setLocale('en');
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user