PHP Gettext not working via cli or apache - php

Running php-5.3.10
This is my first time setting up a website with i18n via gettext. However, the English text is still being printed, instead of the Dutch text I'm expecting. I've been Googling for two days now, but I still haven't found a solution.
The php code, even when run from cli it does not give a translation, so Apache caching is not the issue here. The code:
<?php
// no errors are thrown, sadly
error_reporting(E_ALL);
$domain = 'test';
setlocale(LC_ALL, 'nl_NL.utf8'); // returns 'nl_NL.utf8', I've also tried without '.utf8' etc.
bindtextdomain($domain, dirname(__FILE__) '/locale'); // returns correct path
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain); // returns 'test'
// this prints the date in Dutch so setlocale works
echo strftime("%A %e %B %Y", mktime(0, 0, 0, 12, 22, 1978));
// this should print the translated version but just prints 'Home'
echo ' ' . gettext('Home');
The Dutch locale is installed according to 'locales -a' and is listed as:
nl_AW
nl_AW.utf8
nl_BE.utf8
nl_NL.utf8
This is the .po file:
msgid ""
msgstr ""
"Language: nl\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Type: text/plain; charset=UTF-8\n"
msgid "Home"
msgstr "Thuis"
And it's correctly compiled to a .mo file, msgunfmt gives no errors at least. I've tried to put this file into locale/nl/LC_MESSAGES/, locale/nl_NL/LC_MESSAGES/ and locale/nl_NL.utf8/LC_MESSAGES/. To no avail.
I'm mainly looking for a way to debug this. This whole trial and error approach is getting a bit time consuming.

I found the solution, but no clue WHY I had to do this. For both cli and apache I managed to get translations working. This is what I did.
putenv('LANGUAGE=nl_NL');
Using LANGUAGE together with LC_ALL in putenv also breaks the translation for Apache, so do not use:
putenv('LC_ALL=nl_NL');

Related

Unable to use gettext to retrieve the translated string in .mo files

I'm trying to setup a clean environment to test php's gettext with. I forked from one of the example and started there, but failed to get it work:
https://github.com/yookoala/gettext-example
(If needed, please clone the source code and test yourself)
The main portion of the PHP script:
<?php
// set locale to either first argument or the $_GET['locale']
$localeToSet = $argv[1] ?? $_GET['locale'] ?? 'zh_HK.utf8';
if (($locale = setlocale(LC_ALL, [
$localeToSet,
"$localeToSet.utf8",
"$localeToSet.utf-8",
"$localeToSet.UTF8",
"$localeToSet.UTF-8",
])) === false) {
throw new Exception($localeToSet . ' is not supported in this system');
}
bindtextdomain('messages', 'locale');
textdomain('messages');
printf("locale: %s - \n", $locale);
printf(_("Hello, %s, it is nice to see you today.\n"), "Vic");
The locale/zh_HK/LC_MESSAGES/messages.po file:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Codegroove.net
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL#ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr "Project-Id-Version: Codegroove.net Example Translations 0.0.1\n"
"Report-Msgid-Bugs-To: vmc#codegroove.net\n"
"POT-Creation-Date: 2010-05-28 06:18-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL#ADDRESS>\n"
"Language-Team: LANGUAGE <LL#li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#, php-format
msgid "Hello, %s, it is nice to see you today.\n"
msgstr "你好,%s,很高興今日與你會面。\n"
Both the CLI and PHP test server failed to show the translated text (as it is supposed to be). It's just showing the raw message.
Does anybody here have idea what is wrong with my setup? Or how I might trace the problem?
There is also a command-line version of gettext. Try this:
TEXTDOMAIN=messages TEXTDOMAINDIR=locale LC_ALL=zh_HK.UTF-8 gettext 'Hello, %s, it is nice to see you today.
>'
Instead of the newline, you have to hit ENTER and then add the closing quote. The > comes from your shell.
Does that work? Then you know that the problem lies in your code. And if it doesn't work, the problem is in your setup, your local environment. Try to see which directories and files are considered by gettext, for example with strace or so.
Other possible errors:
The translation is retrieved from an mo file, not a po file. Does it exist? Try msgunfmt locale/zh_HK/LC_MESSAGES/messages.mo.
Try to specify an absolute path for the locale directory with bindtextdomain('messages', '/path/to/locale');
Are you using Windows?
What locale is actually used? You didn't post the output of your script.

