See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=931139. This appears to me to be a glibc bug. The locale in a thread has changed, but glibc continues to use a now incorrect cache. I couldn't find any documentation of how gettext and threads interact. I presume the invalidation need only occur if LC_MESSAGES is changed, not any other category.
Also see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=931456 which has additional details, and a demo program.
I can confirm running the program and seeing: [carlos@athas swbz24936]$ ./test lauseoppivirhe lauseoppivirhe lauseoppivirhe [carlos@athas swbz24936]$ ./test fix lauseoppivirhe erreur de syntaxe syntax error It does seem like a defect that we don't increment _nl_msg_cat_cntr when calling uselocale to set the thread-local locale. The real problem is that _nl_msg_cat_cntr is a global variable that is accessesed by all threads under what appears to be a mix of __libc_setlocale_lock and _nl_state_lock, which also seems wrong and prone to producing a counter that is incorrectly updated. Worse is that because two locks are used to update the data structures, but only one _nl_msg_cat_cntr, it might lead to a case where an update happened in thread A, using __libc_setlocale_lock, and then thread B did an update, using _nl_state_lock, it might see an old value of _nl_msg_cat_cntr, because the locks are different, and writes in thread A are not guaranteed to be seen by thread B. Likewise for other parts of the locales. The solution requires a full review of the locking around _nl_msg_cat_cntr, __libc_setlocale, and _nl_state_lock. Then uselocale needs to be updated to indicate that the locale change invalidates the lookup cache. Looks like a real bug to me.