Localization support (#820)

find locale set with [sys-locale](https://crates.io/crates/sys-locale),
then format with locales.
This commit is contained in:
scarf
2023-03-13 11:44:54 +09:00
committed by GitHub
parent ea56a7c385
commit 7b9290c92c
12 changed files with 190 additions and 42 deletions

View File

@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `--system-protected` to include files with the Windows `system` flag set,
on other platform the same as `--all` [#752](https://github.com/Peltoche/lsd/issues/752)
- Add many icons from https://github.com/Peltoche/lsd/issues/764 [@TruncatedDinosour](https://ari-web.xyz/gh)
- Add support for localization from [scarf](https://github.com/scarf005)
### Fixed
- Do not quote filename when piping into another program from [TeamTamoad](https://github.com/TeamTamoad)

173
Cargo.lock generated
View File

@@ -82,6 +82,12 @@ dependencies = [
"regex-automata",
]
[[package]]
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -97,6 +103,7 @@ dependencies = [
"libc",
"num-integer",
"num-traits",
"pure-rust-locales",
"time",
"winapi",
]
@@ -367,6 +374,15 @@ dependencies = [
"either",
]
[[package]]
name = "js-sys"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -428,10 +444,12 @@ dependencies = [
"human-sort",
"libc",
"lscolors",
"once_cell",
"predicates 1.0.8",
"serde",
"serde_yaml",
"serial_test",
"sys-locale",
"tempfile",
"term_grid",
"terminal_size",
@@ -468,7 +486,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@@ -498,9 +516,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.10.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "os_str_bytes"
@@ -553,7 +571,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@@ -611,6 +629,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "pure-rust-locales"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45c49fc4f91f35bae654f85ebb3a44d60ac64f11b3166ffa609def390c732d8"
[[package]]
name = "quote"
version = "1.0.17"
@@ -800,6 +824,19 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "sys-locale"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee"
dependencies = [
"js-sys",
"libc",
"wasm-bindgen",
"web-sys",
"windows-sys 0.45.0",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@@ -997,6 +1034,70 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
[[package]]
name = "web-sys"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wild"
version = "2.0.4"
@@ -1044,12 +1145,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_aarch64_msvc 0.42.1",
"windows_i686_gnu 0.42.1",
"windows_i686_msvc 0.42.1",
"windows_x86_64_gnu 0.42.1",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.0",
"windows_x86_64_msvc 0.42.1",
]
[[package]]
@@ -1066,10 +1167,34 @@ dependencies = [
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.1",
"windows_i686_gnu 0.42.1",
"windows_i686_msvc 0.42.1",
"windows_x86_64_gnu 0.42.1",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.1",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
@@ -1079,9 +1204,9 @@ checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
@@ -1091,9 +1216,9 @@ checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
@@ -1103,9 +1228,9 @@ checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
@@ -1115,15 +1240,15 @@ checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
@@ -1133,9 +1258,9 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "xattr"

View File

@@ -28,7 +28,9 @@ human-sort = "0.2.2"
term_grid = "0.1.*"
terminal_size = "0.1.*"
thiserror = "1.0"
chrono = "0.4.*"
sys-locale = "0.2.4"
once_cell = "1.17.1"
chrono = { version = "0.4.*", features = ["unstable-locales"] }
chrono-humanize = "0.1.*"
unicode-width = "0.1.*"
lscolors = "0.9.0"

View File

@@ -1,3 +1,4 @@
use super::locale::current_locale;
use crate::color::{ColoredString, Colors, Elem};
use crate::flags::{DateFlag, Flags};
use chrono::{DateTime, Duration, Local};
@@ -42,9 +43,11 @@ impl Date {
}
fn date_string(&self, flags: &Flags) -> String {
let locale = current_locale();
if let Date::Date(val) = self {
match &flags.date {
DateFlag::Date => val.format("%c").to_string(),
DateFlag::Date => val.format_localized("%c", locale).to_string(),
DateFlag::Relative => HumanTime::from(*val - Local::now()).to_string(),
DateFlag::Iso => {
// 365.2425 * 24 * 60 * 60 = 31556952 seconds per year
@@ -55,7 +58,7 @@ impl Date {
val.format("%F").to_string()
}
}
DateFlag::Formatted(format) => val.format(format).to_string(),
DateFlag::Formatted(format) => val.format_localized(format, locale).to_string(),
}
} else {
String::from('-')
@@ -68,6 +71,7 @@ mod test {
use super::Date;
use crate::color::{Colors, ThemeOption};
use crate::flags::{DateFlag, Flags};
use crate::meta::locale::current_locale;
use chrono::{DateTime, Duration, Local};
use crossterm::style::{Color, Stylize};
use std::io;
@@ -80,7 +84,7 @@ mod test {
Command::new("touch")
.arg("-t")
.arg(date.format("%Y%m%d%H%M.%S").to_string())
.arg(&path)
.arg(path)
.status()
}
@@ -127,7 +131,7 @@ mod test {
assert_eq!(
creation_date
.format("%c")
.format_localized("%c", current_locale())
.to_string()
.with(Color::AnsiValue(40)),
date.render(&colors, &flags)
@@ -154,7 +158,7 @@ mod test {
assert_eq!(
creation_date
.format("%c")
.format_localized("%c", current_locale())
.to_string()
.with(Color::AnsiValue(42)),
date.render(&colors, &flags)
@@ -181,7 +185,7 @@ mod test {
assert_eq!(
creation_date
.format("%c")
.format_localized("%c", current_locale())
.to_string()
.with(Color::AnsiValue(36)),
date.render(&colors, &flags)

View File

@@ -41,7 +41,7 @@ mod tests {
use std::process::{Command, ExitStatus};
fn cross_platform_touch(path: &Path) -> io::Result<ExitStatus> {
Command::new("touch").arg(&path).status()
Command::new("touch").arg(path).status()
}
#[test]

View File

@@ -41,7 +41,7 @@ mod tests {
use std::process::{Command, ExitStatus};
fn cross_platform_touch(path: &Path) -> io::Result<ExitStatus> {
Command::new("touch").arg(&path).status()
Command::new("touch").arg(path).status()
}
#[test]

15
src/meta/locale.rs Normal file
View File

@@ -0,0 +1,15 @@
use chrono::Locale;
use once_cell::sync::OnceCell;
use sys_locale::get_locale;
fn locale_str() -> String {
get_locale().unwrap_or_default().replace('-', "_")
}
/// Finds current locale
pub fn current_locale() -> Locale {
const DEFAULT: Locale = Locale::en_US;
static CACHE: OnceCell<Locale> = OnceCell::new();
*CACHE.get_or_init(|| Locale::try_from(locale_str().as_str()).unwrap_or(DEFAULT))
}

View File

@@ -4,6 +4,7 @@ mod filetype;
mod indicator;
mod inode;
mod links;
mod locale;
pub mod name;
mod owner;
mod permissions;
@@ -329,7 +330,7 @@ mod tests {
let path_c = tmp_dir.path().join("ccc.cc");
#[cfg(unix)]
std::os::unix::fs::symlink(&path_c, &path_b).expect("failed to create broken symlink");
std::os::unix::fs::symlink(path_c, &path_b).expect("failed to create broken symlink");
// this needs to be tested on Windows
// likely to fail because of permission issue

View File

@@ -117,7 +117,7 @@ impl Name {
// HyperlinkOption::Auto gets converted to None or Always in core.rs based on tty_available
match std::fs::canonicalize(&self.path) {
Ok(rp) => {
if let Ok(url) = Url::from_file_path(&rp) {
if let Ok(url) = Url::from_file_path(rp) {
// Crossterm does not support hyperlinks as of now
// https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
format!("\x1B]8;;{}\x1B\x5C{}\x1B]8;;\x1B\x5C", url, name)
@@ -426,7 +426,7 @@ mod test {
let colors = Colors::new(color::ThemeOption::NoColor);
let real_path = std::fs::canonicalize(&file_path).expect("canonicalize");
let expected_url = Url::from_file_path(&real_path).expect("absolute path");
let expected_url = Url::from_file_path(real_path).expect("absolute path");
let expected_text = format!(
"\x1B]8;;{}\x1B\x5C{}\x1B]8;;\x1B\x5C",
expected_url, "file.txt"

View File

@@ -12,7 +12,7 @@ pub struct SymLink {
impl From<&Path> for SymLink {
fn from(path: &Path) -> Self {
if let Ok(target) = read_link(path) {
if target.is_absolute() || path.parent() == None {
if target.is_absolute() || path.parent().is_none() {
return Self {
valid: target.exists(),
target: Some(

View File

@@ -367,7 +367,7 @@ mod tests {
let path_d = tmp_dir.path().join("ddd.dd");
#[cfg(unix)]
std::os::unix::fs::symlink(&path_d, &path_c).expect("failed to create broken symlink");
std::os::unix::fs::symlink(path_d, &path_c).expect("failed to create broken symlink");
// this needs to be tested on Windows
// likely to fail because of permission issue

View File

@@ -297,7 +297,7 @@ fn test_dereference_link_broken_link_output() {
let target = dir.path().join("target");
#[cfg(unix)]
fs::symlink(&target, &link).unwrap();
fs::symlink(target, &link).unwrap();
// this needs to be tested on Windows
// likely to fail because of permission issue
@@ -369,7 +369,7 @@ fn test_show_folder_of_symlink_for_long_multi() {
let dir = tempdir();
dir.child("target").child("inside").touch().unwrap();
let link = dir.path().join("link");
fs::symlink("target", &link).unwrap();
fs::symlink("target", link).unwrap();
cmd()
.arg("-l")
@@ -552,7 +552,7 @@ fn test_tree_no_dereference() {
tmp.child("one.d").create_dir_all().unwrap();
tmp.child("one.d/samplefile").touch().unwrap();
let link = tmp.path().join("link");
fs::symlink("one.d", &link).unwrap();
fs::symlink("one.d", link).unwrap();
cmd()
.arg("--tree")
@@ -571,7 +571,7 @@ fn test_tree_dereference() {
tmp.child("one.d").create_dir_all().unwrap();
tmp.child("one.d/samplefile").touch().unwrap();
let link = tmp.path().join("link");
fs::symlink("one.d", &link).unwrap();
fs::symlink("one.d", link).unwrap();
cmd()
.arg("--ignore-config")