add string/number distinction to generated Rust methods

This commit is contained in:
Damien Elmes 2021-03-27 14:17:20 +10:00
parent e4002d7a5e
commit b5b21edd11
3 changed files with 57 additions and 27 deletions

View file

@ -165,9 +165,11 @@ impl From<String> for Variable {
| "kilobytes" | "daysStart" | "daysEnd" | "days" | "secs-per-card" | "remaining"
| "hourStart" | "hourEnd" | "correct" => VariableKind::Int,
"average-seconds" | "cards-per-minute" => VariableKind::Float,
"val" | "found" | "expected" | "part" | "percent" | "day" => VariableKind::Any,
"val" | "found" | "expected" | "part" | "percent" | "day" | "number" | "up"
| "down" | "seconds" | "megs" => VariableKind::Any,
term => {
if term.ends_with("Count") || term.ends_with("Secs") {
let term = term.to_ascii_lowercase();
if term.ends_with("count") {
VariableKind::Int
} else {
VariableKind::String

View file

@ -7,7 +7,7 @@ use inflections::Inflect;
use std::{fmt::Write, fs, path::PathBuf};
use crate::{
extract::{Module, Translation},
extract::{Module, Translation, VariableKind},
gather::{TranslationsByFile, TranslationsByLang},
};
@ -31,9 +31,8 @@ pub fn write_strings(map: &TranslationsByLang, modules: &[Module]) {
fn write_methods(modules: &[Module], buf: &mut String) {
buf.push_str(
r#"
use crate::I18n;
use crate::tr_args;
use fluent::FluentValue;
use crate::{I18n,Number};
use fluent::{FluentValue, FluentArgs};
use std::borrow::Cow;
impl I18n {
@ -46,12 +45,15 @@ impl I18n {
let doc = translation.text.replace("\n", " ");
let in_args;
let out_args;
let var_build;
if translation.variables.is_empty() {
in_args = "".to_string();
out_args = ", None".to_string();
var_build = "".to_string();
} else {
in_args = build_in_args(translation);
out_args = build_out_args(translation);
var_build = build_vars(translation);
out_args = ", Some(args)".to_string();
}
writeln!(
@ -60,6 +62,7 @@ impl I18n {
/// {doc}
#[inline]
pub fn {func}<'a>(&'a self{in_args}) -> Cow<'a, str> {{
{var_build}
self.translate("{key}"{out_args})
}}"#,
func = func,
@ -67,6 +70,7 @@ impl I18n {
doc = doc,
in_args = in_args,
out_args = out_args,
var_build = var_build,
)
.unwrap();
}
@ -75,19 +79,35 @@ impl I18n {
buf.push_str("}\n");
}
fn build_out_args(translation: &Translation) -> String {
let v: Vec<_> = translation
.variables
.iter()
.map(|var| {
format!(
r#""{fluent_name}"=>{rust_name}"#,
fluent_name = var.name,
rust_name = var.name.to_snake_case()
fn build_vars(translation: &Translation) -> String {
if translation.variables.is_empty() {
"let args = None;\n".into()
} else {
let mut buf = String::from(
r#"
let mut args = FluentArgs::new();
"#,
);
for v in &translation.variables {
let fluent_name = &v.name;
let rust_name = v.name.to_snake_case();
let trailer = match v.kind {
VariableKind::Any => "",
VariableKind::Int | VariableKind::Float => ".into()",
VariableKind::String => ".into()",
};
writeln!(
buf,
r#" args.set("{fluent_name}", {rust_name}{trailer});"#,
fluent_name = fluent_name,
rust_name = rust_name,
trailer = trailer,
)
})
.collect();
format!(", Some(tr_args![{}])", v.join(", "))
.unwrap();
}
buf
}
}
fn build_in_args(translation: &Translation) -> String {
@ -95,13 +115,13 @@ fn build_in_args(translation: &Translation) -> String {
.variables
.iter()
.map(|var| {
// let kind = match var.kind {
// VariableKind::Int => "i64",
// VariableKind::Float => "f64",
// VariableKind::String => "&str",
// VariableKind::Any => "&str",
// };
let kind = "impl Into<FluentValue<'a>>";
let kind = match var.kind {
VariableKind::Int => "impl Number",
VariableKind::Float => "impl Number",
VariableKind::String => "impl Into<String>",
// VariableKind::Any => "&str",
_ => "impl Into<FluentValue<'a>>",
};
format!("{}: {}", var.name.to_snake_case(), kind)
})
.collect();

View file

@ -3,7 +3,7 @@
mod generated;
use fluent::{FluentArgs, FluentResource, FluentValue};
use fluent::{types::FluentNumber, FluentArgs, FluentResource, FluentValue};
use fluent_bundle::bundle::FluentBundle as FluentBundleOrig;
use num_format::Locale;
use serde::Serialize;
@ -17,6 +17,14 @@ type FluentBundle<T> = FluentBundleOrig<T, intl_memoizer::concurrent::IntlLangMe
pub use fluent::fluent_args as tr_args;
pub trait Number: Into<FluentNumber> {}
impl Number for i32 {}
impl Number for i64 {}
impl Number for u32 {}
impl Number for f32 {}
impl Number for u64 {}
impl Number for usize {}
fn remapped_lang_name(lang: &LanguageIdentifier) -> &str {
let region = match &lang.region {
Some(region) => Some(region.as_str()),