Skip to main content

lang_lib/
lib.rs

1//! A lightweight, high-performance localization library.
2//!
3//! `lang-lib` loads TOML language files, supports runtime locale switching,
4//! configurable file paths, and automatic fallback chains. It is designed to
5//! be dropped into any project without ceremony.
6//!
7//! # What This Crate Does Well
8//!
9//! - Keeps the runtime model simple: load files once, then translate by key.
10//! - Uses plain TOML so translators and developers can inspect files easily.
11//! - Works across platforms by resolving file paths with native path handling.
12//! - Fails predictably with typed errors when files are missing or invalid.
13//!
14//! # Quick Start
15//!
16//! ```rust,no_run
17//! use lang_lib::{t, Lang};
18//!
19//! // Configure once at startup
20//! Lang::set_path("locales");
21//! Lang::load("en").unwrap();
22//! Lang::load("es").unwrap();
23//! Lang::set_locale("en");
24//!
25//! // Translate anywhere
26//! let msg = t!("bad_password");
27//! let msg_es = t!("bad_password", "es");
28//! let msg_fb = t!("missing_key", fallback: "Default message");
29//! ```
30//! # Small Tutorial
31//!
32//! 1. Create a directory for locale files.
33//! 2. Add one TOML file per locale.
34//! 3. Load the locales your application needs at startup.
35//! 4. Set the active locale for the current process.
36//! 5. Use [`t!`] anywhere you need translated text.
37//!
38//! Example layout:
39//!
40//! ```text
41//! your-app/
42//! |- Cargo.toml
43//! |- src/
44//! |  \- main.rs
45//! \- locales/
46//!    |- en.toml
47//!    \- es.toml
48//! ```
49//!
50//!
51//! # File Format
52//!
53//! Language files are plain TOML, one key per line:
54//!
55//! ```toml
56//! bad_password = "Your password is incorrect."
57//! welcome_user = "Welcome back"
58//! not_found    = "The page you requested does not exist."
59//! ```
60//!
61//! Files are resolved as `{path}/{locale}.toml`.
62//!
63//! # Behavior Notes
64//!
65//! Lookup order is deterministic:
66//!
67//! 1. Requested locale, or the active locale when none is provided
68//! 2. Each configured fallback locale in order
69//! 3. The inline fallback passed to [`t!`]
70//! 4. The key itself
71//!
72//! Non-string TOML values are ignored on purpose. That keeps translation data
73//! flat and avoids surprising coercions at runtime.
74//!
75//! # Examples
76//!
77//! See the runnable example in `examples/basic.rs` for a complete setup using
78//! real locale files.
79//! See `examples/server.rs` for a server-oriented pattern that resolves a
80//! locale per request and passes it explicitly during translation.
81//! See `examples/axum_server.rs` for the same pattern inside a real HTTP
82//! handler using `axum`.
83//! See `examples/actix_server.rs` for the same pattern using `actix-web`.
84//! Locale names must be a single file stem such as `en`, `en-US`, or `pt_BR`.
85
86#![deny(warnings)]
87#![deny(clippy::all)]
88#![deny(missing_docs)]
89
90mod error;
91mod loader;
92mod request;
93mod store;
94
95pub use error::LangError;
96pub use request::{resolve_accept_language, resolve_accept_language_owned};
97pub use store::{Lang, Translator};
98
99/// Translates a key using the active locale.
100///
101/// Falls back through the fallback chain and finally returns the key itself
102/// if no translation is found anywhere.
103///
104/// # Examples
105///
106/// ```rust,no_run
107/// use lang_lib::t;
108///
109/// // Active locale
110/// let msg = t!("greeting");
111///
112/// // Specific locale
113/// let msg = t!("greeting", "es");
114///
115/// // Inline fallback
116/// let msg = t!("unknown_key", fallback: "Hello");
117/// ```
118#[macro_export]
119macro_rules! t {
120    ($key:expr) => {
121        $crate::Lang::translate($key, None, None)
122    };
123    ($key:expr, $locale:expr) => {
124        $crate::Lang::translate($key, Some($locale), None)
125    };
126    ($key:expr, fallback: $fallback:expr) => {
127        $crate::Lang::translate($key, None, Some($fallback))
128    };
129    ($key:expr, $locale:expr, fallback: $fallback:expr) => {
130        $crate::Lang::translate($key, Some($locale), Some($fallback))
131    };
132}