4 个版本 (重大变更)
0.9.0 | 2019 年 3 月 3 日 |
---|---|
0.8.0 | 2019 年 1 月 2 日 |
0.7.0 | 2018 年 2 月 7 日 |
0.6.0 | 2017 年 9 月 22 日 |
#389 在 国际化 (i18n)
每月 821 次下载
用于 25 个包 (4 个直接)
335KB
615 行
UNIC:Rust 的 Unicode 和国际化包
https://github.com/open-i18n/rust-unic
UNIC 是一个开发 Rust 编程语言组件的项目,以提供高质量的、易于使用的 Unicode 和国际化数据及算法的包。换句话说,它就像是 Rust 的 ICU,完全用 Rust 编写,大部分以 safe 模式编写,但在可能的情况下也利用了 unsafe 模式的性能优势。
请参阅 UNIC 更新日志 了解最新版本详情。
项目目标
UNIC 的目标是提供对 Unicode 和国际化功能的所有级别的访问,从 Unicode 字符属性开始,到处理文本的 Unicode 算法,再到基于 Unicode Common Locale Data Repository (CLDR) 的更高级(基于区域设置)的过程。
根据需要,还实现了其他标准和最佳实践,如 IETF RFC。
项目状态
目前 UNIC 正在快速发展:API 在 master
分支上频繁更新,并且每个 0.x
版本之间都会出现 API 破坏。请参阅 公开问题 了解更改计划。
我们预计将在 2018 年发布 1.0
版本,之后将保持 API 的稳定性,前几年可能每年更新一至两次 API。
设计目标
-
UNIC的主要目标是通过易于使用的API提供可靠的性能。因此,新添加的组件可能不会在性能上得到很好的优化,但将进行足够的测试以证明其符合标准,并提供示例以展示用户如何使用它们来解决常见需求。
-
UNIC组件的下一个主要目标是性能和低二进制和内存占用。特别是,优化ASCII和其他常见情况下的运行时将鼓励适应性,而无需担心减慢常规的开发过程。
-
组件将在尽可能的范围内提供一致的数据和算法。通过跨组件测试来捕捉实现之间的任何不一致,而不会减慢开发过程。
组件及其组织
UNIC 组件 采用层次结构组织,从unic
根目录开始,包含主要组件。每个主要组件反过来可能包含一些次要组件。
主要组件的API是为库的最终用户设计的,并期望有广泛的文档,并附带代码示例。
与主要组件相比,次要组件作为向高级别提供数据和算法的提供者,其API预计将更高效,并且可能提供多种访问数据的方式。
UNIC超级组件
unic
超级组件是所有UNIC(主要)组件的集合,提供了一种轻松访问所有功能的方法,当所有或许多组件都需要时,而不是逐个导入组件。这个组件确保所有导入的组件在算法和数据上都是兼容的。
主要代码示例和跨组件集成测试是在这个组件下实现的。
主要组件
-
unic-char
:Unicode字符工具。 -
unic-ucd
:Unicode字符数据库(《UAX#44》)。 -
unic-bidi
:Unicode双向算法(《UAX#9》)。 -
unic-normal
:Unicode规范化形式(《UAX#15》)。 -
unic-segment
:Unicode文本分割算法(《UAX#29》)。 -
unic-idna
:Unicode IDNA兼容处理(《UTS#46》)。 -
unic-emoji
:Unicode表情符号(《UTS#51》)。
应用
unic-cli
:UNIC 命令行工具
代码组织:合并仓库
合并仓库包含这些组件的一些原因:
-
更快的开发。实现新的 Unicode/i18n 组件通常需要依赖其他(低级)组件,而这些组件可能需要进行调整——暴露新的 API、修复错误等,这些都可以在更短的周期和更短的时间内进行开发、测试和审查。
-
实现完整性。对其他组件的多个依赖意味着这些组件需要在某种程度上相互一致。许多 Unicode 算法是由较小的算法组成,假设算法的所有部分都使用相同的 Unicode 数据版本。违反这个假设可能会导致不一致和难以捕获的错误。在合并仓库中,在开发期间以及跨组件(集成)测试期间,都有可能达到更好的完整性。
-
按需付费。小型组件(基本包),仅依赖它们需要的组件,允许用户只引入他们的项目中消费的组件。
-
共享启动。大量扩展 Unicode/i18n 功能需要将源 Unicode/地区数据转换为目标编程语言的格式化结构。在合并仓库中,更容易维护这些启动工具、扩展覆盖范围和使用更高效的数据结构。
文档
- Unicode 和 Rust
- UNIC 版本
- UNIC Unicode API
- UNIC API 指南
- UNIC API 参考(由 docs.rs 自动生成)
如何使用 UNIC
在 Cargo.toml
[dependencies]
unic = "0.9.0" # This has Unicode 10.0.0 data and algorithms
和在 main.rs
extern crate unic;
use unic::ucd::common::is_alphanumeric;
use unic::bidi::BidiInfo;
use unic::normal::StrNormalForm;
use unic::segment::{GraphemeIndices, Graphemes, WordBoundIndices, WordBounds, Words};
use unic::ucd::normal::compose;
use unic::ucd::{is_cased, Age, BidiClass, CharAge, CharBidiClass, StrBidiClass, UnicodeVersion};
fn main() {
// Age
assert_eq!(Age::of('A').unwrap().actual(), UnicodeVersion { major: 1, minor: 1, micro: 0 });
assert_eq!(Age::of('\u{A0000}'), None);
assert_eq!(
Age::of('\u{10FFFF}').unwrap().actual(),
UnicodeVersion { major: 2, minor: 0, micro: 0 }
);
if let Some(age) = '🦊'.age() {
assert_eq!(age.actual().major, 9);
assert_eq!(age.actual().minor, 0);
assert_eq!(age.actual().micro, 0);
}
// Bidi
let text = concat![
"א",
"ב",
"ג",
"a",
"b",
"c",
];
assert!(!text.has_bidi_explicit());
assert!(text.has_rtl());
assert!(text.has_ltr());
assert_eq!(text.chars().nth(0).unwrap().bidi_class(), BidiClass::RightToLeft);
assert!(!text.chars().nth(0).unwrap().is_ltr());
assert!(text.chars().nth(0).unwrap().is_rtl());
assert_eq!(text.chars().nth(3).unwrap().bidi_class(), BidiClass::LeftToRight);
assert!(text.chars().nth(3).unwrap().is_ltr());
assert!(!text.chars().nth(3).unwrap().is_rtl());
let bidi_info = BidiInfo::new(text, None);
assert_eq!(bidi_info.paragraphs.len(), 1);
let para = &bidi_info.paragraphs[0];
assert_eq!(para.level.number(), 1);
assert_eq!(para.level.is_rtl(), true);
let line = para.range.clone();
let display = bidi_info.reorder_line(para, line);
assert_eq!(
display,
concat![
"a",
"b",
"c",
"ג",
"ב",
"א",
]
);
// Case
assert_eq!(is_cased('A'), true);
assert_eq!(is_cased('א'), false);
// Normalization
assert_eq!(compose('A', '\u{030A}'), Some('Å'));
let s = "ÅΩ";
let c = s.nfc().collect::<String>();
assert_eq!(c, "ÅΩ");
// Segmentation
assert_eq!(
Graphemes::new("a\u{310}e\u{301}o\u{308}\u{332}").collect::<Vec<&str>>(),
&["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]
);
assert_eq!(
Graphemes::new("a\r\nb🇺🇳🇮🇨").collect::<Vec<&str>>(),
&["a", "\r\n", "b", "🇺🇳", "🇮🇨"]
);
assert_eq!(
GraphemeIndices::new("a̐éö̲\r\n").collect::<Vec<(usize, &str)>>(),
&[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]
);
assert_eq!(
Words::new(
"The quick (\"brown\") fox can't jump 32.3 feet, right?",
|s: &&str| s.chars().any(is_alphanumeric),
).collect::<Vec<&str>>(),
&["The", "quick", "brown", "fox", "can't", "jump", "32.3", "feet", "right"]
);
assert_eq!(
WordBounds::new("The quick (\"brown\") fox").collect::<Vec<&str>>(),
&["The", " ", "quick", " ", "(", "\"", "brown", "\"", ")", " ", " ", "fox"]
);
assert_eq!(
WordBoundIndices::new("Brr, it's 29.3°F!").collect::<Vec<(usize, &str)>>(),
&[
(0, "Brr"),
(3, ","),
(4, " "),
(5, "it's"),
(9, " "),
(10, "29.3"),
(14, "°"),
(16, "F"),
(17, "!")
]
);
}
您可以在 examples
和 tests
目录下找到更多示例。(随着 UNIC 的扩展,还将添加更多...)
许可
根据您的选择,许可如下:
- Apache License,版本 2.0(《LICENSE-APACHE》或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可(《LICENSE-MIT》或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您提交的任何有意包含在作品中的贡献,都应按上述方式双许可,不附加任何额外的条款或条件。
行为准则
UNIC 项目遵循 Rust 行为准则。您可以在 CODE_OF_CONDUCT.md 或在线 https://www.rust-lang.net.cn/conduct.html 中找到其副本。
lib.rs
:
UNIC — UCD — 名称
是 unic
:Rust 的 Unicode 和国际化包 的组件。
从 Unicode 字符数据库(UCD)访问字符名称属性