@@ -68,6 +68,41 @@ private struct StubPane: View {
6868// MARK: General
6969// MARK: - ════════════════════════════════════════════
7070
71+ // MARK: - Supported App Languages
72+ enum AppLanguage : String , CaseIterable , Identifiable {
73+ case system = " system "
74+ case en = " en "
75+ case de = " de "
76+ case ru = " ru "
77+ var id : String { rawValue }
78+ var displayName : String {
79+ switch self {
80+ case . system: return " System Default "
81+ case . en: return " English "
82+ case . de: return " Deutsch "
83+ case . ru: return " Русский "
84+ }
85+ }
86+ /// Apply language override to UserDefaults (takes effect on next launch)
87+ static func apply( _ language: AppLanguage ) {
88+ if language == . system {
89+ UserDefaults . standard. removeObject ( forKey: " AppleLanguages " )
90+ } else {
91+ UserDefaults . standard. set ( [ language. rawValue] , forKey: " AppleLanguages " )
92+ }
93+ log. info ( " [Settings] Language set to ' \( language. displayName) ' — restart required " )
94+ }
95+ /// Read current setting from UserDefaults
96+ static func current( ) -> AppLanguage {
97+ guard let langs = UserDefaults . standard. array ( forKey: " AppleLanguages " ) as? [ String ] ,
98+ let first = langs. first,
99+ let lang = AppLanguage ( rawValue: first) else {
100+ return . system
101+ }
102+ return lang
103+ }
104+ }
105+ // MARK: - SettingsGeneralPane
71106struct SettingsGeneralPane : View {
72107
73108 @AppStorage ( " settings.appearance " ) private var appearance : String = " system "
@@ -76,6 +111,8 @@ struct SettingsGeneralPane: View {
76111 @AppStorage ( " settings.showHiddenFiles " ) private var showHiddenFiles : Bool = false
77112 @AppStorage ( " settings.showExtensions " ) private var showExtensions : Bool = true
78113 @AppStorage ( " settings.startupPath " ) private var startupPath : String = " home "
114+ @State private var selectedLanguage : AppLanguage = AppLanguage . current ( )
115+ @State private var showRestartHint : Bool = false
79116
80117 var body : some View {
81118 VStack ( alignment: . leading, spacing: 20 ) {
@@ -96,6 +133,32 @@ struct SettingsGeneralPane: View {
96133 }
97134 }
98135
136+ // ── Language ──
137+ SettingsGroupBox {
138+ VStack ( spacing: 0 ) {
139+ SettingsRow ( label: " Language: " , help: " UI language for menus, labels and dialogs " ) {
140+ HStack ( spacing: 12 ) {
141+ Picker ( " " , selection: $selectedLanguage) {
142+ ForEach ( AppLanguage . allCases) { lang in
143+ Text ( lang. displayName) . tag ( lang)
144+ }
145+ }
146+ . labelsHidden ( )
147+ . frame ( width: 180 )
148+ . onChange ( of: selectedLanguage) { _, newLang in
149+ AppLanguage . apply ( newLang)
150+ showRestartHint = newLang != . system
151+ }
152+ if showRestartHint {
153+ Label ( " Restart app to apply " , systemImage: " arrow.clockwise " )
154+ . font ( . system( size: 11 ) )
155+ . foregroundStyle ( . orange)
156+ }
157+ }
158+ }
159+ }
160+ }
161+
99162 // ── Text & Icons ──
100163 SettingsGroupBox {
101164 VStack ( spacing: 0 ) {
0 commit comments