Skip to content

GoldsteinE/ctl10n

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ctl10n

ctl10n (compile time localization) provides you a simple way to embed messages into binary file without embedding them into source. Internally, ctl10n generates a simple macro_rules! macro tr!() from the provided a TOML file with strings.

Basic usage

Add ctl10n to your build-dependencies in your Cargo.toml. If you want to use include_strings you'll need it in dependencies as well.

[package]
name = "example"
version = "0.1"
edition = "2018"

[build-dependencies]
ctl10n = "0.1.0"

[dependencies]
ctl10n = "0.1.0"

Add the following to your build.rs:

use ctl10n;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=strings.toml");
    if let Err(err) = ctl10n::convert_default_strings_file() {
        panic!("{}", err);
    }
}

This will generate the file $OUT_DIR/strings.rs from strings.toml. The TOML file with strings must be a table where all values are strings. Example strings.toml:

message = "Some message"
message-with-args = "Some message with {arg}"

You should include strings.rs somewhere (for example, in lib.rs) to use the generated macro. You can do this by calling the macro ctl10n::include_strings!() or manually, using include!(). After including the macro it can be used like this:

use ctl10n;

ctl10n::include_strings!();

fn main() {
    // `tr!()` with one argument will be translated to string literal
    println!(tr!("message"));
    println!(tr!("message-with-args"), arg = "foobar");
    // `tr!()` with multiple arguments will be translated to formatted `&String`
    println!("{}", tr!("message-with-args", arg = "foobaz"))
}

Output of this code (assuming strings.toml from above):

Some message
Some message with foobar
Some message with foobaz

Trying to use an unknown key or wrong format arguments is a compile-time error.

Multiple locales

You can use environment variables to provide a different locale at compile time:

use std::env;
use std::path::Path;

use ctl10n;

const LOCALES: &[&str] = &["de", "en"];

fn main() {
    for locale in LOCALES {
        println!("cargo:rerun-if-changed=locales/{}.toml", locale);
    }
    println!("cargo:rerun-if-env-changed=LOCALE");
    let locale_file = format!(
        "locales/{}.toml",
        &env::var("LOCALE").unwrap_or("en".to_string())
    );
    let out_file = Path::new(&env::var("OUT_DIR").unwrap()).join("strings.rs");
    // Possible errors: No such file or directory, Path is a directory, The user lacks permissions to remove the file
    // We want to ignore the first error and the other two are catched by ctl10n anyway.
    let _ignore_error = std::fs::remove_file(&out_file);
    ctl10n::convert_strings_file(locale_file, out_file).expect("ctl10n failed");
}

LOCALE=de cargo build

About

Compile-time localisation library for Rust

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages