fix(i18n): translate visual preset parameter sliders

The slider labels (Sensitivity, Bloom, Pixelation, …) live in the shader
modules and were rendered raw, so they stayed English in every locale.
Mark them with msg() and render them through t(); add es and ru entries.
WHOT/BHOT and Ironbow keep their names. Russian Bloom is now «Свечение».

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-12 18:11:20 +04:00
1 parent 70936b58b9
commit eee905e787
11 files changed
+78 -28

No files matched your search

+10 -2
View File
@@ -386,7 +386,11 @@
"modules": [
"src/ui/visualInput.js",
"src/ui/applicationShortcuts.js",
"src/ui/styleParameters.js"
"src/ui/styleParameters.js",
"src/i18n/index.js",
"src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json"
],
"external": []
},
@@ -407,7 +411,11 @@
"src/styles/thermal.js",
"src/styles/anime.js",
"src/styles/noir.js",
"src/styles/snow.js"
"src/styles/snow.js",
"src/i18n/index.js",
"src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json"
],
"external": ["cesium"]
},
+2 -2
View File
@@ -28,6 +28,6 @@ test('the first-run checkbox keeps its native visible label', () => {
});
test('generated style sliders use the visible parameter label as their name', () => {
assert.match(parameters, /label\.textContent\s*=\s*metadata\.label;/);
assert.match(parameters, /slider\.setAttribute\(['"]aria-label['"],\s*metadata\.label\)/);
assert.match(parameters, /label\.textContent\s*=\s*t\(metadata\.label\);/);
assert.match(parameters, /slider\.setAttribute\(['"]aria-label['"],\s*t\(metadata\.label\)\)/);
});
+15 -1
View File
@@ -859,5 +859,19 @@
"LIVE · Roads: OpenStreetMap · Flow: TomTom · {percent}% cov · Unmatched: simulated": "EN VIVO · Vías: OpenStreetMap · Flujo: TomTom · {percent}% cob. · Sin coincidencia: simulado",
"LIVE · Roads: OpenStreetMap · Flow: TomTom · {percent}% cov": "EN VIVO · Vías: OpenStreetMap · Flujo: TomTom · {percent}% cob.",
"SIMULATED · Roads: OpenStreetMap · Flow: TomTom (no matches)": "SIMULADO · Vías: OpenStreetMap · Flujo: TomTom (sin coincidencias)",
"Data source unavailable": "Fuente de datos no disponible"
"Data source unavailable": "Fuente de datos no disponible",
"Saturation": "Saturación",
"Edge Thickness": "Grosor de bordes",
"Contrast": "Contraste",
"Grain": "Grano",
"Vignette": "Viñeta",
"Pixelation": "Pixelado",
"Distortion": "Distorsión",
"Instability": "Inestabilidad",
"Wind": "Viento",
"Gain": "Ganancia",
"Scanlines": "Líneas de barrido",
"Sensitivity": "Sensibilidad",
"WHOT/BHOT": "WHOT/BHOT",
"Ironbow": "Ironbow"
}
+16 -2
View File
@@ -776,7 +776,7 @@
"Feather": "Растушёвка",
"Celestial": "Небо",
"Clean UI": "Чистый интерфейс",
"Bloom": "Bloom",
"Bloom": "Свечение",
"Sharpen": "Резкость",
"Initializing photorealistic world...": "Инициализация фотореалистичного мира...",
"NEAREST": "БЛИЖАЙШАЯ",
@@ -866,5 +866,19 @@
"Voice model: {pendingId} — click to switch to {target}; applies next session": "Голосовая модель: {pendingId} — нажмите, чтобы переключиться на {target}; вступит в силу со следующей сессии",
"Estimated session cost on {modelId} — {responses} response(s). Warns at {warn}, ends the session at {cap}.": "Оценочная стоимость сессии на {modelId} — ответов: {responses}. Предупреждение при {warn}, завершение сессии при {cap}.",
"Radio did not start": "Не удалось запустить радио",
"Running command": "Выполнение команды"
"Running command": "Выполнение команды",
"Saturation": "Насыщенность",
"Edge Thickness": "Толщина контуров",
"Contrast": "Контраст",
"Grain": "Зерно",
"Vignette": "Виньетка",
"Pixelation": "Пикселизация",
"Distortion": "Искажение",
"Instability": "Нестабильность",
"Wind": "Ветер",
"Gain": "Усиление",
"Scanlines": "Строки развёртки",
"Sensitivity": "Чувствительность",
"WHOT/BHOT": "WHOT/BHOT",
"Ironbow": "Ironbow"
}
+4 -2
View File
@@ -1,3 +1,5 @@
import { msg } from '../i18n/index.js';
/**
* Anime / Studio Ghibli Style — Cel-shading + Saturation boost
* Transforms the world into an animated film look
@@ -5,8 +7,8 @@
export const animeShader = {
name: 'anime',
uniforms: {
saturation: { default: 1.0, min: 0, max: 2, label: 'Saturation' },
edgeThick: { default: 0.5, min: 0, max: 1, label: 'Edge Thickness' },
saturation: { default: 1.0, min: 0, max: 2, label: msg('Saturation') },
edgeThick: { default: 0.5, min: 0, max: 1, label: msg('Edge Thickness') },
},
fragmentShader: /* glsl */ `
uniform sampler2D colorTexture;
+5 -3
View File
@@ -1,3 +1,5 @@
import { msg } from '../i18n/index.js';
/**
* Noir Style — Desaturation + High Contrast + Vignette
* Classic film noir / detective movie look
@@ -5,9 +7,9 @@
export const noirShader = {
name: 'noir',
uniforms: {
contrastAmt: { default: 1.2, min: 0, max: 2, label: 'Contrast' },
grainAmt: { default: 0.5, min: 0, max: 1, label: 'Grain' },
vignetteAmt: { default: 0.5, min: 0, max: 1, label: 'Vignette' },
contrastAmt: { default: 1.2, min: 0, max: 2, label: msg('Contrast') },
grainAmt: { default: 0.5, min: 0, max: 1, label: msg('Grain') },
vignetteAmt: { default: 0.5, min: 0, max: 1, label: msg('Vignette') },
},
fragmentShader: /* glsl */ `
uniform sampler2D colorTexture;
+5 -3
View File
@@ -1,3 +1,5 @@
import { msg } from '../i18n/index.js';
/**
* CRT Terminal — Dynamic CRT Monitor Aesthetic
* Pixelation + Bayer dithering + barrel distortion + scanlines +
@@ -12,9 +14,9 @@
export const retroShader = {
name: 'retro',
uniforms: {
pixelation: { default: 5.0, min: 1, max: 10, label: 'Pixelation' },
distortion: { default: 0, min: 0, max: 1, label: 'Distortion' },
instability: { default: 0.4, min: 0, max: 1, label: 'Instability' },
pixelation: { default: 5.0, min: 1, max: 10, label: msg('Pixelation') },
distortion: { default: 0, min: 0, max: 1, label: msg('Distortion') },
instability: { default: 0.4, min: 0, max: 1, label: msg('Instability') },
},
fragmentShader: /* glsl */ `
uniform sampler2D colorTexture;
+4 -2
View File
@@ -1,3 +1,5 @@
import { msg } from '../i18n/index.js';
/**
* Snow Style — White overlay + Desaturation + Falling particles
* Transforms the world into a winter wonderland
@@ -5,8 +7,8 @@
export const snowShader = {
name: 'snow',
uniforms: {
density: { default: 0.6, min: 0, max: 1, label: 'Density' },
wind: { default: 0.5, min: 0, max: 1, label: 'Wind' },
density: { default: 0.6, min: 0, max: 1, label: msg('Density') },
wind: { default: 0.5, min: 0, max: 1, label: msg('Wind') },
},
fragmentShader: /* glsl */ `
uniform sampler2D colorTexture;
+6 -4
View File
@@ -1,3 +1,5 @@
import { msg } from '../i18n/index.js';
/**
* Night Vision / NVG — PVS-14 Image Intensifier Emulation
* P43 phosphor green, intensifier tube bloom, circular vignette,
@@ -12,10 +14,10 @@
export const nightVisionShader = {
name: 'surveillance',
uniforms: {
gain: { default: 0.55, min: 0, max: 1, label: 'Gain' },
bloom: { default: 0.3, min: 0, max: 1, label: 'Bloom' },
scanlineStr: { default: 1.0, min: 0, max: 1, label: 'Scanlines' },
pixelation: { default: 2.5, min: 1, max: 6, label: 'Pixelation' },
gain: { default: 0.55, min: 0, max: 1, label: msg('Gain') },
bloom: { default: 0.3, min: 0, max: 1, label: msg('Bloom') },
scanlineStr: { default: 1.0, min: 0, max: 1, label: msg('Scanlines') },
pixelation: { default: 2.5, min: 1, max: 6, label: msg('Pixelation') },
},
fragmentShader: /* glsl */ `
uniform sampler2D colorTexture;
+7 -5
View File
@@ -1,3 +1,5 @@
import { msg } from '../i18n/index.js';
/**
* FLIR — Forward Looking Infrared
* Military-grade thermal imaging with White-Hot/Black-Hot modes,
@@ -14,11 +16,11 @@
export const thermalShader = {
name: 'thermal',
uniforms: {
sensitivity: { default: 0.75, min: 0, max: 1, label: 'Sensitivity' },
bloom: { default: 0.65, min: 0, max: 1, label: 'Bloom' },
mode: { default: 0.0, min: 0, max: 1, label: 'WHOT/BHOT' },
pixelation: { default: 1.5, min: 1, max: 6, label: 'Pixelation' },
palette: { default: 0.0, min: 0, max: 1, label: 'Ironbow' },
sensitivity: { default: 0.75, min: 0, max: 1, label: msg('Sensitivity') },
bloom: { default: 0.65, min: 0, max: 1, label: msg('Bloom') },
mode: { default: 0.0, min: 0, max: 1, label: msg('WHOT/BHOT') },
pixelation: { default: 1.5, min: 1, max: 6, label: msg('Pixelation') },
palette: { default: 0.0, min: 0, max: 1, label: msg('Ironbow') },
},
fragmentShader: /* glsl */ `
uniform sampler2D colorTexture;
+4 -2
View File
@@ -1,3 +1,5 @@
import { t } from '../i18n/index.js';
/**
* Own generated parameter rows and their input listeners.
* The caller supplies uniform metadata/value access and rendering/persistence
@@ -30,11 +32,11 @@ export function createStyleParameters({
row.className = 'param-slider-row';
const label = documentRef.createElement('span');
label.className = 'param-label';
label.textContent = metadata.label;
label.textContent = t(metadata.label);
const slider = documentRef.createElement('input');
slider.type = 'range';
slider.className = 'param-slider';
slider.setAttribute('aria-label', metadata.label);
slider.setAttribute('aria-label', t(metadata.label));
slider.min = metadata.min;
slider.max = metadata.max;
slider.step = metadata.max <= 1 ? '0.01' : '0.1';