Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
varphone committed Jan 28, 2024
1 parent ee998bd commit f8d816a
Showing 1 changed file with 73 additions and 58 deletions.
131 changes: 73 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

> 🎯 Let's make I18n things to easy!
Rust I18n is a crate for loading localized text from a set of (YAML, JSON or TOML) mapping files. The mappings are converted into data readable by Rust programs at compile time, and then localized text can be loaded by simply calling the provided `t!` or `tr` macro.
Rust I18n is a crate for loading localized text from a set of (YAML, JSON or TOML) mapping files. The mappings are converted into data readable by Rust programs at compile time, and then localized text can be loaded by simply calling the provided [`t!`] macro.

Unlike other I18n libraries, Rust I18n's goal is to provide a simple and easy-to-use API.

Expand All @@ -13,10 +13,14 @@ The API of this crate is inspired by [ruby-i18n](https://github.com/ruby-i18n/i1
## Features

- Codegen on compile time for includes translations into binary.
- Global `t!` or `tr!` macro for loading localized text in everywhere.
- Global [`t!`] macro for loading localized text in everywhere.
- Use YAML (default), JSON or TOML format for mapping localized text, and support mutiple files merging.
- `cargo i18n` Command line tool for checking and extract untranslated texts into YAML files.
- Support all localized texts in one file, or split into difference files by locale.
- Supports specifying a chain of fallback locales for missing translations.
- Supports automatic lookup of language territory for fallback locale. For instance, if `zh-CN` is not available, it will fallback to `zh`. (Since v2.4.0)
- Support short hashed keys for optimize memory usage and lookup speed. (Since v3.1.0)
- Support format variables in [`t!`], and support format variables with [`std::fmt`](https://doc.rust-lang.org/std/fmt/) syntax. (Since v3.1.0)

## Usage

Expand All @@ -30,7 +34,7 @@ rust-i18n = "3"
Load macro and init translations in `lib.rs` or `main.rs`:

```rust,compile_fail,no_run
// Load I18n macro, for allow you use `t!` or `tr!` macro in anywhere.
// Load I18n macro, for allow you use `t!` macro in anywhere.
#[macro_use]
extern crate rust_i18n;
Expand All @@ -39,33 +43,46 @@ i18n!("locales");
// Or just use `i18n!`, default locales path is: "locales" in current crate.
//
// i18n!();
i18n!();
// Config fallback missing translations to "en" locale.
// Use `fallback` option to set fallback locale.
//
// i18n!("locales", fallback = "en");
i18n!("locales", fallback = "en");
// Or more than one fallback with priority.
//
// i18n!("locales", fallback = ["en", "es]);
i18n!("locales", fallback = ["en", "es"]);
// Use a short hashed key as an identifier for long string literals
// to optimize memory usage and lookup speed.
// The key generation algorithm is `${Prefix}${Base62(SipHash13("msg"))}`.
i18n!("locales", minify_key = true);
//
// Alternatively, you can customize the key length, prefix,
// and threshold for the short hashed key.
i18n!("locales",
minify_key = true,
minify_key_len = 12,
minify_key_prefix = "T.",
minify_key_thresh = 64
);
// Now, if the message length exceeds 64, the `t!` macro will automatically generate
// a 12-byte short hashed key with a "T." prefix for it, if not, it will use the original.
```

Or you can import by use directly:

```rust,no_run
// You must import in each files when you wants use `t!` or `tr!` macro.
use rust_i18n::{t, tr};
// You must import in each files when you wants use `t!` macro.
use rust_i18n::t;
rust_i18n::i18n!("locales");
fn main() {
// Find the translation for the string literal `Hello` using the manually provided key `hello`.
println!("{}", t!("hello"));
// Or, find the translation for the string literal `Hello` using the auto-generated key.
println!("{}", tr!("Hello"));
// Use `available_locales!` method to get all available locales.
println!("{:?}", rust_i18n::available_locales!());
}
Expand Down Expand Up @@ -97,8 +114,8 @@ _version: 1
hello: "Hello world"
messages.hello: "Hello, %{name}"

# Key auto-generated by tr!
tr_4Cct6Q289b12SkvF47dXIx: "Hello, %{name}"
# Generate short hashed keys using `minify_key=true, minify_key_thresh=10`
4Cct6Q289b12SkvF47dXIx: "Hello, %{name}"
```
Or use JSON or TOML format, just rename the file to `en.json` or `en.toml`, and the content is like this:
Expand All @@ -109,16 +126,16 @@ Or use JSON or TOML format, just rename the file to `en.json` or `en.toml`, and
"hello": "Hello world",
"messages.hello": "Hello, %{name}",
// Key auto-generated by tr!
"tr_4Cct6Q289b12SkvF47dXIx": "Hello, %{name}"
// Generate short hashed keys using `minify_key=true, minify_key_thresh=10`
"4Cct6Q289b12SkvF47dXIx": "Hello, %{name}"
}
```

```toml
hello = "Hello world"

# Key auto-generated by tr!
tr_4Cct6Q289b12SkvF47dXIx = "Hello, %{name}"
# Generate short hashed keys using `minify_key=true, minify_key_thresh=10`
4Cct6Q289b12SkvF47dXIx = "Hello, %{name}"

[messages]
hello = "Hello, %{name}"
Expand Down Expand Up @@ -158,8 +175,8 @@ messages.hello:
en: Hello, %{name}
zh-CN: 你好,%{name}

# Key auto-generated by tr!
tr_4Cct6Q289b12SkvF47dXIx:
# Generate short hashed keys using `minify_key=true, minify_key_thresh=10`
4Cct6Q289b12SkvF47dXIx:
en: Hello, %{name}
zh-CN: 你好,%{name}
```
Expand All @@ -170,20 +187,20 @@ This is useful when you use [GitHub Copilot](https://github.com/features/copilot
### Get Localized Strings in Rust
Import the `t!` or `tr` macro from this crate into your current scope:
Import the [`t!`] macro from this crate into your current scope:

```rust,no_run
use rust_i18n::{t, tr};
use rust_i18n::t;
```

Then, simply use it wherever a localized string is needed:

```rust,no_run
# use rust_i18n::CowStr;
# fn _rust_i18n_translate(locale: &str, key: &str) -> String { todo!() }
# fn _rust_i18n_try_translate<'r>(locale: &str, key: &'r str) -> Option<std::borrow::Cow<'r, str>> { todo!() }
# macro_rules! t {
# ($($all_tokens:tt)*) => {}
# }
# fn main() {
use rust_i18n::{t, tr};
// use rust_i18n::t;
t!("hello");
// => "Hello world"
Expand All @@ -202,31 +219,14 @@ t!("messages.hello", locale = "zh-CN", name = "Jason", count = 2);
t!("messages.hello", locale = "zh-CN", "name" => "Jason", "count" => 3 + 2);
// => "你好,Jason (5)"
tr!("Hello world");
// => "Hello world" (Key `tr_3RnEdpgZvZ2WscJuSlQJkJ` for "Hello world")

tr!("Hello world", locale = "de");
// => "Hallo Welt!" (Key `tr_3RnEdpgZvZ2WscJuSlQJkJ` for "Hello world")

tr!("Hello, %{name}", name = "world");
// => "Hello, world" (Key `tr_4Cct6Q289b12SkvF47dXIx` for "Hello, %{name}")

tr!("Hello, %{name} and %{other}", name = "Foo", other = "Bar");
// => "Hello, Foo and Bar" (Key `tr_3eULVGYoyiBuaM27F93Mo7` for "Hello, %{name} and %{other}")

tr!("Hello, %{name}", locale = "de", name = "Jason");
// => "Hallo, Jason" (Key `tr_4Cct6Q289b12SkvF47dXIx` for "Hallo, %{name}")

tr!("Hello, %{name}, you serial number is: %{sn}", name = "Jason", sn = 123 : {:08});
t!("Hello, %{name}, you serial number is: %{sn}", name = "Jason", sn = 123 : {:08});
// => "Hello, Jason, you serial number is: 000000123"
# }
```

💡 NOTE: The key `tr_3RnEdpgZvZ2WscJuSlQJkJ` is auto-generated by `tr!()`, and can be extract from source code to localized files with `rust-i18n-cli`.

### Current Locale

You can use `rust_i18n::set_locale` to set the global locale at runtime, so that you don't have to specify the locale on each `t!` or `tr` invocation.
You can use [`rust_i18n::set_locale()`](<set_locale()>) to set the global locale at runtime, so that you don't have to specify the locale on each [`t!`] invocation.

```rust
rust_i18n::set_locale("zh-CN");
Expand Down Expand Up @@ -299,7 +299,7 @@ rust_i18n::i18n!("locales", backend = RemoteI18n::new());

This also will load local translates from ./locales path, but your own `RemoteI18n` will priority than it.

Now you call `t!` or `tr!` will lookup translates from your own backend first, if not found, will lookup from local files.
Now you call [`t!`] will lookup translates from your own backend first, if not found, will lookup from local files.

## Example

Expand All @@ -309,7 +309,7 @@ A minimal example of using rust-i18n can be found [here](https://github.com/long

I18n Ally is a VS Code extension for helping you translate your Rust project.

You can add [i18n-ally-custom-framework.yml](https://github.com/longbridgeapp/rust-i18n/blob/main/.vscode/i18n-ally-custom-framework.yml) to your project `.vscode` directory, and then use I18n Ally can parse `t!` or `tr!` marco to show translate text in VS Code editor.
You can add [i18n-ally-custom-framework.yml](https://github.com/longbridgeapp/rust-i18n/blob/main/.vscode/i18n-ally-custom-framework.yml) to your project `.vscode` directory, and then use I18n Ally can parse `t!` marco to show translate text in VS Code editor.

## Extractor

Expand Down Expand Up @@ -381,24 +381,39 @@ Run `cargo i18n -h` to see details.

```bash
$ cargo i18n -h
cargo-i18n 0.5.0
cargo-i18n 3.1.0
---------------------------------------
Rust I18n command for help you simply to extract all untranslated texts from soruce code.
Rust I18n command to help you extract all untranslated texts from source code.

It will iter all Rust files in and extract all untranslated texts that used `t!` macro.
And then generate a YAML file and merge for existing texts.
It will iterate all Rust files in the source directory and extract all untranslated texts that used `t!` macro. Then it will generate a YAML file and merge with the existing translations.

https://github.com/longbridgeapp/rust-i18n

USAGE:
cargo i18n [OPTIONS] [--] [source]
Usage: cargo i18n [OPTIONS] [-- <SOURCE>]

Arguments:
[SOURCE]
Extract all untranslated I18n texts from source code

[default: ./]

Options:
-t, --translate <TEXT>...
Manually add a translation to the localization file.

This is useful for non-literal values in the `t!` macro.

For example, if you have `t!(format!("Hello, {}!", "world"))` in your code,
you can add a translation for it using `-t "Hello, world!"`,
or provide a translated message using `-t "Hello, world! => Hola, world!"`.

NOTE: The whitespace before and after the key and value will be trimmed.

FLAGS:
-h, --help Prints help information
-V, --version Prints version information
-h, --help
Print help (see a summary with '-h')

ARGS:
<source> Path of your Rust crate root [default: ./]
-V, --version
Print version
```
## Debugging the Codegen Process
Expand All @@ -411,7 +426,7 @@ $ RUST_I18N_DEBUG=1 cargo build
## Benchmark
Benchmark `t!` method, result on Apple M1:
Benchmark [`t!`] method, result on Apple M1:
```bash
t time: [58.274 ns 60.222 ns 62.390 ns]
Expand Down

0 comments on commit f8d816a

Please sign in to comment.