Search code examples
cwindowsgettextmsys2

gettext does not work with account names with international characters


I am using an installed locale folder to get the messages for my application. When using an account name with international characters, the gettext library fails to load and convert the text strings.

Has anyone run into this before? Have a work-around?

I am using the UCRT64 environment in msys2.

Create a user account named: test Gergő and set up msys2.

In the test Gergő account:

cd "/c/Users/test Gergő"
mkdir -p locale/nl/LC_MESSAGES
cp /usr/share/locale/nl/LC_MESSAGES/sed.mo locale/nl/LC_MESSAGES/
cd 

Using the following test code: ( I named it tt.c )

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <libintl.h>
#include <wchar.h>
#include <windows.h>

#define DOM "sed"

int
main (int argc, char *argv [])
{
  wchar_t *wtmp;
  char    buff [512];
  char    tbuff [512];
  char    *tmp;
  size_t  len;


  wtmp = _wgetenv (L"USERPROFILE");
  // wtmp = _wgetenv (L"HOME");
  len = WideCharToMultiByte (CP_UTF8, 0, wtmp, -1, NULL, 0, NULL, NULL);
  WideCharToMultiByte (CP_UTF8, 0, wtmp, -1, buff, len + 1, NULL, NULL);
  wtmp [len] = L'\0';

  sprintf (tbuff, "%s/locale", buff);
  // or vice-versa. fails both ways.
  // just to be sure the path is consistent.
  for (int i = 0; i < strlen (tbuff); ++i) {
    if (tbuff [i] == '\\') {
      tbuff [i] = '/';
    }
  }
  tmp = bindtextdomain (DOM, tbuff);
  fprintf (stderr, "bind: %s\n", tmp);

  tmp = textdomain (DOM);
  fprintf (stderr, "text-dom: %s\n", tmp);

  if (setlocale (LC_MESSAGES, tbuff) == NULL) {
    fprintf (stderr, "set-locale failed\n");
  }

  _wputenv_s (L"LC_MESSAGES", L"nl.UTF-8");

  tmp = gettext ("No match");
  if (strcmp (tmp, "No match") == 0) {
    fprintf (stderr, "NG %s\n", tmp);
  } else {
    fprintf (stderr, "OK %s\n", tmp);
  }

  return 0;
}

Compile:

cc -o tt tt.c -static -lintl -liconv

Run the program within a cmd.exe window:

C:\msys64\home\test Gergő\tt.exe

The string "No match" from sed.mo is not found.

bind: C:\Users\test Gergő\locale
text-dom: sed
NG No match

This works using account names of bll and test user .

The program can also be compiled to retrieve the HOME environment variable and run within msys2 (with the sample locale/ directory installed in the msys2 home). Again it fails with the test Gergő account and works with the bll and test user accounts.


Solution

  • Turns out that libintl includes a wbindtextdomain function. I was digging through the gettext source code and found this. It is not documented in the manual pages, it is documented in the gettext info files.

    To get cmake to locate this function, I checked for the libintl_wbindtextdomain function name.