У меня была та же проблема, и после проверки тысячи раз разных вещей (заголовок кодировки HTTP, заголовок кодировки на странице, кодировка .po файла и т. Д.) Это решило ее:
$gtDomain = "messages";
bindtextdomain($gtDomain, "/path/to/gettext/folder/Locale");
bind_textdomain_codeset($gtDomain, 'UTF-8'); //This was the missing piece.
Иэто более полная выдержка:
$gtLocale = 'fr_FR';
$gtLocaleEnc = "$gtLocale.UTF-8";
//echo "gtLocale #$gtLocale# gtLocaleEnc #$gtLocaleEnc#<br />";
putenv("LANGUAGE=" . $gtLocale); //First priority!
putenv("LANG=" . $gtLocale);
putenv("LC_ALL=" . $gtLocale);
putenv("LC_MESSAGES=" . $gtLocale);
//echo "env LANG #", getenv('LANG'), "#<br />";
//echo "env LC_ALL #", getenv('LC_ALL'), "#<br />";
//echo "env LC_MESSAGES #", getenv('LC_MESSAGES'), "#<br />";
$gtIsLocaleSupported = setlocale(LC_ALL, $gtLocale);
$gtIsLocaleSupportedT = setlocale(LC_MESSAGES, $gtLocale);
//echo "gtIsLocaleSupported #$gtIsLocaleSupported#<br />";
//echo "gtIsLocaleSupportedT #$gtIsLocaleSupportedT#<br />";
//echo "getcwd #", getcwd(), "#<br />";
// Set the text domain as "messages"
$gtDomain = "messages";
//The following means that the catalog "messages"
//e.g. for the locale fr_FR is to be in:
///path/to/gettext/folder/Locale/fr_FR/LC_MESSAGES/messages.mo:
bindtextdomain($gtDomain, "/path/to/gettext/folder/Locale");
bind_textdomain_codeset($gtDomain, 'UTF-8'); //This was the missing piece
//Now set the current catalog to be "messages" in order to test it:
textdomain($gtDomain);
//If your .mo for fr_FR translates "Reference" as "Référence",...
echo _("Reference"); //...then this should yield "Référence".