feat(i18n): localize config editor labels
Harvests PR #2919 by @gordonlu, preserving Codex-aware reasoning effort display while localizing the config editor chrome and default placeholders. Co-authored-by: gordonlu <3125629+gordonlu@users.noreply.github.com>
This commit is contained in:
@@ -39,6 +39,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **Localized config section labels (#2918).** The interactive config view now
|
||||
localizes section and session/saved scope labels while preserving English
|
||||
search terms. Thanks @gordonlu for the PR.
|
||||
- **Localized config editor labels (#2919).** The config editor modal now
|
||||
localizes edit labels, default/unavailable placeholders, and effective
|
||||
currency hints. Thanks @gordonlu for the PR.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **Localized config section labels (#2918).** The interactive config view now
|
||||
localizes section and session/saved scope labels while preserving English
|
||||
search terms. Thanks @gordonlu for the PR.
|
||||
- **Localized config editor labels (#2919).** The config editor modal now
|
||||
localizes edit labels, default/unavailable placeholders, and effective
|
||||
currency hints. Thanks @gordonlu for the PR.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -257,6 +257,17 @@ pub enum MessageId {
|
||||
ConfigSectionMcp,
|
||||
ConfigScopeSession,
|
||||
ConfigScopeSaved,
|
||||
ConfigEditCancelled,
|
||||
ConfigEditTitlePrefix,
|
||||
ConfigEditScopeLabel,
|
||||
ConfigEditCurrentLabel,
|
||||
ConfigEditHintLabel,
|
||||
ConfigEditNewLabel,
|
||||
ConfigEditFooter,
|
||||
ConfigRowEffective,
|
||||
ConfigDefaultValue,
|
||||
ConfigDefaultReasoning,
|
||||
ConfigUnavailable,
|
||||
HelpTitle,
|
||||
HelpFilterPlaceholder,
|
||||
HelpFilterPrefix,
|
||||
@@ -663,6 +674,17 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[
|
||||
MessageId::ConfigSectionMcp,
|
||||
MessageId::ConfigScopeSession,
|
||||
MessageId::ConfigScopeSaved,
|
||||
MessageId::ConfigEditCancelled,
|
||||
MessageId::ConfigEditTitlePrefix,
|
||||
MessageId::ConfigEditScopeLabel,
|
||||
MessageId::ConfigEditCurrentLabel,
|
||||
MessageId::ConfigEditHintLabel,
|
||||
MessageId::ConfigEditNewLabel,
|
||||
MessageId::ConfigEditFooter,
|
||||
MessageId::ConfigRowEffective,
|
||||
MessageId::ConfigDefaultValue,
|
||||
MessageId::ConfigDefaultReasoning,
|
||||
MessageId::ConfigUnavailable,
|
||||
MessageId::HelpTitle,
|
||||
MessageId::HelpFilterPlaceholder,
|
||||
MessageId::HelpFilterPrefix,
|
||||
@@ -1242,6 +1264,19 @@ fn english(id: MessageId) -> &'static str {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "SESSION",
|
||||
MessageId::ConfigScopeSaved => "SAVED",
|
||||
MessageId::ConfigEditCancelled => "Edit cancelled",
|
||||
MessageId::ConfigEditTitlePrefix => "Edit ",
|
||||
MessageId::ConfigEditScopeLabel => "Scope: ",
|
||||
MessageId::ConfigEditCurrentLabel => "Current: ",
|
||||
MessageId::ConfigEditHintLabel => "Hint: ",
|
||||
MessageId::ConfigEditNewLabel => "New: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=apply, Esc=cancel, Ctrl+U=clear, Ctrl+A=all, \u{2190}/\u{2192}=move "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (effective {currency})",
|
||||
MessageId::ConfigDefaultValue => "(default)",
|
||||
MessageId::ConfigDefaultReasoning => "(config/default)",
|
||||
MessageId::ConfigUnavailable => "(unavailable)",
|
||||
MessageId::HelpTitle => "Help",
|
||||
MessageId::HelpFilterPlaceholder => "Type to filter",
|
||||
MessageId::HelpFilterPrefix => "Filter: ",
|
||||
@@ -1794,6 +1829,19 @@ fn vietnamese(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "PHIÊN",
|
||||
MessageId::ConfigScopeSaved => "ĐÃ LƯU",
|
||||
MessageId::ConfigEditCancelled => "Đã hủy chỉnh sửa",
|
||||
MessageId::ConfigEditTitlePrefix => "Sửa ",
|
||||
MessageId::ConfigEditScopeLabel => "Phạm vi: ",
|
||||
MessageId::ConfigEditCurrentLabel => "Hiện tại: ",
|
||||
MessageId::ConfigEditHintLabel => "Gợi ý: ",
|
||||
MessageId::ConfigEditNewLabel => "Mới: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=áp dụng, Esc=hủy, Ctrl+U=xóa, Ctrl+A=tất cả, \u{2190}/\u{2192}=di chuyển "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (hiệu lực {currency})",
|
||||
MessageId::ConfigDefaultValue => "(mặc định)",
|
||||
MessageId::ConfigDefaultReasoning => "(cấu hình/mặc định)",
|
||||
MessageId::ConfigUnavailable => "(không khả dụng)",
|
||||
MessageId::HelpTitle => "Trợ giúp",
|
||||
MessageId::HelpFilterPlaceholder => "Nhập để lọc",
|
||||
MessageId::HelpFilterPrefix => "Bộ lọc: ",
|
||||
@@ -2447,6 +2495,19 @@ fn traditional_chinese(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "會話",
|
||||
MessageId::ConfigScopeSaved => "已儲存",
|
||||
MessageId::ConfigEditCancelled => "編輯已取消",
|
||||
MessageId::ConfigEditTitlePrefix => "編輯 ",
|
||||
MessageId::ConfigEditScopeLabel => "範圍: ",
|
||||
MessageId::ConfigEditCurrentLabel => "目前: ",
|
||||
MessageId::ConfigEditHintLabel => "提示: ",
|
||||
MessageId::ConfigEditNewLabel => "新值: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=套用, Esc=取消, Ctrl+U=清除, Ctrl+A=全選, \u{2190}/\u{2192}=移動 "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (實際 {currency})",
|
||||
MessageId::ConfigDefaultValue => "(預設)",
|
||||
MessageId::ConfigDefaultReasoning => "(設定/預設)",
|
||||
MessageId::ConfigUnavailable => "(無法使用)",
|
||||
MessageId::StatusPickerTitle => " 狀態列 ",
|
||||
MessageId::StatusPickerInstruction => "選擇要在底部顯示的項目:",
|
||||
MessageId::StatusPickerActionToggle => "切換 ",
|
||||
@@ -2511,6 +2572,19 @@ fn japanese(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "セッション",
|
||||
MessageId::ConfigScopeSaved => "保存済み",
|
||||
MessageId::ConfigEditCancelled => "編集をキャンセルしました",
|
||||
MessageId::ConfigEditTitlePrefix => "編集 ",
|
||||
MessageId::ConfigEditScopeLabel => "スコープ: ",
|
||||
MessageId::ConfigEditCurrentLabel => "現在: ",
|
||||
MessageId::ConfigEditHintLabel => "ヒント: ",
|
||||
MessageId::ConfigEditNewLabel => "新規: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=適用, Esc=キャンセル, Ctrl+U=クリア, Ctrl+A=全選択, \u{2190}/\u{2192}=移動 "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (実効 {currency})",
|
||||
MessageId::ConfigDefaultValue => "(デフォルト)",
|
||||
MessageId::ConfigDefaultReasoning => "(設定/デフォルト)",
|
||||
MessageId::ConfigUnavailable => "(利用不可)",
|
||||
MessageId::HelpTitle => "ヘルプ",
|
||||
MessageId::HelpFilterPlaceholder => "入力して絞り込み",
|
||||
MessageId::HelpFilterPrefix => "絞り込み: ",
|
||||
@@ -3054,6 +3128,19 @@ fn chinese_simplified(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "会话",
|
||||
MessageId::ConfigScopeSaved => "已保存",
|
||||
MessageId::ConfigEditCancelled => "编辑已取消",
|
||||
MessageId::ConfigEditTitlePrefix => "编辑 ",
|
||||
MessageId::ConfigEditScopeLabel => "范围: ",
|
||||
MessageId::ConfigEditCurrentLabel => "当前: ",
|
||||
MessageId::ConfigEditHintLabel => "提示: ",
|
||||
MessageId::ConfigEditNewLabel => "新值: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=应用, Esc=取消, Ctrl+U=清除, Ctrl+A=全选, \u{2190}/\u{2192}=移动 "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (实际 {currency})",
|
||||
MessageId::ConfigDefaultValue => "(默认)",
|
||||
MessageId::ConfigDefaultReasoning => "(配置/默认)",
|
||||
MessageId::ConfigUnavailable => "(不可用)",
|
||||
MessageId::HelpTitle => "帮助",
|
||||
MessageId::HelpFilterPlaceholder => "输入以筛选",
|
||||
MessageId::HelpFilterPrefix => "筛选: ",
|
||||
@@ -3537,6 +3624,19 @@ fn portuguese_brazil(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "SESSÃO",
|
||||
MessageId::ConfigScopeSaved => "SALVO",
|
||||
MessageId::ConfigEditCancelled => "Edição cancelada",
|
||||
MessageId::ConfigEditTitlePrefix => "Editar ",
|
||||
MessageId::ConfigEditScopeLabel => "Escopo: ",
|
||||
MessageId::ConfigEditCurrentLabel => "Atual: ",
|
||||
MessageId::ConfigEditHintLabel => "Dica: ",
|
||||
MessageId::ConfigEditNewLabel => "Novo: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=aplicar, Esc=cancelar, Ctrl+U=limpar, Ctrl+A=tudo, \u{2190}/\u{2192}=mover "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (efetivo {currency})",
|
||||
MessageId::ConfigDefaultValue => "(padrão)",
|
||||
MessageId::ConfigDefaultReasoning => "(config/padrão)",
|
||||
MessageId::ConfigUnavailable => "(indisponível)",
|
||||
MessageId::HelpTitle => "Ajuda",
|
||||
MessageId::HelpFilterPlaceholder => "Digite para filtrar",
|
||||
MessageId::HelpFilterPrefix => "Filtro: ",
|
||||
@@ -4108,6 +4208,19 @@ fn spanish_latin_america(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::ConfigSectionMcp => "MCP",
|
||||
MessageId::ConfigScopeSession => "SESIÓN",
|
||||
MessageId::ConfigScopeSaved => "GUARDADO",
|
||||
MessageId::ConfigEditCancelled => "Edición cancelada",
|
||||
MessageId::ConfigEditTitlePrefix => "Editar ",
|
||||
MessageId::ConfigEditScopeLabel => "Ámbito: ",
|
||||
MessageId::ConfigEditCurrentLabel => "Actual: ",
|
||||
MessageId::ConfigEditHintLabel => "Pista: ",
|
||||
MessageId::ConfigEditNewLabel => "Nuevo: ",
|
||||
MessageId::ConfigEditFooter => {
|
||||
" Enter=aplicar, Esc=cancelar, Ctrl+U=limpiar, Ctrl+A=todo, \u{2190}/\u{2192}=mover "
|
||||
}
|
||||
MessageId::ConfigRowEffective => " (efectivo {currency})",
|
||||
MessageId::ConfigDefaultValue => "(predeterminado)",
|
||||
MessageId::ConfigDefaultReasoning => "(config/predeterminado)",
|
||||
MessageId::ConfigUnavailable => "(no disponible)",
|
||||
MessageId::HelpTitle => "Ayuda",
|
||||
MessageId::HelpFilterPlaceholder => "Escribe para filtrar",
|
||||
MessageId::HelpFilterPrefix => "Filtro: ",
|
||||
|
||||
@@ -490,7 +490,7 @@ impl ConfigView {
|
||||
value: settings
|
||||
.default_model
|
||||
.as_deref()
|
||||
.unwrap_or("(default)")
|
||||
.unwrap_or(tr(app.ui_locale, MessageId::ConfigDefaultValue))
|
||||
.to_string(),
|
||||
editable: true,
|
||||
scope: ConfigScope::Saved,
|
||||
@@ -499,7 +499,7 @@ impl ConfigView {
|
||||
section: ConfigSection::Model,
|
||||
key: "reasoning_effort".to_string(),
|
||||
value: settings.reasoning_effort.as_deref().map_or_else(
|
||||
|| "(config/default)".to_string(),
|
||||
|| tr(app.ui_locale, MessageId::ConfigDefaultReasoning).to_string(),
|
||||
|value| {
|
||||
crate::tui::app::ReasoningEffort::from_setting_for_provider(
|
||||
value,
|
||||
@@ -557,10 +557,9 @@ impl ConfigView {
|
||||
ConfigRow {
|
||||
section: ConfigSection::Display,
|
||||
key: "background_color".to_string(),
|
||||
value: settings
|
||||
.background_color
|
||||
.clone()
|
||||
.unwrap_or_else(|| "(default)".to_string()),
|
||||
value: settings.background_color.clone().unwrap_or_else(|| {
|
||||
tr(app.ui_locale, MessageId::ConfigDefaultValue).to_string()
|
||||
}),
|
||||
editable: true,
|
||||
scope: ConfigScope::Saved,
|
||||
},
|
||||
@@ -938,7 +937,7 @@ impl ConfigView {
|
||||
match key.code {
|
||||
KeyCode::Esc => {
|
||||
self.editing = None;
|
||||
self.status = Some("Edit cancelled".to_string());
|
||||
self.status = Some(self.tr(MessageId::ConfigEditCancelled).to_string());
|
||||
ViewAction::None
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
@@ -1056,12 +1055,14 @@ impl ConfigView {
|
||||
};
|
||||
let key = row.key.clone();
|
||||
let original_value = row.value.clone();
|
||||
let initial_value = if (key == "default_model" && original_value == "(default)")
|
||||
|| (key == "reasoning_effort" && original_value == "(config/default)")
|
||||
{
|
||||
String::new()
|
||||
} else {
|
||||
original_value.clone()
|
||||
let initial_value = match config_default_placeholder_message(&key) {
|
||||
Some(message_id)
|
||||
if original_value == tr(self.locale, message_id)
|
||||
|| original_value == tr(Locale::En, message_id) =>
|
||||
{
|
||||
String::new()
|
||||
}
|
||||
_ => original_value.clone(),
|
||||
};
|
||||
|
||||
let buffer: Vec<char> = initial_value.chars().collect();
|
||||
@@ -1090,7 +1091,12 @@ impl ConfigView {
|
||||
let effective_cost_currency =
|
||||
crate::pricing::CostCurrency::from_setting(&self.effective_cost_currency);
|
||||
if saved_cost_currency != effective_cost_currency {
|
||||
return format!("{} (effective {})", row.value, self.effective_cost_currency);
|
||||
return format!(
|
||||
"{}{}",
|
||||
row.value,
|
||||
self.tr(MessageId::ConfigRowEffective)
|
||||
.replace("{currency}", &self.effective_cost_currency)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1112,7 +1118,7 @@ fn config_base_url_row_value(app: &App) -> String {
|
||||
config.provider = Some(app.api_provider.as_str().to_string());
|
||||
config.deepseek_base_url()
|
||||
})
|
||||
.unwrap_or_else(|_| "(unavailable)".to_string())
|
||||
.unwrap_or_else(|_| tr(app.ui_locale, MessageId::ConfigUnavailable).to_string())
|
||||
}
|
||||
|
||||
fn cost_currency_config_value(app: &App) -> String {
|
||||
@@ -1160,7 +1166,18 @@ fn config_hint_for_key(key: &str) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_config_editor_value_line(edit: &ConfigEdit) -> ratatui::text::Line<'static> {
|
||||
fn config_default_placeholder_message(key: &str) -> Option<MessageId> {
|
||||
match key {
|
||||
"default_model" | "background_color" => Some(MessageId::ConfigDefaultValue),
|
||||
"reasoning_effort" => Some(MessageId::ConfigDefaultReasoning),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn render_config_editor_value_line(
|
||||
edit: &ConfigEdit,
|
||||
locale: Locale,
|
||||
) -> ratatui::text::Line<'static> {
|
||||
use ratatui::{
|
||||
style::Style,
|
||||
text::{Line, Span},
|
||||
@@ -1168,7 +1185,7 @@ fn render_config_editor_value_line(edit: &ConfigEdit) -> ratatui::text::Line<'st
|
||||
|
||||
let mut spans = Vec::new();
|
||||
spans.push(Span::styled(
|
||||
"New: ",
|
||||
tr(locale, MessageId::ConfigEditNewLabel),
|
||||
Style::default().fg(palette::TEXT_MUTED),
|
||||
));
|
||||
|
||||
@@ -1357,33 +1374,38 @@ impl ModalView for ConfigView {
|
||||
let (lines, footer) = if let Some(edit) = self.editing.as_ref() {
|
||||
let mut lines: Vec<Line> = Vec::new();
|
||||
lines.push(Line::from(vec![Span::styled(
|
||||
format!("Edit {}", edit.key),
|
||||
format!("{}{}", self.tr(MessageId::ConfigEditTitlePrefix), edit.key),
|
||||
Style::default().fg(palette::DEEPSEEK_SKY).bold(),
|
||||
)]));
|
||||
lines.push(Line::from(""));
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("Scope: ", Style::default().fg(palette::TEXT_MUTED)),
|
||||
Span::styled(
|
||||
self.tr(MessageId::ConfigEditScopeLabel),
|
||||
Style::default().fg(palette::TEXT_MUTED),
|
||||
),
|
||||
Span::raw(edit.scope.label(self.locale)),
|
||||
]));
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("Current: ", Style::default().fg(palette::TEXT_MUTED)),
|
||||
Span::styled(
|
||||
self.tr(MessageId::ConfigEditCurrentLabel),
|
||||
Style::default().fg(palette::TEXT_MUTED),
|
||||
),
|
||||
Span::raw(truncate_view_text(&edit.original_value, 60)),
|
||||
]));
|
||||
lines.push(Line::from(""));
|
||||
lines.push(render_config_editor_value_line(edit));
|
||||
lines.push(render_config_editor_value_line(edit, self.locale));
|
||||
lines.push(Line::from(""));
|
||||
let hint = config_hint_for_key(&edit.key);
|
||||
if !hint.is_empty() {
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("Hint: ", Style::default().fg(palette::TEXT_MUTED)),
|
||||
Span::styled(
|
||||
self.tr(MessageId::ConfigEditHintLabel),
|
||||
Style::default().fg(palette::TEXT_MUTED),
|
||||
),
|
||||
Span::raw(hint),
|
||||
]));
|
||||
}
|
||||
(
|
||||
lines,
|
||||
" Enter=apply, Esc=cancel, Ctrl+U=clear, Ctrl+A=all, \u{2190}/\u{2192}=move "
|
||||
.to_string(),
|
||||
)
|
||||
(lines, self.tr(MessageId::ConfigEditFooter).to_string())
|
||||
} else {
|
||||
let content_height = usize::from(inner.height);
|
||||
let header_lines = 5usize;
|
||||
@@ -2061,7 +2083,7 @@ mod tests {
|
||||
ViewStack, subagent_view_agents, truncate_view_text,
|
||||
};
|
||||
use crate::config::Config;
|
||||
use crate::localization::Locale;
|
||||
use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::settings::Settings;
|
||||
use crate::tools::subagent::{
|
||||
SubAgentAssignment, SubAgentResult, SubAgentStatus, SubAgentType,
|
||||
@@ -2410,7 +2432,7 @@ base_url = "https://api.xiaomimimo.com/v1"
|
||||
.expect("cost_currency row");
|
||||
|
||||
assert_eq!(row.value, "usd");
|
||||
assert_eq!(view.row_display_value(row), "usd (effective cny)");
|
||||
assert_eq!(view.row_display_value(row), "usd (实际 cny)");
|
||||
assert_eq!(Settings::load().expect("settings").cost_currency, "usd");
|
||||
}
|
||||
|
||||
@@ -2479,6 +2501,35 @@ base_url = "https://api.xiaomimimo.com/v1"
|
||||
assert_eq!(row.value, "xhigh");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_view_editing_localized_default_placeholders_starts_blank() {
|
||||
let _guard = ConfigSettingsEnvGuard::new("locale = \"zh-Hans\"\n");
|
||||
let app = create_test_app();
|
||||
let mut view = ConfigView::new_for_app(&app);
|
||||
|
||||
for (key, message_id) in [
|
||||
("default_model", MessageId::ConfigDefaultValue),
|
||||
("reasoning_effort", MessageId::ConfigDefaultReasoning),
|
||||
("background_color", MessageId::ConfigDefaultValue),
|
||||
] {
|
||||
view.selected = view
|
||||
.rows
|
||||
.iter()
|
||||
.position(|row| row.key == key)
|
||||
.unwrap_or_else(|| panic!("{key} row missing"));
|
||||
view.start_edit();
|
||||
|
||||
let edit = view.editing.as_ref().expect("editing should start");
|
||||
assert_eq!(edit.original_value, tr(Locale::ZhHans, message_id));
|
||||
assert!(
|
||||
edit.buffer.is_empty(),
|
||||
"localized default placeholder should not become edit text for {key}"
|
||||
);
|
||||
|
||||
view.editing = None;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_view_filter_matches_group_and_rows() {
|
||||
let mut view = create_config_view(Locale::En);
|
||||
@@ -2717,7 +2768,8 @@ base_url = "https://api.xiaomimimo.com/v1"
|
||||
|
||||
#[test]
|
||||
fn config_view_escape_cancels_editing() {
|
||||
let app = create_test_app();
|
||||
let mut app = create_test_app();
|
||||
app.ui_locale = Locale::En;
|
||||
let mut view = ConfigView::new_for_app(&app);
|
||||
let _ = view.handle_key(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
|
||||
assert!(view.editing.is_some());
|
||||
@@ -2725,7 +2777,10 @@ base_url = "https://api.xiaomimimo.com/v1"
|
||||
let cancel = view.handle_key(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE));
|
||||
assert!(matches!(cancel, ViewAction::None));
|
||||
assert!(view.editing.is_none());
|
||||
assert_eq!(view.status.as_deref(), Some("Edit cancelled"));
|
||||
assert_eq!(
|
||||
view.status.as_deref(),
|
||||
Some(tr(Locale::En, MessageId::ConfigEditCancelled))
|
||||
);
|
||||
}
|
||||
|
||||
/// A modal that doesn't override `handle_paste` must report
|
||||
|
||||
Reference in New Issue
Block a user