From 1c0cbffe27e389cb29324ed98eff0ca52cd16a31 Mon Sep 17 00:00:00 2001 From: psmattas Date: Mon, 17 Aug 2026 21:26:12 +0100 Subject: [PATCH] fix(settings): language picker breaks on a server locale not in our list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live warning: "en_GB" invalid tag, undefined Picker display — the curated OutlineLocale.all didn't include it. Added en_GB explicitly, and made the Picker's item list always include whatever code the server actually reports (falling back to the code itself as the label) so any future unlisted locale degrades gracefully instead of breaking the control. --- Outpost/Features/Account/SettingsView.swift | 16 +++++++++++++++- Outpost/Support/OutlineLocale.swift | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Outpost/Features/Account/SettingsView.swift b/Outpost/Features/Account/SettingsView.swift index b68cede..d125f2b 100644 --- a/Outpost/Features/Account/SettingsView.swift +++ b/Outpost/Features/Account/SettingsView.swift @@ -375,7 +375,7 @@ struct SettingsView: View { ProgressView().controlSize(.small) } else { Picker("Language", selection: languageBinding) { - ForEach(OutlineLocale.all) { locale in + ForEach(displayedLocales) { locale in Text(locale.label).tag(locale.code) } } @@ -443,6 +443,20 @@ struct SettingsView: View { ) } + /// `OutlineLocale.all` is a curated subset, not Outline's full list — + /// a self-hosted server can report a code we don't know about (seen + /// live: "en_GB"). `Picker` needs a `Text` for every possible selection + /// or it logs "invalid tag" and its displayed value goes undefined — + /// appending the current code here (using itself as the label, same + /// fallback `OutlineLocale.label(for:)` already uses) guarantees a + /// match no matter what the server sends. + private var displayedLocales: [OutlineLocale] { + guard let current = session.userLanguage, !OutlineLocale.all.contains(where: { $0.code == current }) else { + return OutlineLocale.all + } + return OutlineLocale.all + [OutlineLocale(code: current, label: OutlineLocale.label(for: current))] + } + private var languageBinding: Binding { Binding( get: { session.userLanguage ?? "en_US" }, diff --git a/Outpost/Support/OutlineLocale.swift b/Outpost/Support/OutlineLocale.swift index 4099726..ab79106 100644 --- a/Outpost/Support/OutlineLocale.swift +++ b/Outpost/Support/OutlineLocale.swift @@ -13,6 +13,7 @@ struct OutlineLocale: Identifiable, Hashable { static let all: [OutlineLocale] = [ OutlineLocale(code: "en_US", label: "English (US)"), + OutlineLocale(code: "en_GB", label: "English (UK)"), OutlineLocale(code: "de_DE", label: "Deutsch"), OutlineLocale(code: "fr_FR", label: "Français"), OutlineLocale(code: "es_ES", label: "Español"),