Crate gettextrs

Source
Expand description

§Safe Rust bindings for gettext.

Usage:

use gettextrs::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Specify the name of the .mo file to use.
    textdomain("hellorust")?;
    // Ask gettext for UTF-8 strings. THIS CRATE CAN'T HANDLE NON-UTF-8 DATA!
    bind_textdomain_codeset("hellorust", "UTF-8")?;

    // You could also use `TextDomain` builder which calls `textdomain` and
    // other functions for you:
    //
    // TextDomain::new("hellorust").init()?;

    // `gettext()` simultaneously marks a string for translation and translates
    // it at runtime.
    println!("Translated: {}", gettext("Hello, world!"));

    // gettext supports plurals, i.e. you can have different messages depending
    // on the number of items the message mentions. This even works for
    // languages that have more than one plural form, like Russian or Czech.
    println!("Singular: {}", ngettext("One thing", "Multiple things", 1));
    println!("Plural: {}", ngettext("One thing", "Multiple things", 2));

    // gettext de-duplicates strings, i.e. the same string used multiple times
    // will have a single entry in the PO and MO files. However, the same words
    // might have different meaning depending on the context. To distinguish
    // between different contexts, gettext accepts an additional string:
    println!("With context: {}", pgettext("This is the context", "Hello, world!"));
    println!(
        "Plural with context: {}",
        npgettext("This is the context", "One thing", "Multiple things", 2));

    Ok(())
}

§UTF-8 is required

By default, gettext converts results to the locale’s codeset. Rust, on the other hand, always encodes strings to UTF-8. The best way to bridge this gap is to ask gettext to convert strings to UTF-8:

bind_textdomain_codeset("hellorust", "UTF-8")?;

…or using TextDomain builder:

TextDomain::new("hellorust")
    .codeset("UTF-8") // Optional, the builder does this by default
    .init()?;

This crate doesn’t do this for you because the encoding is a global setting; changing it can affect other gettext calls in your program, like calls in C or C++ parts of your binary.

If you don’t do this, calls to gettext() and other functions might panic when they encounter something that isn’t UTF-8. They can also garble data as they interpret the other encoding as UTF-8.

Another thing you could do is change the locale, e.g. setlocale(LocaleCategory::LcAll, "fr_FR.UTF-8"), but that would also hard-code the language, defeating the purpose of gettext: if you know the language in advance, you could just write all your strings in that language and be done with that.

Modules§

getters
Query gettext configuration.

Structs§

TextDomain
A builder to configure gettext.

Enums§

LocaleCategory
Locale category enum ported from locale.h.
TextDomainError
Errors that might come up after running the builder.

Functions§

bind_textdomain_codeset
Set encoding of translated messages.
bindtextdomain
Specify the directory that contains MO files for the given domain.
dcgettext
Translate msgid to localized message from the specified domain using custom locale category.
dcngettext
Translate msgid to localized message from the specified domain using custom locale category (with plural support).
dgettext
Translate msgid to localized message from the specified domain.
dngettext
Translate msgid to localized message from the specified domain (with plural support).
gettext
Translate msgid to localized message from the default domain.
ngettext
Translate msgid to localized message from the default domain (with plural support).
npgettext
Translate msgid to localized message from the default domain (with plural support and context support).
pgettext
Translate msgid to localized message from the default domain (with context support).
setlocale
Set current locale.
textdomain
Switch to the specific text domain.