# gettext-rs

Safe bindings for gettext. Please see
[documentation](https://docs.rs/gettext-rs) for details.

## Licensing

This crate depends on `gettext-sys`, which compiles GNU gettext on platforms
that don't have a native gettext implementation. GNU gettext is licensed under
LGPL, and is linked statically, which means **you have to abide by LGPL**. If
you don't want or can't do that, there are two ways out:

1. if you use glibc or musl libc, enable `gettext-system` feature (see below);
2. dynamically link to GNU gettext library you obtained by some other means,
   like a package manager. For details, see environment variables in
   `gettext-sys` documentation.

## Usage

(If you know how to use gettext and just want a gist of this crate's API, [skip
to the next section](#complete-api-example)).

To internationalize your program with gettext, you have to do four things:

1. wrap translatable strings into calls to appropriate gettext functions;
2. use tools to extract those strings into a so-called "PO template file";
3. translate the strings in the template, getting a so-called "message catalog"
   as a result;
4. compile the message catalog from the plain-text, human-readable PO format to
   the binary MO format, and install them into a well-known location like
   _/usr/local/share/locale_.

This crate only covers the first step, the markup. To extract messages, use
`xtr` (`cargo install xtr`). To translate, you can use desktop tools like
[Poedit][], sites like [Crowdin][], or any text editor. To compile from PO to
MO, use `msgfmt` tool from gettext-tools. The way you install files highly depend
on your distribution method, so it's not covered here either.

[Poedit]: https://poedit.net
[Crowdin]: https://crowdin.com

The best resource on gettext is [GNU gettext manual][]. This crate has the same
API, so you should have an easy time transferring the advice from that manual to
this crate. In a pitch, you can also glance at the manpages for C functions
which this crate wraps.

[GNU gettext manual]: https://www.gnu.org/software/gettext/manual/index.html

## Complete API example

```rust
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(())
}
```

## Features

- `gettext-system`: if enabled, _asks_ the crate to use the gettext
    implementation that's part of glibc or musl libc. This only works on:

    * Linux with glibc or musl libc;
    * Windows + GNU (e.g. [MSYS2](https://www.msys2.org/)) with `gettext-devel`
        installed e.g. using:

        ```
        pacman --noconfirm -S base-devel mingw-w64-x86_64-gcc libxml2-devel tar
        ```

    If none of those conditions hold, the crate will proceed to building and
    statically linking its own copy of GNU gettext!

    This enables `gettext-system` feature of the underlying `gettext-sys` crate.

## Environment variables

This crate doesn't use any. See also the documentation for the underlying
`gettext-sys` crate.
