PHP setlocale has no effect

PhpDateSetlocale

Php Problem Overview


The setlocale() function doesn't set the desired language (German).


The goal is to output month names.

This is my test code with trials so far:

<?php

date_default_timezone_set('Europe/Berlin');
setlocale(LC_ALL, 'de_DE.utf8');
// Or
setlocale(LC_ALL, 'de_DE@euro');
// Or
setlocale(LC_ALL, 'de_DE');
// Or
setlocale(LC_ALL, 'de');
// Or
setlocale(LC_ALL, 'ge');


echo strftime('%B');

Output:

> June

instead of

> Juni

Any suggestions?

  • I don't have ssh or other shell access.
  • The script is running on a linux server.

PHP version 5.6

Php Solutions


Solution 1 - Php

Is is quite likely that the German locale is not installed on the server your running the script on - do you have shell access to the server? Then try

locale -a

to see which locales are installed. Also have a look here https://stackoverflow.com/questions/1941956

Solution 2 - Php

For those coming here looking for date() doesn't localize month and weekday names:

== Pay Attention ==

date() is only able to return month/day names in English and won't be able to give you translations for other languages.

Use strftime() instead!

Solution 3 - Php

Your code is correct. You probably just have to install the correct language package on the server you are running the script on.

In the terminal, if the language you want to use is not listed after running the command sudo locale -a, then you'll have to install the missing language by running the following command :

sudo /usr/share/locales/install-language-pack de_DE 

(sudo here is optional if your user has root permissions)

Then if you double check with sudo locale -a you should see de_DE.utf8.

If you want to install french language package run

sudo /usr/share/locales/install-language-pack fr_FR

Then you'll be allowed to set your language to these in PHP by using setlocale(...) exactly like you did it.


Note: If you are in a non utf8 project you'll need to generate other formats from installed packages. Here is how to proceed on ubuntu (this work on debian as well) :

edit /var/lib/locales/supported.d/cs and add the following lines

  fr_FR.iso88591 ISO-8859-1
  fr_CA.iso88591 ISI-8859-1

and run

 sudo dpkg-reconfigure locales

Then by running again sudo locale -a you should see both fr_FR.iso88591 and fr_CA.iso88591 in the list and you can use it in php by calling setlocale(LC_ALL, 'fr_FR.iso88591');

Solution 4 - Php

This solution might help if you don't have shell access to the server.

If you have shell access, then Benjamin Seiller's answer is the best!

As I don't have any other possibilities (shell), I've found a solution with only PHP by using the IntlDateFormatter class.

<?php

// Example vars
$month = '6';
$year = '2014';

$fmt = new IntlDateFormatter('de_DE',
    IntlDateFormatter::FULL,
    IntlDateFormatter::FULL,
    'Europe/Berlin',
    IntlDateFormatter::GREGORIAN);
 
$lastMonth = mktime(0, 0, 0, $month -1, 1, $year);

$showLastMonth =  $fmt->format($lastMonth);
echo $showLastMonth;

Solution 5 - Php

Try this one:

date_default_timezone_set('Europe/Berlin');
$loc=setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');
echo strftime('%B');

Solution 6 - Php

PHP manual page for 'setlocale' sais:

> Note: The return value of setlocale() depends on the system that PHP > is running. It returns exactly what the system setlocale > function returns.

If you have root access (debian) here is the solution:

edit

/etc/locale.gen

You can add/remove which locales you need to use. After saving the file run:

locale-gen

and you should be fine. On my server I had to restart Apache to see changes.

Solution 7 - Php

In my case this does not work:

setlocale(LC_ALL, 'de_AT'); // false

while this does work:

Locale::setDefault('de_AT'); // true

and this does work:

setlocale(LC_ALL, 'de_AT.utf-8'); // true

Output of locale program:

$ locale -a
[...]
C.UTF-8
de_AT.utf-8
de_DE.utf-8
en_AG
[...]

Solution 8 - Php

apt-get install -y locales locales-all

Solution 9 - Php

This was such pain.

I wanted to translate dates to Spanish, and it was working on my localhost but not in the server (Ubuntu 18). It turned out I did not have the correct locale packages.

First I checked the installed packages to ensure they were missing

locale -a

Then I installed the Spanish UTF one using the script

sudo pkg-reconfigure locales

And then I spent hours hitting my head against the table until I realized YOU NEED TO RESTART APACHE!

sudo service apache2 restart

And that's the end of my story. Hope it helps.

Solution 10 - Php

Depending on the underlying OS "de_DE" and others maybe the wrong string.

Under Windows refer this lists:

Usually it's "DEU" or "GERMAN" under Win.

Already mentioned:

Under Linux you can see all locales with the shell command:

locale -a

Solution 11 - Php

PHP have strange support for setlocale() on different versions.

The tests below is on Windows (same machine), Apache 2.4 x64 (same web server), PHP x64 TS (different versions).

setlocale() Return: > Returns the new current locale, or false if the locale functionality is not implemented on your platform, the specified locale does not exist or the category name is invalid.

