Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A better and simply I18n crate for Rust.

License

NotificationsYou must be signed in to change notification settings

vkill/rust-i18n

 
 

Repository files navigation

CIDocsCrates.io

🎯 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 providedt! macro.

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

The API of this crate is inspired byruby-i18n andRails I18n.

Features

  • Codegen on compile time for includes translations into binary.
  • Globalt! 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.

Usage

Add crate dependencies in your Cargo.toml and setup I18n config:

[dependencies]rust-i18n ="2"

Load macro and init translations inlib.rs ormain.rs:

// Load I18n macro, for allow you use `t!` macro in anywhere.#[macro_use]externcrate rust_i18n;// Init translations for current crate.i18n!("locales");// Or just use `i18n!`, default locales path is: "locales" in current crate.//// i18n!();// Config fallback missing translations to "en" locale.// Use `fallback` option to set fallback locale.//// i18n!("locales", fallback = "en");

Or you can import by use directly:

// You must import in each files when you wants use `t!` macro.use rust_i18n::t;rust_i18n::i18n!("locales");fnmain(){println!("{}", t!("hello"));// Use `available_locales!` method to get all available locales.println!("{:?}", rust_i18n::available_locales!());}

Locale file

You can use_version key to specify the version of the locale file, and the default value is1.

Split Localized Texts into Difference Files

_version: 1

You can also split the each language into difference files, and you can choise (YAML, JSON, TOML), for example:en.json:

.├── Cargo.lock├── Cargo.toml├── locales│   ├── zh-CN.yml│   ├── en.yml└── src│   └── main.rs
_version:1hello:'Hello world'messages.hello:'Hello, %{name}'

Or use JSON or TOML format, just rename the file toen.json oren.toml, and the content is like this:

{"_version":1,"hello":"Hello world","messages.hello":"Hello, %{name}"}
hello ="Hello world"[messages]hello ="Hello, %{name}"

All Localized Texts in One File

_version: 2

Make sure all localized files (containing the localized mappings) are located in thelocales/ folder of the project root directory:

.├── Cargo.lock├── Cargo.toml├── locales│   ├── app.yml│   ├── some-module.yml└── src│   └── main.rs└── sub_app│   └── locales│   │   └── app.yml│   └── src│   │   └── main.rs│   └── Cargo.toml

In the localized files, specify the localization keys and their corresponding values, for example, inapp.yml:

_version:2hello:en:Hello worldzh-CN:你好世界messages.hello:en:Hello, %{name}zh-CN:你好,%{name}

This is useful when you useGitHub Copilot, after you write a first translated text, then Copilot will auto generate other locale's translations for you.

Get Localized Strings in Rust

Import thet! macro from this crate into your current scope:

use rust_i18n::t;

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

#fn_rust_i18n_translate(locale:&str,key:&str) ->String{todo!()}#fnmain(){use rust_i18n::t;t!("hello");// => "Hello world"t!("hello", locale ="zh-CN");// => "你好世界"t!("messages.hello", name ="world");// => "Hello, world"t!("messages.hello","name" =>"world");// => "Hello, world"t!("messages.hello", locale ="zh-CN", name ="Jason", count =2);// => "你好,Jason (2)"t!("messages.hello", locale ="zh-CN","name" =>"Jason","count" =>3 +2);// => "你好,Jason (5)"#}

Current Locale

You can userust_i18n::set_locale to set the global locale at runtime, so that you don't have to specify the locale on eacht! invocation.

rust_i18n::set_locale("zh-CN");let locale = rust_i18n::locale();assert_eq!(locale,"zh-CN");

Extend Backend

Since v2.0.0 rust-i18n support extend backend for cusomize your translation implementation.

For example, you can use HTTP API for load translations from remote server:

