From 1322285b0fedb90e3fb0c1eb2a06131fcdc3dfd5 Mon Sep 17 00:00:00 2001 From: Bastian Wagner Date: Fri, 21 Aug 2026 22:59:34 +0200 Subject: [PATCH] fix: close out remaining German player-facing text across web and API tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Repo-wide grep sweep (apps/web/src, apps/api/src) for leftover German content strings missed by Tasks 1-9, mostly in spec fixtures/assertions that mirror already-translated seed content (monster/item names, POI titles and action labels, location names/descriptions) plus a few real source-file gaps: - inventory-detail-panel.component.ts: STAT_LABELS (Waffenschaden, Angriff, Leben, Rüstung) were never translated by Task 6; now match the identical English labels already used in inventory-page.component.html. - app-shell.component.html: aria-label="Spielinhalt" -> "Game content" (this file was outside every prior task's file list). - location-interaction-panel.component.spec.ts: dead NPC-quote fixture translated to match the real wounded-scout POI text. Code comments referencing German source-spec section titles or not-yet-seeded faction names, and inline calculation-documentation comments, are left as-is per the source spec's scope (dev-facing comments may stay German). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01ACkMEDYiwtcfchqKkiUJNX --- .../character-stats.service.spec.ts | 2 +- .../src/characters/characters.service.spec.ts | 6 +- .../combat-equipment-integration.spec.ts | 6 +- apps/api/src/combat/combat.service.spec.ts | 6 +- .../seeds/vertical-slice.seed.spec.ts | 6 +- .../src/equipment/equipment.service.spec.ts | 2 +- apps/api/src/hunting/danger-rating.spec.ts | 4 +- .../src/hunting/hunting.controller.spec.ts | 6 +- apps/api/src/hunting/hunting.service.spec.ts | 30 ++--- .../src/inventory/inventory.service.spec.ts | 8 +- apps/api/src/renown/renown.service.spec.ts | 2 +- .../src/rewards/combat-reward.service.spec.ts | 16 +-- apps/api/src/travel/travel.service.spec.ts | 18 +-- .../world/local-location-interaction.spec.ts | 30 ++--- apps/api/src/world/world.controller.spec.ts | 4 +- apps/api/src/world/world.service.spec.ts | 116 +++++++++--------- apps/web/src/app/app.spec.ts | 4 +- .../src/app/core/api/game-api.service.spec.ts | 2 +- apps/web/src/app/core/resume-combat.spec.ts | 2 +- .../combat-page/combat-page.component.spec.ts | 24 ++-- .../app/features/combat/combat.store.spec.ts | 2 +- .../encounter-card.component.spec.ts | 8 +- .../hunt-page/hunt-page.component.spec.ts | 14 +-- .../features/hunting/hunting.store.spec.ts | 8 +- .../inventory-detail-panel.component.spec.ts | 8 +- .../inventory-detail-panel.component.ts | 8 +- .../inventory-page.component.spec.ts | 12 +- .../inventory/inventory.store.spec.ts | 8 +- .../world/local-location.store.spec.ts | 6 +- ...cation-interaction-panel.component.spec.ts | 16 +-- .../location-page.component.spec.ts | 34 ++--- .../location-poi.component.spec.ts | 12 +- .../location-sidebar.component.spec.ts | 20 +-- .../world/world-page.component.spec.ts | 12 +- .../app/features/world/world.store.spec.ts | 6 +- .../layout/app-shell/app-shell.component.html | 2 +- .../context-panel.component.spec.ts | 8 +- .../item-card/item-card.component.spec.ts | 6 +- 38 files changed, 243 insertions(+), 241 deletions(-) diff --git a/apps/api/src/characters/character-stats.service.spec.ts b/apps/api/src/characters/character-stats.service.spec.ts index 6fd1038..a992aac 100644 --- a/apps/api/src/characters/character-stats.service.spec.ts +++ b/apps/api/src/characters/character-stats.service.spec.ts @@ -61,7 +61,7 @@ describe('CharacterStatsService', () => { expect(stats.armor).toBe(0); }); - it("applies Räuberklinge's weapon damage and bonus attack", async () => { + it("applies the Bandit Blade's weapon damage and bonus attack", async () => { const scope = fakeScope([ { slot: EquipmentSlot.WEAPON, diff --git a/apps/api/src/characters/characters.service.spec.ts b/apps/api/src/characters/characters.service.spec.ts index f5fee6a..e6727ac 100644 --- a/apps/api/src/characters/characters.service.spec.ts +++ b/apps/api/src/characters/characters.service.spec.ts @@ -37,7 +37,7 @@ describe('CharactersService', () => { currentLocation: { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'Südtor von Graufurt', + name: 'Graufurt South Gate', }, }), } as unknown as Repository; @@ -57,7 +57,7 @@ describe('CharactersService', () => { currentLocation: { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'Südtor von Graufurt', + name: 'Graufurt South Gate', }, }); expect(characterStats.calculate).toHaveBeenCalledWith( @@ -78,7 +78,7 @@ describe('CharactersService', () => { currentLocation: { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'Südtor von Graufurt', + name: 'Graufurt South Gate', }, }), } as unknown as Repository; diff --git a/apps/api/src/combat/combat-equipment-integration.spec.ts b/apps/api/src/combat/combat-equipment-integration.spec.ts index f40f766..f8189f6 100644 --- a/apps/api/src/combat/combat-equipment-integration.spec.ts +++ b/apps/api/src/combat/combat-equipment-integration.spec.ts @@ -209,7 +209,7 @@ function monster( return { id: MONSTER_ID, key: 'road-bandit', - name: 'Straßenräuber', + name: 'Road Bandit', level: 2, maxHp: 75, attack: 9, @@ -301,7 +301,7 @@ function createHarness() { itemDefinition({ id: BANDIT_BLADE_DEFINITION_ID, key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', weaponDamage: 11, bonusAttack: 1, iconPath: '/images/items/bandit-blade.png', @@ -360,7 +360,7 @@ function createHarness() { return { state, equipmentService, combatService }; } -describe('equipping Räuberklinge increases combat damage (spec §45, §60)', () => { +describe('equipping the Bandit Blade increases combat damage (spec §45, §60)', () => { it('deals more damage against the same monster after the upgrade than before it', async () => { const { state, combatService, equipmentService } = createHarness(); diff --git a/apps/api/src/combat/combat.service.spec.ts b/apps/api/src/combat/combat.service.spec.ts index c6b339f..4012909 100644 --- a/apps/api/src/combat/combat.service.spec.ts +++ b/apps/api/src/combat/combat.service.spec.ts @@ -193,7 +193,7 @@ function monster( return { id: MONSTER_ID, key: 'ash-rat', - name: 'Aschenratte', + name: 'Ash Rat', level: 1, maxHp: 45, attack: 5, @@ -334,7 +334,7 @@ describe('CombatService', () => { }); expect(combat.monster).toEqual({ key: 'ash-rat', - name: 'Aschenratte', + name: 'Ash Rat', level: 1, maxHp: 45, currentHp: 45, @@ -1016,7 +1016,7 @@ describe('CombatService', () => { characterItemId: 'character-item-1', item: { key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', rarity: 'COMMON', iconPath: '/images/items/bandit-blade.png', }, diff --git a/apps/api/src/database/seeds/vertical-slice.seed.spec.ts b/apps/api/src/database/seeds/vertical-slice.seed.spec.ts index 48a84d9..bdb0b06 100644 --- a/apps/api/src/database/seeds/vertical-slice.seed.spec.ts +++ b/apps/api/src/database/seeds/vertical-slice.seed.spec.ts @@ -250,7 +250,7 @@ describe('seedVisibleVerticalSlice', () => { expect(locationMonsterRepository.rows).toHaveLength(4); }); - it('seeds the local view content of the Verbrannte Straße with four points of interest', async () => { + it('seeds the local view content of the Burned Road with four points of interest', async () => { const locationRepository = new InMemoryRepository(); const dataSource = createDataSource( locationRepository, @@ -306,7 +306,7 @@ describe('seedVisibleVerticalSlice', () => { ]); }); - it('gives the Südtor its own local content so a second location needs no new component', async () => { + it('gives the South Gate its own local content so a second location needs no new component', async () => { const locationRepository = new InMemoryRepository(); const dataSource = createDataSource( locationRepository, @@ -347,7 +347,7 @@ describe('seedVisibleVerticalSlice', () => { locationRepository.rows.push({ id: persistedSouthGateId, key: 'south-gate', - name: 'Veraltetes Südtor', + name: 'Outdated South Gate', }); const dataSource = createDataSource( locationRepository, diff --git a/apps/api/src/equipment/equipment.service.spec.ts b/apps/api/src/equipment/equipment.service.spec.ts index 1d8f681..0dda52e 100644 --- a/apps/api/src/equipment/equipment.service.spec.ts +++ b/apps/api/src/equipment/equipment.service.spec.ts @@ -274,7 +274,7 @@ describe('EquipmentService', () => { const banditBlade = itemDefinition({ id: 'def-bandit-blade', key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', weaponDamage: 11, bonusAttack: 1, iconPath: '/images/items/bandit-blade.png', diff --git a/apps/api/src/hunting/danger-rating.spec.ts b/apps/api/src/hunting/danger-rating.spec.ts index 4d8b0d3..eecb057 100644 --- a/apps/api/src/hunting/danger-rating.spec.ts +++ b/apps/api/src/hunting/danger-rating.spec.ts @@ -6,7 +6,7 @@ const CHARACTER = { attack: 6, armor: 0, hp: 100 }; const CHARACTER_POWER = 44; describe('calculateDangerRating', () => { - it('rates the seeded Aschenratte as MATCH', () => { + it('rates the seeded Ash Rat as MATCH', () => { // Aschenratte: attack 5, armor 0, maxHp 45 // power(monster) = 5*4 + 0*2 + floor(45/5) = 20 + 0 + 9 = 29 // ratio = 29 / 44 = 0.6590909... -> not < 0.65, and < 1.0 -> MATCH @@ -15,7 +15,7 @@ describe('calculateDangerRating', () => { expect(calculateDangerRating(CHARACTER, monster)).toBe(DangerRating.MATCH); }); - it('rates the seeded Straßenräuber as STRONG', () => { + it('rates the seeded Road Bandit as STRONG', () => { // Straßenräuber: attack 9, armor 5, maxHp 75 // power(monster) = 9*4 + 5*2 + floor(75/5) = 36 + 10 + 15 = 61 // ratio = 61 / 44 = 1.3863636... -> not < 1.0, and < 1.7 -> STRONG diff --git a/apps/api/src/hunting/hunting.controller.spec.ts b/apps/api/src/hunting/hunting.controller.spec.ts index 0a9a5b9..d3ca73d 100644 --- a/apps/api/src/hunting/hunting.controller.spec.ts +++ b/apps/api/src/hunting/hunting.controller.spec.ts @@ -37,7 +37,7 @@ describe('HuntingController', () => { it('delegates to huntingService.startHunt with the demo character id and returns its result', async () => { const huntResult = { id: 'hunt-1', - location: { id: 'loc-1', key: 'burned-road', name: 'Verbrannte Strasse' }, + location: { id: 'loc-1', key: 'burned-road', name: 'Burned Road' }, encounters: [], }; startHunt.mockResolvedValue(huntResult); @@ -53,13 +53,13 @@ describe('HuntingController', () => { it('serves the resumable hunt with its encounter statuses', async () => { const huntResult = { id: 'hunt-1', - location: { id: 'loc-1', key: 'burned-road', name: 'Verbrannte Strasse' }, + location: { id: 'loc-1', key: 'burned-road', name: 'Burned Road' }, encounters: [ { id: 'encounter-1', monster: { key: 'ash-rat', - name: 'Aschenratte', + name: 'Ash Rat', level: 1, artworkPath: '/images/monsters/ash-rat.png', }, diff --git a/apps/api/src/hunting/hunting.service.spec.ts b/apps/api/src/hunting/hunting.service.spec.ts index 86362ed..7160b0b 100644 --- a/apps/api/src/hunting/hunting.service.spec.ts +++ b/apps/api/src/hunting/hunting.service.spec.ts @@ -18,8 +18,8 @@ import type { RandomSource } from '../shared/random-source'; const CHARACTER_ID = '10000000-0000-4000-8000-000000000001'; const HUNTING_LOCATION_ID = '20000000-0000-4000-8000-000000000001'; const SAFE_LOCATION_ID = '20000000-0000-4000-8000-000000000002'; -const MONSTER_A_ID = '30000000-0000-4000-8000-000000000001'; // Aschenratte -const MONSTER_B_ID = '30000000-0000-4000-8000-000000000002'; // Strassenraeuber +const MONSTER_A_ID = '30000000-0000-4000-8000-000000000001'; // Ash Rat +const MONSTER_B_ID = '30000000-0000-4000-8000-000000000002'; // Road Bandit const LOCATION_MONSTER_A_ID = '40000000-0000-4000-8000-000000000001'; const LOCATION_MONSTER_B_ID = '40000000-0000-4000-8000-000000000002'; @@ -191,7 +191,7 @@ function huntingLocation(): LocationDefinition { return { id: HUNTING_LOCATION_ID, key: 'burned-road', - name: 'Verbrannte Strasse', + name: 'Burned Road', description: 'A burned road.', regionKey: 'ashen-fields', minRecommendedLevel: 1, @@ -367,12 +367,12 @@ describe('HuntingService', () => { const monsterA = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', ); const monsterB = monsterDefinition( MONSTER_B_ID, 'strassenraeuber', - 'Straßenräuber', + 'Road Bandit', ); const state = createState(); state.characters[0].currentLocationId = HUNTING_LOCATION_ID; @@ -394,7 +394,7 @@ describe('HuntingService', () => { expect(result.location).toEqual({ id: HUNTING_LOCATION_ID, key: 'burned-road', - name: 'Verbrannte Strasse', + name: 'Burned Road', }); expect(dataSource.state.hunts).toHaveLength(1); expect(dataSource.state.hunts[0]).toMatchObject({ @@ -447,12 +447,12 @@ describe('HuntingService', () => { const monsterA = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', ); const monsterB = monsterDefinition( MONSTER_B_ID, 'strassenraeuber', - 'Straßenräuber', + 'Road Bandit', ); const state = createState(); state.characters[0].currentLocationId = HUNTING_LOCATION_ID; @@ -488,7 +488,7 @@ describe('HuntingService', () => { const monsterA = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', ); const state = createState(); state.characters[0].currentLocationId = HUNTING_LOCATION_ID; @@ -524,12 +524,12 @@ describe('HuntingService', () => { const monsterA = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', ); const monsterB = monsterDefinition( MONSTER_B_ID, 'strassenraeuber', - 'Straßenräuber', + 'Road Bandit', ); const state = createState(); state.characters[0].currentLocationId = HUNTING_LOCATION_ID; @@ -559,7 +559,7 @@ describe('HuntingService', () => { const weakMonster = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', { attack: 1, armor: 0, @@ -595,7 +595,7 @@ describe('HuntingService', () => { const monsterA = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', ); const state = createState(); state.characters[0].currentLocationId = HUNTING_LOCATION_ID; @@ -637,7 +637,7 @@ describe('HuntingService', () => { const monsterA = monsterDefinition( MONSTER_A_ID, 'aschenratte', - 'Aschenratte', + 'Ash Rat', ); const state = createState(); state.characters[0].currentLocationId = HUNTING_LOCATION_ID; @@ -696,7 +696,7 @@ describe('HuntingService', () => { expect(result?.location).toEqual({ id: HUNTING_LOCATION_ID, key: 'burned-road', - name: 'Verbrannte Strasse', + name: 'Burned Road', }); expect(result?.encounters.map((encounter) => encounter.status)).toEqual([ HuntEncounterStatus.AVAILABLE, diff --git a/apps/api/src/inventory/inventory.service.spec.ts b/apps/api/src/inventory/inventory.service.spec.ts index a8e968f..dcc1dac 100644 --- a/apps/api/src/inventory/inventory.service.spec.ts +++ b/apps/api/src/inventory/inventory.service.spec.ts @@ -18,8 +18,8 @@ function characterItem(overrides: Partial = {}): CharacterItem { updatedAt: new Date('2026-08-18T09:00:00.000Z'), itemDefinition: { key: 'worn-short-sword', - name: 'Abgenutztes Kurzschwert', - description: 'Die Klinge eines Rekruten, öfter geschliffen als geführt.', + name: 'Worn Shortsword', + description: "A recruit's blade, sharpened more often than it's been swung.", rarity: ItemRarity.COMMON, type: ItemType.EQUIPMENT, equipmentSlot: EquipmentSlot.WEAPON, @@ -66,8 +66,8 @@ describe('InventoryService', () => { equipped: true, item: { key: 'worn-short-sword', - name: 'Abgenutztes Kurzschwert', - description: 'Die Klinge eines Rekruten, öfter geschliffen als geführt.', + name: 'Worn Shortsword', + description: "A recruit's blade, sharpened more often than it's been swung.", rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 8, diff --git a/apps/api/src/renown/renown.service.spec.ts b/apps/api/src/renown/renown.service.spec.ts index 972ccc9..00fe118 100644 --- a/apps/api/src/renown/renown.service.spec.ts +++ b/apps/api/src/renown/renown.service.spec.ts @@ -121,7 +121,7 @@ function milestone( return { id: MILESTONE_ID, key: 'first-hunt', - name: 'Erste erfolgreiche Jagd', + name: 'First Successful Hunt', description: '', renownReward: 1, repeatable: false, diff --git a/apps/api/src/rewards/combat-reward.service.spec.ts b/apps/api/src/rewards/combat-reward.service.spec.ts index 220bbb7..e67e6eb 100644 --- a/apps/api/src/rewards/combat-reward.service.spec.ts +++ b/apps/api/src/rewards/combat-reward.service.spec.ts @@ -158,7 +158,7 @@ function createState(overrides: Partial = {}): State { { id: BANDIT_BLADE, key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', type: ItemType.EQUIPMENT, rarity: ItemRarity.COMMON, iconPath: '/images/items/bandit-blade.png', @@ -239,7 +239,7 @@ describe('CombatRewardService', () => { }); }); - describe('Aschenratte', () => { + describe('Ash Rat', () => { it('grants a silver roll inside 4-7, persisted on the character', async () => { const state = createState(); @@ -266,7 +266,7 @@ describe('CombatRewardService', () => { }); }); - describe('Straßenräuber', () => { + describe('Road Bandit', () => { const banditCombat = combat({ monsterDefinitionId: ROAD_BANDIT_ID }); it('grants a silver roll inside 9-15', async () => { @@ -281,7 +281,7 @@ describe('CombatRewardService', () => { expect(reward.silver).toBe(9); }); - it('persists a dropped Räuberklinge as a CharacterItem and references it in the reward', async () => { + it('persists a dropped Bandit Blade as a CharacterItem and references it in the reward', async () => { const state = createState(); const reward = await service( @@ -301,7 +301,7 @@ describe('CombatRewardService', () => { characterItemId: state.characterItems[0].id, item: { key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', rarity: ItemRarity.COMMON, iconPath: '/images/items/bandit-blade.png', }, @@ -311,7 +311,7 @@ describe('CombatRewardService', () => { expect(state.combatRewardItems).toHaveLength(1); }); - it('reports no items when the Räuberklinge does not drop', async () => { + it('reports no items when the Bandit Blade does not drop', async () => { const state = createState(); const reward = await service(state, fakeLoot()).grantVictoryRewards( @@ -450,7 +450,7 @@ describe('CombatRewardService', () => { { id: BANDIT_BLADE, key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', type: ItemType.EQUIPMENT, rarity: ItemRarity.COMMON, iconPath: '/images/items/bandit-blade.png', @@ -458,7 +458,7 @@ describe('CombatRewardService', () => { { id: BANDIT_HOOD, key: 'bandit-hood', - name: 'Räuberkapuze', + name: 'Bandit Hood', type: ItemType.EQUIPMENT, rarity: ItemRarity.COMMON, iconPath: '/images/items/bandit-hood.png', diff --git a/apps/api/src/travel/travel.service.spec.ts b/apps/api/src/travel/travel.service.spec.ts index 78e9e52..e2ba237 100644 --- a/apps/api/src/travel/travel.service.spec.ts +++ b/apps/api/src/travel/travel.service.spec.ts @@ -167,12 +167,12 @@ function createState(): FakeState { const southGate = location( SOUTH_GATE_ID, 'south-gate', - 'S\u00fcdtor von Graufurt', + 'Graufurt South Gate', ); const burnedRoad = location( BURNED_ROAD_ID, 'burned-road', - 'Verbrannte Stra\u00dfe', + 'Burned Road', ); const character: Character = { id: CHARACTER_ID, @@ -237,12 +237,12 @@ describe('TravelService', () => { originLocation: { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'S\u00fcdtor von Graufurt', + name: 'Graufurt South Gate', }, targetLocation: { id: BURNED_ROAD_ID, key: 'burned-road', - name: 'Verbrannte Stra\u00dfe', + name: 'Burned Road', }, startedAt: new Date('2026-08-18T10:00:00.000Z'), arrivesAt: new Date('2026-08-18T10:00:10.000Z'), @@ -319,12 +319,12 @@ describe('TravelService', () => { originLocation: { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'S\u00fcdtor von Graufurt', + name: 'Graufurt South Gate', }, targetLocation: { id: BURNED_ROAD_ID, key: 'burned-road', - name: 'Verbrannte Stra\u00dfe', + name: 'Burned Road', }, startedAt: new Date('2026-08-18T09:59:50.000Z'), arrivesAt: new Date('2026-08-18T10:00:10.000Z'), @@ -341,12 +341,12 @@ describe('TravelService', () => { originLocation: { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'S\u00fcdtor von Graufurt', + name: 'Graufurt South Gate', }, targetLocation: { id: BURNED_ROAD_ID, key: 'burned-road', - name: 'Verbrannte Stra\u00dfe', + name: 'Burned Road', }, startedAt: new Date('2026-08-18T09:59:50.000Z'), arrivesAt: new Date('2026-08-18T10:00:00.001Z'), @@ -367,7 +367,7 @@ describe('TravelService', () => { targetLocation: { id: BURNED_ROAD_ID, key: 'burned-road', - name: 'Verbrannte Stra\u00dfe', + name: 'Burned Road', }, }); expect(dataSource.state.characters[0].currentLocationId).toBe( diff --git a/apps/api/src/world/local-location-interaction.spec.ts b/apps/api/src/world/local-location-interaction.spec.ts index e89e4d2..ce4a097 100644 --- a/apps/api/src/world/local-location-interaction.spec.ts +++ b/apps/api/src/world/local-location-interaction.spec.ts @@ -17,8 +17,8 @@ const CHARACTER_ID = '10000000-0000-4000-8000-000000000001'; const BURNED_ROAD_POIS: LocationPointOfInterestContent[] = [ { key: 'hunt-area', - title: 'Jagdgebiet', - actionLabel: 'Jagd beginnen', + title: 'Hunting Ground', + actionLabel: 'Begin Hunt', type: 'HUNT', iconKey: 'hunt', xPercent: 52, @@ -27,42 +27,42 @@ const BURNED_ROAD_POIS: LocationPointOfInterestContent[] = [ }, { key: 'inspect-tracks', - title: 'Verdächtige Spuren', - actionLabel: 'Untersuchen', + title: 'Suspicious Tracks', + actionLabel: 'Investigate', type: 'INVESTIGATE', iconKey: 'investigate', xPercent: 32, yPercent: 78, enabled: true, - resultTitle: 'Verdächtige Spuren', + resultTitle: 'Suspicious Tracks', resultText: - 'Zwischen Asche und zerbrochenen Steinen erkennst du mehrere frische Stiefelabdrücke.', + 'Between the ash and broken stones you make out several fresh bootprints.', }, { key: 'sealed-crypt', - title: 'Versiegelte Krypta', + title: 'Sealed Crypt', type: 'DUNGEON', iconKey: 'search', xPercent: 90, yPercent: 20, enabled: false, - resultTitle: 'Versiegelte Krypta', - resultText: 'Noch verschlossen.', + resultTitle: 'Sealed Crypt', + resultText: 'Still sealed.', }, ]; const SOUTH_GATE_POIS: LocationPointOfInterestContent[] = [ { key: 'gate-watch', - title: 'Torwache', - actionLabel: 'Sprechen', + title: 'Gate Watch', + actionLabel: 'Talk', type: 'NPC', iconKey: 'speak', xPercent: 45, yPercent: 52, enabled: true, - resultTitle: 'Torwache', - resultText: 'Nur am Südtor zu hören.', + resultTitle: 'Gate Watch', + resultText: 'Only heard at the South Gate.', }, ]; @@ -109,8 +109,8 @@ describe('WorldService.runLocalInteraction', () => { service.runLocalInteraction(CHARACTER_ID, 'inspect-tracks'), ).resolves.toEqual({ interactionKey: 'inspect-tracks', - title: 'Verdächtige Spuren', - text: 'Zwischen Asche und zerbrochenen Steinen erkennst du mehrere frische Stiefelabdrücke.', + title: 'Suspicious Tracks', + text: 'Between the ash and broken stones you make out several fresh bootprints.', }); }); diff --git a/apps/api/src/world/world.controller.spec.ts b/apps/api/src/world/world.controller.spec.ts index b657634..3e9afa1 100644 --- a/apps/api/src/world/world.controller.spec.ts +++ b/apps/api/src/world/world.controller.spec.ts @@ -19,8 +19,8 @@ describe('WorldController', () => { it('forwards only the interaction key, never a caller-supplied location', () => { const runLocalInteraction = jest.fn().mockResolvedValue({ interactionKey: 'inspect-tracks', - title: 'Verdächtige Spuren', - text: 'Frische Stiefelabdrücke.', + title: 'Suspicious Tracks', + text: 'Fresh bootprints.', }); const controller = new WorldController({ runLocalInteraction, diff --git a/apps/api/src/world/world.service.spec.ts b/apps/api/src/world/world.service.spec.ts index 9b692a8..6a50e9d 100644 --- a/apps/api/src/world/world.service.spec.ts +++ b/apps/api/src/world/world.service.spec.ts @@ -20,23 +20,23 @@ const CHARACTER_ID = '10000000-0000-4000-8000-000000000001'; const SOUTH_GATE_POIS: LocationPointOfInterestContent[] = [ { key: 'gate-watch', - title: 'Torwache', - actionLabel: 'Sprechen', + title: 'Gate Watch', + actionLabel: 'Talk', type: 'NPC', iconKey: 'speak', xPercent: 45, yPercent: 52, enabled: true, - resultTitle: 'Torwache', - resultText: 'Geheimer Servertext.', + resultTitle: 'Gate Watch', + resultText: 'Secret server text.', }, ]; const BURNED_ROAD_POIS: LocationPointOfInterestContent[] = [ { key: 'hunt-area', - title: 'Jagdgebiet', - actionLabel: 'Jagd beginnen', + title: 'Hunting Ground', + actionLabel: 'Begin Hunt', type: 'HUNT', iconKey: 'hunt', xPercent: 52, @@ -45,42 +45,42 @@ const BURNED_ROAD_POIS: LocationPointOfInterestContent[] = [ }, { key: 'inspect-tracks', - title: 'Verdächtige Spuren', - actionLabel: 'Untersuchen', + title: 'Suspicious Tracks', + actionLabel: 'Investigate', type: 'INVESTIGATE', iconKey: 'investigate', xPercent: 32, yPercent: 78, enabled: true, - resultTitle: 'Verdächtige Spuren', - resultText: 'Frische Stiefelabdrücke führen nach Osten.', + resultTitle: 'Suspicious Tracks', + resultText: 'Fresh bootprints lead east.', }, { key: 'sealed-crypt', - title: 'Versiegelte Krypta', - actionLabel: 'Öffnen', + title: 'Sealed Crypt', + actionLabel: 'Open', type: 'DUNGEON', iconKey: 'search', xPercent: 90, yPercent: 20, enabled: false, - resultTitle: 'Versiegelte Krypta', - resultText: 'Noch verschlossen.', + resultTitle: 'Sealed Crypt', + resultText: 'Still sealed.', }, ]; const BURNED_ROAD_ACTIONS: LocationPrimaryActionContent[] = [ { key: 'start-hunt', - label: 'Jagd beginnen', - description: 'Im Gebiet jagen', + label: 'Begin Hunt', + description: 'Hunt in this area', type: 'HUNT', iconKey: 'hunt', enabled: true, }, { key: 'investigate-tracks', - label: 'Spuren untersuchen', + label: 'Investigate tracks', type: 'INVESTIGATE', iconKey: 'investigate', enabled: true, @@ -121,17 +121,17 @@ function poolEntry( // worst entry this pool reads STRONG; judged by what a traveller actually // meets it reads MATCH. const BURNED_ROAD_POOL = [ - poolEntry('Aschenratte', 70, { level: 1, attack: 5, armor: 0, maxHp: 45 }), - poolEntry('Straßenräuber', 30, { level: 2, attack: 9, armor: 5, maxHp: 75 }), + poolEntry('Ash Rat', 70, { level: 1, attack: 5, armor: 0, maxHp: 45 }), + poolEntry('Road Bandit', 30, { level: 2, attack: 9, armor: 5, maxHp: 75 }), ]; function currentLocation(): LocationDefinition { return { id: SOUTH_GATE_ID, key: 'south-gate', - name: 'S\u00fcdtor von Graufurt', + name: 'Graufurt South Gate', description: - 'Das S\u00fcdtor ist der sichere Ausgangspunkt nach S\u00fcden.', + 'The South Gate is the safe starting point heading south.', regionKey: 'ashen-fields', minRecommendedLevel: 1, maxRecommendedLevel: 1, @@ -139,10 +139,10 @@ function currentLocation(): LocationDefinition { isSafe: true, huntingEnabled: false, artworkPath: '/assets/locations/south-gate.webp', - regionName: 'Aschenfelder', - regionTierLabel: 'Gebiet 1', + regionName: 'Ashen Fields', + regionTierLabel: 'Tier 1', locationType: 'TRANSITION', - localDescription: 'Hinter den Wachtfeuern beginnen die Aschenfelder.', + localDescription: 'Beyond the watch-fires begin the Ashen Fields.', localArtworkPath: '/images/backgrounds/Suedtor.png', localPointsOfInterest: SOUTH_GATE_POIS, localPrimaryActions: [], @@ -159,8 +159,8 @@ function burnedRoad(): LocationDefinition { return { id: BURNED_ROAD_ID, key: 'burned-road', - name: 'Verbrannte Stra\u00dfe', - description: 'Eine verbrannte Handelsroute durch die Aschenfelder.', + name: 'Burned Road', + description: 'A burned trade route through the Ashen Fields.', regionKey: 'ashen-fields', minRecommendedLevel: 1, maxRecommendedLevel: 2, @@ -168,14 +168,14 @@ function burnedRoad(): LocationDefinition { isSafe: false, huntingEnabled: true, artworkPath: '/assets/locations/burned-road.webp', - regionName: 'Aschenfelder', - regionTierLabel: 'Gebiet 1', + regionName: 'Ashen Fields', + regionTierLabel: 'Tier 1', locationType: 'HUNTING_GROUND', - localDescription: 'Ein alter Handelsweg, in Asche gelegt.', + localDescription: 'An old trade road, burned to ash.', localArtworkPath: '/images/backgrounds/Aschestrasse.png', localPointsOfInterest: BURNED_ROAD_POIS, localPrimaryActions: BURNED_ROAD_ACTIONS, - localRewardPreview: [{ key: 'silver', label: 'Silber', iconKey: 'silver' }], + localRewardPreview: [{ key: 'silver', label: 'Silver', iconKey: 'silver' }], createdAt: new Date('2026-08-18T09:00:00.000Z'), updatedAt: new Date('2026-08-18T09:00:00.000Z'), characters: [], @@ -244,9 +244,9 @@ describe('WorldService', () => { expect(result).toEqual({ id: SOUTH_GATE_ID, key: 'south-gate', - name: 'S\u00fcdtor von Graufurt', + name: 'Graufurt South Gate', description: - 'Das S\u00fcdtor ist der sichere Ausgangspunkt nach S\u00fcden.', + 'The South Gate is the safe starting point heading south.', regionKey: 'ashen-fields', minRecommendedLevel: 1, maxRecommendedLevel: 1, @@ -254,18 +254,18 @@ describe('WorldService', () => { isSafe: true, huntingEnabled: false, artworkPath: '/assets/locations/south-gate.webp', - regionName: 'Aschenfelder', - regionTierLabel: 'Gebiet 1', + regionName: 'Ashen Fields', + regionTierLabel: 'Tier 1', locationType: 'TRANSITION', - localDescription: 'Hinter den Wachtfeuern beginnen die Aschenfelder.', + localDescription: 'Beyond the watch-fires begin the Ashen Fields.', localArtworkPath: '/images/backgrounds/Suedtor.png', dangerRating: null, recommendationLabel: '1', pointsOfInterest: [ { key: 'gate-watch', - title: 'Torwache', - actionLabel: 'Sprechen', + title: 'Gate Watch', + actionLabel: 'Talk', type: 'NPC', iconKey: 'speak', xPercent: 45, @@ -281,7 +281,7 @@ describe('WorldService', () => { targetLocation: { id: BURNED_ROAD_ID, key: 'burned-road', - name: 'Verbrannte Stra\u00dfe', + name: 'Burned Road', }, travelDurationSeconds: 10, danger: 'LOW', @@ -325,8 +325,8 @@ describe('WorldService', () => { const result = await service.getCurrentLocation(CHARACTER_ID); expect(result.possibleMonsters).toEqual([ - 'Aschenratte', - 'Stra\u00dfenr\u00e4uber', + 'Ash Rat', + 'Road Bandit', ]); expect(findLocationMonsters).toHaveBeenCalledWith({ where: { locationId: BURNED_ROAD_ID, enabled: true }, @@ -373,13 +373,13 @@ describe('WorldService', () => { expect(result).toEqual( expect.objectContaining({ - regionName: 'Aschenfelder', - regionTierLabel: 'Gebiet 1', + regionName: 'Ashen Fields', + regionTierLabel: 'Tier 1', locationType: 'HUNTING_GROUND', - localDescription: 'Ein alter Handelsweg, in Asche gelegt.', + localDescription: 'An old trade road, burned to ash.', localArtworkPath: '/images/backgrounds/Aschestrasse.png', recommendationLabel: '1–2', - rewardPreview: [{ key: 'silver', label: 'Silber', iconKey: 'silver' }], + rewardPreview: [{ key: 'silver', label: 'Silver', iconKey: 'silver' }], }), ); expect(result.primaryActions).toEqual(BURNED_ROAD_ACTIONS); @@ -397,8 +397,8 @@ describe('WorldService', () => { expect(result.pointsOfInterest).toEqual([ { key: 'hunt-area', - title: 'Jagdgebiet', - actionLabel: 'Jagd beginnen', + title: 'Hunting Ground', + actionLabel: 'Begin Hunt', type: 'HUNT', iconKey: 'hunt', xPercent: 52, @@ -407,8 +407,8 @@ describe('WorldService', () => { }, { key: 'inspect-tracks', - title: 'Verdächtige Spuren', - actionLabel: 'Untersuchen', + title: 'Suspicious Tracks', + actionLabel: 'Investigate', type: 'INVESTIGATE', iconKey: 'investigate', xPercent: 32, @@ -417,8 +417,8 @@ describe('WorldService', () => { }, { key: 'sealed-crypt', - title: 'Versiegelte Krypta', - actionLabel: 'Öffnen', + title: 'Sealed Crypt', + actionLabel: 'Open', type: 'DUNGEON', iconKey: 'search', xPercent: 90, @@ -426,8 +426,8 @@ describe('WorldService', () => { enabled: false, }, ]); - expect(JSON.stringify(result)).not.toContain('Frische Stiefelabdrücke'); - expect(JSON.stringify(result)).not.toContain('Noch verschlossen'); + expect(JSON.stringify(result)).not.toContain('Fresh bootprints'); + expect(JSON.stringify(result)).not.toContain('Still sealed'); }); it('derives the encounter preview from the location monster pool', async () => { @@ -435,16 +435,16 @@ describe('WorldService', () => { expect(result.encounterPreview).toEqual([ { - key: 'aschenratte', - name: 'Aschenratte', + key: 'ash rat', + name: 'Ash Rat', level: 1, - iconPath: '/images/monsters/icons/aschenratte-128.png', + iconPath: '/images/monsters/icons/ash rat-128.png', }, { - key: 'straßenräuber', - name: 'Straßenräuber', + key: 'road bandit', + name: 'Road Bandit', level: 2, - iconPath: '/images/monsters/icons/straßenräuber-128.png', + iconPath: '/images/monsters/icons/road bandit-128.png', }, ]); }); diff --git a/apps/web/src/app/app.spec.ts b/apps/web/src/app/app.spec.ts index a8fcf22..dcd4ea0 100644 --- a/apps/web/src/app/app.spec.ts +++ b/apps/web/src/app/app.spec.ts @@ -161,7 +161,7 @@ describe('App', () => { attack: 1, hpRegenPerSecond: 1, hpRegenSince: null, - currentLocation: { id: 'location-id', key: 'south-gate', name: 'Südtor von Graufurt' }, + currentLocation: { id: 'location-id', key: 'south-gate', name: 'Graufurt South Gate' }, }; const value: CharacterResponse = { id: 'character-id', @@ -173,7 +173,7 @@ describe('App', () => { attack: 12, hpRegenPerSecond: 1, hpRegenSince: null, - currentLocation: { id: 'location-id', key: 'south-gate', name: 'Südtor von Graufurt' }, + currentLocation: { id: 'location-id', key: 'south-gate', name: 'Graufurt South Gate' }, }; character.set(decoy); displayedCharacter.set(value); diff --git a/apps/web/src/app/core/api/game-api.service.spec.ts b/apps/web/src/app/core/api/game-api.service.spec.ts index 8601e53..fecf570 100644 --- a/apps/web/src/app/core/api/game-api.service.spec.ts +++ b/apps/web/src/app/core/api/game-api.service.spec.ts @@ -54,7 +54,7 @@ describe('GameApiService', () => { const request = http.expectOne('/api/world/current-location/interactions/inspect-tracks'); expect(request.request.method).toBe('POST'); expect(request.request.body).toEqual({}); - request.flush({ interactionKey: 'inspect-tracks', title: 'Spuren', text: '…' }); + request.flush({ interactionKey: 'inspect-tracks', title: 'Suspicious Tracks', text: '…' }); }); it('escapes an interaction key so it cannot break out of its path segment', () => { diff --git a/apps/web/src/app/core/resume-combat.spec.ts b/apps/web/src/app/core/resume-combat.spec.ts index 0f4303a..d051f5c 100644 --- a/apps/web/src/app/core/resume-combat.spec.ts +++ b/apps/web/src/app/core/resume-combat.spec.ts @@ -12,7 +12,7 @@ const runningCombat: Combat = { player: { name: 'Aric Duskwalker', maxHp: 100, currentHp: 62, potionsRemaining: 2, potionsMax: 2 }, monster: { key: 'road-bandit', - name: 'Straßenräuber', + name: 'Road Bandit', level: 3, maxHp: 75, currentHp: 30, diff --git a/apps/web/src/app/features/combat/combat-page/combat-page.component.spec.ts b/apps/web/src/app/features/combat/combat-page/combat-page.component.spec.ts index 3786b3e..3ba8e77 100644 --- a/apps/web/src/app/features/combat/combat-page/combat-page.component.spec.ts +++ b/apps/web/src/app/features/combat/combat-page/combat-page.component.spec.ts @@ -14,7 +14,7 @@ const activeCombat: Combat = { player: { name: 'Aric Duskwalker', maxHp: 100, currentHp: 95, potionsRemaining: 2, potionsMax: 2 }, monster: { key: 'ash-rat', - name: 'Aschenratte', + name: 'Ash Rat', level: 1, maxHp: 45, currentHp: 31, @@ -28,7 +28,7 @@ const activeCombat: Combat = { rewards: null, }; -const monsterHitLine = 'Aschenratte hits Aric Duskwalker for 5 damage.'; +const monsterHitLine = 'Ash Rat hits Aric Duskwalker for 5 damage.'; function countOccurrences(haystack: string | null, needle: string): number { return haystack ? haystack.split(needle).length - 1 : 0; @@ -97,7 +97,7 @@ describe('CombatPageComponent', () => { expect(element.textContent).toContain('Aric Duskwalker'); expect(element.textContent).toContain('95 / 100'); - expect(element.textContent).toContain('Aschenratte'); + expect(element.textContent).toContain('Ash Rat'); expect(element.textContent).toContain('31 / 45'); expect(element.querySelector('[data-combat-round]')?.textContent).toContain('Round 2'); expect(element.querySelector('[data-combat-attack]')).toBeTruthy(); @@ -169,7 +169,7 @@ describe('CombatPageComponent', () => { const element = fixture.nativeElement as HTMLElement; expect(element.querySelector('[data-combat-telegraph]')?.textContent).toContain( - 'Aschenratte is winding up a Heavy Strike.', + 'Ash Rat is winding up a Heavy Strike.', ); }); @@ -194,16 +194,16 @@ describe('CombatPageComponent', () => { expect(element.textContent).toContain('Aric Duskwalker drinks a potion and heals 35 HP.'); expect(element.textContent).toContain('Aric Duskwalker braces to defend.'); - expect(element.textContent).toContain('Aschenratte is winding up a Heavy Strike.'); - expect(element.textContent).toContain("Aric Duskwalker interrupts Aschenratte's attack."); + expect(element.textContent).toContain('Ash Rat is winding up a Heavy Strike.'); + expect(element.textContent).toContain("Aric Duskwalker interrupts Ash Rat's attack."); }); it('renders the structured events as readable English combat-log entries', async () => { const fixture = await setup(activeCombat); const element = fixture.nativeElement as HTMLElement; - expect(element.textContent).toContain('Aric Duskwalker hits Aschenratte for 14 damage.'); - expect(element.textContent).toContain('Aschenratte hits Aric Duskwalker for 5 damage.'); + expect(element.textContent).toContain('Aric Duskwalker hits Ash Rat for 14 damage.'); + expect(element.textContent).toContain('Ash Rat hits Aric Duskwalker for 5 damage.'); }); it('calls combatStore.performAction("ATTACK") when Attack is clicked', async () => { @@ -334,7 +334,7 @@ describe('CombatPageComponent', () => { await vi.advanceTimersByTimeAsync(540); fixture.detectChanges(); - expect(element.textContent).toContain("Aric Duskwalker interrupts Aschenratte's attack."); + expect(element.textContent).toContain("Aric Duskwalker interrupts Ash Rat's attack."); expect(element.querySelector('[data-combat-telegraph]')).toBeNull(); expect(monster?.classList.contains('sprite--lunge')).toBe(false); }); @@ -557,7 +557,7 @@ describe('CombatPageComponent', () => { it('renders a dropped item with its icon, name, and rarity', async () => { const fixture = await setup({ ...wonWithRewards, - monster: { ...activeCombat.monster, key: 'road-bandit', name: 'Straßenräuber', currentHp: 0 }, + monster: { ...activeCombat.monster, key: 'road-bandit', name: 'Road Bandit', currentHp: 0 }, rewards: { silver: 12, items: [ @@ -565,7 +565,7 @@ describe('CombatPageComponent', () => { characterItemId: 'character-item-1', item: { key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', rarity: 'COMMON', iconPath: '/images/items/bandit-blade.png', }, @@ -579,7 +579,7 @@ describe('CombatPageComponent', () => { expect(element.querySelector('[data-item-icon]')?.getAttribute('src')).toBe( '/images/items/bandit-blade.png', ); - expect(element.querySelector('[data-item-name]')?.textContent).toContain('Räuberklinge'); + expect(element.querySelector('[data-item-name]')?.textContent).toContain('Bandit Blade'); expect(element.querySelector('[data-item-rarity]')?.textContent).toContain('Common'); expect(element.querySelector('[data-reward-empty]')).toBeNull(); }); diff --git a/apps/web/src/app/features/combat/combat.store.spec.ts b/apps/web/src/app/features/combat/combat.store.spec.ts index 0823d73..f727fdf 100644 --- a/apps/web/src/app/features/combat/combat.store.spec.ts +++ b/apps/web/src/app/features/combat/combat.store.spec.ts @@ -13,7 +13,7 @@ const startedCombat: Combat = { player: { name: 'Aric Duskwalker', maxHp: 100, currentHp: 100, potionsRemaining: 2, potionsMax: 2 }, monster: { key: 'ash-rat', - name: 'Aschenratte', + name: 'Ash Rat', level: 1, maxHp: 45, currentHp: 45, diff --git a/apps/web/src/app/features/hunting/encounter-card/encounter-card.component.spec.ts b/apps/web/src/app/features/hunting/encounter-card/encounter-card.component.spec.ts index c37bbc1..e1b4f98 100644 --- a/apps/web/src/app/features/hunting/encounter-card/encounter-card.component.spec.ts +++ b/apps/web/src/app/features/hunting/encounter-card/encounter-card.component.spec.ts @@ -7,7 +7,7 @@ const dawnwolfEncounter: HuntEncounter = { id: 'encounter-id-9f2c', monster: { key: 'dawnwolf', - name: 'Dämmerwolf', + name: 'Dawnwolf', level: 3, artworkPath: '/images/enemies/Dawnwolf.png', }, @@ -19,7 +19,7 @@ const ashRatEncounter: HuntEncounter = { id: 'encounter-id-4b71', monster: { key: 'ash-rat', - name: 'Aschenratte', + name: 'Ash Rat', level: 1, artworkPath: '/images/monsters/ash-rat.png', }, @@ -45,11 +45,11 @@ describe('EncounterCardComponent', () => { const element = render(dawnwolfEncounter); const artwork = element.querySelector('.encounter-card__artwork'); - expect(element.textContent).toContain('Dämmerwolf'); + expect(element.textContent).toContain('Dawnwolf'); expect(element.textContent).toContain('Level 3'); expect(element.textContent).toContain('Suitable'); expect(artwork?.getAttribute('src')).toBe('/images/enemies/Dawnwolf.png'); - expect(artwork?.getAttribute('alt')).toBe('Dämmerwolf'); + expect(artwork?.getAttribute('alt')).toBe('Dawnwolf'); }); it('shows the background-free cut-out instead of the framed artwork when one exists', () => { diff --git a/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts b/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts index 637d7b1..ccdf298 100644 --- a/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts +++ b/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts @@ -19,11 +19,11 @@ const burnedRoad = burnedRoadFixture({ connections: [] }); const threeEncounterHunt: HuntResult = { id: 'hunt-id', - location: { id: 'burned-road-id', key: 'burned-road', name: 'Verbrannte Straße' }, + location: { id: 'burned-road-id', key: 'burned-road', name: 'Burned Road' }, encounters: [ { id: 'encounter-1', - monster: { key: 'ash-rat', name: 'Aschenratte', level: 1, artworkPath: '/images/enemies/AshRat.png' }, + monster: { key: 'ash-rat', name: 'Ash Rat', level: 1, artworkPath: '/images/enemies/AshRat.png' }, dangerRating: 'WEAK', status: 'AVAILABLE', }, @@ -31,7 +31,7 @@ const threeEncounterHunt: HuntResult = { id: 'encounter-2', monster: { key: 'road-bandit', - name: 'Straßenräuber', + name: 'Road Bandit', level: 3, artworkPath: '/images/enemies/RoadBandit.png', }, @@ -40,7 +40,7 @@ const threeEncounterHunt: HuntResult = { }, { id: 'encounter-3', - monster: { key: 'ash-rat', name: 'Aschenratte', level: 1, artworkPath: '/images/enemies/AshRat.png' }, + monster: { key: 'ash-rat', name: 'Ash Rat', level: 1, artworkPath: '/images/enemies/AshRat.png' }, dangerRating: 'WEAK', status: 'AVAILABLE', }, @@ -54,7 +54,7 @@ const startedCombat: Combat = { player: { name: 'Aric Duskwalker', maxHp: 100, currentHp: 100, potionsRemaining: 2, potionsMax: 2 }, monster: { key: 'road-bandit', - name: 'Straßenräuber', + name: 'Road Bandit', level: 3, maxHp: 75, currentHp: 75, @@ -130,7 +130,7 @@ describe('HuntPageComponent', () => { return fixture; } - it('shows the hunting-unavailable state at the Südtor, with no Begin Hunt button, and a way back to the location', async () => { + it('shows the hunting-unavailable state at the South Gate, with no Begin Hunt button, and a way back to the location', async () => { const fixture = await setup(southGate); const element = fixture.nativeElement as HTMLElement; @@ -164,7 +164,7 @@ describe('HuntPageComponent', () => { const cards = element.querySelectorAll('app-encounter-card'); expect(cards.length).toBe(3); - expect(element.textContent).toMatch(/Aschenratte[\s\S]*Straßenräuber[\s\S]*Aschenratte/); + expect(element.textContent).toMatch(/Ash Rat[\s\S]*Road Bandit[\s\S]*Ash Rat/); expect( element.querySelectorAll( '.encounter-card__artwork[src="/images/combat/sprites/ash-rat-760.png"]', diff --git a/apps/web/src/app/features/hunting/hunting.store.spec.ts b/apps/web/src/app/features/hunting/hunting.store.spec.ts index 1a3941a..501c29e 100644 --- a/apps/web/src/app/features/hunting/hunting.store.spec.ts +++ b/apps/web/src/app/features/hunting/hunting.store.spec.ts @@ -8,7 +8,7 @@ import { HuntingStore } from './hunting.store'; const huntResult: HuntResult = { id: 'hunt-id', - location: { id: 'origin-id', key: 'south-gate', name: 'Südtor' }, + location: { id: 'origin-id', key: 'south-gate', name: 'South Gate' }, encounters: [ { id: 'encounter-1', @@ -18,7 +18,7 @@ const huntResult: HuntResult = { }, { id: 'encounter-2', - monster: { key: 'bear', name: 'Bär', level: 3, artworkPath: '/images/enemies/Bear.png' }, + monster: { key: 'bear', name: 'Bear', level: 3, artworkPath: '/images/enemies/Bear.png' }, dangerRating: 'STRONG', status: 'DEFEATED', }, @@ -27,11 +27,11 @@ const huntResult: HuntResult = { const refreshedHuntResult: HuntResult = { id: 'hunt-id-2', - location: { id: 'origin-id', key: 'south-gate', name: 'Südtor' }, + location: { id: 'origin-id', key: 'south-gate', name: 'South Gate' }, encounters: [ { id: 'encounter-3', - monster: { key: 'rat', name: 'Ratte', level: 1, artworkPath: '/images/enemies/Rat.png' }, + monster: { key: 'rat', name: 'Rat', level: 1, artworkPath: '/images/enemies/Rat.png' }, dangerRating: 'WEAK', status: 'AVAILABLE', }, diff --git a/apps/web/src/app/features/inventory/inventory-detail-panel.component.spec.ts b/apps/web/src/app/features/inventory/inventory-detail-panel.component.spec.ts index 1c29b49..5642096 100644 --- a/apps/web/src/app/features/inventory/inventory-detail-panel.component.spec.ts +++ b/apps/web/src/app/features/inventory/inventory-detail-panel.component.spec.ts @@ -10,7 +10,7 @@ const wornSword: InventoryItem = { item: { key: 'worn-short-sword', name: 'Abgenutztes Kurzschwert', - description: 'Beschreibung des Gegenstands.', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 8, @@ -27,8 +27,8 @@ const banditBlade: InventoryItem = { equipped: false, item: { key: 'bandit-blade', - name: 'Räuberklinge', - description: 'Beschreibung des Gegenstands.', + name: 'Bandit Blade', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 11, @@ -46,7 +46,7 @@ const ashPelt: InventoryItem = { item: { key: 'ash-pelt', name: 'Aschenfell', - description: 'Beschreibung des Gegenstands.', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: null, weaponDamage: 0, diff --git a/apps/web/src/app/features/inventory/inventory-detail-panel.component.ts b/apps/web/src/app/features/inventory/inventory-detail-panel.component.ts index df672b5..bbee029 100644 --- a/apps/web/src/app/features/inventory/inventory-detail-panel.component.ts +++ b/apps/web/src/app/features/inventory/inventory-detail-panel.component.ts @@ -11,10 +11,10 @@ interface StatRow { type StatKey = 'weaponDamage' | 'bonusAttack' | 'bonusHp' | 'bonusArmor'; const STAT_LABELS: ReadonlyArray<{ label: string; key: StatKey }> = [ - { label: 'Waffenschaden', key: 'weaponDamage' }, - { label: 'Angriff', key: 'bonusAttack' }, - { label: 'Leben', key: 'bonusHp' }, - { label: 'Rüstung', key: 'bonusArmor' }, + { label: 'Weapon Damage', key: 'weaponDamage' }, + { label: 'Attack', key: 'bonusAttack' }, + { label: 'Health', key: 'bonusHp' }, + { label: 'Armor', key: 'bonusArmor' }, ]; /** Selected-item details and equip comparison (spec §32–37). */ diff --git a/apps/web/src/app/features/inventory/inventory-page.component.spec.ts b/apps/web/src/app/features/inventory/inventory-page.component.spec.ts index 11a2b50..1b5f534 100644 --- a/apps/web/src/app/features/inventory/inventory-page.component.spec.ts +++ b/apps/web/src/app/features/inventory/inventory-page.component.spec.ts @@ -17,7 +17,7 @@ const inventory: InventoryResponse = { item: { key: 'worn-short-sword', name: 'Abgenutztes Kurzschwert', - description: 'Beschreibung des Gegenstands.', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 8, @@ -33,8 +33,8 @@ const inventory: InventoryResponse = { equipped: false, item: { key: 'bandit-blade', - name: 'Räuberklinge', - description: 'Beschreibung des Gegenstands.', + name: 'Bandit Blade', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 11, @@ -70,7 +70,7 @@ const character: CharacterResponse = { attack: 6, hpRegenPerSecond: 1, hpRegenSince: null, - currentLocation: { id: 'loc-1', key: 'south-gate', name: 'Südtor' }, + currentLocation: { id: 'loc-1', key: 'south-gate', name: 'South Gate' }, }; interface SetupOptions { @@ -176,8 +176,8 @@ describe('InventoryPageComponent', () => { equipped: true, item: { key: 'iron-helm', - name: 'Eiserner Helm', - description: 'Beschreibung des Gegenstands.', + name: 'Iron Helm', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'HEAD', weaponDamage: 0, diff --git a/apps/web/src/app/features/inventory/inventory.store.spec.ts b/apps/web/src/app/features/inventory/inventory.store.spec.ts index 887a075..f757e0c 100644 --- a/apps/web/src/app/features/inventory/inventory.store.spec.ts +++ b/apps/web/src/app/features/inventory/inventory.store.spec.ts @@ -16,7 +16,7 @@ const inventory: InventoryResponse = { item: { key: 'worn-short-sword', name: 'Abgenutztes Kurzschwert', - description: 'Beschreibung des Gegenstands.', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 8, @@ -32,8 +32,8 @@ const inventory: InventoryResponse = { equipped: false, item: { key: 'bandit-blade', - name: 'Räuberklinge', - description: 'Beschreibung des Gegenstands.', + name: 'Bandit Blade', + description: 'Item description.', rarity: 'COMMON', equipmentSlot: 'WEAPON', weaponDamage: 11, @@ -61,7 +61,7 @@ const equipment: EquipmentResponse = { const equippedAfter: EquipmentResponse = { ...equipment, - slots: { ...equipment.slots, WEAPON: { characterItemId: 'item-blade', item: { key: 'bandit-blade', name: 'Räuberklinge', rarity: 'COMMON', iconPath: '/images/items/bandit-blade.png' } } }, + slots: { ...equipment.slots, WEAPON: { characterItemId: 'item-blade', item: { key: 'bandit-blade', name: 'Bandit Blade', rarity: 'COMMON', iconPath: '/images/items/bandit-blade.png' } } }, stats: { maxHp: 100, attack: 7, weaponDamage: 11, armor: 0 }, }; diff --git a/apps/web/src/app/features/world/local-location.store.spec.ts b/apps/web/src/app/features/world/local-location.store.spec.ts index 6be9c61..5f8680c 100644 --- a/apps/web/src/app/features/world/local-location.store.spec.ts +++ b/apps/web/src/app/features/world/local-location.store.spec.ts @@ -8,8 +8,8 @@ import { WorldStore } from './world.store'; const trackResult = { interactionKey: 'inspect-tracks', - title: 'Verdächtige Spuren', - text: 'Frische Stiefelabdrücke führen nach Osten.', + title: 'Suspicious Tracks', + text: 'Among the ash and broken stones you make out several fresh bootprints. They lead east, toward the abandoned watchpost.', }; function setup(api: Partial = {}, world: Partial = {}) { @@ -128,7 +128,7 @@ describe('LocalLocationStore', () => { expect( store.interactionKeyOf({ key: 'investigate-tracks', - label: 'Spuren untersuchen', + label: 'Investigate tracks', type: 'INVESTIGATE', iconKey: 'investigate', enabled: true, diff --git a/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.spec.ts b/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.spec.ts index 4a0b040..30fedeb 100644 --- a/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.spec.ts +++ b/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.spec.ts @@ -37,25 +37,27 @@ describe('LocationInteractionPanelComponent', () => { const { element } = await setup({ result: { interactionKey: 'inspect-tracks', - title: 'Verdächtige Spuren', - text: 'Frische Stiefelabdrücke führen nach Osten.', + title: 'Suspicious Tracks', + text: 'Among the ash and broken stones you make out several fresh bootprints. They lead east, toward the abandoned watchpost.', }, }); - expect(element.textContent).toContain('Verdächtige Spuren'); - expect(element.textContent).toContain('Frische Stiefelabdrücke führen nach Osten.'); + expect(element.textContent).toContain('Suspicious Tracks'); + expect(element.textContent).toContain( + 'Among the ash and broken stones you make out several fresh bootprints. They lead east, toward the abandoned watchpost.', + ); }); it('shows an NPC line through the same panel, with no branching choices', async () => { const { element } = await setup({ result: { interactionKey: 'wounded-scout', - title: 'Verwundeter Kundschafter', - text: '„Die Straße ist nicht mehr sicher."', + title: 'Wounded Scout', + text: '"The road isn\'t safe anymore. The raiders are coming from the direction of the old watchpost. If you keep going, keep your eyes open."', }, }); - expect(element.textContent).toContain('Verwundeter Kundschafter'); + expect(element.textContent).toContain('Wounded Scout'); // Exactly one control: close. A dialogue tree is out of scope here. expect(element.querySelectorAll('button')).toHaveLength(1); }); diff --git a/apps/web/src/app/features/world/location-page/location-page.component.spec.ts b/apps/web/src/app/features/world/location-page/location-page.component.spec.ts index 1d2eb97..102e0be 100644 --- a/apps/web/src/app/features/world/location-page/location-page.component.spec.ts +++ b/apps/web/src/app/features/world/location-page/location-page.component.spec.ts @@ -62,11 +62,11 @@ describe('LocationPageComponent', () => { it('names the place and its region straight away', async () => { const { element } = await setup(); - expect(element.querySelector('h1')?.textContent).toContain('Verbrannte Straße'); - expect(element.textContent).toContain('Gebiet 1'); - expect(element.textContent).toContain('Aschenfelder'); + expect(element.querySelector('h1')?.textContent).toContain('Burned Road'); + expect(element.textContent).toContain('Tier 1'); + expect(element.textContent).toContain('Ashen Fields'); expect(element.textContent).toContain( - 'Ein alter Handelsweg, der durch Feuer und Krieg in Asche gelegt wurde.', + 'An old trade road, burned to ash by fire and war. Charred carts, broken weapons, and silenced cries line the path into the Ashen Fields.', ); }); @@ -75,7 +75,7 @@ describe('LocationPageComponent', () => { const image = element.querySelector('img') as HTMLImageElement; expect(image.getAttribute('src')).toBe('/images/backgrounds/Aschestrasse.png'); - expect(image.getAttribute('alt')).toBe('Location view: Verbrannte Straße'); + expect(image.getAttribute('alt')).toBe('Location view: Burned Road'); }); it('places every hotspot on the artwork', async () => { @@ -96,10 +96,10 @@ describe('LocationPageComponent', () => { const actions = element.querySelectorAll('[data-action]'); expect([...actions].map((action) => action.querySelector('.location-action__label')?.textContent?.trim())).toEqual([ - 'Jagd beginnen', - 'Spuren untersuchen', - 'Umgebung durchsuchen', - 'Zur Karte', + 'Begin Hunt', + 'Investigate tracks', + 'Search surroundings', + 'To Map', ]); }); @@ -173,13 +173,13 @@ describe('LocationPageComponent', () => { interactionResult.set({ interactionKey: 'inspect-tracks', - title: 'Verdächtige Spuren', - text: 'Frische Stiefelabdrücke führen nach Osten.', + title: 'Suspicious Tracks', + text: 'Among the ash and broken stones you make out several fresh bootprints. They lead east, toward the abandoned watchpost.', }); fixture.detectChanges(); expect(element.querySelector('[data-interaction-panel]')?.textContent).toContain( - 'Frische Stiefelabdrücke führen nach Osten.', + 'Among the ash and broken stones you make out several fresh bootprints. They lead east, toward the abandoned watchpost.', ); // The scene is not replaced by the panel. expect(element.querySelector('img')).not.toBeNull(); @@ -234,7 +234,7 @@ describe('LocationPageComponent', () => { it('renders a second location from its own data alone', async () => { const { element } = await setup(southGateFixture(southGateContent())); - expect(element.querySelector('h1')?.textContent).toContain('Südtor von Graufurt'); + expect(element.querySelector('h1')?.textContent).toContain('Graufurt South Gate'); expect(element.querySelectorAll('app-location-poi')).toHaveLength(1); expect(element.querySelectorAll('[data-action]')).toHaveLength(1); }); @@ -245,8 +245,8 @@ function southGateContent(): Partial { pointsOfInterest: [ { key: 'gate-watch', - title: 'Torwache', - actionLabel: 'Sprechen', + title: 'Gate Watch', + actionLabel: 'Talk', type: 'NPC', iconKey: 'speak', xPercent: 45, @@ -257,8 +257,8 @@ function southGateContent(): Partial { primaryActions: [ { key: 'talk-to-watch', - label: 'Wache ansprechen', - description: 'Lage erfragen', + label: 'Talk to the watch', + description: 'Ask about the situation', type: 'NPC', iconKey: 'speak', enabled: true, diff --git a/apps/web/src/app/features/world/location-poi/location-poi.component.spec.ts b/apps/web/src/app/features/world/location-poi/location-poi.component.spec.ts index 27b057d..ac059c2 100644 --- a/apps/web/src/app/features/world/location-poi/location-poi.component.spec.ts +++ b/apps/web/src/app/features/world/location-poi/location-poi.component.spec.ts @@ -4,8 +4,8 @@ import { LocationPoiComponent } from './location-poi.component'; const wagon: LocationPointOfInterest = { key: 'search-abandoned-wagon', - title: 'Verlassener Wagen', - actionLabel: 'Durchsuchen', + title: 'Abandoned Wagon', + actionLabel: 'Search', type: 'SEARCH', iconKey: 'search', xPercent: 80, @@ -53,8 +53,8 @@ describe('LocationPoiComponent', () => { const { fixture } = await setup(); const text = (fixture.nativeElement as HTMLElement).textContent ?? ''; - expect(text).toContain('Verlassener Wagen'); - expect(text).toContain('Durchsuchen'); + expect(text).toContain('Abandoned Wagon'); + expect(text).toContain('Search'); }); it('emits the whole hotspot when clicked', async () => { @@ -102,7 +102,7 @@ describe('LocationPoiComponent', () => { it('describes itself with both title and action for screen readers', async () => { const { button } = await setup(); - expect(button.getAttribute('aria-label')).toBe('Verlassener Wagen: Durchsuchen'); + expect(button.getAttribute('aria-label')).toBe('Abandoned Wagon: Search'); }); it('falls back to the title alone when a hotspot has no action label', async () => { @@ -111,6 +111,6 @@ describe('LocationPoiComponent', () => { actionLabel: undefined, }); - expect(button.getAttribute('aria-label')).toBe('Verlassener Wagen'); + expect(button.getAttribute('aria-label')).toBe('Abandoned Wagon'); }); }); diff --git a/apps/web/src/app/features/world/location-sidebar/location-sidebar.component.spec.ts b/apps/web/src/app/features/world/location-sidebar/location-sidebar.component.spec.ts index b19e394..f77a03c 100644 --- a/apps/web/src/app/features/world/location-sidebar/location-sidebar.component.spec.ts +++ b/apps/web/src/app/features/world/location-sidebar/location-sidebar.component.spec.ts @@ -20,8 +20,8 @@ describe('LocationSidebarComponent', () => { const element = await render(burnedRoadFixture()); const text = element.textContent ?? ''; - expect(text).toContain('Aschenfelder'); - expect(text).toContain('Verbrannte Straße'); + expect(text).toContain('Ashen Fields'); + expect(text).toContain('Burned Road'); expect(text).toContain('Hunting Ground'); expect(text).toContain('1–2'); }); @@ -44,8 +44,8 @@ describe('LocationSidebarComponent', () => { const encounters = element.querySelectorAll('[data-sidebar="encounters"] li'); expect([...encounters].map((item) => item.textContent?.trim())).toEqual([ - 'Aschenratte', - 'Straßenräuber', + 'Ash Rat', + 'Road Bandit', ]); expect(element.textContent).toContain('the hunt rolls independently'); }); @@ -55,10 +55,10 @@ describe('LocationSidebarComponent', () => { const interactions = element.querySelectorAll('[data-sidebar="interactions"] li'); expect([...interactions].map((item) => item.textContent?.trim())).toEqual([ - 'Jagd beginnen', - 'Untersuchen', - 'Durchsuchen', - 'Sprechen', + 'Begin Hunt', + 'Investigate', + 'Search', + 'Talk', ]); }); @@ -72,7 +72,7 @@ describe('LocationSidebarComponent', () => { }); expect(element.querySelector('[data-sidebar="interactions"]')?.textContent).not.toContain( - 'Sprechen', + 'Talk', ); }); @@ -81,7 +81,7 @@ describe('LocationSidebarComponent', () => { const rewards = element.querySelectorAll('[data-sidebar="rewards"] li'); expect([...rewards].map((item) => item.textContent?.trim())).toEqual([ - 'Ausrüstung', + 'Equipment', 'Material', ]); }); diff --git a/apps/web/src/app/features/world/world-page.component.spec.ts b/apps/web/src/app/features/world/world-page.component.spec.ts index 6056ee3..475cca9 100644 --- a/apps/web/src/app/features/world/world-page.component.spec.ts +++ b/apps/web/src/app/features/world/world-page.component.spec.ts @@ -16,7 +16,7 @@ const burnedRoadConnection: CurrentLocationConnection = { targetLocation: { id: 'burned-road-id', key: 'burned-road', - name: 'Verbrannte Straße', + name: 'Burned Road', }, travelDurationSeconds: 10, danger: 'LOW', @@ -84,7 +84,7 @@ describe('WorldPageComponent', () => { expect(store.selectConnection).toHaveBeenCalledWith(burnedRoadConnection); expect(element.textContent).toContain('Destination'); - expect(element.textContent).toContain('Verbrannte Straße'); + expect(element.textContent).toContain('Burned Road'); expect(element.textContent).toContain('00:00:10'); expect(element.textContent).toContain('Low'); }); @@ -129,7 +129,7 @@ describe('WorldPageComponent', () => { it('renders the server-derived countdown while travel is active without enabling another start', () => { store.currentTravel.set({ status: 'TRAVELLING', - originLocation: { id: 'south-gate-id', key: 'south-gate', name: 'Südtor von Graufurt' }, + originLocation: { id: 'south-gate-id', key: 'south-gate', name: 'Graufurt South Gate' }, targetLocation: burnedRoadConnection.targetLocation, startedAt: '2026-08-19T06:00:00.000Z', arrivesAt: '2026-08-19T06:00:06.000Z', @@ -140,7 +140,7 @@ describe('WorldPageComponent', () => { fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; - expect(element.textContent).toContain('Destination: Verbrannte Straße'); + expect(element.textContent).toContain('Destination: Burned Road'); expect(element.textContent).toContain('Arrival in'); expect(element.textContent).toContain('00:00:06'); expect(element.querySelector('[data-travel-start]')?.disabled).toBe(true); @@ -194,7 +194,7 @@ describe('WorldPageComponent', () => { store.arrived.set({ id: 'burned-road-id', key: 'burned-road', - name: 'Verbrannte Straße', + name: 'Burned Road', }); fixture.detectChanges(); @@ -207,7 +207,7 @@ describe('WorldPageComponent', () => { it('stays on the map while a journey is still running', () => { store.currentTravel.set({ status: 'TRAVELLING', - originLocation: { id: 'south-gate-id', key: 'south-gate', name: 'Südtor von Graufurt' }, + originLocation: { id: 'south-gate-id', key: 'south-gate', name: 'Graufurt South Gate' }, targetLocation: burnedRoadConnection.targetLocation, startedAt: '2026-08-20T10:00:00.000Z', arrivesAt: '2026-08-20T10:00:10.000Z', diff --git a/apps/web/src/app/features/world/world.store.spec.ts b/apps/web/src/app/features/world/world.store.spec.ts index 19e2856..9374450 100644 --- a/apps/web/src/app/features/world/world.store.spec.ts +++ b/apps/web/src/app/features/world/world.store.spec.ts @@ -21,12 +21,12 @@ const character: CharacterResponse = { attack: 6, hpRegenPerSecond: 1, hpRegenSince: null, - currentLocation: { id: 'origin-id', key: 'south-gate', name: 'Südtor' }, + currentLocation: { id: 'origin-id', key: 'south-gate', name: 'South Gate' }, }; const currentLocation = southGateFixture({ id: 'origin-id', - name: 'Südtor', + name: 'South Gate', description: 'Der Ausgang zur Wildnis.', dangerLevel: 1, connections: [ @@ -34,7 +34,7 @@ const currentLocation = southGateFixture({ targetLocation: { id: 'target-id', key: 'burned-road', - name: 'Verbrannte Straße', + name: 'Burned Road', }, travelDurationSeconds: 10, danger: 'LOW', diff --git a/apps/web/src/app/layout/app-shell/app-shell.component.html b/apps/web/src/app/layout/app-shell/app-shell.component.html index d0dd1be..2098179 100644 --- a/apps/web/src/app/layout/app-shell/app-shell.component.html +++ b/apps/web/src/app/layout/app-shell/app-shell.component.html @@ -3,7 +3,7 @@
-
+
@if (showContextPanel()) { diff --git a/apps/web/src/app/layout/context-panel/context-panel.component.spec.ts b/apps/web/src/app/layout/context-panel/context-panel.component.spec.ts index 7a7b80b..5438a04 100644 --- a/apps/web/src/app/layout/context-panel/context-panel.component.spec.ts +++ b/apps/web/src/app/layout/context-panel/context-panel.component.spec.ts @@ -6,7 +6,7 @@ import { ContextPanelComponent } from './context-panel.component'; const southGate = { id: 'south-gate-id', key: 'south-gate', - name: 'Südtor von Graufurt', + name: 'Graufurt South Gate', description: 'Der letzte sichere Schritt vor den Aschenfeldern.', regionKey: 'ashen-fields', minRecommendedLevel: 1, @@ -23,11 +23,11 @@ const burnedRoad = { ...southGate, id: 'burned-road-id', key: 'burned-road', - name: 'Verbrannte Straße', + name: 'Burned Road', isSafe: false, huntingEnabled: true, artworkPath: '/images/backgrounds/Aschestrasse.png', - possibleMonsters: ['Aschenratte', 'Straßenräuber'], + possibleMonsters: ['Ash Rat', 'Road Bandit'], }; describe('ContextPanelComponent', () => { @@ -97,7 +97,7 @@ describe('ContextPanelComponent', () => { const element = fixture.nativeElement as HTMLElement; expect(element.textContent).toContain('Possible Encounters'); - expect(element.textContent).toContain('Aschenratte, Straßenräuber'); + expect(element.textContent).toContain('Ash Rat, Road Bandit'); expect(element.textContent).not.toMatch(/\d+\s?%/); }); }); diff --git a/apps/web/src/app/shared/item-card/item-card.component.spec.ts b/apps/web/src/app/shared/item-card/item-card.component.spec.ts index d66e44b..b2a367a 100644 --- a/apps/web/src/app/shared/item-card/item-card.component.spec.ts +++ b/apps/web/src/app/shared/item-card/item-card.component.spec.ts @@ -4,7 +4,7 @@ import { ItemCardComponent } from './item-card.component'; const banditBlade: RewardItemSummary = { key: 'bandit-blade', - name: 'Räuberklinge', + name: 'Bandit Blade', rarity: 'COMMON', iconPath: '/images/items/bandit-blade.png', }; @@ -27,8 +27,8 @@ describe('ItemCardComponent', () => { const icon = element.querySelector('[data-item-icon]'); expect(icon?.getAttribute('src')).toBe('/images/items/bandit-blade.png'); - expect(icon?.getAttribute('alt')).toBe('Räuberklinge'); - expect(element.querySelector('[data-item-name]')?.textContent).toContain('Räuberklinge'); + expect(icon?.getAttribute('alt')).toBe('Bandit Blade'); + expect(element.querySelector('[data-item-name]')?.textContent).toContain('Bandit Blade'); expect(element.querySelector('[data-item-rarity]')?.textContent).toContain('Common'); });