Files
RouterOS/RouterOSAssistant/Core/Localization/L10n.swift
T
KayandClaude Sonnet 5 0d16d05cb3 M16: Zweisprachigkeit (DE/EN) im Experte-Tab, eigener L10n-Helfer statt String Catalog
.environment(\.locale) + Localizable.xcstrings schaltete Text(LocalizedStringKey)
live nachweislich nicht um. Ersetzt durch Core/Localization/L10n.swift
(Dictionary-Lookup je AppStorage("appLanguage")), Umschalt-Button in der Toolbar.
Vollständig übersetzt: alle Tab-Namen, alle Menü-Kategorien, kompletter
Experte-Tab inkl. Firewall-Formulare. 60 Tests grün, live bestätigt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDmUd93KxsYGr2kLTotWnG
2026-09-15 15:54:26 +02:00

70 lines
4.2 KiB
Swift

import Foundation
/// Manual in-app language switch. Not built on `.environment(\.locale)` + a String Catalog:
/// that combination only redirects Calendar/DateFormatter-style locale-aware APIs — confirmed
/// live that toggling the environment override had no effect on `Text(LocalizedStringKey)`
/// content, which resolves against the bundle's own preferred-localizations negotiation fixed
/// at launch, not a runtime environment value. This does the substitution directly: `L10n.t`
/// looks up an English string in a plain dictionary keyed by the German source text, returning
/// the German text itself when untranslated or when `language == "de"`. Every call site passes
/// its own observed `appLanguage` so SwiftUI's diffing sees the dependency and re-renders on toggle.
enum L10n {
static func t(_ german: String, _ language: String) -> String {
guard language == "en" else { return german }
return translations[german] ?? german
}
private static let translations: [String: String] = [
"Verbinden": "Connect",
"Einrichten": "Setup",
"Übersicht": "Topology",
"Geräte": "Devices",
"Experte": "Expert",
"Sicherungen": "Backups",
"Firewall: Filter-Regeln": "Firewall: Filter Rules",
"Firewall: NAT (Portweiterleitung etc.)": "Firewall: NAT (port forwarding etc.)",
"Firewall: Mangle (Markierung/QoS-Vorbereitung)": "Firewall: Mangle (marking/QoS prep)",
"Firewall: Raw (vor Connection-Tracking)": "Firewall: Raw (before connection tracking)",
"Firewall: Adress-Listen": "Firewall: Address Lists",
"Interfaces (Bridge, VLAN, VPN-Tunnel...)": "Interfaces (bridge, VLAN, VPN tunnel...)",
"IP-Adressierung & Dienste": "IP Addressing & Services",
"Routing": "Routing",
"VPN-Server/Clients": "VPN Servers/Clients",
"WLAN / CAPsMAN": "Wi-Fi / CAPsMAN",
"Queues / Bandbreiten-Steuerung": "Queues / Bandwidth Control",
"System": "System",
"Werkzeuge & Überwachung": "Tools & Monitoring",
"Nicht verbunden": "Not connected",
"Verbinde dich zuerst im Tab \"Verbinden\" mit deinem Router.": "Connect to your router first in the \"Connect\" tab.",
"Eigener Menüpfad": "Custom Menu Path",
"Jeder RouterOS-Menüpfad ist erreichbar, auch wenn er oben nicht gelistet ist — die Felder erscheinen dann generisch (Schlüssel/Wert), ohne kuratierte Erklärung.":
"Any RouterOS menu path is reachable, even if it's not listed above — fields then appear generically (key/value), without a curated explanation.",
"Menüpfad, z.B. /ip firewall filter": "Menu path, e.g. /ip firewall filter",
"Der RouterOS-CLI-Pfad, z.B. \"/interface wireguard\" oder \"/routing ospf instance\".":
"The RouterOS CLI path, e.g. \"/interface wireguard\" or \"/routing ospf instance\".",
"REST-Pfad, z.B. ip/firewall/filter": "REST path, e.g. ip/firewall/filter",
"Derselbe Pfad in REST-API-Schreibweise: führende \"/\" weg, Leerzeichen zu \"/\".":
"The same path in REST API notation: drop the leading \"/\", turn spaces into \"/\".",
"Öffnen": "Open",
"Kein Menü ausgewählt": "No menu selected",
"Wähle links einen RouterOS-Bereich aus.": "Select a RouterOS area on the left.",
"Eintrag löschen": "Delete entry",
"Einstellungen": "Settings",
"Einträge": "Entries",
"Neu hinzufügen": "Add new",
"Eintrag wirklich löschen?": "Really delete this entry?",
"Löschen": "Delete",
"Abbrechen": "Cancel",
"Weitere Parameter (frei)": "Additional Parameters (free-form)",
"Für alles, was oben nicht als eigenes Feld aufgeführt ist — RouterOS-Parametername genau wie in der Dokumentation.":
"For anything not listed as its own field above — use the exact RouterOS parameter name as in the documentation.",
"Parameter": "Parameter",
"Wert": "Value",
"Parameter hinzufügen": "Add parameter",
"Wird ausgeführt": "About to run",
"Anlegen": "Create",
"Speichern": "Save",
"Jetzt am Router anwenden?": "Apply on the router now?"
]
}