gettext-rs icon indicating copy to clipboard operation
gettext-rs copied to clipboard

No way to test translated strings

Open mks-h opened this issue 3 years ago • 3 comments

There is currently no way to force gettext functions to return specific strings. This means I cannot test if the macros I'm working on at #89 fall back to default strings when returned ones are broken. I believe there are two ways to solve the problem:

  1. For testing, use container populated with translation files;
  2. Fake gettext functions and use some magic of constants to specify which string to return.

I find the first option too cumbersome, so I'll investigate second.

mks-h avatar Jan 14 '22 13:01 mks-h

I'm on the road right now, so just a couple pointers. I can clarify on Sunday if you have questions.

bindtextdomain() takes a path to a directory with a structure similar to /usr/locale. We can create such a directory and populate it with known data, which we will then request via gettext() and friends.

The data is described by a PO file, and compiled into MO files which are put into the locator directory under an appropriate language tag. See gettext manual and /usr/locale on your own machine.

Minoru avatar Jan 14 '22 17:01 Minoru

We can create such a directory and populate it with known data, which we will then request via gettext() and friends.

Yeah, but we will have to initialize it before testing somehow, which is cumbersome.

I have came up with a solutrion that will suffice for now. The idea is to, in each testing function, have an inlined module with a "gettextrs" name that declares a fake gettext function and reexports formatter from the actual gettextrs. Like so:

#[test]
fn nothing_to_format_translated() {
    mod gettextrs {
        pub use ::gettextrs::formatter;
        pub fn gettext<T: Into<String>>(_msgid: T) -> String {
                "Привіт, світ!".into()
        }
    }

    assert_eq!(gettext!("Hello, World!"), "Привіт, світ!");
}

I've put up a declarative macro that simplifies the generation of a module. So, in the end, it looks like so:

#[test]
fn nothing_to_format_translated() {
    fake!(gettext, "Привіт, світ!");

    assert_eq!(gettext!("Hello, World!"), "Привіт, світ!");
}

This approach limits me to using one message per test, which is fair. The problem is that it works because procedural gettext macros use gettextrs::gettext(...) path's which can be confused with a gettextrs module. I could have used ::gettextrs::gettext(...), which can't be confused, but then there is also a feature in cargo that allow renaming dependencies for which I have to get the actual name of the crate anyway... So I'll deal with that later.

I'll leave this issue open for now since it will have to be revisited.

mks-h avatar Jan 14 '22 23:01 mks-h

The other problem is that I have to duplicate function definitions, which might get out of sync with actual implementations. Not an issue today, but it can certainly become one.

mks-h avatar Jan 14 '22 23:01 mks-h