Fonctions Gettext

Sommaire

add a note add a note

User Contributed Notes 44 notes

up
16
jeremy at jeremy dot se dot nospam
10 years ago
As some of you have mentioned, you must have the locales compiled on your system first. How this is done is depending on your system/distribution *sigh*

In every case you need to have gettext installed on your system. Users running a Linux with a recent version of libc will have gettext in libc already.

Here's an example for those of you running Ubuntu Edgy.

First of all, have a look in /usr/share/i18n/SUPPORTED, here are the locales that are supported on your system. To compile a locale we will use the command "locale-gen". ("man 8 locale-gen" is good reading)

This command reads configuration from files in the folder /var/lib/locales/supported.d/ In these files the locales and charsets are defined.

If we take swedish as an example, start by creating a file called "sv" in /var/lib/locales/supported.d/ and then put in something like "sv_SE.UTF8 UTF8" (without the " ") This says that we want the locale sv_SE to be built with charmap UTF-8. Check the file /usr/share/i18n/SUPPORTED for other alternatives.

Now we run "locale-gen" which will compile all locales defined in /var/lib/locales/supported.d/ and put them in /usr/lib/locales (yes that's a lot of locations...)

Now you're ready to go...

Create a php-file (e.g. hello.php) where all strings you want to translate are surrounded with _("string here");

next run "xgettext hello.php", this creates a file called messages.po, which is you translation-file (pot). Change the "Content-Type: text/plain; charset=CHARSET\n" in this file and replace CHARSET with UTF-8 in this case. Next translate all strings like this.

#: hello.php:3
msgid "hello!"
msgstr "hej!"

Save and use the command "msgfmt -o hello.mo messages.po" which will create a compiled .mo file called hello.mo

This file is then placed in a directory structure somewhere your Apache can read it. The structure looks like this:

"locale/sv/LC_MESSAGES/hello.mo"

Next, let php know what we're doing. We point to where we have our translations. Add the following at the top of hello.php

bindtextdomain('hello','/somepath/locale');

This binds the file hello.mo to the locale/ directory you created.
Then set the locale. LC_ALL tells that we want everything translated. Might not be good at all times, as another person here suggested.

setlocale(LC_ALL, "sv_SE.UTF-8");

Finally select the that we want to use hello.mo

textdomain('hello');

That should be it! Try it out..

If you get any problems try restarting Apache as it seems to cache the locales.

If you are running command line you might have to set the environment variable LANGUAGE to your locale as well. I didn't have to do that to get it working in apache though, but you might...

putenv("LANGUAGE=sv_SE.UTF-8");
up
4
C Snover
11 years ago
I think that it bears mentioning that most documentation and tutorials you will find say that you should setenv(LC_ALL, $locale), but this only works IF THE LOCALE IS VALID ON THE LOCAL MACHINE. If you are using a locale that does not exist on the system or is not valid (like something returned from the HTTP Accept-Language header, such as 'ja', which is never a valid locale because it does not include the country code JP), you will probably be pulling your hair out for HOURS trying to figure out why the damn thing isn't working.

What I have found is that setting the LANGUAGE variable (eg. setenv("LANGUAGE=$locale")) will allow gettext to search inside your locale directories, even if the locale is not actually valid on the local system.

So, to summarize:

This will work:
<?php
$locale
= 'ja'; // Pretend this came from the Accept-Language header
$locale_dir = './locale'; // your .po and .mo files should be at $locale_dir/$locale/LC_MESSAGES/messages.{po,mo}

putenv("LANGUAGE=$locale");
bindtextdomain('messages', $locale_dir);
textdomain('messages');
?>

This will not work:
<?php
$locale
= 'ja';
$locale_dir = './locale';

putenv("LC_ALL=$locale");
bindtextdomain('messages', $locale_dir);
textdomain('messages');
?>

This will also not work:
<?php
$locale
= 'ja';
$locale_dir = './locale';

setlocale(LC_ALL, $locale);
bindtextdomain('messages', $locale_dir);
textdomain('messages');
?>

Nor will this work:
<?php
$locale
= 'ja';
$locale_dir = './locale';

setlocale(LC_MESSAGES, $locale);
bindtextdomain('messages', $locale_dir);
textdomain('messages');
?>

For reference, this was tested on PHP 5.1.2 + LigHTTPd 1.4.11 + gettext 0.14.5 on Ubuntu Dapper 6.06. It should be true for any variant of Linux, however, as well as older versions of these software packages.
up
1
Sbastien Ballest-Antich
9 years ago
A workaround to use heredoc and gettext strings with sprintf :
<?php
$hd
= <<<EOD
   <p>%s</p>
   <p>%s</p>
EOD;
$hdgt = sprintf($hd, _('Heredoc'), _('gettext'));
var_dump($hdgt);
?>
up
1
SEWilco
10 years ago
People have suggested several combinations of configuration options.  Consider trying nested loops with various combinations of language names (with and without character set suffixes) and pathnames.  A gettext() call in the middle of the loops can test for success (a string being translated).

"Of 4374 localization setup variations tested there were 0 successes."

Sometimes one just has to fix the system and PHP configuration.
up
2
kocio at irc dot pl
13 years ago
Following three lines take about 0.5 second to execute (Debian, Celeron 2GHz, 256MB RAM):

setlocale(LC_ALL, 'pl_PL');
bindtextdomain('my_domain', '../dir/' . 'locale');
textdomain('my_domain');

I think that such delay is important enough to be mentioned in the documentation. In my particular case, it means more than doubled execution time for the entire script.
up
1
analpaper{gmail}
9 years ago
in response to richard:
i was using the wildcard * for sometime ago without problem, until today.

i used:
<?php bindtextdomain( '*', './locale' ); ?>
but it seems to fail under some environments (i dont know why, but in diff machines with same software the result is not always as expected)..

then, with:
<?php bindtextdomain( "*", './locale' ); ?>
all is nicely translated again.

i use single quotes always if possible, now there are another think to remember.
---
live2code
up
1
jon at nospam dot foo
10 years ago
I'm sure I'll confuse further, but I feel compelled to chime in.  I got stuck on this a bit...

It's absolutely critical that your gettext installation supports the locale you are trying to use in your setlocale(LC_MESSAGES,$locale) call.

This does not work:

setlocale(LC_MESSAGES,"en");

in OpenSUSE 10.2, because /usr/lib/locale does not contain the directory "en" (out of the box), even though your custom LC_MESSAGES domain location might.

In OpenSUSE 10.2, at least, /usr/lib/locale contains for USA English:

en_US
en_US.iso885915
en_US.utf8

(again, not "en").

It might be possible to set up an alias, I'm not sure (does anyone have a idea about this).

My goal was to use HTTP_ACCEPT_LANGUAGE to set locale (I realize that locale != language, but it seems that gettext uses locale to assign language (scratches head) ).  Opera in OS X does not send "en_US".  However, Firefox does out of the box.  I'm not sure if it's supposed to work this way, but it seems like it should, and so the way Opera handles this appears to be an issue.  Incidentally, Safari simples send "en" in HTTP_ACCEPT_LANGUAGE, and will also not work.

This compelled me to set a configurable default locale (e.g "en_US") in my PHP app, which one probably should do anyway, because HTTP_ACCEPT_LANGUAGE might be blank.
up
1
djogopatrao at gmail dot com
11 years ago
Juan Liska, I found an alternative. Instead of renaming or adding a alias to the locale, I simply changed

$language = 'pt_BR';

to

$language = 'pt_BR.UTF-8';
putenv("LANG=$language");
setlocale(LC_ALL, $language)

and it did work fine!
up
1
konrads/smelkovs/gmail/com
11 years ago
re LC_MESSAGES for windows users, LC_MESSAGES should be defi0ned as 5
up
1
richard at hirner dot at
11 years ago
the * wildcard doesn't work for me (php 5)... I have to use bindtextdomain for each textdomain
up
1
webmaster [at] ttw [dash] tool [dot] de
11 years ago
If you want to use messages from multiple domains with .mo-files residing in non-standard locations remember to place a bindtextdomain()-call for each domain as "unbound" domains will be looked for in the standard location (usually "/usr/share/locale" on *nix)

<?php

    bindtextdomain
('foo','/some/dir/with/mo_files');
   
bindtextdomain('bar','/another/mo_file/dir');

    echo
dgettext('foo','Text to be translated using the foo-catalog.');
    echo
dgettext('bar','Text from a different catalog named bar.');

?>

If all the .mo-files you are using reside in one and the same directory, you may use the "*"-wildcard like this:

<?php

    bindtextdomain
('*','/directory/with/all/mo_files');

?>

This code was tested on PHP 5.1.4
up
1
info at adaniels dot nl
11 years ago
As stated by robert at klugher dot com:
The environment setting 'LANGUAGE' gets priority above any local setting. This means that changing LC_ALL/LC_MESSAGES and LANG as done in almost all examples, won't do anything.

So if you've done
<?php   
    $language
= "nl_NL";
   
putenv("LANG=$language");
   
setlocale(LC_ALL, $language);
    ...
?>
but the text is still displayed in english. Try also setting the LANGUAGE variable.
<?php   
    $language
= "nl_NL";
   
putenv("LANGUAGE=$language");
   
putenv("LANG=$language");
   
setlocale(LC_ALL, $language);
    ...
?>
up
1
birkholz at web dot de
11 years ago
> stefan+usenet at froehlich dot priv dot at wrote at 5-May-2004 01:30:
> Reading the line
>
> <? php setlocale(LC_ALL, 'de_DE'); ?>
>
> here over and over again, I have to warn using it, as there are severe caveats.
> For certain locales, LC_NUMERIC swaps period and comma, which may e.g. lead to
> decimals silently stripped of numbers, when inserting rows into an SQL database.
>So DON'T do this, but use
>
> <? php setlocale(LC_MESSAGES, 'de_DE'); ?>
>
> instead, which does exactly what you want, without any nasty side effecs.

For all Windows-Users:
Be warned the LC_MESSAGES seems to be NOT set on Windows with PHP 5.1.2, so if you develope applications for a Linux-System and want to make it multi-language using gettext, you will get problems using LC_MESSAGES on your Windows-Developement-Box.
You can try to solve this problem by putting a

<?php if (!defined('LC_MESSAGES')) define('LC_MESSAGES', 6); ?>

to your script to get no warning if you pass LC_MESSAGES to the setlocale()-function.
up
1
Juan Liska
12 years ago
if you're having trouble with setlocale (if it's returning false) on ubuntu or debian:

