i18n_build/
lib.rs

1//! This library is designed for use within the
2//! [cargo-i18n](https://crates.io/crates/cargo_i18n) tool for
3//! localizing crates. It has been exposed and published as a library
4//! to allow its direct use within project build scripts if required.
5//!
6//! `xtr` (installed with `cargo install xtr`), and GNU Gettext CLI
7//! tools `msginit`, `msgfmt`, `msgmerge` and `msgcat` to be present
8//! in your system path.
9//!
10//! # Optional Features
11//!
12//! The `i18n-build` crate has the following optional Cargo features:
13//!
14//! + `localize`
15//!   + Enables the runtime localization of this library using
16//!     [localize()](#localize()) function via the
17//!     [i18n-embed](https://crates.io/crates/i18n-embed) crate
18
19pub mod error;
20pub mod gettext_impl;
21pub mod util;
22pub mod watch;
23
24use anyhow::Result;
25use i18n_config::Crate;
26
27/// Run the i18n build process for the provided crate, which must
28/// contain an i18n config.
29pub fn run(crt: Crate) -> Result<()> {
30    let mut crates: Vec<Crate> = Vec::new();
31
32    let mut parent = crt.find_parent();
33
34    crates.push(crt);
35
36    while parent.is_some() {
37        crates.push(parent.unwrap());
38        parent = crates.last().unwrap().find_parent();
39    }
40
41    crates.reverse();
42
43    let mut crates_iter = crates.iter_mut();
44
45    let mut parent = crates_iter
46        .next()
47        .expect("expected there to be at least one crate");
48
49    for child in crates_iter {
50        child.parent = Some(parent);
51        parent = child;
52    }
53
54    let last_child_crt = parent;
55
56    let i18n_config = last_child_crt.config_or_err()?;
57    if i18n_config.gettext.is_some() {
58        gettext_impl::run(last_child_crt)?;
59    }
60
61    Ok(())
62}
63
64#[cfg(feature = "localize")]
65mod localize_feature {
66    use i18n_embed::{
67        gettext::{gettext_language_loader, GettextLanguageLoader},
68        DefaultLocalizer,
69    };
70    use std::sync::OnceLock;
71
72    use rust_embed::RustEmbed;
73
74    #[derive(RustEmbed)]
75    #[folder = "i18n/mo"]
76    pub struct Translations;
77
78    static TRANSLATIONS: Translations = Translations {};
79
80    fn language_loader() -> &'static GettextLanguageLoader {
81        static LANGUAGE_LOADER: OnceLock<GettextLanguageLoader> = OnceLock::new();
82
83        LANGUAGE_LOADER.get_or_init(|| gettext_language_loader!())
84    }
85
86    /// Obtain a [Localizer](i18n_embed::Localizer) for localizing this library.
87    ///
88    /// ⚠️ *This API requires the following crate features to be activated: `localize`.*
89    pub fn localizer() -> DefaultLocalizer<'static> {
90        DefaultLocalizer::new(language_loader(), &TRANSLATIONS)
91    }
92}
93
94#[cfg(feature = "localize")]
95pub use localize_feature::localizer;