#pubmod reqwest{#pubmod blocking{#pubstructResponse;#implResponse{#pubfntext(&self) ->Result<String,Box<dyn std::error::Error>>{todo!()}#}#pubfnget(_url:&str) ->Result<Response,Box<dyn std::error::Error>>{todo!()}#}#}#use std::collections::HashMap;use rust_i18n::Backend;pubstructRemoteI18n{trs:HashMap<String,HashMap<String,String>>,}implRemoteI18n{fnnew() ->Self{// fetch translations from remote URLlet response = reqwest::blocking::get("https://your-host.com/assets/locales.yml").unwrap();let trs = serde_yaml::from_str::<HashMap<String,HashMap<String,String>>>(&response.text().unwrap()).unwrap();returnSelf{            trs};}}implBackendforRemoteI18n{fnavailable_locales(&self) ->Vec<&str>{returnself.trs.keys().map(|k| k.as_str()).collect();}fntranslate(&self,locale:&str,key:&str) ->Option<&str>{// Write your own lookup logic here.// For example load from databasereturnself.trs.get(locale)?.get(key).map(|k| k.as_str());}}

Now you can init rust_i18n by extend your own backend:

#structRemoteI18n;#implRemoteI18n{#fnnew() ->Self{todo!()}#}#impl rust_i18n::BackendforRemoteI18n{#fnavailable_locales(&self) ->Vec<&str>{todo!()}#fntranslate(&self,locale:&str,key:&str) ->Option<&str>{todo!()}#}rust_i18n::i18n!("locales", backend =RemoteI18n::new());

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

Now you callt! will lookup translates from your own backend first, if not found, will lookup from local files.

Example

A minimal example of using rust-i18n can be foundhere.

I18n Ally

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

You can addi18n-ally-custom-framework.yml to your project.vscode directory, and then use I18n Ally can parset! marco to show translate text in VS Code editor.

Extractor

Experimental

We provided acargo i18n command line tool for help you extract the untranslated texts from the source code and then write into YAML file.

In current only output YAML, and use_version: 2 format.

You can install it viacargo install rust-i18n-cli, then you getcargo i18n command.

$ cargo install rust-i18n-cli

Extractor Config

💡 NOTE:package.metadata.i18n config section in Cargo.toml is just work forcargo i18n command, if you don't use that, you don't need this config.

[package.metadata.i18n]# The available locales for your application, default: ["en"].# available-locales = ["en", "zh-CN"]# The default locale, default: "en".# default-locale = "en"# Path for your translations YAML file, default: "locales".# This config for let `cargo i18n` command line tool know where to find your translations.# You must keep this path same as the one you pass to method `rust_i18n::i18n!`.# load-path = "locales"

Rust I18n providered ai18n bin for help you extract the untranslated texts from the source code and then write into YAML file.

$ cargo install rust-i18n-cli# Now you have `cargo i18n` command

After that the untranslated texts will be extracted and saved intolocales/TODO.en.yml file.

You also can special the locale by use--locale option:

$cd your_project_root_directory$ cargo i18nChecking [en] and generating untranslated texts...Found 1 new texts need to translate.----------------------------------------Writing to TODO.en.ymlChecking [fr] and generating untranslated texts...Found 11 new texts need to translate.----------------------------------------Writing to TODO.fr.ymlChecking [zh-CN] and generating untranslated texts...All thing done.Checking [zh-HK] and generating untranslated texts...Found 11 new texts need to translate.----------------------------------------Writing to TODO.zh-HK.yml

Runcargo i18n -h to see details.

$ cargo i18n -hcargo-i18n 0.5.0---------------------------------------Rust I18ncommandforhelp you simply to extract all untranslated texts from soruce code.It will iter all Rust filesin and extract all untranslated texts that used`t!` macro.Andthen generate a YAML file and mergefor existing texts.https://github.com/longbridgeapp/rust-i18nUSAGE:    cargo i18n [OPTIONS] [--] [source]FLAGS:    -h, --help       Printshelp information    -V, --version    Prints version informationARGS:<source>    Path of your Rust crate root [default: ./]

Debugging the Codegen Process

TheRUST_I18N_DEBUG environment variable can be used to print out some debugging infos when code is being generated at compile time.

$ RUST_I18N_DEBUG=1 cargo build

Benchmark

Benchmarkt! method, result on Apple M1:

t                       time:   [100.91 ns 101.06 ns 101.24 ns]t_with_args             time:   [495.56 ns 497.88 ns 500.64 ns]

The result101 ns (0.0001 ms) means if there have 10K translate texts, it will cost 1ms.

License

MIT

About

A better and simply I18n crate for Rust.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust99.0%
  • Makefile1.0%

[8]ページ先頭

©2009-2025 Movatter.jp