1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with // this file, You can obtain one at https://mozilla.org/MPL/2.0/. //! 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). //! //! # Usage //! //! 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 crowbook_intl; //! use crowbook_intl::{Localizer, Extractor}; //! //! fn main() { //! // Generate a `lang/default.pot` containing strings used to call `lformat!` //! let mut extractor = Extractor::new(); //! extractor.add_messages_from_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/src")).unwrap(); //! extractor.write_pot_file(concat!(env!("CARGO_MANIFEST_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 crowbook_intl_runtime; //! #[macro_use] mod localize_macros; //! ``` //! //! 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 !" //! ``` //! //! # Updating your translation //! //! 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`](https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html) //! 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.) //! //! # Warning //! //! In case the complexity of the operation didn't discourage you, I should warn you //! that this library is highly experimental at this time. extern crate regex; #[macro_use] extern crate lazy_static; extern crate walkdir; mod common; mod macrogen; mod lang; mod error; mod localizer; mod message; mod extractor; pub use error::{Result, Error}; pub use localizer::Localizer; pub use extractor::Extractor;