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
Related
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.
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);
I'm trying to add translations to my webpage.
Unfortunately my translation isn't being read.
However, one translation is read (even though I ask for a different one).
My php code looks like this:
$language = "en_US"; //Hardcoded for debugging purposes
define("FOLDER_SPECIFICATION", "./locale/");
define("DOMAIN", "messages");
define("CODE_SET", "UTF-8");
putenv("LANG=" . $language);
setlocale(LC_ALL, $language);
bindtextdomain(DOMAIN, FOLDER_SPECIFICATION);
bind_textdomain_codeset(DOMAIN, CODE_SET);
textdomain(DOMAIN);
My folder structure looks like this:
root >
locale >
en_US >
LC_MESSAGES >
messages.mo
messages.po
nl_NL >
LC_MESSAGES >
messages.mo
messages.po
If I change the $language variable to en_US or nl_NL it still grabs the translation from nl_NL, if I remove the nl_NL folder it doesnt translate at all, this together means one thing: The en_US translation isn't being read.
Both messages.po contain headers and such and both are valid (I loaded them in poedit).
My question is: Why does it grab nl_NL even though I never told the code to grab it, and why isn't the other translation (en_US) being read?
Both .po files look like this (the 'Language' tag in the headers are obviously different):
msgid ""
msgstr ""
"Project-Id-Version: My Project\n"
"POT-Creation-Date: 2014-08-05 13:32+0100\n"
"PO-Revision-Date: 2016-04-19 10:43+0200\n"
"Last-Translator: \n"
"Language-Team: someone <s.omeone#something.com> \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.7\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: nl_UL\n"
"X-Poedit-SourceCharset: UTF-8\n"
msgid "Banaan"
msgstr "Banana"
msgid "Appel"
msgstr "Apple"
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');
I've always heard about gettext - I know it's some sort of unix command to lookup a translation based on the string argument provided, and then produces a .pot file but can someone explain to me in layman's terms how this is taken care of in a web framework?
I might get around to looking at how some established framework has done it, but a layman's explanation would help because it just might help clear the picture a bit more before I actually delve into things to provide my own solution.
The gettext system echoes strings from a set of binary files that are created from source text files containing the translations in different languages for the same sentence.
The lookup key is the sentence in a "base" language.
in your source code you will have something like
echo _("Hello, world!");
for each language you will have a corresponding text file with the key and the translated version (note the %s that can be used with printf functions)
french
msgid "Hello, world!"
msgstr "Salut, monde!"
msgid "My name is %s"
msgstr "Mon nom est %s"
italian
msgid "Hello, world!"
msgstr "Ciao, mondo!"
msgid "My name is %s"
msgstr "Il mio nome è %s"
These are the main steps you need to go through for creating your localizations
all your text output must use gettext functions (gettext(), ngettext(), _())
use xgettext (*nix) to parse your php files and create the base .po text file
use poedit to add translation texts to the .po files
use msgfmt (*nix) to create the binary .mo file from the .po file
put the .mo files in a directory structure like
locale/de_DE/LC_MESSAGES/myPHPApp.mo
locale/en_EN/LC_MESSAGES/myPHPApp.mo
locale/it_IT/LC_MESSAGES/myPHPApp.mo
then you php script must set the locale that need to be used
The example from the php manual is very clear for that part
<?php
// Set language to German
setlocale(LC_ALL, 'de_DE');
// Specify location of translation tables
bindtextdomain("myPHPApp", "./locale");
// Choose domain
textdomain("myPHPApp");
// Translation is looking for in ./locale/de_DE/LC_MESSAGES/myPHPApp.mo now
// Print a test message
echo gettext("Welcome to My PHP Application");
// Or use the alias _() for gettext()
echo _("Have a nice day");
?>
Always from the php manual look here for a good tutorial