nano /etc/locale.gen

make sure that the locales taht you want are in the list, if not, add them. for instance, i wanted es_GT (b/c i have an app that must run on redhat and debian, i cant change to es_GT.UTF-8) so, add:

es_GT UTF-8

then run:

locale-gen

you now have the locales you want, not just the ones the system magically came with
up
1
milky#users:sf/net
12 years ago
There exists an emulation for the gettext functions - obviously slower than the native binding, but can be used on shared servers which lack the extension. It is believed to be rather useful as fallback (comes already encapsulated with if-function_exists checks).
See the exte/ directoryin the [n issgetm>
So if you've done
">r />allaowing at th/>What
up
1
milky#users:sf/net&gc204 01hus="genanchor" href="#53693"> ¶
12 ye ye8ago
If you want to use messages fropports theaowing at t/>setlocale(LC.UTF8afe mf y, but caby putteLOCALE o if yos=".inibr />
up
1
milky#users:sf/netpco-s="genanchor" href="#53693"> ¶
12 ye4-27ago
People have suggested seveHP-orts the sr a Linuxfallbacka'm not oks lorts theMOle_dir/tm>---a>s ">r />s
up
<0 href="#53693" class="name"> milky#users:sf/net
116years4 11:2trong>
People have suggested sevGrts thebr />me witre the oks a'm n*ocale_dirg LC_ALLakeocaleprrtsyencstd ser varintio, I'm not , add:

>twMESSys witn usd wit-Languacu've />

yo1. Rems tohould webtensio.NUMERng.
Tf-funcmight haeywo/>snot okms toig webtensio (fMERng.
at does not exis the exhost)sing Lvero, add:ng.
-Lang above=doma ihis douage");$m unti= 0uage");$aowing at tDiro= = />

d
up
1
milky#users:sf/net
13 ye6rs ag2:4strong>
If you want to use messages orts the>setlocale(LC.heckseven if the, ie 'zh_CN', magicgoale(LC_te2hally va.
ng.
up
1
milky#users:sf/net
133ears 6ago<>
If you want to use messagC/ diEeven class="defau/>make sures.mply ewant t" the LA en_GB.ISO- /><-1" (ation. In bepand) class="defaumake sures.ave pan>nn_GB.ISO- /><-15 ISO- /><-15 ossible to sesed to work thion>
nnaby ting o be N/>
nnaby spanmad >
up
1
milky#users:sf/net- cogrep-a clbss="genanchor" href="#63718"> ¶
133earsv> 12:2trong>
4
If you want to use messagOsud urubleaowing at t/is/on> beES to the serovr al jusnet'eaowing at t/ not sure i camees t on revailefault">< to se0:
&gahe>setlmagicalahe--calepme wit'Accept-La will 'g>'et be/1.1OS X into ou maellones thdo anyway jusnet ">r />< to sNbr /alaheC_MESally vanet&g jusnetliveis mannls witn
-
milky#users:sf/net
133ea7rs4 01:1
milky#users:sf/net
133ea6-17ago
133ea6-13ago<41coong>
There exists an emulation foppear...
re it socalebsp; Ildt jusX11/>
up
milky#users:sf/net
133ea6-08 10:4
There exists an emulationNbr /ao Cthe r N/>ne
rdiv>
up
milky#users:sf/netThe environment ses="genanchor" href="#74741"> ¶
133ea2rs ag5:>
If you want to use messagOn iaoielinstead offter
yoan SQypromighuallyn> ,g Seec stanmighuomd locpan>The saowing at t/>
br />in Opeed me to set Eg.
br />
yoI atiable.
call e>re iaowing at t/>


Sre iaowing at t/>
up
milky#users:sf/net
133ea2r05 10:3trong>
4
There exists an emulation for t's abbr / tur /ial/>132/06/13/ wh.ulatit cl claello.p"> ">r />132/06/13/ wh.ulatle="2div>
up
milky#users:sf/net
133ea1-29ago<>
There exists an emulationF- obvt it suninlmagicaocale(LC_g locahf you ms lt haedGUevenserovr ar 5)... I re tryibblems using Lvers yetlocre iinb/>n at tat ctuff>&gs="default"><br />Seec_($s=") {uage
up
milky#users:sf/net- coenlu>-a claass="genanchor" href="#53693"> ¶
133ea1-16 08:20coong>
milky#users:sf/net
132ea6-s ag6
If you want to use messages fro (b/c tanf .moSuSE De e. fro aaed glibc- falselrpmu omdebrorts thehave. o set o set mfg ralphisdiv>
up
milky#users:sf/net
132ea6-ng t7:47trong>
If you want to use messages froetlo beclueywsives I am, pntai/ toghuallello.pd L:r />yo1. AlSAGES ddo anu tot in or itge)
ulnrng.
ngcept fro aaed o hinesthat nsi "n"'s>atieveded oosualishn>
up
<0 href="#53693" class="name"> milky#users:sf/net
138-33ea7 11:2
If you want to use messages fro wGEldt
t ,ndotlya .p />
< to se0:tage uscatalog.'hy naslnrfor t(g bef.ge)ine
= yo{lt">$language(('LC_MESSAGES');

'LC_MESSAGES');

);

>
> instead, whs="/If y your scrip set Yg L stann for each ievedxorts the(gnu uatlng.)u deveged PySAGneprt><-ns wil=g bei--span>
and it did wo class="defau$orts thl/>
andr /lt;/If y your scrip set Tg rThis mtinm wanud to

nm wanud to-ilng./s)d3"usernotes-voteu">up
s)d3"usdiv class="tally" id="V42109" title="10s)d3"php?id=53693&page=ref.gettex12015 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down <0 href="#53693" class="name"> milky#users:sf/net138-33pand/-1:2
If you want to u1 trouble5:4wit-ipith .m6div>t ,ndotlya .p />
3693&a,t...&ded oosualEX11r />o LAntwif (!nyway jusnethreflks). ks les_ES,mo}
f="/man22052 'de_DE'22052 Hbe/mo="keyword">);
   
