Skip to content

Commit

Permalink
refactor(tui): replace rust-i18n with i18n-embed
Browse files Browse the repository at this point in the history
  • Loading branch information
nc7s committed Dec 12, 2024
1 parent 0e14427 commit cec26eb
Show file tree
Hide file tree
Showing 26 changed files with 1,609 additions and 346 deletions.
604 changes: 396 additions & 208 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ petgraph = "0.6.5"
pretty_assertions = "1.4.1"
rand = "0.8.5"
ratatui = "0.29.0"
rust-i18n = "3.1.2"
rust-embed = "8.5"
i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] }
i18n-embed-fl = "0.9"
serde = { version = "1.0.201", default-features = false }
serde_json = { version = "1.0.117", default-features = false }
serde_with = { version = "3.11.0", default-features = false, features = ["macros"] }
Expand Down
6 changes: 4 additions & 2 deletions crates/trippy-tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ itertools.workspace = true
maxminddb.workspace = true
petgraph.workspace = true
ratatui.workspace = true
rust-i18n.workspace = true
rust-embed.workspace = true
i18n-embed.workspace = true
i18n-embed-fl.workspace = true
serde = { workspace = true, default-features = false, features = [ "derive" ] }
serde_json.workspace = true
serde_with.workspace = true
Expand All @@ -59,4 +61,4 @@ pretty_assertions.workspace = true
test-case.workspace = true

[lints]
workspace = true
workspace = true
4 changes: 4 additions & 0 deletions crates/trippy-tui/i18n.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fallback_language = "en"

[fluent]
assets_dir = "../../i18n"
6 changes: 3 additions & 3 deletions crates/trippy-tui/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::config::{LogFormat, LogSpanEvents, Mode, TrippyConfig};
use crate::frontend::TuiConfig;
use crate::geoip::GeoIpLookup;
use crate::locale::{locale, set_locale};
use crate::locale;
use crate::{frontend, report};
use anyhow::{anyhow, Error};
use std::net::IpAddr;
Expand All @@ -15,8 +15,8 @@ use trippy_privilege::Privilege;

