feat(web): translate slot, rarity, danger, and location-type labels to English
Translates the four static Angular label maps (SLOT_LABELS, RARITY_LABELS, DANGER_LABELS, LOCATION_TYPE_LABELS) and the inventory detail panel's hardcoded item-type fallback per the English Game Content Foundation design doc glossary. Updates every spec assertion across the web app that checks rendered text sourced from these maps, including specs owned by later tasks (combat-page, encounter-card, inventory-page) where they render one of these labels. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -580,7 +580,7 @@ describe('CombatPageComponent', () => {
|
||||
'/images/items/bandit-blade.png',
|
||||
);
|
||||
expect(element.querySelector('[data-item-name]')?.textContent).toContain('Räuberklinge');
|
||||
expect(element.querySelector('[data-item-rarity]')?.textContent).toContain('Gewöhnlich');
|
||||
expect(element.querySelector('[data-item-rarity]')?.textContent).toContain('Common');
|
||||
expect(element.querySelector('[data-reward-empty]')).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('EncounterCardComponent', () => {
|
||||
|
||||
expect(element.textContent).toContain('Dämmerwolf');
|
||||
expect(element.textContent).toContain('Stufe 3');
|
||||
expect(element.textContent).toContain('Passend');
|
||||
expect(element.textContent).toContain('Suitable');
|
||||
expect(artwork?.getAttribute('src')).toBe('/images/enemies/Dawnwolf.png');
|
||||
expect(artwork?.getAttribute('alt')).toBe('Dämmerwolf');
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ export class InventoryDetailPanelComponent {
|
||||
});
|
||||
|
||||
/** Stand-in for items with no slot: the API does not expose an item type. */
|
||||
protected readonly typeLabel = computed(() => 'Gegenstand');
|
||||
protected readonly typeLabel = computed(() => 'Item');
|
||||
|
||||
protected readonly statRows = computed<StatRow[]>(() => {
|
||||
const item = this.item();
|
||||
|
||||
@@ -149,9 +149,9 @@ describe('InventoryPageComponent', () => {
|
||||
const { fixture } = await setup();
|
||||
const text = (fixture.nativeElement as HTMLElement).querySelector('.inventory-page__equipment-list')?.textContent ?? '';
|
||||
|
||||
expect(text).toContain('Waffe');
|
||||
expect(text).toContain('Weapon');
|
||||
expect(text).toContain('Abgenutztes Kurzschwert');
|
||||
expect(text).toContain('Kopf');
|
||||
expect(text).toContain('Head');
|
||||
expect(text).toContain('Leer');
|
||||
});
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { EquipmentSlot } from '../../core/api/game-api.models';
|
||||
|
||||
/** German slot names, shared by the paper doll and the item detail panel. */
|
||||
/** Slot names, shared by the paper doll and the item detail panel. */
|
||||
export const SLOT_LABELS: Readonly<Record<EquipmentSlot, string>> = {
|
||||
WEAPON: 'Waffe',
|
||||
HEAD: 'Kopf',
|
||||
CHEST: 'Brust',
|
||||
HANDS: 'Handschuhe',
|
||||
LEGS: 'Beine',
|
||||
FEET: 'Stiefel',
|
||||
AMULET: 'Amulett',
|
||||
WEAPON: 'Weapon',
|
||||
HEAD: 'Head',
|
||||
CHEST: 'Chest',
|
||||
HANDS: 'Hands',
|
||||
LEGS: 'Legs',
|
||||
FEET: 'Feet',
|
||||
AMULET: 'Amulet',
|
||||
};
|
||||
|
||||
@@ -22,14 +22,14 @@ describe('LocationSidebarComponent', () => {
|
||||
|
||||
expect(text).toContain('Aschenfelder');
|
||||
expect(text).toContain('Verbrannte Straße');
|
||||
expect(text).toContain('Jagdgebiet');
|
||||
expect(text).toContain('Hunting Ground');
|
||||
expect(text).toContain('1–2');
|
||||
});
|
||||
|
||||
it('shows the danger rating as the shared badge', async () => {
|
||||
const element = await render(burnedRoadFixture());
|
||||
|
||||
expect(element.querySelector('app-danger-badge')?.textContent).toContain('Passend');
|
||||
expect(element.querySelector('app-danger-badge')?.textContent).toContain('Suitable');
|
||||
});
|
||||
|
||||
it('calls a location with no hostile pool safe instead of inventing a rating', async () => {
|
||||
|
||||
@@ -4,14 +4,14 @@ import { DangerBadgeComponent } from '../../../shared/danger-badge/danger-badge.
|
||||
import { LocationIconComponent } from '../location-icon/location-icon.component';
|
||||
|
||||
const LOCATION_TYPE_LABELS: Readonly<Record<string, string>> = {
|
||||
SAFE_HUB: 'Zuflucht',
|
||||
TRANSITION: 'Übergang',
|
||||
HUNTING_GROUND: 'Jagdgebiet',
|
||||
QUEST_LOCATION: 'Questort',
|
||||
OUTPOST: 'Außenposten',
|
||||
ELITE_ZONE: 'Elitegebiet',
|
||||
BOSS_LOCATION: 'Bossort',
|
||||
DUNGEON_ENTRANCE: 'Verlieseingang',
|
||||
SAFE_HUB: 'Safe Haven',
|
||||
TRANSITION: 'Transition',
|
||||
HUNTING_GROUND: 'Hunting Ground',
|
||||
QUEST_LOCATION: 'Quest Location',
|
||||
OUTPOST: 'Outpost',
|
||||
ELITE_ZONE: 'Elite Zone',
|
||||
BOSS_LOCATION: 'Boss Location',
|
||||
DUNGEON_ENTRANCE: 'Dungeon Entrance',
|
||||
};
|
||||
|
||||
interface InteractionSummary {
|
||||
|
||||
@@ -3,20 +3,20 @@ import type { DangerRating } from '../../core/api/game-api.models';
|
||||
import { DangerBadgeComponent } from './danger-badge.component';
|
||||
|
||||
const expectations: Array<{ rating: DangerRating; label: string; modifierClass: string }> = [
|
||||
{ rating: 'WEAK', label: 'Schwach', modifierClass: 'danger-badge--weak' },
|
||||
{ rating: 'MATCH', label: 'Passend', modifierClass: 'danger-badge--match' },
|
||||
{ rating: 'STRONG', label: 'Stark', modifierClass: 'danger-badge--strong' },
|
||||
{ rating: 'WEAK', label: 'Weak', modifierClass: 'danger-badge--weak' },
|
||||
{ rating: 'MATCH', label: 'Suitable', modifierClass: 'danger-badge--match' },
|
||||
{ rating: 'STRONG', label: 'Strong', modifierClass: 'danger-badge--strong' },
|
||||
{
|
||||
rating: 'VERY_DANGEROUS',
|
||||
label: 'Sehr gefährlich',
|
||||
label: 'Very Dangerous',
|
||||
modifierClass: 'danger-badge--very-dangerous',
|
||||
},
|
||||
{ rating: 'DEADLY', label: 'Tödlich', modifierClass: 'danger-badge--deadly' },
|
||||
{ rating: 'DEADLY', label: 'Deadly', modifierClass: 'danger-badge--deadly' },
|
||||
];
|
||||
|
||||
describe('DangerBadgeComponent', () => {
|
||||
for (const { rating, label, modifierClass } of expectations) {
|
||||
it(`renders the German label "${label}" and modifier class for ${rating}`, () => {
|
||||
it(`renders the label "${label}" and modifier class for ${rating}`, () => {
|
||||
const fixture = TestBed.createComponent(DangerBadgeComponent);
|
||||
fixture.componentRef.setInput('rating', rating);
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -2,11 +2,11 @@ import { Component, Input } from '@angular/core';
|
||||
import { DangerRating } from '../../core/api/game-api.models';
|
||||
|
||||
const DANGER_LABELS: Record<DangerRating, string> = {
|
||||
WEAK: 'Schwach',
|
||||
MATCH: 'Passend',
|
||||
STRONG: 'Stark',
|
||||
VERY_DANGEROUS: 'Sehr gefährlich',
|
||||
DEADLY: 'Tödlich',
|
||||
WEAK: 'Weak',
|
||||
MATCH: 'Suitable',
|
||||
STRONG: 'Strong',
|
||||
VERY_DANGEROUS: 'Very Dangerous',
|
||||
DEADLY: 'Deadly',
|
||||
};
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -21,7 +21,7 @@ async function setup(item: RewardItemSummary, quantity = 1) {
|
||||
}
|
||||
|
||||
describe('ItemCardComponent', () => {
|
||||
it('renders the icon, name, and German rarity label', async () => {
|
||||
it('renders the icon, name, and rarity label', async () => {
|
||||
const fixture = await setup(banditBlade);
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
@@ -29,19 +29,19 @@ describe('ItemCardComponent', () => {
|
||||
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(element.querySelector('[data-item-rarity]')?.textContent).toContain('Gewöhnlich');
|
||||
expect(element.querySelector('[data-item-rarity]')?.textContent).toContain('Common');
|
||||
});
|
||||
|
||||
it('labels the other rarities in German too', async () => {
|
||||
it('labels the other rarities too', async () => {
|
||||
const rare = await setup({ ...banditBlade, rarity: 'RARE' });
|
||||
expect(
|
||||
(rare.nativeElement as HTMLElement).querySelector('[data-item-rarity]')?.textContent,
|
||||
).toContain('Selten');
|
||||
).toContain('Rare');
|
||||
|
||||
const epic = await setup({ ...banditBlade, rarity: 'EPIC' });
|
||||
expect(
|
||||
(epic.nativeElement as HTMLElement).querySelector('[data-item-rarity]')?.textContent,
|
||||
).toContain('Episch');
|
||||
).toContain('Epic');
|
||||
});
|
||||
|
||||
it('hides the quantity for a single item and shows it for a stack', async () => {
|
||||
|
||||
@@ -2,9 +2,9 @@ import { Component, computed, input } from '@angular/core';
|
||||
import type { ItemRarity, RewardItemSummary } from '../../core/api/game-api.models';
|
||||
|
||||
export const RARITY_LABELS: Readonly<Record<ItemRarity, string>> = {
|
||||
COMMON: 'Gewöhnlich',
|
||||
RARE: 'Selten',
|
||||
EPIC: 'Episch',
|
||||
COMMON: 'Common',
|
||||
RARE: 'Rare',
|
||||
EPIC: 'Epic',
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user