Revision [2132]

This is an old revision of MultiLanguageNumbers made by PhilDaintree on 2011-09-10 00:59:07.

 

Multi Language Number Formatting

The Problem

Some locales use different characters for the thousands separator and the decimal point. e.g. Europe tends to use a comma "," as a decimal point instead of the English full stop "." the French use a space rather than a comma for the thousands separator. e.g.

2,345.67

would be written

2 345,67

For people used to seeing and writing numbers in these alternative formats webERP is next to useless especially in the accounting area.

The Solution

In the includes/LanguageSetup.php script we have been using:

$Locale = setlocale (LC_NUMERIC, 'en_US');

in order to display web-pages in the users locale with appropriate thousands separators and decimal points we must use either:
$Locale = setlocale (LC_NUMERIC, $_SESSION['Language']);


OR

$Locale = setlocale (LC_ALL, $_SESSION['Language']);


LC_ALL sets all settings for the locale to the user selected locale. However, it does not set LC_MESSAGES to the locale for some reason which I don't understand. I have settled on:

$Locale = setlocale (LC_ALL, $_SESSION['Language']);
$LocaleInfo = localeconv();
if (defined('LC_MESSAGES')){
    $Locale = setlocale (LC_MESSAGES, $_SESSION['Language']);
}


The reason the locale for LC_MESSAGES is only set when it is defined is that it returns a message on some systems that are not compiled with libintl (in particular Windows)
We used to only set the locale when the system was using the gettext for translations. However, now we are using the locale to display numbers correctly too so we need to set the locale correctly which ever method we are using to translate language strings.


number_format function

I had thought that the number_format would be smart enough to display numbers in the user's locale correctly. However, it appears not.
The function localeconv() returns an array containing the thousands_sep and decimal_point characters of the locale. Tim developed a nice function that uses this to format numbers appropriately for the locale. He put this in the file includes/MiscFunctions.php

function locale_number_format($Number, $DecimalPlaces) {
    global $LocaleInfo;
    return number_format($Number,$DecimalPlaces,$LocaleInfo['decimal_point'],$LocaleInfo['thousands_sep']);
}

function locale_money_format($Number, $DecimalPlaces) {
    return money_format('%!.' . $DecimalPlaces . 'n',$Number);
}

/* and to parse the input of the user into useable number */

function filter_number_format($Number) {
    global $LocaleInfo;
    return str_replace($LocaleInfo['decimal_point'],'.',str_replace($LocaleInfo['thousands_sep'],'',$Number));
}


PHP actually does have a function already that does a similar thing for money formats called money_format - the syntax of this function is a bit weird though. Tim pointed out that some locales use a different characters again for formatting currency numbers as opposed to quantity numbers, so another function locale_money_format is also required.

Filtering Numbers Input

Numbers input in the locale of the user could potentially cause issues, as it seems that all arithmetic in PHP takes place using full stops for decimal points and no thousands separator (OR the locale of the server?? in which case the filter_number_format function will need some modification). To get numbers that are input converted to numbers that the system can use we need to pass them through a new function. Also critically, SQL does not deal with thousands separators at all and decimal points must be full stops as per ANSI SQL. All numbers going to SQL must be run though this filter_number_format() function.

What is to be Done?

I have converted all occurrences of number_format() in the scripts to use the locale_number_format() function.

So the first step is to update your svn repository to the very latest trunk.

Each script that uses numbers (and hence has the locale_number_format() function in it needs to be gone through:
  1. Replacing the function locale_number_format() with the locale_money_format function (which takes the same parameters) when the variable being formatted is money. You could use and find and replace - provided the find and replace function of the editor allows you to interactively choose of whether to replace or not following a find.
  1. Check all $_POST variables (I use find $_POST in my editor) that are meant to contain a number and ensure they are encapsulated inside the filter_number_format() function before they are used in any calculations or used in any SQL
  1. Test the script and make sure you can add records and delete records using input in the format of a different locale and that numbers are displayed correctly for the locale.
  1. Commit the changed script back to SVN

I think that's it!! However, there are a lot of scripts....

I have divided the scripts up between those that are helping with this project - see the link below:

ScriptsDisplayNumbers Scripts That Use locale_number_format() function


Valid XHTML :: Valid CSS: :: Powered by WikkaWiki