Description
This is an idea that I had that leverages the Rust type system and macro system, rather then using stringly-typed arguments (well sort of). It's inspired by Diesel.
First the client that the user has to write:
translate_module!("/path/to/translation/files");
translate!(English, "hello-world");
translate!(Dutch, "intro", "Thomas");
(I know it's still looks stringly-typed, but under the hood it isn't).
The translate_module
will create a new module based on the provided directory. The only (public) API this will define is the translate
macro, which has the following API:
macro_rules! translate {
($lang:tt, $msg:expr, $($arg:tt)*) => { ... };
}
It takes a Language
item (will get back to that), a message (just like MessageContext.get_message
now) and optional arguments used to format the message (like MessageContext.format
).
Now to use Rust's type system. First we'll start off by generating an index or hash for each available translation message, something like:
const _TRANSLATE_HELLO_WORLD: usize = 0;
const _TRANSLATE_INTO: usize = 1;
And the message in an array or a hash map, for each language:
// This could also be hash maps or something.
_TRANSLATIONS_ENGLISH: [&'static str; 2] = ["Hello, world!", "Welcome, { $name }."];
_TRANSLATIONS_DUTCH: [&'static str; 2] = ["Hallo, wereld!", "Welkom, { $name }."];
We can check at compile time if the index/hash and message exists and if not fail the compilation. The Language
item provided to translate
will define what array/hash map to used, e.g. _TRANSLATIONS_DUTCH
for Dutch.
Next for the formatting we'll have a single function inside ether the fluent crate or the generated module, to which the translation string and the other provided arguments to format the message gets passed. Something like this:
// translate!(English, "hello-world") translates into:
translate(_TRANSLATIONS_ENGLISH[_TRANSLATE_HELLO_WORLD])
// translate!(Dutch, "intro", "Thomas")
translate(_TRANSLATIONS_DUTCH[_TRANSLATE_INTO], "Thomas")
Looking forward to a reply, although I don't expect it very soon it got quite long.