Detailed changes
@@ -870,6 +870,30 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
return m, m.current.Init()
+ case tui.LanguageChangedMsg:
+ // Rebuild all models with new translations
+ // Keep current view type but recreate with fresh i18n
+ switch curr := m.current.(type) {
+ case *tui.Settings:
+ // Preserve settings state when rebuilding
+ newSettings := tui.NewSettings(m.config)
+ newSettings.RestoreState(curr.GetState())
+ m.current = newSettings
+ case *tui.Composer:
+ // Preserve composer state if possible, for now just refresh
+ m.current = tui.NewChoice()
+ case *tui.Inbox:
+ m.current = tui.NewChoice()
+ case *tui.FolderInbox:
+ // Just rebuild settings view, folder inbox will be recreated on next navigation
+ m.current = tui.NewSettings(m.config)
+ default:
+ // For other views, return to choice menu
+ m.current = tui.NewChoice()
+ }
+ m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
+ return m, m.current.Init()
+
case tui.GoToSettingsMsg:
m.current = tui.NewSettings(m.config)
m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
@@ -526,6 +526,8 @@ type SendRSVPMsg struct {
}
// RSVPResultMsg signals that RSVP was sent (or failed)
+type LanguageChangedMsg struct{}
+
type RSVPResultMsg struct {
Err error
Response string // "ACCEPTED", "DECLINED", "TENTATIVE"
@@ -75,6 +75,16 @@ type Settings struct {
confirmingDisable bool
}
+type SettingsState struct {
+ ActivePane SettingsPane
+ ActiveCategory SettingsCategory
+ MenuCursor int
+ GeneralCursor int
+ AccountsCursor int
+ ThemeCursor int
+ ListsCursor int
+}
+
func NewSettings(cfg *config.Config) *Settings {
if cfg == nil {
cfg = &config.Config{}
@@ -110,6 +120,28 @@ func NewSettings(cfg *config.Config) *Settings {
}
}
+func (m *Settings) GetState() SettingsState {
+ return SettingsState{
+ ActivePane: m.activePane,
+ ActiveCategory: m.activeCategory,
+ MenuCursor: m.menuCursor,
+ GeneralCursor: m.generalCursor,
+ AccountsCursor: m.accountsCursor,
+ ThemeCursor: m.themeCursor,
+ ListsCursor: m.listsCursor,
+ }
+}
+
+func (m *Settings) RestoreState(state SettingsState) {
+ m.activePane = state.ActivePane
+ m.activeCategory = state.ActiveCategory
+ m.menuCursor = state.MenuCursor
+ m.generalCursor = state.GeneralCursor
+ m.accountsCursor = state.AccountsCursor
+ m.themeCursor = state.ThemeCursor
+ m.listsCursor = state.ListsCursor
+}
+
func (m *Settings) Init() tea.Cmd {
return textinput.Blink
}
@@ -54,6 +54,10 @@ func (m *Settings) updateGeneral(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
nextIdx := (currentIdx + 1) % len(langs)
m.cfg.Language = langs[nextIdx]
_ = config.SaveConfig(m.cfg)
+ // Apply language change immediately
+ i18n.GetManager().SetLanguage(m.cfg.Language)
+ // Trigger full UI rebuild
+ return m, func() tea.Msg { return LanguageChangedMsg{} }
case 5: // Edit Signature
if msg.String() == "enter" || msg.String() == "right" || msg.String() == "l" {
return m, func() tea.Msg { return GoToSignatureEditorMsg{} }
@@ -77,7 +81,7 @@ func (m *Settings) viewGeneral() string {
{"settings_general.hide_tips", onOff(m.cfg.HideTips), "Hide helpful hints displayed at the bottom of the screen."},
{"settings_general.disable_notifications", onOff(m.cfg.DisableNotifications), "Turn off desktop notifications for new mail."},
{"settings_general.date_format", getDateFormatLabel(m.cfg.DateFormat), "Change how dates and times are displayed."},
- {"settings_general.language", getLanguageLabel(m.cfg.GetLanguage()), "Change the interface language. Restart required."},
+ {"settings_general.language", getLanguageLabel(m.cfg.GetLanguage()), "Change the interface language. Changes apply instantly."},
{"settings_general.signature", getSignatureStatus(), "Configure the signature appended to your outgoing emails."},
}