B64 as douage");
ht haedh );
   
tion de"v> s wil"o n clpand douage"s="sup!.pco/purt);
    yo.
e tmy>s wil'="20s/>yote.dosy22052 rt(<:rrayh(y22052 ref="/span class="default">$langus="defau'en'setlocale()-function. =pword">);

$langus="defau'fr'setlocale()-function. =pword">);

$langus="defau'it'setlocale()-function. =pword">);

i22052 ref="/lass="default">$langus="defau'pt'setlocale()-function. =pword">);

$langus="defau'eo'setlocale()-function. =pword">);

$langus="defau'nl'setlocale()-function. =pword">);

do's22052 rt<. rta / nguage(span>rt<. < {i22052 ref="/span class="default">$langution de"v# s wil"o l';cUAGE envi .pn deoteri/projs wil'22052 ref="/span class="default">$langu/divsoineasy>s ="keyword">);
   
);
  &nb. nguage
tion de"v# P"denote.L>e tmy>s wil'="20i7031greead o 22052 #LFilorts th_greead o thrwer threhaedhf="/man22052 rt);
    );
   
<) =ref. exactly what you want, witho"\ Isetlocale()-function. 66f="/man22052 }y22052 rt);> decis lbhresics e
s550"usdiv class="tally" id="V42109" title="10s550"php?id=53693&page=ref.gettex12015 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down <0 href="#53693" class="name"> milky#users:sf/net
138-33 ta
If you want to u1 09messa3:52it-ipith .m6div>t ,ndotlya .p />
3693&a,t...s wil]iv class="not[}
&lny err"defa classi "n"uruonmensimply/manitinbr / (N ipd">);d.6f="/man22052 SISO-d,"="dem hines( sou wa="7031= >m>sen clpand capar d]>ba"703 with />put / es_ES,mo}
p"d>);< useful the [n it...2whea>
<-div class="f="/man22052 t() = >d="70retlo class=f="/man22052 o class="defa "n"u// SeLOCAd puten'es_ES'uage");
setlocale(LC22052 ranguage)
s wil'r /it' f="/manasy>s wil';class= each do6f="/mans"sns wil", ".r /><22052 ecetti="defaul// .r 22052 es_ES,mo}


