PHP gettext() - putenv and setlocale - php

I see most of the examples are using something like:
putenv('LC_ALL=de_DE');
setlocale(LC_ALL, 'de_DE');
bindtextdomain("myPHPApp", "./locale");
echo gettext("Welcome to My PHP Application");
If I only want to get message translation done, I've tried that only putenv is needed, and I don't need to the functions provided by setlocale such as time, MONETARY etc.
So, it is safe to ignore the setlocale?

No it is required.
You can of course do setlocale(LC_ALL, ''); as other answer is suggesting but this will just make it fall back to environmental variable set by putenv a line above.
What can be in fact removed is putenv call. At least for me the following snippet is still returning German translation:
putenv('LC_ALL=en_US');
setlocale(LC_ALL, 'de_DE');
bindtextdomain("myPHPApp", "./locale");
echo gettext("Welcome to My PHP Application");
Another good thing you can use setlocale for is checking if given locale is actually installed in the system. E.g.:
if (false === setlocale(LC_ALL, $localeCode)) {
throw new LocaleNotSupportedException(sprintf('Locale "%s" is not installed in the system.', $localeCode));
}
echo gettext("Welcome to My PHP Application");
And also there's no need go set locale before binding a domain. You can also do it anytime after.

It seems you would be safe in not including it.
If locale is NULL or the empty string "", the locale names will be set
from the values of environment variables with the same names as the
above categories, or from "LANG".
Info: http://us2.php.net//manual/en/function.setlocale.php

Related

PHP Gettext: temporary language switch?

Is it possible to temporary switch a language with the php gettext module? I would like to change the language since an e-mail should be generated in two language for two different receivers.
You need to set the LC_* variable(s). Like this:
putenv('LC_ALL=de_DE');
setlocale(LC_ALL, 'de_DE');
renderEmail();
putenv('LC_ALL=en_US');
setlocale(LC_ALL, 'en_US');
renderEmail();

Convert en_US to to en-US

I'm writing a PHP application that supports multiple languages.
When setting the locale in PHP, I am required to provide a value defined in, what I believe to be, RFC 1766 / ISO 639, according to the setlocale documentation.
setlocale( LC_ALL, 'en_US' );
var_dump( setlocale( LC_MESSAGES, '0' ) );
// string(5) "en_US"
When using this locale to describe the HTML lang attribute, validation fails because it is not formatted to RFC 5646. The RFC 5646 value for this language is actually en-US (note the use of a hyphen instead of an underscore).
Using this value in PHP's setlocale function, as above, results in the following output:
string(1) "C"
I have no idea why it is returning a value of C, but I presume it is because the locale provided was incorrectly formatted. C being the original server default, which is described as ASCII (thanks to #Cheery for the reference).
So, I'm wondering what I should do about that. I could, feasibly, use PHP's str_replace function to switch - to _ before outputting the lang attribute, like so:
<?php setlocale( 'en_US' ); ?>
<!doctype html>
<html lang="<?= str_replace( '_', '-', setlocale(LC_MESSAGES, '0') ); ?>">
...
But, I'm concerned that there may be other differences between the two language specifications that could yield an unexpected problem down the road. If so, is there a preferred way to translate the language codes already in PHP, or a translation class that can be used?
Bonus question, why does my server default to value of C for the locale?
You need to have in mind that setLocal accept many types of "locale" names like names and mixed things, for example in (from php documentation):
$loc_de = setlocale(LC_ALL, 'de_DE#euro', 'de_DE', 'de', 'ge');
You have 'de_DE#euro' which isn't a valid HTML lang code.
So first, you need to ensure that is in the format lang_region before trying to convert it.
You can set local language codes using "setlocale".
You can find here it's documentation as well as this and other examples
Example where they try different possible locale names for german:
<?php
/* Set locale to Dutch */
setlocale(LC_ALL, 'nld_nld');
/* Output: vrijdag 22 december 1978 */
echo strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978));
/* try different possible locale names for german as of PHP 4.3.0 */
$loc_de = setlocale(LC_ALL, 'de_DE#euro', 'de_DE', 'deu_deu');
echo "Preferred locale for german on this system is '$loc_de'";
?>

Setlocale returns false (WAMP)

I have working localization in my project. Working means that my project gets translated to whatever language I have in the locale/sk folder, sk for slovak being my default system language.
Setting to any other language doesn't work. I have tried $lang = 'cs', 'cz', 'en', 'en_UK', 'en_UK.utf8' and others. Still, only the translation in the 'sk' folder is taken and still the setlocale() function returns false. I have tried to change default language in browser - no effect.
This is my code:
putenv("LANG=$lang");
setlocale(LC_ALL, $lang);
bindtextdomain("messages", realpath("../localem"));
textdomain("messages");
...
_("Welcome!")
I have also tried these:
putenv("LANGUAGE=$lang");
putenv('LC_ALL=$lang');
Any suggestions are welcome.
Edit:
$loc = array('nor');
if (setlocale(LC_ALL, $loc)==false) print ' false'; else print setlocale(LC_ALL, $loc);
'nor' prints Norwegian (Bokmĺl)_Norway.1252, 'rus' russian, but 'svk' prints false and so does 'cze'.
On the list all of these are mentioned:
http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.80%29.aspx
Windows uses another format for the locale setting, see MSDN: List of Country/Region Strings.
You can send a list of locales to setlocale by sending in an array, such as to get Norwegian month names and time formats:
setlocale(LC_TIME, array('nb_NO.UTF-8', 'no_NO.UTF-8', 'nor'));
Windows might however return strings in another encoding than UTF-8, so you might want to handle this manually (converting from cpXXXX to UTF-8).

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