/// Run the trippy application.
pub fn run_trippy(cfg: &TrippyConfig, pid: u16) -> anyhow::Result<()> {
set_locale(cfg.tui_locale.as_deref());
let locale = locale();
let locale = locale::init(cfg.tui_locale.as_deref())?;

let _guard = configure_logging(cfg);
let resolver = start_dns_resolver(cfg)?;
let geoip_lookup = create_geoip_lookup(cfg, &locale)?;
Expand Down
12 changes: 9 additions & 3 deletions crates/trippy-tui/src/frontend/columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ pub enum ColumnStatus {
impl Display for ColumnStatus {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Shown => write!(f, "{}", t!("on")),
Self::Hidden => write!(f, "{}", t!("off")),
Self::Shown => f.write_str(&t!("on")),
Self::Hidden => f.write_str(&t!("off")),
}
}
}
Expand Down Expand Up @@ -271,8 +271,11 @@ impl ColumnType {
/// The name of the column in the current locale.
#[allow(clippy::cognitive_complexity)]
pub(self) fn name(&self) -> Cow<'_, str> {
if self == &Self::Ttl {
return "#".into();
}
match self {
Self::Ttl => Cow::Borrowed("#"),
Self::Ttl => unreachable!(),
Self::Host => t!("column_host"),
Self::LossPct => t!("column_loss_pct"),
Self::Sent => t!("column_snd"),
Expand All @@ -298,6 +301,7 @@ impl ColumnType {
Self::Bloss => t!("column_bloss"),
Self::FlossPct => t!("column_floss_pct"),
}
.into()
}

/// The width of the column.
Expand Down Expand Up @@ -426,6 +430,7 @@ mod tests {
#[test_case(ColumnType::StdDev, "StDev")]
#[test_case(ColumnType::Status, "Sts")]
fn test_column_display_formatting(c: ColumnType, heading: &'static str) {
let _ = crate::locale::init(Some("en"));
assert_eq!(format!("{c}"), heading);
}

Expand All @@ -438,6 +443,7 @@ mod tests {

#[test]
fn test_column_constraints() {
let _ = crate::locale::init(Some("en"));
let columns = Columns::from(TuiColumns::default());
let constraints = columns.constraints(Rect::new(0, 0, 80, 0));
assert_eq!(
Expand Down
10 changes: 5 additions & 5 deletions crates/trippy-tui/src/frontend/render/bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ pub fn render(f: &mut Frame<'_>, rect: Rect, app: &TuiApp) {
Protocol::Icmp => format!(
"{}/{}",
fmt_target_family(app.tracer_config().data.target_addr()),
t!("ICMP"),
"ICMP",
),
Protocol::Udp => format!(
"{}/{}/{}",
fmt_target_family(app.tracer_config().data.target_addr()),
t!("UDP"),
"UDP",
app.tracer_config().data.multipath_strategy(),
),
Protocol::Tcp => format!(
"{}/{}",
fmt_target_family(app.tracer_config().data.target_addr()),
t!("TCP"),
"TCP",
),
});

Expand Down Expand Up @@ -113,8 +113,8 @@ pub fn render(f: &mut Frame<'_>, rect: Rect, app: &TuiApp) {

fn fmt_privilege_mode(privilege_mode: PrivilegeMode) -> Cow<'static, str> {
match privilege_mode {
PrivilegeMode::Privileged => t!("privileged"),
PrivilegeMode::Unprivileged => t!("unprivileged"),
PrivilegeMode::Privileged => t!("privileged").into(),
PrivilegeMode::Unprivileged => t!("unprivileged").into(),
}
}

Expand Down
25 changes: 14 additions & 11 deletions crates/trippy-tui/src/frontend/render/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,15 @@ pub fn render(f: &mut Frame<'_>, app: &TuiApp, rect: Rect) {
let flow_count = app.tracer_data().flows().len();
format!(
", {}",
t!("discovered_flows",
"hop_count" => hop_count,
"flow_count" => flow_count,
"plural_flows" => plural_flows
t!(
"discovered_flows",
hop_count = hop_count,
flow_count = flow_count,
plural_flows = plural_flows,
)
)
} else {
format!(", {}", t!("discovered", "hop_count" => hop_count))
format!(", {}", t!("discovered", hop_count = hop_count))
};
let left_line = vec![
Line::from(vec![
Expand Down Expand Up @@ -183,7 +184,7 @@ fn render_source(app: &TuiApp) -> String {
format_ip(app, addr)
}
} else {
String::from(t!("unknown"))
t!("unknown")
}
}

Expand Down Expand Up @@ -253,16 +254,18 @@ fn render_status(app: &TuiApp) -> String {
let failure_rate = format!("{failure_rate:.1}");
format!(
" [{}❗]",
t!("status_failures",
"failure_count" => failure_count,
"total_probes" => total_probes,
"failure_rate" => failure_rate)
t!(
"status_failures",
failure_count = failure_count,
total_probes = total_probes,
failure_rate = failure_rate
)
)
} else {
String::new()
};
if app.selected_tracer_data.error().is_some() {
String::from(t!("status_failed"))
t!("status_failed")
} else if let Some(start) = app.frozen_start {
let frozen = format_duration(Duration::from_secs(
start.elapsed().unwrap_or_default().as_secs(),
Expand Down
6 changes: 3 additions & 3 deletions crates/trippy-tui/src/frontend/render/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ pub fn render(f: &mut Frame<'_>, app: &TuiApp) {
Line::raw(r#" "#),
Line::raw(t!("help_tagline")),
Line::raw(r#" "#),
Line::raw(t!("help_show_settings", key = s)),
Line::raw(t!("help_show_bindings", key = b)),
Line::raw(t!("help_show_columns", key = c)),
Line::raw(t!("help_show_settings", key = s.to_string())),
Line::raw(t!("help_show_bindings", key = b.to_string())),
Line::raw(t!("help_show_columns", key = c.to_string())),
Line::raw(r#" "#),
Line::raw(r#" https://github.com/fujiapple852/trippy "#),
Line::raw(r#" "#),
Expand Down
61 changes: 30 additions & 31 deletions crates/trippy-tui/src/frontend/render/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,44 +134,43 @@ fn format_all_settings(app: &TuiApp) -> Vec<(String, String, Vec<SettingsItem>)>
let move_up = app.tui_config.bindings.previous_hop_address.to_string();
vec![
(
t!("settings_tab_tui_title").to_string(),
t!("settings_tab_tui_desc").to_string(),
t!("settings_tab_tui_title"),
t!("settings_tab_tui_desc"),
tui_settings,
),
(
t!("settings_tab_trace_title").to_string(),
t!("settings_tab_trace_desc").to_string(),
t!("settings_tab_trace_title"),
t!("settings_tab_trace_desc"),
trace_settings,
),
(
t!("settings_tab_dns_title").to_string(),
t!("settings_tab_dns_desc").to_string(),
t!("settings_tab_dns_title"),
t!("settings_tab_dns_desc"),
dns_settings,
),
(
t!("settings_tab_geoip_title").to_string(),
t!("settings_tab_geoip_desc").to_string(),
t!("settings_tab_geoip_title"),
t!("settings_tab_geoip_desc"),
geoip_settings,
),
(
t!("settings_tab_bindings_title").to_string(),
t!("settings_tab_bindings_desc").to_string(),
t!("settings_tab_bindings_title"),
t!("settings_tab_bindings_desc"),
bindings_settings,
),
(
t!("settings_tab_theme_title").to_string(),
t!("settings_tab_theme_desc").to_string(),
t!("settings_tab_theme_title"),
t!("settings_tab_theme_desc"),
theme_settings,
),
(
t!("settings_tab_columns_title").to_string(),
t!("settings_tab_columns_title"),
t!(
"settings_tab_columns_desc",
c = toggle_column,
d = move_down,
u = move_up
)
.to_string(),
),
columns_settings,
),
]
Expand All @@ -192,7 +191,7 @@ fn format_tui_settings(app: &TuiApp) -> Vec<SettingsItem> {
"tui-privacy-max-ttl",
app.tui_config
.privacy_max_ttl
.map_or_else(|| t!("off").to_string(), |m| m.to_string()),
.map_or_else(|| t!("off"), |m| m.to_string()),
),
SettingsItem::new(
"tui-address-mode",
Expand All @@ -211,7 +210,7 @@ fn format_tui_settings(app: &TuiApp) -> Vec<SettingsItem> {
"tui-max-addrs",
app.tui_config
.max_addrs
.map_or_else(|| t!("auto").to_string(), |m| m.to_string()),
.map_or_else(|| t!("auto"), |m| m.to_string()),
),
SettingsItem::new(
"tui-custom-columns",
Expand All @@ -226,12 +225,12 @@ fn format_trace_settings(app: &TuiApp) -> Vec<SettingsItem> {
let interface = if let Some(iface) = cfg.data.interface() {
iface.to_string()
} else {
t!("auto").to_string()
t!("auto")
};
let (src_port, dst_port) = match cfg.data.port_direction() {
PortDirection::None => (t!("na").to_string(), t!("na").to_string()),
PortDirection::FixedDest(dst) => (t!("auto").to_string(), format!("{}", dst.0)),
PortDirection::FixedSrc(src) => (format!("{}", src.0), t!("auto").to_string()),
PortDirection::None => (t!("na"), t!("na")),
PortDirection::FixedDest(dst) => (t!("auto"), format!("{}", dst.0)),
PortDirection::FixedSrc(src) => (format!("{}", src.0), t!("auto")),
PortDirection::FixedBoth(src, dst) => (format!("{}", src.0), format!("{}", dst.0)),
};
vec![
Expand Down Expand Up @@ -318,7 +317,7 @@ fn format_geoip_settings(app: &TuiApp) -> Vec<SettingsItem> {
app.tui_config
.geoip_mmdb_file
.as_deref()
.map_or_else(|| t!("none").to_string(), ToString::to_string),
.map_or_else(|| t!("none"), ToString::to_string),
)]
}

Expand Down Expand Up @@ -528,21 +527,21 @@ pub const SETTINGS_TAB_COLUMNS: usize = 6;
/// The name and number of items for each tabs in the setting dialog.
pub fn settings_tabs() -> [(String, usize); 7] {
[
(t!("settings_tab_tui_title").to_string(), 9),
(t!("settings_tab_trace_title").to_string(), 17),
(t!("settings_tab_dns_title").to_string(), 5),
(t!("settings_tab_geoip_title").to_string(), 1),
(t!("settings_tab_bindings_title").to_string(), 37),
(t!("settings_tab_theme_title").to_string(), 33),
(t!("settings_tab_columns_title").to_string(), 0),
(t!("settings_tab_tui_title"), 9),
(t!("settings_tab_trace_title"), 17),
(t!("settings_tab_dns_title"), 5),
(t!("settings_tab_geoip_title"), 1),
(t!("settings_tab_bindings_title"), 37),
(t!("settings_tab_theme_title"), 33),
(t!("settings_tab_columns_title"), 0),
]
}

/// The settings table header.
pub fn settings_table_header() -> [String; 2] {
[
t!("settings_table_header_setting").to_string(),
t!("settings_table_header_value").to_string(),
t!("settings_table_header_setting"),
t!("settings_table_header_value"),
]
}

Expand Down
2 changes: 1 addition & 1 deletion crates/trippy-tui/src/frontend/render/splash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn render(f: &mut Frame<'_>, app: &TuiApp, rect: Rect) {
r#" |_||_| |_| .__/ .__/\_, |"#.into(),
r#" |_| |_| |__/ "#.into(),
"".into(),
t!("awaiting_data"),
t!("awaiting_data").into(),
];
let line: Vec<_> = splash
.into_iter()
Expand Down
4 changes: 2 additions & 2 deletions crates/trippy-tui/src/frontend/render/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ fn render_hostname(
}
}
} else {
(format!("{}", t!("no_response")), 1)
(t!("no_response"), 1)
};
(Cell::from(hostname), count)
}
Expand Down Expand Up @@ -522,7 +522,7 @@ fn render_hostname_with_details(
format_details(hop, index, dns, geoip_lookup, config)
}
} else {
format!("{}", t!("no_response"))
t!("no_response")
};
(Cell::from(rendered), 7)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/trippy-tui/src/frontend/render/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ fn render_map_info_panel(f: &mut Frame<'_>, app: &TuiApp, rect: Rect, entries: &
format!("**{}**", t!("hidden"))
} else {
match locations.as_slice() {
_ if app.tui_config.geoip_mmdb_file.is_none() => t!("geoip_not_enabled").to_string(),
_ if app.tui_config.geoip_mmdb_file.is_none() => t!("geoip_not_enabled"),
[] if selected_hop.addr_count() > 0 => format!(
"{} {} ({})",
t!("geoip_no_data_for_hop"),
Expand Down
3 changes: 0 additions & 3 deletions crates/trippy-tui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ mod print;
mod report;
mod util;

// initialize the i18n system.
rust_i18n::i18n!("locales", fallback = "en");

/// Run the Trippy application.
pub fn trippy() -> anyhow::Result<()> {
let args = Args::parse();
Expand Down
Loading

0 comments on commit cec26eb

Please sign in to comment.