itiv class="note" id="4210f="/man22052 ass="vote2261
5141"usdiv class="tally" id="V42109" title="105141"hp?id=53693&page=ref.gettext229 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down
141"usdiv class="tally" id="V42109" title="105141"hp?id=53693&page=ref.gettex
milky#users:sf/net 138-33elita11:2
People have sugges3-30sage5oppear...n at tates(at tdiv> iz> l10SAGEe>'eaowa GPL'd your scrlnceetool:h/>132/06/13/ wh.iki.fi/elita1ge) 5042"usdiv class="tally" id="V42109" title="105042"hp?id=53693&page=ref.gettext229 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down
042"usdiv class="tally" id="V42109" title="105042"hp?id=53693&page=ref.gettex
milky#users:sf/net 138-33de) 032"usdiv class="tally" id="V42109" title="105032"hp?id=53693&page=ref.gettex
milky#users:sf/net 138-33susk 1:2 4312"usdiv class="tally" id="V42109" title="104312"hp?id=53693&page=ref.gettexs316 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down
2"usdiv class="tally" id="V42109" title="104312"hp?id=53693&page=ref.gettex
milky#users:sf/net 138-33mikolaj1:2 tion de"v> vote2919 yo\ht )..\my=536\ stan\bgr_BGR\v class="no\mv class2109"> $langu/divsoineasy>s ="keyword">);
   
