A library to localize strings, translating them according to runtime options.
Basically, this library allows your project to generate a lformat!
macro, that behaves
similarly to format!
, except the message string (the first argument) might get translated
(if you can find the appropriate string for the language).
First, you'll need to add the following to your Cargo.toml
file:
```toml build = "build.rs"
[build-dependencies] crowbook-intl = "0.1.0"
[dependencies] crowbook-intl-runtime = "0.1.0" ```
You'll then need to create the build.rs
file, which can look like this:
```rust,ignore extern crate crowbookintl; use crowbookintl::{Localizer, Extractor};
fn main() {
// Generate a lang/default.pot
containing strings used to call lformat!
let mut extractor = Extractor::new();
extractor.addmessagesfromdir(concat!(env!("CARGOMANIFESTDIR"), "/src")).unwrap();
extractor.writepotfile(concat!(env!("CARGOMANIFEST_DIR"), "/lang/default.pot")).unwrap();
// Generate the `localize_macros.rs` file
let mut localizer = Localizer::new(&extractor);
// Use env::var instead of env! to avoid problems when cross-compiling
let dest_path = Path::new(&env::var("OUT_DIR").unwrap())
.join("localize_macros.rs");
localizer.write_macro_file(dest_path).unwrap();
} ```
This will create a localize_macros.rs
at build time somewhere in OUT_DIR
, containing the lformat!
macro.
To actually use this macro, you have to create a src/localize_macros.rs
file that includes it:
rust,ignore
include!(concat!(env!("OUT_DIR"), "/localize_macros.rs"));
To use it, the last step is to modify your src/lib/lib.rs
file:
```rust,ignore extern crate crowbookintlruntime;
```
Once this is done, you can start replacing your calls to format!
with calls to lformat!
.
In order to get translation, you'll need to actually translate the strings in separate
files, and set your build.rs
to load them.
E.g., if you have the following code:
rust,ignore
println!("{}", lformat!("Hello, world!"));
and you want it translated in french, you'll have to create a lang/fr.po
file
from the lang/default.pot
file containing:
text
msgid "Hello, world!";
msgstr "Bonjour le monde !";
And load it in your build.rs
file:
rust,ignore
let mut localizer = Localizer::new();
localizer.add_lang("fr", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/fr.mp"))).unwrap();
(...)
Once this is done, you can use the localize_macros::set_lang
function
to switch the language at runtime:
rust,ignore
use crowbook_intl_runtime::set_lang;
set_lang("en");
println!("{}", lformat!("Hello, world!")); // prints "Hello, world!"
set_lang("fr");
println!("{}", lformat!("Hello, world!")); // prints "Bonjour le monde !"
When you add new strings that need to be translated (by more calls to lformat!
),
or when you change the content of existing strings, you can use Gettext's msgmerge
and msgcmp
commands to update your translation. While it is not guaranteed that the formats are
strictly identical, it should work. (That is, it is a bug if it doesn't; but at this
stage, this library is absolutely not guaranteed to be bug-free.)
crowbook-intl
doesn't handle correctly raw string literals in lformat!
(they won't be translated correctly).In case the complexity of the operation didn't discourage you, I should warn you that this library is highly experimental at this time.
This is free software, published under the Mozilla Public License, version 2.0.
See the documentation on docs.rs.
See the ChangeLog file.