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
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: (c) 2023 Hubert Figuière
//! Implement the proc macros.
//!
#![doc = include_str!("../README.md")]
use proc_macro::{Delimiter, Group, TokenStream, TokenTree};
use quote::quote;
#[proc_macro]
/// Wrapper macro to use [`gettextrs::gettext!`] or
/// [`gettextrs::ngettext!`] in a way that allow xgettext to find
/// strings for `.po` files as it doesn't support a keyword with a
/// `!`.
///
/// ```
/// use i18n_format::i18n_fmt;
///
/// let number = 1;
/// let s = i18n_fmt! {
/// i18n_fmt("This is number {}, make it so !", number)
/// };
///
/// let count = 2;
/// let message = i18n_fmt! {
/// i18n_nfmt("Counted {} item", "Counted {} items", count, count)
/// };
/// ```
///
/// Both `i18n_fmt` and `i18n_nfmt` are placeholders, in the block for
/// `i18n_fmt!` either will be replaced by a call to
/// [`gettextrs::gettext!`] or [`gettextrs::ngettext!`], respectively.
/// Specify `i18n_fmt` and `i18n_nfmt:1,2` as keywords for calls to
/// xgettext.
pub fn i18n_fmt(body: TokenStream) -> TokenStream {
let mut macro_block: TokenStream = quote!(
use gettextrs::*;
)
.into();
macro_block.extend(body.into_iter().map(move |tt| {
if let TokenTree::Ident(ref i) = tt {
match i.to_string().as_str() {
"i18n_fmt" => {
return TokenTree::Group(Group::new(Delimiter::None, quote!(gettext!).into()))
}
"i18n_nfmt" => {
return TokenTree::Group(Group::new(Delimiter::None, quote!(ngettext!).into()))
}
_ => {}
}
}
tt
}));
[TokenTree::Group(Group::new(Delimiter::Brace, macro_block))]
.into_iter()
.collect()
}