I'm using setlocale to display dates in Russian.
setlocale(LC_TIME, 'ru_RU');
My question is, will ru_RU be enough or is it safer to provide a number of alternative language params?
Well, you want dates in Russian, you've set the locale for time-related functions to ru_RU, so that's basically it.
I'd advise you to set the current locale as a secondary choice for LC_TIME, in case ru_RU is not available :
setlocale(LC_TIME, 'ru_RU', setlocale(LC_TIME, '0'));
// setlocale() with '0' will return the current settings without applying changes.
The current locale setting was set by the system administrator, and it is very unlikely to go unavailable.
setlocale() affects a lot of things you should answer yourself if these things covers your needs.
It has two params setlocale ( int $category , array $locale )
$ategory can be(from manual) set to one of these constants:
LC_ALL for all of the below
LC_COLLATE for string comparison, see strcoll()
LC_CTYPE for character classification and conversion, for example strtoupper()
LC_MONETARY for localeconv()
LC_NUMERIC for decimal separator (See also localeconv())
LC_TIME for date and time formatting with strftime()
LC_MESSAGES for system responses (available if PHP was compiled with libintl)
Also look at this quote from manual:
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.
Related
I want to show the names of days and month in the language the browser provides.
So I can set the language using setlocale, like : setlocale(LC_ALL, 'nl_NL')
Then the names are all in dutch.
And I can get the browser language with: $_SERVER["HTTP_ACCEPT_LANGUAGE"]
So if my browser is Dutch $_SERVER["HTTP_ACCEPT_LANGUAGE"] returns 'nl' not 'nl_NL'
But setlocale(LC_ALL, 'nl') does not work.
I need a conversion method, so nl is converted to nl_NL.
Not only dutch (that would be simple), but also the other languages.
Or a completely other method :-)
regards Jan
The strftime() function according to this section of the PHP docs, should be used when trying to use a different language
To format dates in other languages, you should use the setlocale() and
strftime() functions instead of date().
When using setlocale() with the following parameters
setlocale(LC_ALL, "es_ES", 'Spanish_Spain', 'Spanish');
and strftime()
$mes = strftime('%B', strtotime($semana->semana . "+{$diaPos} days"));
returns the month in english.
One solution I could approach is allocating a constant variable pointing the translations vs the months given by this function, so I would be able to return the correct name.
But it doesn't seem very elegant to me.
I'm using PHP7 on a debian based distro.
In order to use locale you need to have it generated in your system. On debian you should run as root:
dpkg-reconfigure locales
and then your script should work.
I got PHP 7.0.8 (FPM) running on FreeBSD 10.1 and nginx. I need to display time in preferred format by the country where user resides.
setlocale(LC_ALL, "ru_RU.UTF-8");
date_default_timezone_set("Europe/Moscow");
echo strftime('%X', time());
// Returns 21:23:12 (correct) because 24-hr format is preferred in Russia.
setlocale(LC_ALL, "en_US.UTF-8");
date_default_timezone_set("America/New_York");
echo strftime('%X', time());
// Returns 21:23:12 (incorrect) must return 9:23:12 pm as preferred format in U.S.
This looks like an issue with my server or PHP version, because
other users are getting correct results.
locale -a return contains both ru_RU.UTF-8 and en_US.UTF-8.
echo setlocale(LC_ALL, "en_US.UTF-8") returns correct locale.
No special configuration is applied.
Please help me to resolve this. Thanks.
%X Preferred time representation based on locale, without the date
P.S. Preferred date %x works correctly displaying dd.mm.yyyy for Russia and mm/dd/yyyy for U.S.
Same on FreeBSD 10.3:
php -r 'date_default_timezone_set("Europe/Paris"); var_dump(setlocale(LC_ALL, "en_US.UTF-8"), strftime("%X", time()));'
string(11) "en_US.UTF-8"
string(8) "15:03:07"
First, ls -l /usr/share/locale/en_US.UTF-8/LC_TIME returns:
/usr/share/locale/en_US.UTF-8/LC_TIME# -> ../en_US.ISO8859-1/LC_TIME
So en_US.UTF-8 is, in fact, a symlink to en_US.ISO8859-1.
Then, If we look into /usr/src/share/timedef/en_US.ISO8859-1.src (you need sources installed), we find:
#
# X_fmt
#
%H:%M:%S
Which explains the actual result when you would expect %I:%M:%S %p (or %r).
Possible solutions:
fill a bug report if you think it is relevant and/or1 patch the file above then rebuild world (I guess)
handle this specific case:
echo strftime(0 === strpos(setlocale(LC_ALL, '0'), 'en_US') ? '%r' : '%X');
prefer using IntlDateFormatter which does not rely on system-locales (assumed by ICU library). Eg:
$timefmt = new IntlDateFormatter('en_US', IntlDateFormatter::NONE, IntlDateFormatter::MEDIUM);
$timefmt->format(date_create());
1 it seems that X_fmt is valued to %I:%M:%S %p in trunk and 11-STABLE
Update:
the commit altering X_fmt was reverted since (ie on FreeBSD >= 11, X_fmt is still defined as %H:%M:%S)
on FreeBSD 11, the file defining time formats is /usr/src/share/timedef/en_US.UTF-8.src (the symbolic link to en_US.ISO8859-1 locale is gone)
Excerpt from /usr/share/i18n/locales/en_US on ubuntu 12.04:
% Appropriate time representation (%X)
% "%r"
t_fmt "<U0025><U0072>"
%
% Appropriate AM/PM time representation (%r)
% "%I:%M:%S %p"
t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
<U0025><U0070>"
Please note the %I in AM/PM date for %r.
the %X in unicode is 25 70 which is %P.
And from man date (stripped for simplicity):
%H hour (00..23)
%I hour (01..12)
%p locale's equivalent of either AM or PM; blank if not known
%P like %p, but lower case
%r locale's 12-hour clock time (e.g., 11:11:04 PM)
%R 24-hour hour and minute; same as %H:%M
%x locale's date representation (e.g., 12/31/99)
%X locale's time representation (e.g., 23:13:48)
Reading all this file, it should work as expected so I suspect your setup use a different locale file or fallback to C locale (if the locale file is not there for example)
Now for setlocale, it will return false only in case you give a bad variable (I.e LCAL instead of LCALL) but will return what the system returns for other cases:
Note: The return value of setlocale() depends on the system that PHP
is running. It returns exactly what the system setlocale function
returns.
On "linuxes" setlocale returns NULL which is not always seen as false (see here) which may be a source of your problem, I can't swear as I've no FreeBSD running to confirm this point.
I've run locale -a on my server and can see that it's got Arabic locale settings installed:
ar_AE
ar_AE.iso88596
ar_AE.utf8
However, if I set the locale via:
$locale = array('ar_AE', 'ar_AE.iso88596', 'ar_AE.utf8', 'ar');
setlocale(LC_TIME, $locale);
and output it:
strftime('%A %d %B', $current_date)
The displayed date is in English, not Arabic.
Arabic is the only language this isn't working for: the site I'm working on is in 15 languages and all the others display a translated date.
What's going wrong?
This worked for me with no problems at all.
setlocale(LC_ALL, 'ar_AE.utf8');
If this does not work, then there is another code in your PHP file that interferes with the language.
In a template I display the day and month of a specific date :
<div class="jour"><?php echo date('d',strtotime($content->getCreatedAt())) ?></div>
<div class="mois"><?php echo date('M',strtotime($content->getCreatedAt())) ?></div>
This works fine, problem is the month name is in English. Where do I specify that I want the month names in another locale, French for instance ?
Symfony has a format_date helper among the Date helpers that is i18n-aware. The formats are unfortunately badly documented, see this link for a hint on them.
default_culture only applies for the symfony internationalisation framework, not for native PHP functions. If you want to change this setting project wide, I would do so in config/ProjectConfiguration.class.php, using setlocale, and then use strftime rather than date:
// config/ProjectConfigration.class.php
setlocale(LC_TIME, 'fr_FR');
// *Success.php
<div class="jour"><?php echo strftime('%d',strtotime($content->getCreatedAt())) ?></div>
<div class="mois"><?php echo strftime('%b',strtotime($content->getCreatedAt())) ?></div>
Note that this requires locale settings to be enabled on your machine. To check, do var_dump(setlocale(LC_ALL, 'fr_FR')); If the result is false, you cannot use setlocale to do this and probably need to write the translation code yourself. Furthermore, you will need to have the correct locale installed on your system. To check what locales are installed, do locale -a at the command line.
Sorry for butting in so late in the day, but I would like to add my own thoughts here. The best international date format that I have come up with is "%e %b %Y", e.g. 9 Mar 2012. I find this much more readable than the ISO format "%Y-%m-%d", e.g. 2012-03-09. According to the docs, the %x format should be locale sensitive, but it does not work for me, at least not on the iPhone. This may be because Safari is not passing the locale in the HTML headers, I do not know.
It is sometimes useful to use an array with different possible values to setlocale().
Especially to support different environments (windows, linux, ...)
setlocale(LC_TIME, array('fr', 'fr_FR', 'fr_FR.utf8', 'french', 'french_FRANCE', 'french_FRANCE.utf8'));
echo strftime("%A %d %B", strtotime(date("Y-m-d")));
As the documentation states:
If locale is an array or followed by additional parameters then each array element or parameter is tried to be set as new locale until success. This is useful if a locale is known under different names on different systems or for providing a fallback for a possibly not available locale.