feat(i18n): bind angular host/player copy to shared locale catalog
This commit is contained in:
@@ -5,6 +5,7 @@ import { FormsModule } from '@angular/forms';
|
||||
import { createApiClient } from '../../../../../src/api/client';
|
||||
import { createSessionContextStore } from '../../../../../src/spa/session-context-store';
|
||||
import { createVerticalSliceController } from '../../../../../src/spa/vertical-slice';
|
||||
import { clientHasNoAudioOutput, resolvePreferredLocale, t } from '../../lobby-i18n';
|
||||
|
||||
interface SessionDetail {
|
||||
session: { code: string; status: string; current_round: number };
|
||||
@@ -27,35 +28,35 @@ function resolveLocalStorage(): Storage | undefined {
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule],
|
||||
template: `
|
||||
<h2>Player SPA gameplay flow</h2>
|
||||
<h2>{{ copy('player.title') }}</h2>
|
||||
|
||||
<div class="panel">
|
||||
<label>Session code <input [(ngModel)]="sessionCode" /></label>
|
||||
<label>Nickname <input [(ngModel)]="nickname" /></label>
|
||||
<button (click)="refreshSession()" [disabled]="loading">Refresh</button>
|
||||
<button (click)="joinSession()" [disabled]="loading">Join</button>
|
||||
<div class="panel" [attr.data-client-has-no-audio-output]="clientHasNoAudioOutput">
|
||||
<label>{{ copy('common.session_code') }} <input [(ngModel)]="sessionCode" /></label>
|
||||
<label>{{ copy('player.nickname') }} <input [(ngModel)]="nickname" /></label>
|
||||
<button (click)="refreshSession()" [disabled]="loading">{{ copy('common.refresh') }}</button>
|
||||
<button (click)="joinSession()" [disabled]="loading">{{ copy('player.join') }}</button>
|
||||
</div>
|
||||
|
||||
<p *ngIf="connectionState === 'reconnecting'" class="error">
|
||||
Reconnecting… trying to refresh session state.
|
||||
<button type="button" (click)="retryReconnect()" [disabled]="loading">Retry now</button>
|
||||
<button type="button" (click)="returnToJoin()" [disabled]="loading">Back to join</button>
|
||||
{{ copy('player.reconnecting_text') }}
|
||||
<button type="button" (click)="retryReconnect()" [disabled]="loading">{{ copy('player.retry_now') }}</button>
|
||||
<button type="button" (click)="returnToJoin()" [disabled]="loading">{{ copy('common.back_to_join') }}</button>
|
||||
</p>
|
||||
<p *ngIf="connectionState === 'offline'" class="error">
|
||||
You are offline. Reconnect to continue gameplay.
|
||||
<button type="button" (click)="retryReconnect()" [disabled]="loading">Retry now</button>
|
||||
<button type="button" (click)="returnToJoin()" [disabled]="loading">Back to join</button>
|
||||
{{ copy('player.offline_text') }}
|
||||
<button type="button" (click)="retryReconnect()" [disabled]="loading">{{ copy('player.retry_now') }}</button>
|
||||
<button type="button" (click)="returnToJoin()" [disabled]="loading">{{ copy('common.back_to_join') }}</button>
|
||||
</p>
|
||||
|
||||
<p *ngIf="loading" class="hint">{{ loadingMessage }}</p>
|
||||
|
||||
<div class="panel" *ngIf="session">
|
||||
<p><strong>Status:</strong> {{ session.session.status }}</p>
|
||||
<p *ngIf="session.round_question"><strong>Prompt:</strong> {{ session.round_question.prompt }}</p>
|
||||
<p><strong>{{ copy('common.status') }}:</strong> {{ session.session.status }}</p>
|
||||
<p *ngIf="session.round_question"><strong>{{ copy('common.prompt') }}:</strong> {{ session.round_question.prompt }}</p>
|
||||
|
||||
<label>Løgn <input [(ngModel)]="lieText" [disabled]="loading || session.session.status !== 'lie'" /></label>
|
||||
<button (click)="submitLie()" [disabled]="loading || session.session.status !== 'lie'">Submit lie</button>
|
||||
<button *ngIf="submitError?.kind === 'lie'" (click)="submitLie()" [disabled]="loading">Retry lie submit</button>
|
||||
<label>{{ copy('player.lie_label') }} <input [(ngModel)]="lieText" [disabled]="loading || session.session.status !== 'lie'" /></label>
|
||||
<button (click)="submitLie()" [disabled]="loading || session.session.status !== 'lie'">{{ copy('player.submit_lie') }}</button>
|
||||
<button *ngIf="submitError?.kind === 'lie'" (click)="submitLie()" [disabled]="loading">{{ copy('player.retry_lie_submit') }}</button>
|
||||
|
||||
<div class="answers" *ngIf="session.round_question?.answers?.length">
|
||||
<button
|
||||
@@ -69,11 +70,11 @@ function resolveLocalStorage(): Storage | undefined {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button (click)="submitGuess()" [disabled]="loading || session.session.status !== 'guess' || !selectedGuess">Submit guess</button>
|
||||
<button *ngIf="submitError?.kind === 'guess'" (click)="submitGuess()" [disabled]="loading">Retry guess submit</button>
|
||||
<button (click)="submitGuess()" [disabled]="loading || session.session.status !== 'guess' || !selectedGuess">{{ copy('player.submit_guess') }}</button>
|
||||
<button *ngIf="submitError?.kind === 'guess'" (click)="submitGuess()" [disabled]="loading">{{ copy('player.retry_guess_submit') }}</button>
|
||||
|
||||
<div *ngIf="session.session.status === 'finished' && finalLeaderboard.length">
|
||||
<h3>Final leaderboard</h3>
|
||||
<h3>{{ copy('player.final_leaderboard') }}</h3>
|
||||
<ol>
|
||||
<li *ngFor="let entry of finalLeaderboard">{{ entry.nickname }}: {{ entry.score }}</li>
|
||||
</ol>
|
||||
@@ -84,12 +85,15 @@ function resolveLocalStorage(): Storage | undefined {
|
||||
<p *ngIf="submitError" class="error">{{ submitError.message }}</p>
|
||||
|
||||
<div class="panel" *ngIf="error || submitError">
|
||||
<button type="button" (click)="retryReconnect()" [disabled]="loading">Retry</button>
|
||||
<button type="button" (click)="returnToJoin()" [disabled]="loading">Back to join</button>
|
||||
<button type="button" (click)="retryReconnect()" [disabled]="loading">{{ copy('common.retry') }}</button>
|
||||
<button type="button" (click)="returnToJoin()" [disabled]="loading">{{ copy('common.back_to_join') }}</button>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class PlayerShellComponent implements OnInit, OnDestroy {
|
||||
locale = resolvePreferredLocale();
|
||||
readonly clientHasNoAudioOutput = clientHasNoAudioOutput;
|
||||
|
||||
sessionCode = '';
|
||||
nickname = '';
|
||||
playerId = 0;
|
||||
@@ -198,17 +202,21 @@ export class PlayerShellComponent implements OnInit, OnDestroy {
|
||||
get loadingMessage(): string {
|
||||
switch (this.loadingTransition) {
|
||||
case 'join':
|
||||
return 'Joining session… restoring your player state.';
|
||||
return this.copy('player.loading_join');
|
||||
case 'submit-lie':
|
||||
return 'Submitting lie… waiting for guess phase.';
|
||||
return this.copy('player.loading_submit_lie');
|
||||
case 'submit-guess':
|
||||
return 'Submitting guess… waiting for reveal.';
|
||||
return this.copy('player.loading_submit_guess');
|
||||
case 'refresh':
|
||||
default:
|
||||
return 'Loading latest session state…';
|
||||
return this.copy('player.loading_refresh');
|
||||
}
|
||||
}
|
||||
|
||||
copy(key: string): string {
|
||||
return t(key, this.locale);
|
||||
}
|
||||
|
||||
private normalizeCode(value: string): string {
|
||||
return value.trim().toUpperCase();
|
||||
}
|
||||
@@ -352,7 +360,7 @@ export class PlayerShellComponent implements OnInit, OnDestroy {
|
||||
this.syncRouteFromSession();
|
||||
this.markOnline();
|
||||
} catch (error) {
|
||||
this.error = `Session refresh failed: ${this.toMessage(error)}`;
|
||||
this.error = `${this.copy('player.session_refresh_failed')}: ${this.toMessage(error)}`;
|
||||
this.markConnectionIssue(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -382,7 +390,7 @@ export class PlayerShellComponent implements OnInit, OnDestroy {
|
||||
this.syncRouteFromSession();
|
||||
this.markOnline();
|
||||
} catch (error) {
|
||||
this.error = `Join failed: ${this.toMessage(error)}`;
|
||||
this.error = `${this.copy('player.join_failed')}: ${this.toMessage(error)}`;
|
||||
this.markConnectionIssue(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -410,7 +418,7 @@ export class PlayerShellComponent implements OnInit, OnDestroy {
|
||||
await this.refreshSession();
|
||||
this.markOnline();
|
||||
} catch (error) {
|
||||
this.submitError = { kind: 'lie', message: `Lie submit failed: ${this.toMessage(error)}` };
|
||||
this.submitError = { kind: 'lie', message: `${this.copy('player.lie_submit_failed')}: ${this.toMessage(error)}` };
|
||||
this.markConnectionIssue(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -438,7 +446,7 @@ export class PlayerShellComponent implements OnInit, OnDestroy {
|
||||
await this.refreshSession();
|
||||
this.markOnline();
|
||||
} catch (error) {
|
||||
this.submitError = { kind: 'guess', message: `Guess submit failed: ${this.toMessage(error)}` };
|
||||
this.submitError = { kind: 'guess', message: `${this.copy('player.guess_submit_failed')}: ${this.toMessage(error)}` };
|
||||
this.markConnectionIssue(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
|
||||
Reference in New Issue
Block a user