31

I have this part of the function, which gives me name of the months in English. How can I translate them to my local language (Serbian)?

$month_name = date('F', mktime(0, 0, 0, $i));

Where $i is the number of the month (values 1 - 12). See also PHP:mktime.

Avatar
  • 14,622
  • 9
  • 119
  • 198
Sasha
  • 8,521
  • 23
  • 91
  • 174

6 Answers6

27

You should use setlocale():

setlocale(LC_TIME, 'fr_FR');
$month_name = date('F', mktime(0, 0, 0, $i));

In this case it would set it to French. For your case it should be one of the following:

  1. sr_BA - Serbian (Montenegro)
  2. sr_CS - Serbian (Serbia)
  3. sr_ME - Serbian (Serbia and Montenegro)
rid
  • 61,078
  • 31
  • 152
  • 193
MAXIM
  • 1,223
  • 1
  • 9
  • 16
  • 14
    My `date` is locale unaware, my `strftime` is not. If yours is locale aware... what's your PHP version? – Wrikken Dec 12 '12 at 17:56
  • 3
    But notice that [`setlocale` sets the locale process wide](http://php.net/manual/en/function.setlocale.php#refsect1-function.setlocale-notes) (causing unexpected behavior with multiple threads when using multi-threading). Thread safe alternative: [IntlDateFormatter](http://php.net/manual/en/class.intldateformatter.php) – Matteo B. Sep 12 '14 at 09:25
  • 4
    This solution is incorrect. Let's say it's 2019-01-30, the function mktime() without the fifth and sixth parameter will use the current day and year, so if it's 2019-01-30 and you want to know $i = 2 (February), the result will be March, because 2019-02-30 doesn't exist and it will be interpreted as a date in March. To avoid this problem, use for example: mktime(0, 0, 0, $i, 1, 2019). Anyway, don't use this solution, because it will give the wrong result on certain specific dates. So many incorrect answers on Stackoverflow ... – Maarten Bruins Jan 30 '19 at 16:23
22

You should use setlocale() and strftime():

setlocale(LC_TIME, 'sr_CS');
$month_name = strftime('%B', mktime(0, 0, 0, $i));
Arnold Daniels
  • 16,516
  • 4
  • 53
  • 82
15

Here is an example with IntlDateFormatter

$format = new IntlDateFormatter('sr_CS', IntlDateFormatter::NONE, 
              IntlDateFormatter::NONE, NULL, NULL, "MMM");
$monthName = datefmt_format($format, mktime(0, 0, 0, $i));
Arnaud
  • 7,259
  • 10
  • 50
  • 71
  • Hello, here please change locale to "en" and month number to 11. Then it shows me dec and not Nov. Can you please guide? – Apoorva Shah Oct 31 '18 at 06:54
9

For all who struggle with German (and de_DE), make sure you are using the right language code. Login to your server and run locale -a to see a list of all available ones. For me it shows:

C
C.UTF-8
de_AT.utf8
de_BE.utf8
de_CH.utf8
de_DE.utf8
de_LI.utf8
de_LU.utf8
...

You need to use one of those codes.

Then you can use:

date_default_timezone_set('Europe/Berlin');
setlocale(LC_ALL, 'de_DE.utf8');
$date_now = date('Y-m-d');
$month_available = strftime('%B %Y', strtotime($date_now));
$month_next = strftime('%B %Y', strtotime($date_now.' +1 month'));

and "März 2020" etc. get displayed correctly.

Avatar
  • 14,622
  • 9
  • 119
  • 198
5

This question asks how to get a list of months, I only see hints, not a complete code answer so:

If you have IntlDateFormatter available - which is available in most of the cases, you can create a formatter in a given locale and repeatedly push a date to it created just based on month number

// or any other locales like pl_PL, cs_CZ, fr_FR, zh, zh_Hans, ...
$locale = 'en_GB';
$dateFormatter = new IntlDateFormatter(
    $locale,
    IntlDateFormatter::LONG, // date type
    IntlDateFormatter::NONE  // time type
);
$dateFormatter->setPattern('LLLL'); // full month name with NO DECLENSION ;-)
$months_locale = [];
for ($month_number = 1; $month_number <= 12; ++$month_number) {
    $months_locale[] = $dateFormatter->format(
        // 'n' => month number with no leading zeros
        DateTime::createFromFormat('n', (string)$month_number)
    );
}
// test output
echo "<pre>";
var_dump($months_locale);
echo "</pre>";

Note: LLLL takes care of not-declining, but it does not take care of the lowercase/uppercase of the first letter if the languages has such things.
Good example is that you can get January for en_GB but leden for cs_CZ
If you want all letters lowercase => use mb_strtolower($month_name); - docs
If you want just the FIRST letter to be upper case =>
=> use mb_convert_case($month_name, MB_CASE_TITLE, 'UTF-8'); - docs

Always use mb_* functions or their variations for locale-originating strings !

So no, don't use ucfirst !

jave.web
  • 13,880
  • 12
  • 91
  • 125
0

It is good idea to pass the encoding when setting the locale:

 <?php    
 date_default_timezone_set('Europe/Belgrade');
 setlocale(LC_TIME, array('sr_CS.UTF-8', 'sr.UTF-8'));
Bud Damyanov
  • 30,171
  • 6
  • 44
  • 52