mirror of
https://github.com/Andre-Bzk/twitch4steamdeck.git
synced 2026-11-15 09:33:09 +01:00
feat: add German and English UI language support
A single-language interface makes the app less usable for part of the audience and encourages more hardcoded copy as new screens and states are added. Introducing a shared i18n path with a persisted language preference gives the UI one consistent way to present text and lowers the risk of partial or inconsistent localization over time. The surrounding copy cleanup belongs in the same change because it aligns existing labels, messages, and settings text with that translation structure instead of leaving mixed localization approaches in place.
This commit is contained in:
@@ -55,7 +55,7 @@ export class AuthService extends EventEmitter {
|
||||
async startDeviceFlow(): Promise<DeviceFlowStartInfo> {
|
||||
if (!this.isConfigured()) {
|
||||
throw new Error(
|
||||
'TWITCH_CLIENT_ID nicht gesetzt. Trage MAIN_VITE_TWITCH_CLIENT_ID in .env ein.'
|
||||
'TWITCH_CLIENT_ID is not set. Add MAIN_VITE_TWITCH_CLIENT_ID to .env.'
|
||||
)
|
||||
}
|
||||
this.cancelFlow()
|
||||
|
||||
+2
-2
@@ -111,7 +111,7 @@ app.whenReady().then(async () => {
|
||||
await auth.init()
|
||||
const helix = new HelixClient(clientId, async () => {
|
||||
const token = await auth.getValidAccessToken()
|
||||
if (!token) throw new Error('Kein gueltiges Twitch-Access-Token vorhanden')
|
||||
if (!token) throw new Error('No valid Twitch access token available')
|
||||
return token
|
||||
})
|
||||
const playback = new PlaybackService()
|
||||
@@ -126,7 +126,7 @@ app.whenReady().then(async () => {
|
||||
})
|
||||
|
||||
if (!clientId) {
|
||||
log.warn('[twitch4steamdeck] MAIN_VITE_TWITCH_CLIENT_ID nicht gesetzt — Login wird im UI als nicht konfiguriert angezeigt.')
|
||||
log.warn('[twitch4steamdeck] MAIN_VITE_TWITCH_CLIENT_ID is not set — the UI will show login as not configured.')
|
||||
}
|
||||
|
||||
createWindow()
|
||||
|
||||
@@ -398,14 +398,14 @@ export function startGamepadReader(getWindow: () => BrowserWindow | null): () =>
|
||||
reader = new EvdevReader(eventPath, onKey)
|
||||
if (reader.start()) {
|
||||
readers.set(jsPath, reader)
|
||||
log.info(`[gamepad] geöffnet (evdev): ${jsPath} → ${eventPath}`)
|
||||
log.info(`[gamepad] opened (evdev): ${jsPath} → ${eventPath}`)
|
||||
}
|
||||
} else {
|
||||
// Fallback to legacy joystick API when no /sys mapping is found
|
||||
reader = new JoystickFallbackReader(jsPath, onKey)
|
||||
if (reader.start()) {
|
||||
readers.set(jsPath, reader)
|
||||
log.info(`[gamepad] geöffnet (js-fallback): ${jsPath}`)
|
||||
log.info(`[gamepad] opened (js-fallback): ${jsPath}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export const IPC = {
|
||||
playbackGetQualities: 'playback:get-qualities',
|
||||
/** main → renderer */
|
||||
playbackEvent: 'playback:event',
|
||||
/** main → renderer: HLS-URL + Metadaten für den Renderer-seitigen Video-Player */
|
||||
/** main → renderer: HLS URL + metadata for the renderer-side video player */
|
||||
playbackHlsUrl: 'playback:hls-url',
|
||||
|
||||
appGetCacheSize: 'app:get-cache-size',
|
||||
|
||||
@@ -19,7 +19,7 @@ export class PlaybackService extends EventEmitter {
|
||||
} catch (e) {
|
||||
this.emit('playback-event', {
|
||||
kind: 'error',
|
||||
message: `Stream-URL konnte nicht abgerufen werden: ${e}`
|
||||
message: `Failed to resolve stream URL: ${e}`
|
||||
} satisfies PlaybackEvent)
|
||||
return
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export class PlaybackService extends EventEmitter {
|
||||
} catch (e) {
|
||||
this.emit('playback-event', {
|
||||
kind: 'error',
|
||||
message: `Stream-URL konnte nicht abgerufen werden: ${e}`
|
||||
message: `Failed to resolve stream URL: ${e}`
|
||||
} satisfies PlaybackEvent)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ export interface VodProgress {
|
||||
completed: boolean
|
||||
}
|
||||
|
||||
/** Gibt für alle übergebenen vodIds vorhandene History-Einträge zurück. */
|
||||
/** Returns existing history entries for all passed vodIds. */
|
||||
export function getProgressMap(vodIds: string[]): Record<string, VodProgress> {
|
||||
if (vodIds.length === 0) return {}
|
||||
const placeholders = vodIds.map(() => '?').join(',')
|
||||
|
||||
@@ -54,24 +54,24 @@ export interface HelixGame {
|
||||
box_art_url: string
|
||||
}
|
||||
|
||||
/** Simplified game info für den Renderer. */
|
||||
/** Simplified game info for the renderer. */
|
||||
export interface GameInfo {
|
||||
id: string
|
||||
name: string
|
||||
/** Boxart-URL bereits auf 285×380 aufgelöst */
|
||||
/** Box art URL already resolved to 285×380 */
|
||||
boxArtUrl: string
|
||||
/** Summe der Zuschauer aus den Top-100-Streams der Kategorie */
|
||||
/** Sum of viewers from the top-100 streams in the category */
|
||||
viewerCount?: number
|
||||
}
|
||||
|
||||
/** Simplified VOD info für den Renderer. */
|
||||
/** Simplified VOD info for the renderer. */
|
||||
export interface VodInfo {
|
||||
id: string
|
||||
title: string
|
||||
createdAt: string
|
||||
durationSeconds: number
|
||||
viewCount: number
|
||||
/** Thumbnail URL bereits auf 440×248 aufgelöst */
|
||||
/** Thumbnail URL already resolved to 440×248 */
|
||||
thumbnailUrl: string
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user