diff --git a/supacode/Features/Help/AskAgentHelpPrompt.swift b/supacode/Features/Help/AskAgentHelpPrompt.swift index 3e1d6c2a..47e4ed40 100644 --- a/supacode/Features/Help/AskAgentHelpPrompt.swift +++ b/supacode/Features/Help/AskAgentHelpPrompt.swift @@ -25,18 +25,30 @@ nonisolated enum AskAgentHelpPrompt { case japanese } + /// The user's top system-preferred language, independent of the app's bundle + /// localizations. Prowl ships English only, so `Locale.current` is capped to + /// English even on, say, a Simplified-Chinese system — but the prompt should + /// follow the *system* language. `Locale.preferredLanguages` is not capped. + static func systemPreferredLocale() -> Locale { + Locale(identifier: Locale.preferredLanguages.first ?? "en") + } + /// Resolve which prompt language to use from a locale. Chinese disambiguates - /// Hans/Hant by script, falling back to region (TW/HK/MO → Traditional). - /// Anything we don't translate falls back to English (which still asks the - /// agent to reply in the user's preferred language). + /// Hans/Hant by script (then the identifier text, then region — e.g. + /// `zh-Hans-JP` is Simplified even though its region is JP). Anything we don't + /// translate falls back to English (which still asks the agent to reply in the + /// user's preferred language). static func languageKey(for locale: Locale) -> LanguageKey { switch locale.language.languageCode?.identifier { case "ja": return .japanese case "zh": - if let script = locale.language.script?.identifier { - return script == "Hant" ? .traditionalChinese : .simplifiedChinese - } + let script = locale.language.script?.identifier + if script == "Hant" { return .traditionalChinese } + if script == "Hans" { return .simplifiedChinese } + let identifier = locale.identifier + if identifier.contains("Hant") { return .traditionalChinese } + if identifier.contains("Hans") { return .simplifiedChinese } switch locale.region?.identifier { case "TW", "HK", "MO": return .traditionalChinese diff --git a/supacode/Features/Help/AskAgentHelpView.swift b/supacode/Features/Help/AskAgentHelpView.swift index c5061e7b..3831d2cc 100644 --- a/supacode/Features/Help/AskAgentHelpView.swift +++ b/supacode/Features/Help/AskAgentHelpView.swift @@ -12,7 +12,7 @@ struct AskAgentHelpView: View { init( docsDirectoryPath: String = AskAgentHelpView.resolvedDocsDirectoryPath, - locale: Locale = .current, + locale: Locale = AskAgentHelpPrompt.systemPreferredLocale(), onDone: @escaping () -> Void ) { self.strings = AskAgentHelpPrompt.strings(docsDirectoryPath: docsDirectoryPath, locale: locale) diff --git a/supacodeTests/AskAgentHelpPromptTests.swift b/supacodeTests/AskAgentHelpPromptTests.swift index 74ed62f7..95925b39 100644 --- a/supacodeTests/AskAgentHelpPromptTests.swift +++ b/supacodeTests/AskAgentHelpPromptTests.swift @@ -18,6 +18,14 @@ struct AskAgentHelpPromptTests { #expect(AskAgentHelpPrompt.languageKey(for: Locale(identifier: "zh-Hans")) == .simplifiedChinese) } + // Script wins over region: e.g. a Simplified-Chinese user living in Japan + // reports `zh-Hans-JP` — region JP must not flip it to English/Traditional. + @Test func chineseScriptWinsOverNonChineseRegion() { + #expect(AskAgentHelpPrompt.languageKey(for: Locale(identifier: "zh-Hans-JP")) == .simplifiedChinese) + #expect(AskAgentHelpPrompt.languageKey(for: Locale(identifier: "zh-Hant-JP")) == .traditionalChinese) + #expect(AskAgentHelpPrompt.languageKey(for: Locale(identifier: "zh-Hans-US")) == .simplifiedChinese) + } + @Test func promptEmbedsResolvedDocPaths() { let docs = "/Applications/Prowl.app/Contents/Resources/docs" let strings = AskAgentHelpPrompt.strings(docsDirectoryPath: docs, locale: Locale(identifier: "en_US"))