Localisation involves changing various parts of application output like display of dates , time , numbers , language etc according to the standards of the geographical region of a user. Localisation is an important feature of applications that targets users across the globe and not just one region.
So here are a set of simple tips and techniques every php application can do to make itself more locale-friendly.
1. Set timezone of the application
The application should explicitly set a timezone for itself. Otherwise the timezone of the machine/server would be taken up, which may not be what the user wants.
1
| date_default_timezone_set( 'America/Chicago' ); |
This should be done at the earliest in the script.
The
timezone_identifiers_list()
function can be used to generate a list of timezones from which the user can select. Here is a quick example :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| /** @brief Get a list of timezones available for use in the application */ function get_timezones() { $o = array (); $t = timezone_identifiers_list(); foreach ( $t as $a ) { $t = '' ; //Get the time difference $zone = new DateTimeZone( $a ); $seconds = $zone ->getOffset( new DateTime( "now" , $zone ) ); $hours = sprintf( "%+02d" , intval ( $seconds /3600)); $minutes = sprintf( "%02d" , ( $seconds %3600)/60 ); $t = $a . " [ $hours:$minutes ]" ; $o [ $a ] = $t ; } ksort( $o ); return $o ; } |
This would give you a complete list like this :
[Africa/Abidjan] => Africa/Abidjan [ +0:00 ]
[Africa/Accra] => Africa/Accra [ +0:00 ]
[Africa/Addis_Ababa] => Africa/Addis_Ababa [ +3:00 ]
[Africa/Algiers] => Africa/Algiers [ +1:00 ]
[Africa/Asmara] => Africa/Asmara [ +3:00 ]
[Africa/Bamako] => Africa/Bamako [ +0:00 ]
[Africa/Bangui] => Africa/Bangui [ +1:00 ]
[Africa/Banjul] => Africa/Banjul [ +0:00 ]
[Africa/Bissau] => Africa/Bissau [ +0:00 ]
[Africa/Accra] => Africa/Accra [ +0:00 ]
[Africa/Addis_Ababa] => Africa/Addis_Ababa [ +3:00 ]
[Africa/Algiers] => Africa/Algiers [ +1:00 ]
[Africa/Asmara] => Africa/Asmara [ +3:00 ]
[Africa/Bamako] => Africa/Bamako [ +0:00 ]
[Africa/Bangui] => Africa/Bangui [ +1:00 ]
[Africa/Banjul] => Africa/Banjul [ +0:00 ]
[Africa/Bissau] => Africa/Bissau [ +0:00 ]
Make a select tag dropdown out of it and let the user select his/her timezone.
2. Set the mysql timezone from the application
Applications are often hosted on servers that are in a different timezone , compared to that of the developer or the application user. Hence the timezone of mysql needs to be set properly to that of the application.
Mysql can be put in the same timezone as the application by doing :
1
2
| $c = mysqli_connect( $host , $username , $password ); mysqli_query( $c , "SET `time_zone` = '" . date ('P ')."' "); |
The php date function with P parameter gives the time difference between GMT and the applications timezone. The same is passed to mysql.
TIMESTAMP
For timestamp columns in mysql , any date-time combinations passed would be converted to correct timestamp by mysql , since mysql itself is in the correct timezone.
DATETIME
When using datetime columns , the application must convert the date-time values to UTC , and then save in mysql.
When fetching back from database they must be converted to the application's timezone.
When fetching back from database they must be converted to the application's timezone.
Save to database :
1
2
3
4
5
6
7
| $time_to_save = date ( 'Y-m-d h:i:s' ); //Current time of user that is to be saved in a datetime mysql column $d = new DateTime( $time_to_save , new DateTimeZone(date_default_timezone_get()) ); $d ->setTimezone( new DateTimeZone( 'UTC' ) ); //Move to UTC $mysql_datetime = $d ->format( "Y-m-d h:i:s" ); //BUZZ!! Ready to save datetime value in database |
Note :
1. Since the mysql timezone is being set from within the application , certain queries may give tricky output. Here is an example :
You are developing an application on your local system and have set the timezone to 'Asia/Singapore' , but your own computer's timezone is 'Asia/Kolkata'
Now inside your application you are running a certain query :
1
2
3
4
5
| $time_schedule = "2012-04-13 10:30:00" $query = "SELECT * FROM table WHERE time_schedule = '$time_schedule'" ; //Execute the query //some rows |
When you run the same query in phpmyadmin or mysql terminal and you might get different output/rows selected.
This happens because timezone of application+mysql is different from mysql outside. You application sees different time in the database column time_schedule and phpmyadmin/mysql terminal sees a different time.
3. Set collation for database at the time of creation
The collation of the database should be set to the correct one , right in the beginning.
ALTER DATABASE db_name CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Or modify it from the Operations tab in phpmyadmin. Setting the collation and character set in the beginning ensures that all later tables, columns take up the same by default.
4. Set character set of mysql connection object
When the application is displaying non english charaters , then it must set the mysql connection's character encoding. Its simple :
1
| mysqli_set_charset ( $c , 'UTF8' ); |
5. Set correct character set for htmlentities
Function htmlentities is used to echo content , that was previously provided by the user.
Prior to php 5.4 the default character encoding used is ISO-8859-1 which cannot display languages like hindi , bengali , russian etc.
Prior to php 5.4 the default character encoding used is ISO-8859-1 which cannot display languages like hindi , bengali , russian etc.
1
2
| $value = htmlentities( $value , ENT_QUOTES , 'UTF-8' ); echo $value ; |
Php 5.4 onwards the default encoding will be UTF-8 which will solve most problems , but still better be aware about it if your application is multilingual.
The function mb_list_encodings can be used to generate a list.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| /** @brief Get the list of supported encodings using the mb_list_encodings function */ function get_supported_encodings() { $e = mb_list_encodings(); $list = array (); foreach ( $e as $c => $val ) { $list [ $val ] = $val ; } return $list ; } |
Would generate a list like this :
[UTF-32BE] => UTF-32BE
[UTF-32LE] => UTF-32LE
[UTF-16] => UTF-16
[UTF-16BE] => UTF-16BE
[UTF-16LE] => UTF-16LE
[UTF-8] => UTF-8
[UTF-7] => UTF-7
[UTF7-IMAP] => UTF7-IMAP
[ASCII] => ASCII
[EUC-JP] => EUC-JP
[SJIS] => SJIS
[UTF-32LE] => UTF-32LE
[UTF-16] => UTF-16
[UTF-16BE] => UTF-16BE
[UTF-16LE] => UTF-16LE
[UTF-8] => UTF-8
[UTF-7] => UTF-7
[UTF7-IMAP] => UTF7-IMAP
[ASCII] => ASCII
[EUC-JP] => EUC-JP
[SJIS] => SJIS
Select one and save in the database.
6. Set encoding for non html content by sending the correct headers
When echoing content like css , javascript , xml etc. set the correct encoding via the header function like this :
XML
header('Content-Type: text/xml; charset=utf-8');
//Echo rest of the xml content
//Echo rest of the xml content
Javascript
header('Content-Type: text/javascript; charset=utf-8');
//Echo rest of the javascript content
//Echo rest of the javascript content
7. Set correct character set for html and xml output
HTML : This goes in the head tag of an html document
1
| < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" > |
html5 supports :
1
| < meta charset = "utf-8" > |
XML : The first line of an xml document has the encoding specified
1
| <? xml version = "1.0" encoding = "utf-8" ?> |
8. Set correct locale
Locale settings provide useful locale related settings like how to format numbers , currency symbol etc. The correct locale for the application should be setup as early as possible in the script.
1
| setlocale(LC_ALL, 'en_US.UTF-8' ); |
Provide the user with a list of locales to select from. Check here to learn how to do that.
9. Format numbers according to locale
When displaying numbers like plain number or currency numbers , format them with comma , decimal etc properly using function money_format. Here is a quick example :
1
2
3
4
5
6
7
8
9
10
11
12
| $amount = '100000' ; //Format numbers in Indian format - Lakh , Crore setlocale(LC_MONETARY, 'en_IN' ); $am = money_format( '%!i' , $amount ); echo $am ; //1,00,000.00 //Format in million , billion echo "<br />" ; setlocale(LC_MONETARY, 'en_US.utf8' ); $am = money_format( '%!i' , $amount ); echo $am ; //100,000.00 |
10. Format display of dates
Format date display according to user format. Some different kind of date formats used are
ISO Format : 2012-04-13 (YYYY-MM-DD) Asian countries : 13-04-2012 (DD-MM-YYYY) USA : 04-13-2012 (MM-DD-YYYY)
Dates have to be formatted both when displaying and when being entered in a form.
Form entry : 13/04/2012 or 04/13/2012 Display : 13 Apr 2012 or Apr 13, 2012
Formatting date with strftime :
1
2
3
4
5
| $format = '%d-%b-%Y' ; $stamp = time(); $display_format = strftime ( $format , $stamp ); echo $display_format ; //Output 14-04-2012 |
Formatting with DateTime object :
1
2
3
4
| $t = date ( 'Y-m-d h:i:s' ); $d = new DateTime( $t , new DateTimeZone(date_default_timezone_get()) ); $display_format = $d ->format( "d-m-Y" ); echo $display_format ; //15-04-2012 |
User should be have the option to select formats for displaying date and entering dates in forms. The user selected format , for example d-m-Y can be saved in database and reloaded next time.
11. Make the application multilingual
Finally change the language of the application to what the user wants. There are many ways to make your application multilingual. One way is to collect all label text in your application and fetch the translations from google translate service. Find out more on google.
Conclusion
Applications should be localised properly for better user experience. Applications should allow the user to select the localisation settings like timezone , locale , language , date display format etc.
0 comments:
Post a Comment