From 965cbfbb7ee049ce6b0cce6c011f5eff666580e4 Mon Sep 17 00:00:00 2001 From: jslyrd Date: Tue, 16 Jul 2024 22:32:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8B=B1=E6=96=87=E5=B8=AE?= =?UTF-8?q?=E5=8A=A9=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/Cargo.toml | 1 + common/src/cli.rs | 406 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 319 insertions(+), 88 deletions(-) diff --git a/common/Cargo.toml b/common/Cargo.toml index 80fa20b..fae5719 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -16,6 +16,7 @@ serde_yaml = "0.9.32" getopts = "0.2.21" gethostname = "0.4.3" uuid = { version = "1.8.0", features = ["v4"] } +sys-locale = "0.3.1" [features] default = [] diff --git a/common/src/cli.rs b/common/src/cli.rs index f5c5c8b..af86454 100644 --- a/common/src/cli.rs +++ b/common/src/cli.rs @@ -5,10 +5,12 @@ use crate::{config, generated_serial_number}; use anyhow::anyhow; use console::style; use getopts::Options; +use std::collections::HashMap; use std::io; use std::net::Ipv4Addr; use std::path::PathBuf; use std::str::FromStr; +use sys_locale::get_locale; use vnt::channel::punch::PunchModel; use vnt::channel::UseChannelType; use vnt::cipher::CipherModel; @@ -43,48 +45,145 @@ pub fn parse_args_config() -> anyhow::Result, bool)> let args: Vec = std::env::args().collect(); let program = args[0].clone(); let mut opts = Options::new(); - opts.optopt("k", "", "组网标识", ""); - opts.optopt("n", "", "设备名称", ""); - opts.optopt("d", "", "设备标识", ""); - opts.optflag("c", "", "关闭交互式命令"); - opts.optopt("s", "", "注册和中继服务器地址", ""); - opts.optmulti("e", "", "stun服务器", ""); - opts.optflag("a", "", "使用tap模式"); - opts.optopt("", "nic", "虚拟网卡名称,windows下使用tap则必填", ""); - opts.optmulti("i", "", "配置点对网(IP代理)入站时使用", ""); - opts.optmulti("o", "", "配置点对网出站时使用", ""); - opts.optopt("w", "", "客户端加密", ""); - opts.optflag("W", "", "服务端加密"); - opts.optopt("u", "", "自定义mtu(默认为1430)", ""); - opts.optopt("", "ip", "指定虚拟ip", ""); - opts.optflag("", "relay", "仅使用服务器转发"); - opts.optopt("", "par", "任务并行度(必须为正整数)", ""); - opts.optopt("", "model", "加密模式", ""); - opts.optflag("", "finger", "指纹校验"); - opts.optopt("", "punch", "取值ipv4/ipv6", ""); - opts.optopt("", "ports", "监听的端口", ""); - opts.optflag("", "cmd", "开启窗口输入"); - opts.optflag("", "no-proxy", "关闭内置代理"); - opts.optflag("", "first-latency", "优先延迟"); - opts.optopt("", "use-channel", "使用通道 relay/p2p", ""); - opts.optopt("", "packet-loss", "丢包率", ""); - opts.optopt("", "packet-delay", "延迟", ""); - opts.optmulti("", "dns", "dns", ""); - opts.optmulti("", "mapping", "mapping", ""); - opts.optmulti("", "vnt-mapping", "vnt-mapping", ""); - opts.optopt("f", "", "配置文件", ""); - opts.optopt("", "compressor", "压缩算法", ""); - opts.optflag("", "disable-stats", "关闭流量统计"); - //"后台运行时,查看其他设备列表" - opts.optflag("", "add", "后台运行时,添加地址"); - opts.optflag("", "list", "后台运行时,查看其他设备列表"); - opts.optflag("", "all", "后台运行时,查看其他设备完整信息"); - opts.optflag("", "info", "后台运行时,查看当前设备信息"); - opts.optflag("", "route", "后台运行时,查看数据转发路径"); - opts.optflag("", "chart_a", "后台运行时,查看流量统计"); - opts.optopt("", "chart_b", "后台运行时,查看流量统计", ""); - opts.optflag("", "stop", "停止后台运行"); - opts.optflag("h", "help", "帮助"); + // 获取系统语言 + let language = get_locale().unwrap_or_else(|| String::from("en-US")); + if language.starts_with("zh") { + opts.optopt("k", "", "组网标识", ""); + opts.optopt("n", "", "设备名称", ""); + opts.optopt("d", "", "设备标识", ""); + opts.optflag("c", "", "关闭交互式命令"); + opts.optopt("s", "", "注册和中继服务器地址", ""); + opts.optmulti("e", "", "stun服务器", ""); + opts.optflag("a", "", "使用tap模式"); + opts.optopt("", "nic", "虚拟网卡名称,windows下使用tap则必填", ""); + opts.optmulti("i", "", "配置点对网(IP代理)入站时使用", ""); + opts.optmulti("o", "", "配置点对网出站时使用", ""); + opts.optopt("w", "", "客户端加密", ""); + opts.optflag("W", "", "服务端加密"); + opts.optopt("u", "", "自定义mtu(默认为1430)", ""); + opts.optopt("", "ip", "指定虚拟ip", ""); + opts.optflag("", "relay", "仅使用服务器转发"); + opts.optopt("", "par", "任务并行度(必须为正整数)", ""); + opts.optopt("", "model", "加密模式", ""); + opts.optflag("", "finger", "指纹校验"); + opts.optopt("", "punch", "取值ipv4/ipv6", ""); + opts.optopt("", "ports", "监听的端口", ""); + opts.optflag("", "cmd", "开启窗口输入"); + opts.optflag("", "no-proxy", "关闭内置代理"); + opts.optflag("", "first-latency", "优先延迟"); + opts.optopt("", "use-channel", "使用通道 relay/p2p", ""); + opts.optopt("", "packet-loss", "丢包率", ""); + opts.optopt("", "packet-delay", "延迟", ""); + opts.optmulti("", "dns", "dns", ""); + opts.optmulti("", "mapping", "mapping", ""); + opts.optmulti("", "vnt-mapping", "vnt-mapping", ""); + opts.optopt("f", "", "配置文件", ""); + opts.optopt("", "compressor", "压缩算法", ""); + opts.optflag("", "disable-stats", "关闭流量统计"); + //"后台运行时,查看其他设备列表" + opts.optflag("", "add", "后台运行时,添加地址"); + opts.optflag("", "list", "后台运行时,查看其他设备列表"); + opts.optflag("", "all", "后台运行时,查看其他设备完整信息"); + opts.optflag("", "info", "后台运行时,查看当前设备信息"); + opts.optflag("", "route", "后台运行时,查看数据转发路径"); + opts.optflag("", "chart_a", "后台运行时,查看流量统计"); + opts.optopt("", "chart_b", "后台运行时,查看流量统计", ""); + opts.optflag("", "stop", "停止后台运行"); + opts.optflag("h", "help", "帮助"); + } else { + opts.optopt("k", "", "Network token", ""); + opts.optopt("n", "", "Network name", ""); + opts.optopt("d", "", "Device id", ""); + opts.optflag("c", "", "Close interactive command"); + opts.optopt( + "s", + "", + "registration and relay server addresses", + "", + ); + opts.optmulti("e", "", "STUN servers", ""); + opts.optflag("a", "", "Tap mode"); + opts.optopt( + "", + "nic", + "Virtual network adapter name, required when using Tap mode on Windows", + "", + ); + opts.optmulti( + "i", + "", + "Configuring inbound point-to-site (IP proxy) usage", + "", + ); + opts.optmulti( + "o", + "", + "Configuring outbound point-to-site usage", + "", + ); + opts.optopt("w", "", "Client encryption", ""); + opts.optflag("W", "", "Server-side encryption"); + opts.optopt("u", "", "Customize MTU (default is 1430)", ""); + opts.optopt("", "ip", "Specify virtual IP", ""); + opts.optflag("", "relay", "Use server-side forwarding only"); + opts.optopt( + "", + "par", + "Concurrency level (must be a positive integer)", + "", + ); + opts.optopt("", "model", "Encryption mode", ""); + opts.optflag("", "finger", "Fingerprint verification"); + opts.optopt("", "punch", "Value can be either IPv4 or IPv6", ""); + opts.optopt("", "ports", "Listening port", ""); + opts.optflag("", "cmd", "Enable window input"); + opts.optflag("", "no-proxy", "Disable built-in proxy"); + opts.optflag("", "first-latency", "Priority delay"); + opts.optopt("", "use-channel", "Use channel relay/p2p", ""); + opts.optopt("", "packet-loss", "Packet loss rate", ""); + opts.optopt("", "packet-delay", "Latency", ""); + opts.optmulti("", "dns", "dns", ""); + opts.optmulti("", "mapping", "mapping", ""); + opts.optmulti("", "vnt-mapping", "vnt-mapping", ""); + opts.optopt("f", "", "Configuration file", ""); + opts.optopt("", "compressor", "Compression algorithm", ""); + opts.optflag("", "disable-stats", "Disable traffic statistics"); + //"后台运行时,查看其他设备列表" + opts.optflag("", "add", "When running in the background, add an address"); + opts.optflag( + "", + "list", + "When running in the background, view the list of other devices", + ); + opts.optflag( + "", + "all", + "When running in the background, view comprehensive information about other devices", + ); + opts.optflag( + "", + "info", + "When running in the background, view information about the current device", + ); + opts.optflag( + "", + "route", + "When running in the background, view the data forwarding path", + ); + opts.optflag( + "", + "chart_a", + "When running in the background, view traffic statistics", + ); + opts.optopt( + "", + "chart_b", + "When running in the background, view traffic statistics", + "", + ); + opts.optflag("", "stop", "Stop running in the background"); + opts.optflag("h", "help", "help"); + } let matches = match opts.parse(&args[1..]) { Ok(m) => m, Err(f) => { @@ -113,10 +212,13 @@ pub fn parse_args_config() -> anyhow::Result, bool)> } else if matches.opt_present("all") { command::command(command::CommandEnum::All); return Ok(None); - } else if matches.opt_present("chart_a") { + } + #[cfg(feature = "command")] + if matches.opt_present("chart_a") { command::command(command::CommandEnum::ChartA); return Ok(None); } + #[cfg(feature = "command")] if let Some(v) = matches.opt_str("chart_b") { command::command(command::CommandEnum::ChartB(v)); return Ok(None); @@ -337,38 +439,122 @@ pub fn parse_args_config() -> anyhow::Result, bool)> Ok(Some((config, vnt_link_config, cmd))) } +fn get_description(key: &str, language: &str) -> String { + // 设置一个全局的映射来存储中英文对照 + let descriptions: HashMap<&str, (&str, &str)> = [ + ("-k ", ("使用相同的token,就能组建一个局域网络", "Use the same token to form a local network")), + ("-n ", ("给设备一个名字,便于区分不同设备,默认使用系统版本", "Give the device a name to distinguish it, defaults to system version")), + ("-d ", ("设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip,注意不能重复", "Device unique identifier, used by the server to allocate virtual IP when --ip parameter is not used, must be unique")), + ("-s ", ("注册和中继服务器地址,协议支持使用tcp://和ws://和wss://,默认为udp://", "Registration and relay server address, protocols support using tcp://, ws://, and wss://, default is udp://")), + ("-e ", ("stun服务器,用于探测NAT类型,可使用多个地址,如-e stun.miwifi.com -e turn.cloudflare.com", "STUN server for detecting NAT type, can specify multiple addresses, e.g., -e stun.miwifi.com -e turn.cloudflare.com")), + ("-a", ("使用tap模式,默认使用tun模式,使用tap时需要配合'--nic'参数指定tap网卡", "Use tap mode, default is tun mode, specify '--nic' parameter with tap network card")), + ("-i ", ("配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3,可指定多个网段", "Used when configuring point-to-point network (IP proxy), -i 192.168.0.0/24,10.26.0.3 allows receiving data from subnet 192.168.0.0/24 and forwarding to 10.26.0.3, specify multiple subnets")), + ("-o ", ("配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段", "Used when configuring point-to-point network, -o 192.168.0.0/24 allows forwarding data to 192.168.0.0/24, specify multiple subnets")), + ("-w ", ("使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "Encrypt client data with keys generated by this password, server cannot decrypt, clients must use the same password to communicate")), + ("-W", ("加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确", "Encrypt the data currently being communicated between the client and server, please pay attention to whether the server fingerprint is correct")), + ("-u ", ("自定义mtu(不加密默认为1450,加密默认为1410", "Customize MTU (1450 by default without encryption, 1410 with encryption)")), + ("-f ", ("读取配置文件中的配置", "Read configuration from file")), + ("--ip ", ("指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", "Specify virtual IP, must be unique and valid within server subnet, by default allocated by server")), + ("--model ", ("加密模式(默认aes_gcm),可选值{}", "Encryption mode (default aes_gcm), options {}")), + ("--finger", ("增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启", "Add data fingerprint verification for increased security, client must enable if server does")), + ("--punch ", ("取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞", "Values ipv4/ipv6/all, ipv4 for IPv4 hole punching only")), + ("--ports ", ("取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担", "Values 0~65535, specify a group of local listening ports, defaults to two random ports, using many ports increases network load")), + ("--cmd", ("开启交互式命令,使用此参数开启控制台输入", "Enable interactive command mode, use this parameter to enable console input")), + ("--no-proxy", ("关闭内置代理,如需点对网则需要配置网卡NAT转发", "Disable built-in proxy, configure network card NAT forwarding for point-to-point networking")), + ("--first-latency", ("优先低延迟的通道,默认情况优先使用p2p通道", "Prioritize low-latency channels, defaults to prioritizing p2p channel")), + ("--use-channel ", ("使用通道 relay/p2p/all,默认两者都使用", "Use channel relay/p2p/all, defaults to using both")), + ("--nic ", ("指定虚拟网卡名称", "Specify virtual network card name")), + ("--packet-loss <0>", ("模拟丢包,取值0~1之间的小数,程序会按设定的概率主动丢包,可用于模拟弱网", "Simulate packet loss, value between 0 and 1, program actively drops packets based on set probability, useful for simulating weak networks")), + ("--packet-delay <0>", ("模拟丢包,取值0~1之间的小数,程序会按设定的概率主动丢包,可用于模拟弱网", "Simulate latency, integer, in milliseconds (ms). The program will delay sending packets according to the set value and can be used to simulate weak networks")), + ("--dns ", ("DNS服务器地址,可使用多个dns,不指定时使用系统解析", "DNS server address, can specify multiple DNS servers, defaults to system resolution if not specified")), + ("--mapping ", ("端口映射,例如 --mapping udp:0.0.0.0:80-domain:80 映射目标是本地路由能访问的设备", "Port mapping, e.g., --mapping udp:0.0.0.0:80-domain:80 maps to a device accessible by local routing")), + ("--compressor-all ", ("启用压缩,可选值lz4/zstd<,level>,level为压缩级别,例如 --compressor lz4 或--compressor zstd,10", "Enable compression, options lz4/zstd<,level>, level is compression level, e.g., --compressor lz4 or --compressor zstd,10")), + ("--compressor-lz4 ", ("启用压缩,可选值lz4,例如 --compressor lz4", "Enable compression, option lz4, e.g., --compressor lz4")), + ("--compressor-zstd ", ("启用压缩,可选值zstd<,level>,level为压缩级别,例如 --compressor zstd,10", "Enable compression, options zstd<,level>, level is compression level, e.g., --compressor zstd,10")), + ("--vnt-mapping ", ("vnt地址映射,例如 --vnt-mapping tcp:80-10.26.0.10:80 映射目标是vnt网络或其子网中的设备", "VNT address mapping, e.g., --vnt-mapping tcp:80-10.26.0.10:80 maps to a device in VNT network or its subnet")), + ("--disable-stats", ("关闭流量统计", "Disable traffic statistics")), + ("--list", ("后台运行时,查看其他设备列表", "View list of other devices when running in background")), + ("--all", ("后台运行时,查看其他设备完整信息", "View complete information of other devices when running in background")), + ("--info", ("后台运行时,查看当前设备信息", "View information of current device when running in background")), + ("--route", ("后台运行时,查看数据转发路径", "View data forwarding path when running in background")), + ("--chart_a", ("后台运行时,查看所有IP的流量统计", "View traffic statistics of all IPs when running in background")), + ("--chart_b ", ("后台运行时,查看单个IP的历史流量", "View historical traffic of a single IP when running in background")), + ("--stop", ("停止后台运行", "Stop running in background")) + // ... 其他选项 + ] + .iter() + .cloned() + .collect(); + + if let Some(&(zh, en)) = descriptions.get(key) { + if language.starts_with("zh") { + return zh.to_string(); // 返回 String 类型 + } + // 默认返回英文 + return en.to_string(); // 返回 String 类型 + } + // 如果没有找到对应的键,则返回空字符串 + String::new() +} + fn print_usage(program: &str, _opts: Options) { + // 获取系统语言 Locale::user_default().unwrap_or_else(|_| Locale::default()); + let language = get_locale().unwrap_or_else(|| String::from("en-US")); println!("Usage: {} [options]", program); println!("version:{}", vnt::VNT_VERSION); println!("Serial:{}", generated_serial_number::SERIAL_NUMBER); println!("Options:"); println!( " -k {}", - green("使用相同的token,就能组建一个局域网络".to_string()) + green(get_description("-k ", &language).to_string()) ); - println!(" -n 给设备一个名字,便于区分不同设备,默认使用系统版本"); - println!(" -d 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip,注意不能重复"); println!( - " -s 注册和中继服务器地址,协议支持使用tcp://和ws://和wss://,默认为udp://" + " -n {}", + get_description("-n ", &language) + ); + println!( + " -d {}", + get_description("-d ", &language) + ); + println!( + " -s {}", + get_description("-s ", &language) + ); + println!( + " -e {}", + get_description("-e ", &language) ); - println!(" -e stun服务器,用于探测NAT类型,可使用多个地址,如-e stun.miwifi.com -e turn.cloudflare.com"); #[cfg(target_os = "windows")] #[cfg(feature = "integrated_tun")] + println!(" -a {}", get_description("-a", &language)); println!( - " -a 使用tap模式,默认使用tun模式,使用tap时需要配合'--nic'参数指定tap网卡" + " -i {}", + get_description("-i ", &language) + ); + println!( + " -o {}", + get_description("-o ", &language) + ); + println!( + " -w {}", + get_description("-w ", &language) ); - println!(" -i 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据"); - println!(" 并转发到10.26.0.3,可指定多个网段"); - println!(" -o 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段"); - - println!(" -w 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信"); #[cfg(feature = "server_encrypt")] - println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确"); - println!(" -u 自定义mtu(不加密默认为1450,加密默认为1410)"); + println!(" -W {}", get_description("-W", &language)); + println!( + " -u {}", + get_description("-u ", &language) + ); #[cfg(feature = "file_config")] - println!(" -f 读取配置文件中的配置"); + println!( + " -f {}", + get_description("-f ", &language) + ); - println!(" --ip 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配"); + println!( + " --ip {}", + get_description("--ip ", &language) + ); let mut enums = String::new(); #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] enums.push_str("/aes_gcm"); @@ -382,7 +568,8 @@ fn print_usage(program: &str, _opts: Options) { enums.push_str("/sm4_cbc"); enums.push_str("/xor"); println!( - " --model 加密模式(默认aes_gcm),可选值{}", + " --model {}{}", + get_description("--model ", &language), &enums[1..] ); #[cfg(any( @@ -393,45 +580,88 @@ fn print_usage(program: &str, _opts: Options) { feature = "aes_ecb", feature = "sm4_cbc" ))] - println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启"); - println!(" --punch 取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞"); - println!(" --ports 取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担"); + println!( + " --finger {}", + get_description("--finger", &language) + ); + println!( + " --punch {}", + get_description("--punch ", &language) + ); + println!( + " --ports {}", + get_description("--ports ", &language) + ); #[cfg(feature = "command")] - println!(" --cmd 开启交互式命令,使用此参数开启控制台输入"); + println!( + " --cmd {}", + get_description("--cmd", &language) + ); #[cfg(feature = "ip_proxy")] #[cfg(feature = "integrated_tun")] - println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发"); - println!(" --first-latency 优先低延迟的通道,默认情况优先使用p2p通道"); - println!(" --use-channel 使用通道 relay/p2p/all,默认两者都使用"); - #[cfg(not(feature = "vn-link-model"))] - println!(" --nic 指定虚拟网卡名称"); - println!(" --packet-loss <0> 模拟丢包,取值0~1之间的小数,程序会按设定的概率主动丢包,可用于模拟弱网"); println!( - " --packet-delay <0> 模拟延迟,整数,单位毫秒(ms),程序会按设定的值延迟发包,可用于模拟弱网" + " --no-proxy {}", + get_description("--no-proxy", &language) + ); + println!( + " --first-latency {}", + get_description("--first-latency", &language) + ); + println!( + " --use-channel {}", + get_description("--use-channel ", &language) + ); + #[cfg(not(feature = "vn-link-model"))] + println!( + " --nic {}", + get_description("--nic ", &language) + ); + println!( + " --packet-loss <0> {}", + get_description("--packet-loss <0>", &language) + ); + println!( + " --packet-delay <0> {}", + get_description("--packet-delay <0>", &language) + ); + println!( + " --dns {}", + get_description("--dns ", &language) ); - println!(" --dns DNS服务器地址,可使用多个dns,不指定时使用系统解析"); #[cfg(feature = "port_mapping")] - println!(" --mapping 端口映射,例如 --mapping udp:0.0.0.0:80-domain:80 映射目标是本地路由能访问的设备"); + println!( + " --mapping {}", + get_description("--mapping ", &language) + ); #[cfg(all(feature = "lz4", feature = "zstd"))] - println!(" --compressor 启用压缩,可选值lz4/zstd<,level>,level为压缩级别,例如 --compressor lz4 或--compressor zstd,10"); + println!( + " --compressor {}", + get_description("--compressor-all ", &language) + ); #[cfg(feature = "lz4")] #[cfg(not(feature = "zstd"))] - println!(" --compressor 启用压缩,可选值lz4,例如 --compressor lz4"); + println!( + " --compressor {}", + get_description("--compressor-lz4 ", &language) + ); #[cfg(feature = "zstd")] #[cfg(not(feature = "lz4"))] - println!(" --compressor 启用压缩,可选值zstd<,level>,level为压缩级别,例如 --compressor zstd,10"); + println!( + " --compressor {}", + get_description("--compressor-zstd ", &language) + ); #[cfg(not(feature = "integrated_tun"))] println!( " --vnt-mapping {}", - green( - "vnt地址映射,例如 --vnt-mapping tcp:80-10.26.0.10:80 映射目标是vnt网络或其子网中的设备" - .to_string() - ) + green(get_description("--vnt-mapping ", &language).to_string()) + ); + println!( + " --disable-stats {}", + get_description("--disable-stats", &language) ); - println!(" --disable-stats 关闭流量统计"); println!(); #[cfg(feature = "command")] { @@ -442,34 +672,34 @@ fn print_usage(program: &str, _opts: Options) { // ); println!( " --list {}", - yellow("后台运行时,查看其他设备列表".to_string()) + yellow(get_description("--list", &language).to_string()) ); println!( " --all {}", - yellow("后台运行时,查看其他设备完整信息".to_string()) + yellow(get_description("--all", &language).to_string()) ); println!( " --info {}", - yellow("后台运行时,查看当前设备信息".to_string()) + yellow(get_description("--info", &language).to_string()) ); println!( " --route {}", - yellow("后台运行时,查看数据转发路径".to_string()) + yellow(get_description("--route", &language).to_string()) ); println!( " --chart_a {}", - yellow("后台运行时,查看所有IP的流量统计".to_string()) + yellow(get_description("--chart_a", &language).to_string()) ); println!( " --chart_b {}", - yellow("后台运行时,查看单个IP的历史流量".to_string()) + yellow(get_description("--chart_b ", &language).to_string()) ); println!( " --stop {}", - yellow("停止后台运行".to_string()) + yellow(get_description("--stop", &language).to_string()) ); } - println!(" -h, --help 帮助"); + println!(" -h, --help display help information(显示帮助信息)"); } fn green(str: String) -> impl std::fmt::Display {