gettext in php always returns input string

I need to get my php code multilingual. The translations are POEdit.com exports.
Because I want to display single and plurals I have to use gettext (the php array export of POEditor does not support plurals).
My problem:
Gettext does always return the input string (msgid), not the translated text.
My setup:
Windows 7 64-Bit german system locale
EasyPHP Devserver
Apache 2.4.18
PHP 5.6.17 + gettext enabled
Folders and Files:
web root = C:\Users\SM\PhpstormProjects\website
locales = C:\Users\SM\PhpstormProjects\website\src\i18n
polish translation = C:\Users\SM\PhpstormProjects\website\src\i18n\plk\LC_MESSAGES\messages.mo
PHP Code:
define('_LOCALES_DIR', 'C:\Users\SM\PhpstormProjects\website\src\i18n');
$locale = "plk";
$domain = "messages";
$rv['putenv'] = putenv("LC_ALL=" . $locale);
$rv['setlocale'] = setlocale(LC_ALL, $locale);
$rv['bindtextdomain'] = bindtextdomain($domain, _LOCALES_DIR);
$rv['bind_textdomain_codeset'] = bind_textdomain_codeset($domain,"UTF-8");
$rv['textdomain'] = textdomain($domain);
print_r($rv);
echo "pl: " . gettext("Benutzername");
PHP Output:
Array (
[putenv] => 1
[setlocale] => Polish_Poland.1250
[bindtextdomain] => C:\Users\SM\PhpstormProjects\website\src\i18n
[bind_textdomain_codeset] => UTF-8
[textdomain] => messages
)
pl: Benutzername
Expected output: "pl: użytkownik"
The .po file looks like this:
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: POEditor.com\n"
"Project-Id-Version: website\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#:
msgctxt "Usermanagement"
msgid "E-Mail"
msgstr "e-mail"
#:
msgctxt "Usermanagement"
msgid "Passwort"
msgstr "hasło"
#:
msgctxt "Usermanagement"
msgid "Benutzername"
msgstr "użytkownik"
What I tried:
The return value of the setlocale("plk") ist "Polish_Poland.1250" so I tried to rename the "i18n/plk" folder to "i18n/Polish_Poland.1250" without luck.
use Polish_Poland.1250 as input language
Polish is only an example, tried it with different languages
added ".UTF8" and ".UTF-8" to the locale
tried php-gettext
checked the installed locales with the help of this script: https://stackoverflow.com/a/23286243
But always the same result :(
Does one of you have any ideas what am I doing wrong or could trie to get it to work?
UPDATE 2016-07-15 12:45:
One of my mistakes is the missing context, I had to use gettext() like this gettext("Usermanagement\004Benutzername");. Now it loads text from the mo files, but the wrong one. It always loads the mo file located in the "i18n/de_DE" folder. (Remember de_DE is the default language of my Windows installation). Even setlocale returns the entered locale (setlocales way to tell he successfully changed the locale), always de_DE is used. :/
I also tried additionally to set these to environment variables without any luck:
$rv['putenv=LANG'] = putenv('LANG='.$locale);
$rv['putenv=LANGUAGE'] = putenv('LANGUAGE='.$locale);

Gettext example not working on Windows 7 - XAMPP

I have the latest XAMPP (3.2.1) with PHP 5.6.8 and gettext enabled. I'm trying to get gettext() working there using a sample I've found on the internet: https://github.com/leftnode/gettext-example , but it is not working.
Other code I've tried (translation.php):
<?php
session_start();
$textdomain = "messages";
$lang = "de_DE";
echo(putenv("LC_ALL=".$lang)."<br>"); // outputs 1
setlocale(LC_ALL, $lang);
echo(bindtextdomain($textdomain, "locale")."<br>"); // successfully outputs the correct path to locale
textdomain($textdomain);
echo ((function_exists("_") && function_exists("gettext"))?"gettext loaded\n<br>":""); // outputs gettext loaded
$name = "Vic";
printf(_("Hello, %s, it is nice to see you today.\n"), $name); // outputs original english
?>
translation files - compiled with Poedit 1.8.1 (messages.po)
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Codegroove.net
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL#ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Codegroove.net Example Translations 0.0.1\n"
"Report-Msgid-Bugs-To: vmc#codegroove.net\n"
"POT-Creation-Date: 2015-06-01 11:34+0100\n"
"PO-Revision-Date: 2015-06-01 11:38+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.1\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: _\n"
"X-Poedit-Basepath: ..\\..\\..\\\n"
"X-Poedit-SearchPath-0: .\n"
#: translation.php:15
msgid "Hello, %s, it is nice to see you today.\n"
msgstr "Hallo, %s, es ist schön dich zu sehen heute.\n"
File locations
gettext\translation.php
gettext\locale\de_DE\LC_MESSAGES\messages.po
gettext\locale\de_DE\LC_MESSAGES\messages.mo
What else can I try to make the gettext working?
I've found out that the locale is not set correctly although PHP reports it does. There is a bug in PHP that is causing this: https://bugs.php.net/bug.php?id=66265
As a result gettext always uses system default locale for translations (after creating translations with my system locale it actually works).
Related StackOverflow question: Gettext will always use system default locale
Although the bug is closed and it should somewhat partially work I wasn't able to get it running.
Instead I'm now using PHP solution that reads gettext .po files and that works: php-gettext (https://launchpad.net/php-gettext)
I had the same problem and found the solution by setting the LANG-parameter before starting apache.
I open up a Command-Prompt (as administrator), next:
set LANG=nl_NL
xampp-control
After afull day with nothing working I have found a proper working and simple 5 line workaround which i explain in a different post:
GetText doesn't translate my text properly when using dutch

Translation to hebrew with PHP/Gettext fails

I've searched hours for a solution for this including in the documentation.
trying to use gettext for hebrew translations,
using PHP 5.3.1 and wamp,
it prints out "hello world" and not the Hebrew equivalent
$directory = '/locale';
$domain = 'messages';
$locale ="he_IL";
putenv("LANG=".$locale); //not needed for my tests, but people say it's useful for windows
setlocale( LC_ALL, $locale);
bindtextdomain($domain, $directory);
textdomain($domain);
bind_textdomain_codeset($domain, 'UTF-8');
echo _("hello world");
I use poedit to create the mo/po files, they are located on:
./locale/he_IL/LC_MESSAGES/messages.mo
the php file is at "./"
Why don't I get the hebrew text?
Ok solved,
Had to update to PHP version 5.3.5/5.3.10
and because I'm using windows I had to use this locale "Hebrew_Israel.1255"
instead of "he_IL" (that's how windows calls the hebrew locale anyway).
Of course I had to also rename the folders in the ./locale to "Hebrew_Israel.1255"
Now the system successfully chooses the locale
as pointed out by MarcB, PHP isn't magically going to translate the words into different language for you. but there are several different solutions out there to help you out. you can make use of google translator API to convert the text between different languages for example.
try {
$gt = new Gtranslate;
echo "Translating [Hello World] from English to German => ".$gt->english_to_german("hello world")."<br/>";
echo "Translating [Ciao mondo] Italian to English => ".$gt->it_to_en("Ciao mondo")."<br/>";
} catch (GTranslateException $ge) {
echo $ge->getMessage();
}
you can read more about google translator API here http://code.google.com/p/gtranslate-api-php/
You should check that "he_IL" locale is installed in your system. I don't know how to do it in Windows, but in Linux you can run "locale -a"(http://linux.about.com/library/cmd/blcmdl1_locale.htm) to see all locales installed.

PHP Gettext - No translation

I am trying to use the PHP gettext extension in order to translate some strings. All functions appear to return the correct values but calling gettext()/_() returns the original string only. The PO/MO files seem correct and I believe I have set the directories up correctly. I am running WAMP Server with PHP 5.3.10 on Windows (also tried running 5.3.4 and 5.3.8 because I have the installations).
Firstly, see /new2/www/index.php:
$locale = 'esn'; # returns Spanish_Spain.1252 in var dump
putenv("LC_ALL={$locale}"); // Returns TRUE
setlocale(LC_ALL, $locale); // Returns 'Spanish_Spain.1252'
$domain = 'messages';
bindtextdomain($domain, './locale'); // Returns C:\wamp\www\new2\www\locale
bind_textdomain_codeset($domain, 'UTF-8'); // Returns UTF-8
textdomain($domain); // Returns'messages'
print gettext("In the dashboard"); // Prints the original text, not the translation.
exit;
I have created the following file structure:
www/new2/www/locale/Spanish_Spain.1252/LC_MESSAGES/messages.mo
I have also tried replacing Spanish_Spain.1252 with: es_ES, esn, esp, Spanish, and Spanish_Spain.
The PO file used to generate the MO is like so (only the relevant entry given):
#: C:\wamp\www\new2/www/index.php:76
msgid "In the dashboard"
msgstr "TRANSLATED es_ES DASHBOARD"
This was generated using PoEdit. I have restarted Apache after adding any new .MO file. Also note that I was previously using Zend_Translate with Gettext and it was translating correctly. I wish to rely on the native gettext extension, though, in part because I am attempting to create a lightweight framework of my own.
Any help would be appreciated.
Edit: Amended directory structure. Note - will be able to try recent answers within 24hrs.
I set this up on my XAMPP instance and figure it out.
Flat out setlocale does not work on Windows, so what it returns is irrelevant.
For Windows you set the locale using the standard language/country codes (in this case es_ES is Spanish as spoken in Spain)
Under your locale directory create es_ES/LC_MESSAGES/. This where your messages.mo file lives.
$locale = 'es_ES';
putenv("LC_ALL={$locale}"); // Returns TRUE
$domain = 'messages';
bindtextdomain($domain, './locale');
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain); // Returns'messages'
print gettext("In the dashboard");
exit;
I am not sure if this made a different, but I did two things when creating the po file. In poEdit under File -> Preferences I changed the Line ending format to Windows. And after I created the initial po with poEdit I opened the file in Notepad++ and switched the encoding type to UTF-8 as poEdit did not do this.
I hope this at least points you in the right direction.
References
PHP Localization Tutorial on Windows
Country Codes
Language Codes
Your code mentions this as the return value from bindtextdomain:
C:\wamp\www\new2\www\locale
With the setlocale of Spanish_Spain.1252 and textdomain of messages, calls to gettext will look in this path:
C:\wamp\www\new2\www\locale\Spanish_Spain.1252\LC_MESSAGES\messages.mo
But you created the file structure of:
www/new2/locale/Spanish_Spain.1252/LC_MESSAGES/messages.mo
^^
www/ missing here
Edit
Okay, so that didn't help. I've created a test script on Windows and using POEdit like you:
$locale = "Dutch_Netherlands.1252";
putenv("LC_ALL=$locale"); // 'true'
setlocale(LC_ALL, $locale); // 'Dutch_Netherlands.1252'
bindtextdomain("messages", "./locale"); // 'D:\work\so\l10n\locale'
textdomain("messages"); // 'messages'
echo _("Hello world"); // 'Hallo wereld'
My folder structure is like this:
D:\work\so\l10n\
\locale\Dutch_Netherlands.1252\LC_MESSAGES\messages.mo
\locale\Dutch_Netherlands.1252\LC_MESSAGES\messages.po
\test.php
Hope it helps, although it looks almost identical to yours. A few things I found online:
It's important to set the character set in .po file
Spaces inside the localization file might have a UTF8 alternative, so be wary of key lookups failing. Probably the best thing to test first is keys without spaces at all.
A suggestion: you may need the full locale for the .mo file. This is probably Spanish_Spain.UTF8 or esn_esn.UTF8 or esn_esp.UTF8 (not 1252, as you change the code base).
To track what directory it's looking for, you can install Process monitor (http://technet.microsoft.com/en-us/sysinternals/bb896645). It spews out bucket loads on info, but you should be able to find out which file/directory is being looked for.
(My other thought is to check file permissions - but if you already had something similar in Zend_Translate, then probably not the cause, but worth checking anyway).
Sorry if not good - but might give you a clue.
Look here. It works for me on windows and on linux also. The last values in the array works for windows. List of languages names can be found here. My catalogs are in
./locales/en/LC_MESSAGES/domain.mo
/cs/LC_MESSAGES/domain.mo
I have never tried using gettext on Windows, but each time I had problems with gettext on linux systems, the reason was that an appropriate language pack was not installed.
Problem can be also that when you change your *.po and *.mo files, you have to restart the Apache Server. This can be problem, so you can use workaround - always rename these files to some new name and they will be reloaded.

Categories