extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use std::path::Path;
use std::{env, fs};
use syn::{parse_macro_input, LitStr};
use toml::Value;
#[proc_macro]
pub fn translate(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as LitStr);
#[cfg(feature = "en")]
let lang = "en";
#[cfg(feature = "es")]
let lang = "es";
#[cfg(feature = "fr")]
let lang = "fr";
#[cfg(feature = "ru")]
let lang = "ru";
let base_dir = match env::var("CARGO_MANIFEST_DIR") {
Ok(dir) => dir,
Err(_) => {
".".to_string()
}
};
let target_path = Path::new(&base_dir).join(format!("translations/{}.toml", lang));
let content = match fs::read_to_string(&target_path) {
Ok(content) => content,
Err(e) => {
return syn::Error::new(
proc_macro2::Span::call_site(),
format!("Error reading file '{}': {}", target_path.display(), e),
)
.to_compile_error()
.into();
}
};
let parsed_toml = content.parse::<toml::Value>().unwrap();
let content = get_nested(&parsed_toml, &input.value())
.expect(format!("Error translating key {} not found", input.value()).as_str())
.as_str()
.expect(
format!(
"Expected a string value on translation key {}",
input.value()
)
.as_str(),
);
let content_literal = proc_macro2::Literal::string(&content);
let output = quote! { #content_literal };
output.into()
}
fn get_nested<'a>(value: &'a Value, key: &str) -> Option<&'a Value> {
key.split('.').fold(Some(value), |acc, k| acc?.get(k))
}