[wp-trac] [WordPress Trac] #7753: Use of localized calendar system and translating digits in entire WordPress

WordPress Trac wp-trac at lists.automattic.com
Tue Sep 16 11:31:54 GMT 2008


#7753: Use of localized calendar system and translating digits in entire WordPress
-------------------------+--------------------------------------------------
 Reporter:  kambiz.k     |       Owner:  anonymous        
     Type:  enhancement  |      Status:  new              
 Priority:  normal       |   Milestone:  2.7              
Component:  i18n         |     Version:  2.6.1            
 Severity:  normal       |    Keywords:  has-patch, tested
-------------------------+--------------------------------------------------
 Current implementation of WordPress (v2.6.2) do not offer a mechanism to
 globally convert '''Gregorian Calendar System to Localized Calendar
 System''', and to translate '''Latin Digits to Localized Digits'''.

 == Localization of Calendar System ==

 To convert Gregorian Calendar System to Localized Calendar System (like
 Jewish, Hijri, Jalali, and so on) some users use the_post and
 get_comment_date filters. However this is just a workaround and has some
 problems:

 1. These filters have to ignore output of their respective WordPress
 functions, and recompute the new output from scratch. This is not only a
 performance drawback, but also breaks consistency of code.

 2. Every single filter should have its own callback function because each
 callback can manage only one object (e.g. post or comment). If user needs
 to localize dates in other places, should write new callback functions.

 5. In some cases, there is no way to use filters for changing calendar
 syste (for example dates shown by plugins or dates shown in admin area).

 The solution is quite simple. WordPress as well as plugins use either
 mysql2date or date_i18n to format date and time. What we need is a filter
 in these functions to apply on the unixtimestamp and return the converted
 date/time.

 Actually, we need the filter only in date_i18n function. When translate
 parameter of mysql2date function is true, it should call date_i18n but in
 the current implementation has duplicated code).

 == Localization of Numbers ==

 As same as the calendar system, some users get benefit of available
 filters in conjunction with heavy regular expressions to translate digits
 of numbers to their language locale. Of course there is no filter for
 every single item and users have to leave some numbers as Latin.

 WordPress has already a function named number_format_i18n that eveybody
 calls it to format numbers. If we apply a filter to output of this
 function, we can translate digits of numbers all in one place, and of
 course with a better performance.

 By applying a filter on output of date_i18n function, we can translate
 digits in date and time too.

 == RECOMMENDED CODE ==

 Here is the code that I suggest for mysql2date, date_i18n, and
 number_format_i18n functions (attached as a patch and tested with v2.6.2).

 {{{
 function mysql2date( $dateformatstring, $mysqlstring, $translate = true )
 {
         global $wp_locale;
         $m = $mysqlstring;
         if ( empty( $m ) )
                 return false;

         if( 'G' == $dateformatstring ) {
                 return gmmktime(
                         (int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2
 ), (int) substr( $m, 17, 2 ),
                         (int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2
 ), (int) substr( $m, 0, 4 )
                 );
         }

         $i = mktime(
                 (int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2 ),
 (int) substr( $m, 17, 2 ),
                 (int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2 ), (int)
 substr( $m, 0, 4 )
         );

         if( 'U' == $dateformatstring )
                 return $i;

         if ( -1 == $i || false == $i )
                 $i = 0;

         if ( $translate ) // localizing names or calendar system
                 $j = date_i18n( $dateformatstring, $i );
         else
                 $j = @date( $dateformatstring, $i );

         /*
         if ( !$j ) // for debug purposes
                 echo $i." ".$mysqlstring;
         */

         return $j;
 }
 }}}

 {{{
 function date_i18n( $dateformatstring, $unixtimestamp ) {
         global $wp_locale;
         $i = $unixtimestamp;
         // Sanity check for PHP 5.1.0-
         if ( -1 == $i )
                 $i = false;

         // Let the user convert date from Gregorian to localized calendar
 system
         $j = apply_filters( 'pre_date_i18n', $dateformatstring, $i );
         if ($j !== $dateformatstring)
                 return $j;

         if ( ( !empty( $wp_locale->month ) ) && ( !empty(
 $wp_locale->weekday ) ) ) {
                 $datemonth = $wp_locale->get_month( date( 'm', $i ) );
                 $datemonth_abbrev = $wp_locale->get_month_abbrev(
 $datemonth );
                 $dateweekday = $wp_locale->get_weekday( date( 'w', $i ) );
                 $dateweekday_abbrev = $wp_locale->get_weekday_abbrev(
 $dateweekday );
                 $datemeridiem = $wp_locale->get_meridiem( date( 'a', $i )
 );
                 $datemeridiem_capital = $wp_locale->get_meridiem( date(
 'A', $i ) );
                 $dateformatstring = ' '.$dateformatstring;
                 $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" .
 backslashit( $dateweekday_abbrev ), $dateformatstring );
                 $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" .
 backslashit( $datemonth ), $dateformatstring );
                 $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" .
 backslashit( $dateweekday ), $dateformatstring );
                 $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" .
 backslashit( $datemonth_abbrev ), $dateformatstring );
                 $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" .
 backslashit( $datemeridiem ), $dateformatstring );
                 $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" .
 backslashit( $datemeridiem_capital ), $dateformatstring );

                 $dateformatstring = substr( $dateformatstring, 1, strlen(
 $dateformatstring ) -1 );
         }
         $j = @date( $dateformatstring, $i );

         // Let the user translate digits from latin to localized language
         return apply_filters( 'date_i18n', $j);
 }
 }}}

 {{{
 function number_format_i18n( $number, $decimals = null ) {
         global $wp_locale;
         // let the user override the precision only
         $decimals = ( is_null( $decimals ) ) ?
 $wp_locale->number_format['decimals'] : intval( $decimals );

         $num = number_format( $number, $decimals,
 $wp_locale->number_format['decimal_point'],
 $wp_locale->number_format['thousands_sep'] );

         // let the user translate digits from latin to localized language
         return apply_filters( 'number_format_i18n', $num );
 }
 }}}

 == Example of Usage ==

 We need two functions as core of our localization.

 {{{
 // Converts Latin digits to Persian ones
 function latin_to_persian($number) {
   $latin = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
   $persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹');
   return str_replace($latin, $persian, $number);
 }

 // Represents a Unix timestamp as Jalali date/time
 function gregorian_to_jalali($formatstring, $unixtimestamp) {
   // do the work and calculate $the_jalali_date
   return latin_to_persian($the_jalali_date);
 }
 }}}

 By use of the new filters we localize date and numbers in entire WordPress
 with no pain.

 {{{
 // Changes date to the new calendar system
 add_filter('pre_date_i18n', 'gregorian_to_jalali', 10, 2);
 // Translates digits of numbers
 add_filter('number_format_i18n', 'latin_to_persian', 10, 1);

 }}}

 That's all!

-- 
Ticket URL: <http://trac.wordpress.org/ticket/7753>
WordPress Trac <http://trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list