#locale #unit #macro #proc-macro #language #dict #mauzi

nightly macro mauzi_macros

'mauzi'的辅助库。请直接使用'mauzi'。

2个版本

使用旧的Rust 2015

0.0.2 2017年9月2日
0.0.1 2017年8月26日

#17 in #dict


用于 mauzi

MIT/Apache

48KB
925 lines

Mauzi

一个用于国际化的实验性库,使用proc_macro宏。 这仅仅是我的一个实验;这个库不再开发了。

这个库背后的想法如下:i18n通常是通过编写特殊格式的文本文件来完成的。翻译者还可以使用一些特殊功能来简化复数等操作。与其使用具有奇怪语法的外部文件,我认为Rust将受益于拥有更类型安全的工具。你可以在模板库领域中看到类似的东西:有一些库以字符串作为输入(handlebars、tera等)。然后是maud:在这里,模板是以proc_macro内的语法编写的。这提供了更高的类型安全性,并带来了一些其他好处。

这个库希望成为i18n的“maud”。要了解这个库的样子:请看这个示例

mod dict {
    use mauzi::mauzi;

    mauzi! {
        // The first thing in the macro invocation is the Locale definition.
        // Here you define which languages and regions your dictionary
        // supports.
        enum Locale {
            // You can have languages without distinguishing between regions...
            De,
            // ... but you can have regions for a given language, too.
            En { Gb, Us },
        }

        // A simple translation unit: it returns a string depending on the
        // locale.
        unit fav_color {
            De => "Was ist deine Lieblingsfarbe?",
            En(Gb) => "What is your favourite colour?",
            En(Us) => "What is your favorite color?",
        }

        // Translation units can take parameters. Those are declared in a pair
        // of parenthesis, just like parameters for a Rust function.
        //
        // You can then use the parameter in the string with the `{param}`
        // syntax.
        unit greet(name: &str) {
            En(Gb) => "Hi {name}! Are you all right, mate?",
            En(Us) => "Hi {name}! How are you, buddy?",
            De => "Hallo {name}, wie geht's dir?",
        }

        // Instead of simple strings, you can specify your own Rust code which
        // will generate a string instead. Note that you can't use the fancy
        // `{param}` syntax as above.
        unit new_emails(count: u32) {
            // Note that the region is omitted here. You can do that if the
            // region doesn't matter. This is equivalent to `En(_)`.
            En => {
                match count {
                    1 => "You have one new email".to_string(),
                    _ => format!("You have {} new emails", count),
                }
            }
            De => {
                match count {
                    1 => "Sie haben eine neue E-Mail".to_string(),
                    _ => format!("Sie haben {} neue E-Mails", count),
                }
            }
        }

        // You can also specify custom return types. However, this requires you
        // to specify raw bodies. Custom return types are mostly useful for
        // preformatted HTML, like the `maud::Markup` type.
        unit number_of_umlauts -> u32 {
            De => { 3 },
            En => { 0 },
        }
    }
}

fn main() {
    use dict::{Locale, EnRegion};

    let locales = [
        Locale::De,
        Locale::En(EnRegion::Gb),
        Locale::En(EnRegion::Us),
    ];

    for &locale in &locales {
        println!("--- for {:?} ---", locale);
        let dict = dict::new(locale);

        // All translation keys are simple functions. You can access it like
        // calling a function.
        println!("greet       => {}", dict.greet("Ferris"));
        println!("fav_color   => {}", dict.fav_color());
        println!("new_emails  => {}", dict.new_emails(3));
        println!("umlauts     => {}", dict.number_of_umlauts());
    }
}

状态

这个库只是一个实验。我使用这个库的项目已经不存在了,所以我没有直接的动力去开发这个库。也许我会在将来再次访问这个库。

防患未然,双倍努力(一串脏技巧)

目前这个库和Rust 1.0之前的元素周期表中的 flerovium制成的纸牌屋一样不稳定。部分原因是我对某些事物缺乏理解,部分原因在于proc_macro特性的不完整和不稳定。在这里,我想列出我现在使用的所有邪恶技巧。

模拟模块系统

我无法将 mauzi-modules 映射到 Rust 模块。问题在于,从子模块中,我需要使用在根模块中定义的 Dict。理论上看起来很简单,但由于宏的清洁性(我想?),实际上很复杂。几乎没有任何 use 语句按预期工作。也许 这个 被采纳后能解决这个问题,也许不能。我在这里 也对类似的问题发表过评论。也许这已经可行,但我找不到解决方案。

当前的解决方案是在子模块中为类型构建长名称。所以,而不是

dict::bar::baz::Dict

... 类型是

dict::bar___this_is_a_bad_solution___baz___this_is_a_bad_solution___Dict

加载子模块文件

过程宏无法确定它是在哪个文件中被调用的。这意味着我们不知道在哪里查找子模块文件!这已经在这里讨论过。

当前的解决方案使用 CARGO_MANIFEST_PATH 并添加 src/。这意味着

  • 您必须在直接位于 src/ 文件夹中的文件中调用 mauzi! 宏。
  • 任何不在 src/ 中的项目都无法正常工作(例如,在 examples/ 中的示例)

许可证

根据您的选择,受以下任一许可证的许可:

贡献

除非您明确表示,否则根据 Apache-2.0 许可证定义,您提交的任何有意包含在作品中的贡献,将如上所述双重许可,没有额外的条款或条件。


lib.rs:

此crate定义了过程宏 mauzi!

您不应该直接使用此crate,而应使用 mauzi。宏在那里重新导出。

依赖项

~31KB