PHP function setlocale() … and numbers can be damaged
codestyling | 04. February 2009 | 04:29
At many Blogs and forums you can read the same story about localized month name issues if a theme or plugin doesn’t use the WordPress build in functions for that purpose. In most cases this will be roughly handled by just take the setlocale() function and override the OS locale settings.
There are also WordPress plugins in the wild used for blogging multi-lingual. Those plugins mostly set the locale depending on choosen language hardly without any chance to suppress it at backend.
Let’s take a common practical example to show up what the differences can be, if you switch from US locale (standard) to german locale. The next code block demonstrates how the german locale would be activated:
<?php setlocale(LC_ALL, "de_DE.utf-8"); ?>
or the better known short form (if OS supports it):
<?php setlocale(LC_ALL, "de_DE"); ?>
This may solve your issue with monthly names returned by the PHP date() function but produces much more bigger and sometimes hidden problems.
If you want to use a decimal value at your HTML generation output and it has to be converted into string value, you will be astonished about the damaged layout you will get presented at frontend page. Also for this case i have a simple example:
<?php $my_float = 32.5; echo "<div style='width:$my_float%;'>Hallo</div>"; ?>
What would you expect in your browsers HTML view? I’m sure, you expect this:
<div style='width:32.5%;'>Hallo</div>
But this is not what you get! Instead you will get this result:
<div style='width:32,5%;'>Hallo</div>
But this percentage value is not longer a valid decimal value, because the browser doesn’t support german decimal separation at stylesheets. So your container has not a width of 32.5% it will get the full 100% width because browser skipping wrong values (as long as no floats are defined).
Unexpected? Surprised? This is just the game with separator chars. CSS and also PHP only supports the US decimal separation and so all afterwards actions and calculations will fail because of unknown separator char.
I have also a more global example, how you can get in trouble at your backend even if you think, you did no wrong things. Most of you may know or have tested the Google Sitemap Generator. This plugin works well as long as the locale is set to US or “C” standard. If you change this using setlocale() to german, the Sitemap Generator can’t evaluate the frequency values for dedicated sections of your sitemap. This is because the numbers will be converted from text input (post request) into float the wrong way.
If the settings page sends as example “0,5″ as value, the plugin converts it into float. But PHP strictly assumes ‘.’ as decimal separator char and thats why you will get 0.0 as result. The comma char ends the numeric, so the convertion has failed.
This leads to 2 different problems:
- you can only choose between frequency of 0% or 100%, because all values less that 1,0 will be converted to 0 !
- Google Webmaster Tools complains aggressive that all you values are the same and 100% or may ignore the sections that have accidentally got a 0% frequency !
This is SEO horror, isn’t it? But what can you do now to solve this?
a) keep hands of setlocale() and start using WordPress build in functions
WordPress supports a localization resistant date function, that should be used whenever you need month names at your prefered date outputs:
<php
echo date_i18n( 'D F j G:i:s T Y', strtotime( $post->post_date ) );
?>
It produces this results:
Sat March 10 15:16:08 MST 2001 (english, Standard WordPress)
Sam März 10 15:16:08 MST 2001 (german, with german language file)
b) set your locale as before but reset the decimal separator
There may be cases, you may need setting the locale anyway (even if i don’t know when this should be nessessary). If so, you can simply reset the decimal separator after setting the entired locale:
<?php
setlocale(LC_ALL, "de_DE");
setlocale(LC_NUMERIC, 'C');
?>
This reset to ‘C’ locale for numerical values tell the operating system and PHP, that the C/C++ type of decimal separator has to be used which is defined as ‘.’ for programming languages. Now you get your locale based month names if you are using the ordinary PHP date() function but you get also correct calculated and converted numerical values (but you loose your locale known decimal sep char).
Conclusion: If you play games with the locale settings you should always know, what impact this may have. The result can be a wide range of issues, starting with damaged HTML layouts, crashing Javascripts or ends up with crashing or functionless plugins.
I hope this article may help you understand where traps could be and why sometimes issues can occur suddenly.





