#![doc = include_str!("../README.md")]
use std::{ops::Deref, sync::LazyLock};
#[doc(hidden)]
pub use rust_i18n_macro::{_minify_key, _tr, i18n};
pub use rust_i18n_support::{
try_load_locales, AtomicStr, Backend, BackendExt, CowStr, MinifyKey, SimpleBackend,
DEFAULT_MINIFY_KEY, DEFAULT_MINIFY_KEY_LEN, DEFAULT_MINIFY_KEY_PREFIX,
DEFAULT_MINIFY_KEY_THRESH,
};
static CURRENT_LOCALE: LazyLock<AtomicStr> = LazyLock::new(|| AtomicStr::from("en"));
pub fn set_locale(locale: &str) {
CURRENT_LOCALE.replace(locale);
}
pub fn locale() -> impl Deref<Target = str> {
CURRENT_LOCALE.as_str()
}
pub fn replace_patterns(input: &str, patterns: &[&str], values: &[String]) -> String {
let input_bytes = input.as_bytes();
let mut pattern_pos = smallvec::SmallVec::<[usize; 64]>::new();
let mut stage = 0;
for (i, &b) in input_bytes.iter().enumerate() {
match (stage, b) {
(1, b'{') => {
stage = 2;
pattern_pos.push(i);
}
(2, b'}') => {
stage = 0;
pattern_pos.push(i);
}
(_, b'%') => {
stage = 1;
}
_ => {}
}
}
let mut output: Vec<u8> = Vec::with_capacity(input_bytes.len() + 128);
let mut prev_end = 0;
let pattern_values = patterns.iter().zip(values.iter());
for pos in pattern_pos.chunks_exact(2) {
let start = pos[0];
let end = pos[1];
let key = &input_bytes[start + 1..end];
if prev_end < start {
let prev_chunk = &input_bytes[prev_end..start - 1];
output.extend_from_slice(prev_chunk);
}
if let Some((_, v)) = pattern_values
.clone()
.find(|(&pattern, _)| pattern.as_bytes() == key)
{
output.extend_from_slice(v.as_bytes());
} else {
output.extend_from_slice(&input_bytes[start - 1..end + 1]);
}
prev_end = end + 1;
}
if prev_end < input_bytes.len() {
let remaining = &input_bytes[prev_end..];
output.extend_from_slice(remaining);
}
unsafe { String::from_utf8_unchecked(output) }
}
#[macro_export]
#[allow(clippy::crate_in_macro_def)]
macro_rules! t {
($($all:tt)*) => {
crate::_rust_i18n_t!($($all)*)
}
}
#[macro_export]
#[allow(clippy::crate_in_macro_def)]
macro_rules! tkv {
($msg:literal) => {
crate::_rust_i18n_tkv!($msg)
};
}
#[macro_export(local_inner_macros)]
#[allow(clippy::crate_in_macro_def)]
macro_rules! available_locales {
() => {
crate::_rust_i18n_available_locales()
};
}
#[cfg(test)]
mod tests {
use crate::{locale, CURRENT_LOCALE};
fn assert_locale_type(s: &str, val: &str) {
assert_eq!(s, val);
}
#[test]
fn test_locale() {
assert_locale_type(&locale(), &CURRENT_LOCALE.as_str());
assert_eq!(&*locale(), "en");
}
}