From 21770367e2ef1879c813387273265760f9d6e9f8 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Sun, 14 Aug 2022 21:07:04 +0800 Subject: [PATCH] make `date format` supports locale (#6306) * add --locale flag to make output support locale * implement again based on nu-utils get_system_locale_string * add comment --- Cargo.lock | 7 +++ crates/nu-command/Cargo.toml | 2 +- crates/nu-command/src/date/format.rs | 12 +++- .../nu-command/tests/commands/date/format.rs | 63 +++++++++++++++++++ crates/nu-utils/src/locale.rs | 4 +- 5 files changed, 82 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d18b8811..493bf884b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,6 +539,7 @@ dependencies = [ "js-sys", "num-integer", "num-traits", + "pure-rust-locales", "serde", "time 0.1.44", "wasm-bindgen", @@ -3676,6 +3677,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "pure-rust-locales" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45c49fc4f91f35bae654f85ebb3a44d60ac64f11b3166ffa609def390c732d8" + [[package]] name = "pwd" version = "1.4.0" diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index e26890bee..d941d5eec 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -33,7 +33,7 @@ base64 = "0.13.0" byteorder = "1.4.3" bytesize = "1.1.0" calamine = "0.18.0" -chrono = { version = "0.4.21", features = ["serde"] } +chrono = { version = "0.4.21", features = ["serde", "unstable-locales"] } chrono-humanize = "0.2.1" chrono-tz = "0.6.3" crossterm = "0.24.0" diff --git a/crates/nu-command/src/date/format.rs b/crates/nu-command/src/date/format.rs index 8a9e47c6a..66184586b 100644 --- a/crates/nu-command/src/date/format.rs +++ b/crates/nu-command/src/date/format.rs @@ -1,5 +1,4 @@ -use chrono::Local; -use chrono::{DateTime, TimeZone}; +use chrono::{DateTime, Local, Locale, TimeZone}; use nu_engine::CallExt; use nu_protocol::{ @@ -7,6 +6,7 @@ use nu_protocol::{ engine::{Command, EngineState, Stack}, Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value, }; +use nu_utils::locale::get_system_locale_string; use std::fmt::{Display, Write}; use super::utils::parse_date_from_string; @@ -98,7 +98,13 @@ where Tz::Offset: Display, { let mut formatter_buf = String::new(); - let format = date_time.format(formatter); + let locale: Locale = get_system_locale_string() + .map(|l| l.replace('-', "_")) // `chrono::Locale` needs something like `xx_xx`, rather than `xx-xx` + .unwrap_or_else(|| String::from("en_US")) + .as_str() + .try_into() + .unwrap_or(Locale::en_US); + let format = date_time.format_localized(formatter, locale); match formatter_buf.write_fmt(format_args!("{}", format)) { Ok(_) => Value::String { diff --git a/crates/nu-command/tests/commands/date/format.rs b/crates/nu-command/tests/commands/date/format.rs index be3f25424..4f0f874ee 100644 --- a/crates/nu-command/tests/commands/date/format.rs +++ b/crates/nu-command/tests/commands/date/format.rs @@ -12,3 +12,66 @@ fn formatter_not_valid() { assert!(actual.err.contains("invalid format")); } + +#[test] +fn locale_format_respect_different_locale() { + let actual = nu!( + locale: "en_US", + pipeline( + r#" + "2021-10-22 20:00:12 +01:00" | date format "%c" + "# + ) + ); + assert!(actual.out.contains("Fri 22 Oct 2021 08:00:12 PM +01:00")); + + let actual = nu!( + locale: "en_GB", + pipeline( + r#" + "2021-10-22 20:00:12 +01:00" | date format "%c" + "# + ) + ); + assert!(actual.out.contains("Fri 22 Oct 2021 20:00:12 +01:00")); + + let actual = nu!( + locale: "de_DE", + pipeline( + r#" + "2021-10-22 20:00:12 +01:00" | date format "%c" + "# + ) + ); + assert!(actual.out.contains("Fr 22 Okt 2021 20:00:12 +01:00")); + + let actual = nu!( + locale: "zh_CN", + pipeline( + r#" + "2021-10-22 20:00:12 +01:00" | date format "%c" + "# + ) + ); + assert!(actual.out.contains("2021年10月22日 星期五 20时00分12秒")); + + let actual = nu!( + locale: "ja_JP", + pipeline( + r#" + "2021-10-22 20:00:12 +01:00" | date format "%c" + "# + ) + ); + assert!(actual.out.contains("2021年10月22日 20時00分12秒")); + + let actual = nu!( + locale: "fr_FR", + pipeline( + r#" + "2021-10-22 20:00:12 +01:00" | date format "%c" + "# + ) + ); + assert!(actual.out.contains("ven. 22 oct. 2021 20:00:12 +01:00")); +} diff --git a/crates/nu-utils/src/locale.rs b/crates/nu-utils/src/locale.rs index bcdfe20fb..47241618e 100644 --- a/crates/nu-utils/src/locale.rs +++ b/crates/nu-utils/src/locale.rs @@ -27,13 +27,13 @@ pub fn get_system_locale() -> Locale { } #[cfg(debug_assertions)] -fn get_system_locale_string() -> Option { +pub fn get_system_locale_string() -> Option { std::env::var(LOCALE_OVERRIDE_ENV_VAR) .ok() .or_else(sys_locale::get_locale) } #[cfg(not(debug_assertions))] -fn get_system_locale_string() -> Option { +pub fn get_system_locale_string() -> Option { sys_locale::get_locale() }