i18n(de): address code review findings

Localize a legacy Nepal base shot only when the applied pack marker binds
that title to this exact shot id, so a user shot renamed to a built-in
title stays as typed in every locale.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-29 14:52:45 +04:00
1 parent a0c8b6f893
commit 0e45bcdf14
3 files changed
+80 -15

No files matched your search

+14 -13
View File
@@ -1071,7 +1071,7 @@ export function displayShotTitle(title, shot = undefined, scene = undefined) {
const fromRecipe = shot
? Boolean(shot.sourcePackId) ||
recipeDeclaresShotTitle(scene?.id, text) ||
shotPackDeclaresBaseTitle(scene, text)
shotPackBindsShot(scene, text, shot)
: true;
if (fromRecipe && BUILTIN_SHOT_TITLES.has(text)) return t(text);
const numbered = /^Shot ([1-9]\d*)$/.exec(text);
@@ -1079,21 +1079,22 @@ export function displayShotTitle(title, shot = undefined, scene = undefined) {
}
/**
* Whether a shot pack that upgraded this scene declares the title for one of
* its legacy base shots. The upgrade rebuilds those shots without a
* sourcePackId (see SceneDirector._bootstrapLegacyShotPacks), so the pack's
* own shots in the scene vouch for them.
* @param {{shots?: Array<{sourcePackId?: string}>}} [scene]
* Whether a shot pack applied to this scene binds this title to this exact
* shot. The legacy upgrade rebuilds the base shots without a sourcePackId
* (see SceneDirector._bootstrapLegacyShotPacks), but the pack marker records
* their ids, so a user shot that only shares the title is not vouched for.
* @param {{appliedShotPacks?: Array<{shotBindings?: Object<string, string>}>}} [scene]
* @param {string} title
* @param {{id?: string}} shot
* @returns {boolean}
*/
function shotPackDeclaresBaseTitle(scene, title) {
const shots = Array.isArray(scene?.shots) ? scene.shots : [];
return SCENE_APPEND_RECIPES.some(
(pack) =>
pack.legacySceneBootstrap?.cameraPath?.some(
(keyframe) => keyframe?.title === title,
) && shots.some((item) => item?.sourcePackId === pack.id),
function shotPackBindsShot(scene, title, shot) {
const packs = Array.isArray(scene?.appliedShotPacks)
? scene.appliedShotPacks
: [];
return (
Boolean(shot?.id) &&
packs.some((pack) => pack?.shotBindings?.[title] === shot.id)
);
}
+15 -2
View File
@@ -151,12 +151,25 @@ test('the base shots of a scene the Nepal pack upgraded localize', () => {
setLocale('de');
const title = pack.legacySceneBootstrap.cameraPath[0].title;
const base = { id: 'shot-base', title };
// A user shot renamed to the same built-in title is not the bound one.
const renamed = { id: 'shot-user', title };
const upgraded = {
id: 'scene-upgraded',
shots: [base, { id: 'shot-pack', title: 'x', sourcePackId: pack.id }],
shots: [
base,
{ id: 'shot-pack', title: 'x', sourcePackId: pack.id },
renamed,
],
appliedShotPacks: [
{ id: pack.id, version: 1, shotBindings: { [title]: base.id } },
],
};
assert.equal(displayShotTitle(title, base, upgraded), displayShotTitle(title));
assert.equal(
displayShotTitle(title, base, upgraded),
displayShotTitle(title),
);
assert.notEqual(displayShotTitle(title), title);
assert.equal(displayShotTitle(title, renamed, upgraded), title);
// The same title in a scene no pack touched stays as typed.
assert.equal(
displayShotTitle(title, base, { id: 'scene-user', shots: [base] }),
+51
View File
@@ -0,0 +1,51 @@
// Reproduction: a user-authored shot whose typed title equals a legacy base
// title of the Nepal pack must stay as typed in an upgraded scene.
import test from 'node:test';
import assert from 'node:assert/strict';
import { SCENE_APPEND_RECIPES, displayShotTitle } from './recipes.js';
import { setLocale } from '../i18n/index.js';
test.afterEach(() => setLocale('en'));
test('a user shot named like a legacy base shot stays as typed in an upgraded scene', () => {
const pack = SCENE_APPEND_RECIPES.find(
(recipe) => recipe.legacySceneBootstrap?.cameraPath?.length,
);
assert.ok(pack, 'Nepal append pack with legacy bootstrap');
const baseTitles = pack.legacySceneBootstrap.cameraPath.map((k) => k.title);
// Shape written by SceneDirector._bootstrapLegacyShotPacks + appendShotPack:
// base shots without sourcePackId, pack shots with it, marker bindings.
const base = baseTitles.map((title, i) => ({ id: `base-${i}`, title }));
const packShot = {
id: 'pack-0',
title: 'Upper Valley Collapse',
sourcePackId: pack.id,
};
// Captured by captureShot ("Shot 10"), then renamed by the user.
const userShot = { id: 'user-1', title: 'Bhote Koshi Flood Path' };
const scene = {
id: 'scene-user-upgraded',
shots: [...base, packShot, userShot],
appliedShotPacks: [
{
id: pack.id,
version: Number(pack.version) || 1,
shotBindings: Object.fromEntries(base.map((s) => [s.title, s.id])),
},
],
};
for (const locale of ['de', 'ru', 'es']) {
setLocale(locale);
// The real base shot localizes (intended by the branch).
assert.notEqual(
displayShotTitle(base[5].title, base[5], scene),
base[5].title,
);
// The user's shot must stay as typed.
assert.equal(
displayShotTitle(userShot.title, userShot, scene),
userShot.title,
`${locale}: user-typed title was translated`,
);
}
});