So, I will use the tests below on different version of PHP. Tested on PHP 7.0 - 8.1.

var_dump(setlocale(LC_ALL, 'en_US'));

PHP 7.0, 7.1 return 'en_US'.
PHP 7.2+ (or newer) return false.

var_dump(setlocale(LC_ALL, 'en-US'));

PHP 7.0+ return 'en-US'.

And for testing with multiple values to see which one will be accepted by setlocale() function.
I use this array.

$locale = ['en_US.UTF-8', 'en-US.UTF-8', 'en.UTF-8', 'en-US', 'en_US', 'en'];
var_dump(setlocale(LC_ALL, $locale));

PHP 7.0, 7.1 return 'en_US.UTF-8'.
PHP 7.2+ return 'en-US.UTF-8'.

As you can see that if PHP did supported 'en_US' for old version it doesn't mean will be supported on newer version.

For OP's case, maybe try with this array to see which locale will be accepted.

$locale = ['de_DE.UTF-8', 'de-DE.UTF-8', 'de.UTF-8', 'de_DE', 'de-DE', 'de', 'ge'];
var_dump(setlocale(LC_ALL, $locale));

The result maybe different on Linux or other OS.

Solution 12 - Php

Thanks to Rico Neitzel for the hint. Instead of trying to format php date, use strftime. To see the first 3 letters of month name in your language (Ex. Dez instead of Dec from Dezembro and not December), follow the locale instalation instructions above, and then:

date command: date('d M Y') // impossible to change from English

setlocale( LC_ALL, "pt_BR"); // Portuguese, replace with your locale
echo strftime('%e %b %G');
result: "4 Dez 2016"

/**
 * datelo funcion (date with locale)
 * Credits: Sergio Abreu 
 * http://sites.sitesbr.net
 * NOTE: Depend on availability of the locale in server.
 *
 */

function datelo( $str, $locale='en_US', $time=null){

  if( $time === null){  $time = time(); }

  if ( preg_match("/[DlFM]/", $str)){

     setlocale(LC_ALL, $locale);

     $dict = array( 'd'=>'%d', 'D'=>'%a', 'j'=>'%e', 'l'=>'%A', 'N'=>'%u', 'w'=>'%w', 'F'=>'%B', 
      'm'=>'%m', 'M'=>'%b', 'Y'=>'%G', 'g'=>'%l', 'G'=>'%k', 'h'=>'%I', 'H'=>'%H', 'i'=>'%M', 
      's'=>'%S', 'S'=>'', 'z'=>'%j', 'n'=>'%m', ' '=>' ', '-'=>'-', '/'=>'/', ':'=>':', ','=>',');

     $chars = preg_split("//", $str);
     $nstr = '';

     foreach ($chars as $c){
        if ($c){ //skip empties
          $nc = $dict[$c];
          if( $c === 'n'){ // Fixes the extra zero
            $nc = preg_replace("/^0+/", '', strftime( $nc));   
          }
          elseif( $c === 'z'){ // Fixes the extra zero and decrease 1
            $nc = preg_replace("/^0+/", '',  strftime( $nc)); // 023 turns 23
            $nc = intval($nc) - 1;
          }          
          $nstr .= $nc;
        }
   }
   return strftime( $nstr);     

  }else{ // not localized
    return date( $str, $time);
 } 
}

Solution 13 - Php

If your are on a Red Hat machine you can run :

localedef -v -c -i de_DE -f UTF-8 de_DE.UTF-8

Then restart your Apache server

Solution 14 - Php

I hope this help por php 7.4

When I tried to print a date in spanish, it give me the english version.

So I print in terminal all my lang packages:

# locale -a

it gives me no one for spanish, so a run:

# sudo /usr/share/locales/install-language-pack es_ES

and change te setlocale in code to:

<?php 
setlocale (LC_TIME, "es_ES", "es_ES.iso88591", "spanish");
?>

after that, restart the php service with:

/etc/init.d/php7.4-fpm restart

and that's it

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontoesslabView Question on Stackoverflow
Solution 1 - PhpBenjamin SeillerView Answer on Stackoverflow
Solution 2 - PhpRico NeitzelView Answer on Stackoverflow
Solution 3 - PhpsvassrView Answer on Stackoverflow
Solution 4 - PhptoesslabView Answer on Stackoverflow
Solution 5 - Phpsephoy08View Answer on Stackoverflow
Solution 6 - PhptrojanView Answer on Stackoverflow
Solution 7 - PhpMichael KäferView Answer on Stackoverflow
Solution 8 - PhpLauris KuznecovsView Answer on Stackoverflow
Solution 9 - PhpSalvi PascualView Answer on Stackoverflow
Solution 10 - Phpcoding BottView Answer on Stackoverflow
Solution 11 - PhpveeView Answer on Stackoverflow
Solution 12 - PhpSergio AbreuView Answer on Stackoverflow
Solution 13 - PhpGautierView Answer on Stackoverflow
Solution 14 - PhpmaikosoftView Answer on Stackoverflow