rt);
   
);
   
up
421="usdiv class="tally" id="V42109" title="10421="hp?id=53693&page=ref.gettexs316 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down
21="usdiv class="tally" id="V42109" title="10421="hp?id=53693&page=ref.gettex
milky#users:sf/net 138-33stdivn+ongne
If you want to use5latia4:30obvt it suntlocale(LC.heckseven if the, ie 'zh_CN', magicgoale(LC_t21="usda will g 'de_DE'6);
   
', ".r
> instead, which does exactly what you want, witho'ht...'setlocale()-function.
/divsoine
s slt;?t" it, wppeto drnumb 'de_DE'6);
    ', "lass="no
> instead, which does exactly what you want, witho'ht...'setlocale()-function.
/divsoine
t"lny nast itthateffecsp?id=53693&page=ref.gettex8164 ;vote=up" title="Vote up!" clyn> "usernotes-voteu">up
"usdiv class="tally" id="V42109" title="10 "hp?id=53693&page=ref.gettex2979 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down
"usdiv class="tally" id="V42109" title="10 "hp?id=53693&page=ref.gettex
milky#users:sf/netT9uv> T9uv" title="2005-06-09 06:12">138-33ag5:> <851"usdiv class="tally" id="V42109" title="10<851"hp?id=53693&page=ref.gettex28542;vote=up" title="Vote up!" clasclass="usernotes-voted">down
1"usdiv class="tally" id="V42109" title="10<851"hp?id=53693&page=ref.gettex
milky#users:sf/net 138-33yledo...2aonfrero milky#users:sf/net 138-33ywlieb>tsign hotmgRHmdiv class="text" id="Hcom42109"> 1397"usdiv class="tally" id="V42109" title="101397"php?id=53693&page=ref.gettex12015 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down <0 href="#53693" class="name"> milky#users:sf/net 138-33Anonymous class="text" id="Hcom42109"> 1394"usdiv class="tally" id="V42109" title="101394"hp?id=53693&page=ref.gettex2979 ;vote=up" title="Vote up!" clasclass="usernotes-voted">down <0 href="#53693" class="name"> milky#users:sf/net 138-33Anonymous class="text" id="Hcom42109">
There exists an1 07-11le5:4wit-ipith .m6div>t ,ndotlya .p />
3693&a,t...ngcam>t">< the [n i)"f="/man22052 soa fufocpe/1.1agcam> lgiv class="n'> lgiv class="n' cdiv> ');22052 es_ET226Divei c'err"dMsg','/glt,al/div> ' );22052 t226Divei c'myPlas');22052 p"denuageT2261'Welc.n ')u6f="/manll g/f="/manif($err)p"denf(dGgeT2261'err"dMsg','focpe/1.1)e vrr"deh-se')u6f="/man22052 Ivanh l)ywo= ge)


lass="tally" id="add09" title=sect93&page=ref.greOCAd <=
limshurc='/imlass/ 6-0m>addu/ i .php?i nanchols ihac>