eZ Publish  [trunk]
ezlocale.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZLocale class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package lib
00009  */
00010 
00011 /*! \defgroup eZLocale Locale system */
00012 
00013 /*!
00014   \class eZLocale ezlocale.php
00015   \ingroup eZLocale
00016   \brief Provides unified access to locale information and conversions.
00017 
00018   The eZLocale class handles locale information and can format time, date, numbers and currency
00019   for correct display for a given locale. The locale conversion uses plain numerical values for
00020   dates, times, numbers and currency, if you want more elaborate conversions consider using the
00021   eZDate, eZTime, eZDateTime and eZCurrency classes.
00022 
00023   The first time a locale object is created (ie. eZLocale::instance() ) you must be sure to set
00024   a language using setLanguage before using any textual conversions.
00025 
00026   Example:
00027 
00028 \code
00029 
00030 // Fetch the default values supplied by site.ini
00031 $locale = eZLocale::instance();
00032 
00033 // Make sure PHP is to the correct locale
00034 $locale->initPHP();
00035 
00036 print( $locale->formatTime() . '<br>' ); // Display current time
00037 print( $locale->formatDate() . '<br>' ); // Display current day
00038 
00039 foreach ( $locale->weekDays() as $day ) // Print a week with 3 letter daynames
00040 {
00041     print( $locale->shortDayName( $day ) . '<br>' );
00042 }
00043 \endcode
00044 
00045 Countries are specified by the ISO 3166 Country Code
00046 http://www.iso.ch/iso/en/prods-services/iso3166ma/index.html
00047 User-assigned code elements
00048 http://www.iso.ch/iso/en/prods-services/iso3166ma/04background-on-iso-3166/reserved-and-user-assigned-codes.html#userassigned
00049 
00050 
00051 Language is specified by the ISO 639 Language Code
00052 http://www.w3.org/WAI/ER/IG/ert/iso639.htm
00053 
00054 Currency/funds are specified by the ISO 4217
00055 http://www.bsi-global.com/Technical+Information/Publications/_Publications/tig90.xalter
00056 
00057 
00058 Discussion on Norwegian locales
00059 https://lister.ping.uio.no/pipermail/lister.ping.uio.no/i18n-nn/2002-April.txt
00060 http://www.sprakrad.no/oss.htm
00061 
00062 
00063 The date and time formats are quite similar to the builtin PHP date function,
00064 the main differences are those which returns textual representations of months
00065 and days.
00066 More info on the date function here:
00067 http://www.php.net/manual/en/function.date.php
00068 
00069 The following characters are not recognized in the format string:
00070 
00071 - B - Swatch Internet time
00072 - S - English ordinal suffix for the day of the month, 2 characters; i.e. "st", "nd", "rd" or "th"
00073 
00074 The following characters are recognized in the format string:
00075 
00076 - a - "am" or "pm"
00077 - A - "AM" or "PM"
00078 - d - day of the month, 2 digits with leading zeros; i.e. "01" to "31"
00079 - D - day of the week, textual, 3 letters; e.g. "Fri"
00080 - F - month, textual, long; e.g. "January"
00081 - g - hour, 12-hour format without leading zeros; i.e. "1" to "12"
00082 - G - hour, 24-hour format without leading zeros; i.e. "0" to "23"
00083 - h - hour, 12-hour format; i.e. "01" to "12"
00084 - H - hour, 24-hour format; i.e. "00" to "23"
00085 - i - minutes; i.e. "00" to "59"
00086 - I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
00087 - j - day of the month without leading zeros; i.e. "1" to "31"
00088 - l (lowercase 'L') - day of the week, textual, long; e.g. "Friday"
00089 - L - boolean for whether it is a leap year; i.e. "0" or "1"
00090 - m - month; i.e. "01" to "12"
00091 - M - month, textual, 3 letters; e.g. "Jan"
00092 - n - month without leading zeros; i.e. "1" to "12"
00093 - O - Difference to Greenwich time in hours; e.g. "+0200"
00094 - s - seconds; i.e. "00" to "59"
00095 - t - number of days in the given month; i.e. "28" to "31"
00096 - T - Timezone setting of this machine; e.g. "EST" or "MDT"
00097 - U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
00098 - w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday)
00099 - W - ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)
00100 - Y - year, 4 digits; e.g. "1999"
00101 - y - year, 2 digits; e.g. "99"
00102 - z - day of the year; i.e. "0" to "365"
00103 - Z - timezone offset in seconds (i.e. "-43200" to "43200"). The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.
00104 - c - ISO 8601 date; i.e. 2004-02-12T15:19:21+00:00
00105 - r - RFC 2822 formated date; i.e. Thu, 21 Dec 2000 16:01:07 +0200
00106 
00107 \sa eZLanguage
00108 */
00109 
00110 class eZLocale
00111 {
00112     const DEBUG_INTERNALS = false;
00113 
00114     /*!
00115      Initializes the locale with the locale string \a $localeString.
00116      All locale data is read from locale/$localeString.ini
00117     */
00118     function eZLocale( $localeString )
00119     {
00120         $this->IsValid = false;
00121         $this->TimePHPArray = array( 'g', 'G', 'h', 'H', 'i', 's', 'U', 'I', 'L', 't' );
00122         $this->DatePHPArray = array( 'd', 'j', 'm', 'n', 'O', 'S', 'T', 'U', 'w', 'W', 'Y', 'y', 'z', 'Z', 'I', 'L', 't' );
00123         $this->DateTimePHPArray = array( 'd', 'j', 'm', 'n', 'O', 'T', 'U', 'w', 'W', 'Y', 'y', 'z', 'Z',
00124                                          'g', 'G', 'h', 'H', 'i', 's', 'S', 'U', 'I', 'L', 't', 'a', 'c', 'r' );
00125         $this->TimeArray = preg_replace( '/.+/', '%$0', $this->TimePHPArray );
00126         $this->DateArray = preg_replace( '/.+/', '%$0', $this->DatePHPArray );
00127         $this->DateTimeArray = preg_replace( '/.+/', '%$0', $this->DateTimePHPArray );
00128 
00129         $this->TimeSlashInputArray = preg_replace( '/.+/', '/(?<!%)$0/', $this->TimePHPArray );
00130         $this->DateSlashInputArray = preg_replace( '/.+/', '/(?<!%)$0/', $this->DatePHPArray );
00131         $this->DateTimeSlashInputArray = preg_replace( '/.+/', '/(?<!%)$0/', $this->DateTimePHPArray );
00132 
00133         $this->TimeSlashOutputArray = preg_replace( '/.+/', '\\\\$0', $this->TimePHPArray );
00134         $this->DateSlashOutputArray = preg_replace( '/.+/', '\\\\$0', $this->DatePHPArray );
00135         $this->DateTimeSlashOutputArray = preg_replace( '/.+/', '\\\\$0', $this->DateTimePHPArray );
00136 
00137         $this->HTTPLocaleCode = '';
00138         $this->functionMap = array(
00139             'time' => 'formatTime',
00140             'shorttime' => 'formatShortTime',
00141             'date' => 'formatDate',
00142             'shortdate' => 'formatShortDate',
00143             'datetime' => 'formatDateTime',
00144             'shortdatetime' => 'formatShortDateTime',
00145             'currency' => 'formatCurrencyWithSymbol',
00146             'clean_currency' => 'formatCleanCurrency',
00147             'number' => 'formatNumber',
00148         );
00149 
00150         $this->DayNames = array( 0 => 'sun', 1 => 'mon', 2 => 'tue',
00151                                  3 => 'wed', 4 => 'thu', 5 => 'fri', 6 => 'sat' );
00152         $this->MonthNames = array( 1 => 'jan', 2 => 'feb', 3 => 'mar',
00153                                    4 => 'apr', 5 => 'may', 6 => 'jun',
00154                                    7 => 'jul', 8 => 'aug', 9 => 'sep',
00155                                    10 => 'oct', 11 => 'nov', 12 => 'dec' );
00156         $this->WeekDays = array( 0, 1, 2, 3, 4, 5, 6 );
00157         $this->Months = array( 1, 2, 3, 4, 5, 6,
00158                                7, 8, 9, 10, 11, 12 );
00159 
00160         $locale = eZLocale::localeInformation( $localeString );
00161 
00162         $this->CountryCode = $locale['country'];
00163         $this->CountryVariation = $locale['country-variation'];
00164         $this->LanguageCode = $locale['language'];
00165         $this->LocaleCode = $locale['locale'];
00166         $this->TranslationCode = $locale['locale'];
00167         $this->Charset = $locale['charset'];
00168         $this->OverrideCharset = $locale['charset'];
00169 
00170         $this->LocaleINI = array( 'default' => null, 'variation' => null );
00171         $this->CountryINI = array( 'default' => null, 'variation' => null );
00172         $this->LanguageINI = array( 'default' => null, 'variation' => null );
00173 
00174         // Figure out if we use one locale file or separate country/language file.
00175         $localeINI = $this->localeFile();
00176         $countryINI = $localeINI;
00177         $languageINI = $localeINI;
00178         if ( $localeINI === null )
00179         {
00180             $countryINI = $this->countryFile();
00181             $languageINI = $this->languageFile();
00182         }
00183 
00184         $this->reset();
00185 
00186         $this->IsValid = true;
00187 
00188         // Load country information
00189         if ( $countryINI !== null )
00190         {
00191             $this->initCountry( $countryINI );
00192         }
00193         else
00194         {
00195             $this->IsValid = false;
00196             eZDebug::writeError( 'Could not load country settings for ' . $this->CountryCode, 'eZLocale' );
00197         }
00198 
00199         // Load language information
00200         if ( $languageINI !== null )
00201         {
00202             $this->initLanguage( $languageINI );
00203         }
00204         else
00205         {
00206             $this->IsValid = false;
00207             eZDebug::writeError( 'Could not load language settings for ' . $this->LanguageCode, 'eZLocale' );
00208         }
00209 
00210 
00211         // Load variation if any
00212         if ( $this->countryVariation() )
00213         {
00214             $localeVariationINI = $this->localeFile( true );
00215             $countryVariationINI = $localeVariationINI;
00216             $languageVariationINI = $localeVariationINI;
00217             if ( $localeVariationINI === null )
00218             {
00219                 $countryVariationINI = $this->countryFile( true );
00220                 $languageVariationINI = $this->languageFile( true );
00221             }
00222 
00223             // Load country information
00224             if ( $countryVariationINI !== null )
00225             {
00226                 $this->initCountry( $countryVariationINI );
00227             }
00228 
00229             // Load language information
00230             if ( $languageVariationINI !== null )
00231             {
00232                 $this->initLanguage( $languageVariationINI );
00233             }
00234         }
00235 
00236         if ( $this->MondayFirst )
00237         {
00238             $this->WeekDays[] = array_shift( $this->WeekDays );
00239         }
00240 
00241         $this->AM = 'am';
00242         $this->PM = 'pm';
00243     }
00244 
00245     /*!
00246      \private
00247     */
00248     function reset()
00249     {
00250         $this->TimeFormat = '';
00251         $this->ShortTimeFormat = '';
00252         $this->DateFormat = '';
00253         $this->ShortDateFormat = '';
00254         $this->DateTimeFormat = '';
00255         $this->ShortDateTimeFormat = '';
00256 
00257         $this->MondayFirst = false;
00258 
00259         $this->Country = '';
00260         $this->CountryComment = '';
00261 
00262         $this->DecimalSymbol = '';
00263         $this->ThousandsSeparator = '';
00264         $this->FractDigits = 2;
00265         $this->NegativeSymbol = '-';
00266         $this->PositiveSymbol = '';
00267 
00268         $this->CurrencyDecimalSymbol = '';
00269         $this->CurrencyName = '';
00270         $this->CurrencyShortName = '';
00271         $this->CurrencyThousandsSeparator = '';
00272         $this->CurrencyFractDigits = 2;
00273         $this->CurrencyNegativeSymbol = '-';
00274         $this->CurrencyPositiveSymbol = '';
00275         $this->CurrencySymbol = '';
00276         $this->CurrencyPositiveFormat = '';
00277         $this->CurrencyNegativeFormat = '';
00278         $this->CountryNames = '';
00279 
00280         $this->LanguageName = '';
00281         $this->LanguageComment = '';
00282         $this->IntlLanguageName = '';
00283         $this->AllowedCharsets = array();
00284 
00285         $this->ShortDayNames = array();
00286         $this->LongDayNames = array();
00287         foreach ( $this->DayNames as $day )
00288         {
00289             $this->ShortDayNames[$day] = '';
00290             $this->LongDayNames[$day] = '';
00291         }
00292 
00293         $this->ShortMonthNames = array();
00294         $this->LongMonthNames = array();
00295         foreach ( $this->MonthNames as $month )
00296         {
00297             $this->ShortMonthNames[$month] = '';
00298             $this->LongMonthNames[$month] = '';
00299         }
00300 
00301         $this->ShortWeekDayNames = array();
00302         $this->LongWeekDayNames = array();
00303         foreach( $this->WeekDays as $wday )
00304         {
00305             $code = $this->DayNames[$wday];
00306             $this->ShortWeekDayNames[$wday] = '';
00307             $this->LongWeekDayNames[$wday] = '';
00308         }
00309     }
00310 
00311     /*!
00312      \return true if the locale is valid, ie the locale file could be loaded.
00313     */
00314     function isValid()
00315     {
00316         return $this->IsValid;
00317     }
00318 
00319     /*!
00320      \private
00321     */
00322     function initCountry( &$countryINI )
00323     {
00324         $countryINI->assign( 'DateTime', 'TimeFormat', $this->TimeFormat );
00325         $countryINI->assign( 'DateTime', 'ShortTimeFormat', $this->ShortTimeFormat );
00326         $countryINI->assign( 'DateTime', 'DateFormat', $this->DateFormat );
00327         $countryINI->assign( 'DateTime', 'ShortDateFormat', $this->ShortDateFormat );
00328         $countryINI->assign( 'DateTime', 'DateTimeFormat', $this->DateTimeFormat );
00329         $countryINI->assign( 'DateTime', 'ShortDateTimeFormat', $this->ShortDateTimeFormat );
00330 
00331         if ( $countryINI->hasVariable( 'DateTime', 'MondayFirst' ) )
00332             $this->MondayFirst = strtolower( $countryINI->variable( 'DateTime', 'MondayFirst' ) ) == 'yes';
00333 
00334         $countryINI->assign( 'RegionalSettings', 'Country', $this->Country );
00335         $countryINI->assign( "RegionalSettings", "CountryComment", $this->CountryComment );
00336 
00337         $countryINI->assign( 'Numbers', 'DecimalSymbol', $this->DecimalSymbol );
00338         $countryINI->assign( 'Numbers', 'ThousandsSeparator', $this->ThousandsSeparator );
00339         $countryINI->assign( 'Numbers', 'FractDigits', $this->FractDigits );
00340         $countryINI->assign( 'Numbers', 'NegativeSymbol', $this->NegativeSymbol );
00341         $countryINI->assign( 'Numbers', 'PositiveSymbol', $this->PositiveSymbol );
00342 
00343         $countryINI->assign( 'Currency', 'DecimalSymbol', $this->CurrencyDecimalSymbol );
00344         $countryINI->assign( 'Currency', 'Name', $this->CurrencyName );
00345         $countryINI->assign( 'Currency', 'ShortName', $this->CurrencyShortName );
00346         $countryINI->assign( 'Currency', 'ThousandsSeparator', $this->CurrencyThousandsSeparator );
00347         $countryINI->assign( 'Currency', 'FractDigits', $this->CurrencyFractDigits );
00348         $countryINI->assign( 'Currency', 'NegativeSymbol', $this->CurrencyNegativeSymbol );
00349         $countryINI->assign( 'Currency', 'PositiveSymbol', $this->CurrencyPositiveSymbol );
00350         $countryINI->assign( 'Currency', 'Symbol', $this->CurrencySymbol );
00351         $countryINI->assign( 'Currency', 'PositiveFormat', $this->CurrencyPositiveFormat );
00352         $countryINI->assign( 'Currency', 'NegativeFormat', $this->CurrencyNegativeFormat );
00353         if ( $countryINI->hasVariable( 'CountryNames', 'Countries' ) )
00354             $this->CountryNames = $countryINI->variable( 'CountryNames', 'Countries' );
00355 
00356     }
00357 
00358     /*!
00359      \private
00360     */
00361     function initLanguage( &$languageINI )
00362     {
00363         $languageINI->assign( "RegionalSettings", "LanguageName", $this->LanguageName );
00364         $languageINI->assign( "RegionalSettings", "InternationalLanguageName", $this->IntlLanguageName );
00365         $languageINI->assign( "RegionalSettings", "LanguageComment", $this->LanguageComment );
00366         $languageINI->assign( 'RegionalSettings', 'TranslationCode', $this->TranslationCode );
00367 
00368         if ( $this->OverrideCharset == '' )
00369         {
00370             $charset = false;
00371             if ( $languageINI->hasVariable( 'Charset', 'Preferred' ) )
00372             {
00373                 $charset = $languageINI->variable( 'Charset', 'Preferred' );
00374                 if ( $charset != '' )
00375                     $this->Charset = $charset;
00376             }
00377         }
00378         if ( $languageINI->hasVariable( 'Charset', 'Allowed' ) )
00379         {
00380             $this->AllowedCharsets = $languageINI->variable( 'Charset', 'Allowed' );
00381         }
00382         else
00383         {
00384             if ( $languageINI->hasVariable( 'Charset', 'Preferred' ) )
00385                 $this->AllowedCharsets[] = $languageINI->variable( 'Charset', 'Preferred' );
00386         }
00387 
00388 
00389         if ( !is_array( $this->ShortDayNames ) )
00390             $this->ShortDayNames = array();
00391         if ( !is_array( $this->LongDayNames ) )
00392             $this->LongDayNames = array();
00393 
00394         $tmpShortDayNames = array();
00395         if ( $languageINI->hasGroup( 'ShortDayNames' ) )
00396             $tmpShortDayNames = $languageINI->variableMulti( 'ShortDayNames', $this->DayNames );
00397         $tmpLongDayNames = array();
00398         if ( $languageINI->hasGroup( 'LongDayNames' ) )
00399             $tmpLongDayNames = $languageINI->variableMulti( 'LongDayNames', $this->DayNames );
00400         foreach ( $this->DayNames as $key => $day )
00401         {
00402             if ( isset( $tmpShortDayNames[$key] ) )
00403                 $this->ShortDayNames[$day] = $tmpShortDayNames[$key];
00404             if ( isset( $tmpLongDayNames[$key] ) )
00405                 $this->LongDayNames[$day] = $tmpLongDayNames[$key];
00406         }
00407 
00408 
00409         if ( !is_array( $this->ShortMonthNames ) )
00410             $this->LongMonthNames = array();
00411         if ( !is_array( $this->ShortMonthNames ) )
00412             $this->LongMonthNames = array();
00413 
00414         $tmpShortMonthNames = array();
00415         if ( $languageINI->hasGroup( 'ShortMonthNames' ) )
00416             $tmpShortMonthNames = $languageINI->variableMulti( 'ShortMonthNames', $this->MonthNames );
00417         $tmpLongMonthNames = array();
00418         if ( $languageINI->hasGroup( 'LongMonthNames' ) )
00419             $tmpLongMonthNames = $languageINI->variableMulti( 'LongMonthNames', $this->MonthNames );
00420         foreach ( $this->MonthNames as $key => $day )
00421         {
00422             if ( isset( $tmpShortMonthNames[$key] ) )
00423                 $this->ShortMonthNames[$day] = $tmpShortMonthNames[$key];
00424             if ( isset( $tmpLongMonthNames[$key] ) )
00425                 $this->LongMonthNames[$day] = $tmpLongMonthNames[$key];
00426         }
00427 
00428 
00429         if ( !is_array( $this->ShortWeekDayNames ) )
00430             $this->ShortWeekDayNames = array();
00431         if ( !is_array( $this->LongWeekDayNames ) )
00432             $this->LongWeekDayNames = array();
00433 
00434         foreach ( $this->WeekDays as $key => $day )
00435         {
00436             if ( isset( $tmpShortDayNames[$key] ) )
00437                 $this->ShortWeekDayNames[$day] = $tmpShortDayNames[$key];
00438             if ( isset( $tmpLongDayNames[$key] ) )
00439                 $this->LongWeekDayNames[$day] = $tmpLongDayNames[$key];
00440         }
00441 
00442         if ( $languageINI->hasVariable( 'HTTP', 'ContentLanguage' ) )
00443             $this->HTTPLocaleCode = $languageINI->variable( 'HTTP', 'ContentLanguage' );
00444     }
00445 
00446     /*!
00447      \return a regexp which can be used for locale matching.
00448      The following groups are defiend
00449      - 1 - The language identifier
00450      - 2 - The separator and the country (3)
00451      - 3 - The country identifier
00452      - 4 - The separator and the charset (5)
00453      - 5 - The charset
00454      - 6 - The separator and the variation (7)
00455      - 7 - The variation
00456      \note The groyps 4 and 5 will only be used if \a $withCharset is \c true.
00457            The groups 6 and 7 will only be used if \a $withVariations is \c true.
00458      \param $withVariations If \c true it will include variations of locales (ends with @identifier)
00459     */
00460     static function localeRegexp( $withVariations = true, $withCharset = true )
00461     {
00462         return "([a-zA-Z]+)([_-]([a-zA-Z]+))?" . ( $withCharset ? "(\.([a-zA-Z-]+))?" : '' ) . ( $withVariations ? "(@([a-zA-Z0-9]+))?" : '' );
00463     }
00464 
00465     /*!
00466      Decodes a locale string into language, country and charset and returns an array with the information.
00467      Country and charset is optional, country is specified with a - or _ followed by the country code (NO, GB),
00468      charset is specified with a . followed by the charset name.
00469      Examples of locale strings are: nor-NO, en_GB.utf8, nn_NO
00470     */
00471     function localeInformation( $localeString )
00472     {
00473         $info = null;
00474         if ( preg_match( '/^([a-zA-Z]+)([_-]([a-zA-Z]+))?(\.([a-zA-Z-]+))?(@([a-zA-Z0-9]+))?/', $localeString, $regs ) )
00475         {
00476             $info = array();
00477             $language = strtolower( $regs[1] );
00478             $country = '';
00479             if ( isset( $regs[3] ) )
00480                 $country = strtoupper( $regs[3] );
00481             $charset = '';
00482             if ( isset( $regs[5] ) )
00483                 $charset = strtolower( $regs[5] );
00484             $countryVariation = '';
00485             if ( isset( $regs[7] ) )
00486                 $countryVariation = strtolower( $regs[7] );
00487             $locale = $language;
00488             if ( $country !== '' )
00489                 $locale .= '-' . $country;
00490             $info['language'] = $language;
00491             $info['country'] = $country;
00492             $info['country-variation'] = $countryVariation;
00493             $info['charset'] = $charset;
00494             $info['locale'] = $locale;
00495         }
00496         else
00497         {
00498             $info = array();
00499             $locale = strtolower( $localeString );
00500             $language = $locale;
00501             $info['language'] = $language;
00502             $info['country'] = '';
00503             $info['country-variation'] = '';
00504             $info['charset'] = '';
00505             $info['locale'] = $locale;
00506         }
00507         return $info;
00508     }
00509 
00510     /*!
00511      Sets locale information in PHP. This means that some of the string/sort functions in
00512      PHP will work with non-latin1 characters.
00513      Make sure setLanguage is called before this.
00514     */
00515     function initPHP( $charset = false )
00516     {
00517         if ( $charset === false )
00518             $charset = $this->Language->code();
00519         setlocale( LC_ALL, $charset );
00520     }
00521 
00522     function attributes()
00523     {
00524         return array_keys( eZLocale::attributeFunctionMap() );
00525     }
00526 
00527     function hasAttribute( $attribute )
00528     {
00529         $attributeMap = eZLocale::attributeFunctionMap();
00530         if ( isset( $attributeMap[$attribute] ) )
00531             return true;
00532         else
00533             return false;
00534     }
00535 
00536     function attribute( $attribute )
00537     {
00538         $attributeMap = eZLocale::attributeFunctionMap();
00539         if ( isset( $attributeMap[$attribute] ) )
00540         {
00541             $method = $attributeMap[$attribute];
00542             if ( method_exists( $this, $method ) )
00543             {
00544                 return $this->$method();
00545             }
00546             else
00547             {
00548                 eZDebug::writeError( "Unknown method '$method' specified for attribute '$attribute'", __METHOD__ );
00549                 return null;
00550             }
00551         }
00552 
00553         eZDebug::writeError( "Attribute '$attribute' does not exist", __METHOD__ );
00554         return null;
00555     }
00556 
00557     function attributeFunctionMap()
00558     {
00559         return array( 'charset' => 'charset',
00560                       'allowed_charsets' => 'allowedCharsets',
00561                       'country_name' => 'countryName',
00562                       'country_comment' => 'countryComment',
00563                       'country_code' => 'countryCode',
00564                       'country_variation' => 'countryVariation',
00565                       'language_name' => 'languageName',
00566                       'intl_language_name' => 'internationalLanguageName',
00567                       'language_code' => 'languageCode',
00568                       'language_comment' => 'languageComment',
00569                       'locale_code' => 'localeCode',
00570                       'locale_full_code' => 'localeFullCode',
00571                       'http_locale_code' => 'httpLocaleCode',
00572                       'decimal_symbol' => 'decimalSymbol',
00573                       'thousands_separator' => 'thousandsSeparator',
00574                       'decimal_count' => 'decimalCount',
00575                       'negative_symbol' => 'negativeSymbol',
00576                       'positive_symbol' => 'positiveSymbol',
00577                       'currency_decimal_symbol' => 'currencyDecimalSymbol',
00578                       'currency_thousands_separator' => 'currencyThousandsSeparator',
00579                       'currency_decimal_count' => 'currencyDecimalCount',
00580                       'currency_negative_symbol' => 'currencyNegativeSymbol',
00581                       'currency_positive_symbol' => 'currencyPositiveSymbol',
00582                       'currency_symbol' => 'currencySymbol',
00583                       'currency_name' => 'currencyName',
00584                       'currency_short_name' => 'currencyShortName',
00585                       'is_monday_first' => 'isMondayFirst',
00586                       'weekday_name_list' => 'weekDayNames',
00587                       'weekday_short_name_list' => 'weekDayShortNames',
00588                       'weekday_number_list' => 'weekDays',
00589                       'month_list' => 'months',
00590                       'month_name_list' => 'monthsNames',
00591                       'is_valid' => 'isValid' );
00592     }
00593 
00594     /*!
00595      Returns the charset for this locale.
00596      \note It returns an empty string if no charset was set from the locale file.
00597     */
00598     function charset()
00599     {
00600         return $this->Charset;
00601     }
00602 
00603     /*!
00604      \return an array with charsets that this locale can work with.
00605     */
00606     function allowedCharsets()
00607     {
00608         return $this->AllowedCharsets;
00609     }
00610 
00611     /*!
00612      Returns the name of the country in British English.
00613     */
00614     function countryName()
00615     {
00616         return $this->Country;
00617     }
00618 
00619     /*!
00620      Returns the comment for the country, if any.
00621     */
00622     function countryComment()
00623     {
00624         return $this->CountryComment;
00625     }
00626 
00627     /*!
00628      Returns the code for the country. eg. 'NO'
00629     */
00630     function countryCode()
00631     {
00632         return $this->CountryCode;
00633     }
00634 
00635     /*!
00636      Returns the variation for the country. eg. 'spraakraad'
00637     */
00638     function countryVariation()
00639     {
00640         return $this->CountryVariation;
00641     }
00642 
00643     /*!
00644      Returns the language code for this language, for instance nor for norwegian or eng for english.
00645     */
00646     function languageCode()
00647     {
00648         return $this->LanguageCode;
00649     }
00650 
00651     /*!
00652      Returns the comment for the language, if any.
00653     */
00654     function languageComment()
00655     {
00656         return $this->LanguageComment;
00657     }
00658 
00659     /*!
00660      Returns the locale code which is used for translation files. Normally this is the same as localeCode()
00661      but for some locales translation from other languages can be used
00662 
00663      e.g. por-MZ (Mozambique) uses por-PT for translation.
00664 
00665      \deprecated since eZ Publish 4.1, use localeFullCode() instead
00666     */
00667     function translationCode()
00668     {
00669         return $this->TranslationCode;
00670     }
00671 
00672     /*!
00673      Returns the locale code for this language which is the language and the country with a dash (-) between them,
00674      for instance nor-NO or eng-GB.
00675     */
00676     function localeCode()
00677     {
00678         return $this->LocaleCode;
00679     }
00680 
00681     /*!
00682      Same as localeCode() but appends the country variation if it is set.
00683     */
00684     function localeFullCode()
00685     {
00686         $locale = $this->LocaleCode;
00687         $variation = $this->countryVariation();
00688         if ( $variation )
00689             $locale .= "@" . $variation;
00690         return $locale;
00691     }
00692 
00693     /*!
00694      \return the locale code which can be set in either HTTP headers or the HTML file.
00695              The locale code is first check for in the RegionalSettings/HTTPLocale setting in site.ini,
00696              if that is empty it will use the value from localeCode().
00697      \sa localeCode
00698     */
00699     function httpLocaleCode()
00700     {
00701         $ini = eZINI::instance();
00702         $localeCode = '';
00703         if ( $ini->hasVariable( 'RegionalSettings', 'HTTPLocale' ) )
00704         {
00705             $localeCode = $ini->variable( 'RegionalSettings', 'HTTPLocale' );
00706         }
00707         if ( $localeCode == '' and
00708              $this->HTTPLocaleCode != '' )
00709             $localeCode = $this->HTTPLocaleCode;
00710         if ( $localeCode == '' )
00711             $localeCode = $this->localeCode();
00712         return $localeCode;
00713     }
00714 
00715     /*!
00716      \static
00717      Returns the current locale code for this language which is the language and the country with a dash (-) between them,
00718      for instance nor-NO or eng-GB.
00719      \sa localeCode, instance
00720     */
00721     static function currentLocaleCode()
00722     {
00723         $locale = eZLocale::instance();
00724         return $locale->localeCode();
00725     }
00726 
00727     /*!
00728      Returns the name of the language in its own tounge.
00729     */
00730     function languageName()
00731     {
00732         return $this->LanguageName;
00733     }
00734 
00735     /*!
00736      Returns the name of the language in English (eng).
00737     */
00738     function internationalLanguageName()
00739     {
00740         return $this->IntlLanguageName;
00741     }
00742 
00743     /*!
00744      Returns the currency symbol for this locale.
00745     */
00746     function currencySymbol()
00747     {
00748         return $this->CurrencySymbol;
00749     }
00750 
00751     /*!
00752      Returns the name of the currency.
00753     */
00754     function currencyName()
00755     {
00756         return $this->CurrencyName;
00757     }
00758 
00759     /*!
00760      Returns the short name of the currency.
00761     */
00762     function currencyShortName()
00763     {
00764         return $this->CurrencyShortName;
00765     }
00766 
00767     /*!
00768      Returns true if the week starts with monday, false if sunday.
00769      \sa weekDays()
00770     */
00771     function isMondayFirst()
00772     {
00773         return $this->MondayFirst;
00774     }
00775 
00776     /*!
00777      \return the decimal symbol for normal numbers.
00778     */
00779     function decimalSymbol()
00780     {
00781         return $this->DecimalSymbol;
00782     }
00783 
00784     /*!
00785      \return the thousand separator for normal numbers.
00786     */
00787     function thousandsSeparator()
00788     {
00789         return $this->ThousandsSeparator;
00790     }
00791 
00792     /*!
00793      \return the number of decimals for normal numbers.
00794     */
00795     function decimalCount()
00796     {
00797         return $this->FractDigits;
00798     }
00799 
00800     /*!
00801      \return the negative symbol for normal numbers.
00802     */
00803     function negativeSymbol()
00804     {
00805         return $this->NegativeSymbol;
00806     }
00807 
00808     /*!
00809      \return the positive symbol for normal numbers.
00810     */
00811     function positiveSymbol()
00812     {
00813         return $this->PositiveSymbol;
00814     }
00815 
00816     /*!
00817      \return the decimal symbol for currencies.
00818     */
00819     function currencyDecimalSymbol()
00820     {
00821         return $this->CurrencyDecimalSymbol;
00822     }
00823 
00824     /*!
00825      \return the thousand separator for currencies.
00826     */
00827     function currencyThousandsSeparator()
00828     {
00829         return $this->CurrencyThousandsSeparator;
00830     }
00831 
00832     /*!
00833      \return the number of decimals for currencies.
00834     */
00835     function currencyDecimalCount()
00836     {
00837         return $this->CurrencyFractDigits;
00838     }
00839 
00840     /*!
00841      \return the negative symbol for currencies.
00842     */
00843     function currencyNegativeSymbol()
00844     {
00845         return $this->CurrencyNegativeSymbol;
00846     }
00847 
00848     /*!
00849      \return the positive symbol for currencies.
00850     */
00851     function currencyPositiveSymbol()
00852     {
00853         return $this->CurrencyPositiveSymbol;
00854     }
00855 
00856     /*!
00857      Returns an array with the days of the week according to locale information.
00858      Each entry in the array can be supplied to the shortDayName() and longDayName() functions.
00859      \sa isMondayFirst(), weekDayNames()
00860     */
00861     function weekDays()
00862     {
00863         return $this->WeekDays;
00864     }
00865 
00866     /*!
00867      Returns the months of the year as an array. This only supplied for completeness.
00868      \sa weekDays(), monthsNames()
00869     */
00870     function months()
00871     {
00872         return $this->Months;
00873     }
00874 
00875     /*!
00876      Returns the names of months as an array.
00877      \sa months()
00878     */
00879     function monthsNames()
00880     {
00881         return $this->LongMonthNames;
00882     }
00883 
00884     /*!
00885      Returns the same array as in weekDays() but with all days translated to text.
00886     */
00887     function weekDayNames( $short = false )
00888     {
00889         if ( $short )
00890             $dayList = $this->ShortWeekDayNames;
00891         else
00892             $dayList = $this->LongWeekDayNames;
00893 
00894         $resultDayList = array();
00895         foreach ( $this->WeekDays as $day )
00896         {
00897             $resultDayList[ $day ] = $dayList[ $day ];
00898         }
00899         return $resultDayList;
00900     }
00901 
00902     /*!
00903      Returns the same array as in weekDayNames() but with short version of days.
00904     */
00905     function weekDayShortNames()
00906     {
00907         return $this->weekDayNames( true );
00908     }
00909 
00910     /*!
00911      Returns the method name belonging to a qualifier
00912     */
00913     function getFormattingFunction( $qualifier )
00914     {
00915         if ( isset( $this->functionMap[$qualifier] ) )
00916         {
00917             return $this->functionMap[$qualifier];
00918         }
00919         else
00920         {
00921             return false;
00922         }
00923     }
00924 
00925     /*!
00926      Returns eZLocale object by HTTP locale code $httpLocaleCode
00927     */
00928     static function fetchByHttpLocaleCode( $httpLocaleCode )
00929     {
00930         $locales = self::localeList( true );
00931         foreach ( $locales as $locale )
00932         {
00933             if ( $locale->httpLocaleCode() == $httpLocaleCode )
00934                 return $locale;
00935         }
00936 
00937         return false;
00938     }
00939 
00940     /*!
00941      Formats the time $time according to locale information and returns it. If $time
00942      is not specified the current time is used.
00943     */
00944     function formatTime( $time = false )
00945     {
00946         return $this->formatTimeType( $this->TimeFormat, $time );
00947     }
00948 
00949     /*!
00950      Formats the time $time according to locale information for short times and returns it. If $time
00951      is not specified the current time is used.
00952     */
00953     function formatShortTime( $time = false )
00954     {
00955         return $this->formatTimeType( $this->ShortTimeFormat, $time );
00956     }
00957 
00958     /*!
00959      Formats the time $time according to the format $fmt. You shouldn't call this
00960      directly unless you want to deviate from the locale settings.
00961      \sa formatTime(), formatShortTime()
00962     */
00963     function formatTimeType( $fmt, $time = false )
00964     {
00965         if ( $time == false )
00966             $time = time();
00967 
00968         $text = date( eZLocale::transformToPHPFormat( $fmt, $this->TimePHPArray ), $time );
00969         return  str_replace( array( '%a', '%A' ),
00970                              array( $this->meridiemName( $time, false ),
00971                                     $this->meridiemName( $time, true ) ),
00972                              $text );
00973     }
00974 
00975     /*!
00976      Returns the name for the meridiem ie am (ante meridiem) or pm (post meridiem).
00977      If $time is not supplied or false the current time is used. If $upcase is false
00978      the name is in lowercase otherwise uppercase.
00979      The time is defined to be am if the hour is less than 12 and pm otherwise. Normally
00980      the hours 00 and 12 does not have am/pm attached and are instead called Midnight and Noon,
00981      but for simplicity the am/pm is always attached (if the locale allows it).
00982     */
00983     function meridiemName( $time = false, $upcase = false )
00984     {
00985         if ( $time == false )
00986             $time = time();
00987         $hour = date( 'G', $time );
00988         $name = $hour < 12 ? $this->AM : $this->PM;
00989         if ( $upcase )
00990             $name = strtoupper( $name );
00991         return $name;
00992     }
00993 
00994     /*!
00995      Formats the date $date according to locale information and returns it. If $date
00996      is not specified the current date is used.
00997     */
00998     function formatDate( $date = false )
00999     {
01000         return $this->formatDateType( $this->DateFormat, $date );
01001     }
01002 
01003     /*!
01004      Formats the date $date according to locale information for short dates and returns it. If $date
01005      is not specified the current date is used.
01006     */
01007     function formatShortDate( $date = false )
01008     {
01009         return $this->formatDateType( $this->ShortDateFormat, $date );
01010     }
01011 
01012     /*!
01013      Formats the date and time $date according to locale information and returns it. If $date
01014      is not specified the current date is used.
01015     */
01016     function formatDateTime( $date = false )
01017     {
01018         return $this->formatDateTimeType( $this->DateTimeFormat, $date );
01019     }
01020 
01021     /*!
01022      Formats the date and time $date according to locale information for short dates and returns it.
01023      If $date is not specified the current date is used.
01024     */
01025     function formatShortDateTime( $date = false )
01026     {
01027         return $this->formatDateTimeType( $this->ShortDateTimeFormat, $date );
01028     }
01029 
01030     /*!
01031      Formats the date $date according to the format $fmt. You shouldn't call this
01032      directly unless you want to deviate from the locale settings.
01033      \sa formatDate(), formatShortDate()
01034     */
01035     function formatDateType( $fmt, $date = false )
01036     {
01037         if ( $date === false )
01038         {
01039             $date = time();
01040         }
01041         else if ( empty( $date ) )
01042         {
01043             $date = 0;
01044         }
01045 
01046         $text = date( eZLocale::transformToPHPFormat( $fmt, $this->DatePHPArray ), $date );
01047         return str_replace( array( '%D', '%l', '%M', '%F' ),
01048                             array( $this->shortDayName( date( 'w', $date ) ),
01049                                    $this->longDayName( date( 'w', $date ) ),
01050                                    $this->shortMonthName( date( 'n', $date ) ),
01051                                    $this->longMonthName( date( 'n', $date ) ) ),
01052                             $text );
01053     }
01054 
01055     /*!
01056      Formats the date and time \a $datetime according to the format \a $fmt.
01057      You shouldn't call this directly unless you want to deviate from the locale settings.
01058      \sa formatDateTime(), formatShortDateTime()
01059     */
01060     function formatDateTimeType( $fmt, $datetime = false )
01061     {
01062         if ( $datetime === false )
01063         {
01064             $datetime = time();
01065         }
01066         else if ( empty( $datetime ) )
01067         {
01068             $datetime = 0;
01069         }
01070 
01071         $text = date( eZLocale::transformToPHPFormat( $fmt, $this->DateTimePHPArray ), $datetime );
01072         // Replace some special 'date' formats that needs to be handled
01073         // internally by the i18n system and not by PHP
01074         return str_replace( array( '%D', '%l', '%M', '%F',
01075                                    '%a', '%A' ),
01076                             array( $this->shortDayName( date( 'w', $datetime ) ),
01077                                    $this->longDayName( date( 'w', $datetime ) ),
01078                                    $this->shortMonthName( date( 'n', $datetime ) ),
01079                                    $this->longMonthName( date( 'n', $datetime ) ),
01080                                    $this->meridiemName( $datetime, false ),
01081                                    $this->meridiemName( $datetime, true ) ),
01082                             $text );
01083     }
01084 
01085     /*!
01086      \private
01087      \static
01088      Transforms the date/time string \a $fmt into a string that can be
01089      passed to the PHP function 'date'.
01090      \param $fmt An eZ Publish locale format, %x means a 'formatting character' from PHPs 'date' function.
01091      \param $allowed An array with characters that are considered allowed 'formatting characters'
01092                      Any character not found in this array will be kept intact by escaping it.
01093      \sa http://www.php.net/manual/en/function.date.php
01094     */
01095     static function transformToPHPFormat( $fmt, $allowed )
01096     {
01097         // This goes trough each of the characters in the format
01098         // string $fmt, if a valid %x character is found it is replaced
01099         // with just x (like date expects).
01100         // It will also escape all characters in the range a-z and A-Z
01101         // expect does that are valid %x formats.
01102         // A special case is formats of the type %%, they will become %
01103         $dateFmt = '';
01104         $offs = 0;
01105         $len = strlen( $fmt );
01106         while ( $offs < $len )
01107         {
01108             $char = $fmt[$offs];
01109             if ( $char == '%' )
01110             {
01111                 if ( $offs + 1 < $len )
01112                 {
01113                     $type = $fmt[$offs + 1];
01114                     if ( $type == '%' )
01115                     {
01116                         $dateFmt .= '%';
01117                     }
01118                     else if ( ( $type >= 'a' and $type <= 'z' ) or
01119                               ( $type >= 'A' and $type <= 'Z' ) )
01120                     {
01121                         // Escape the $type character if it is not in
01122                         // the allowed 'format character' list
01123                         if ( !in_array( $type, $allowed ) )
01124                             $dateFmt .= '%\\';
01125                         $dateFmt .= $type;
01126                     }
01127                     else
01128                     {
01129                         $dateFmt .= $char . $type;
01130                     }
01131                     $offs += 2;
01132                 }
01133                 else
01134                 {
01135                     $dateFmt .= '\\' . $char;
01136                     ++$offs;
01137                 }
01138             }
01139             else
01140             {
01141                 // Escape a-zA-Z to avoid PHPs 'date' using them as a 'format character'
01142                 if ( ( $char >= 'a' and $char <= 'z' ) or
01143                      ( $char >= 'A' and $char <= 'Z' ) )
01144                     $dateFmt .= '\\';
01145                 $dateFmt .= $char;
01146                 ++$offs;
01147             }
01148         }
01149         return $dateFmt;
01150     }
01151 
01152     /*!
01153      Formats the number $number according to locale information and returns it.
01154     */
01155     function formatNumber( $number )
01156     {
01157         $neg = $number < 0;
01158         $num = $neg ? -$number : $number;
01159         $text = number_format( $num, $this->FractDigits, $this->DecimalSymbol, $this->ThousandsSeparator );
01160         return ( $neg ? $this->NegativeSymbol : $this->PositiveSymbol ) . $text;
01161     }
01162 
01163     /*!
01164      Formats the number according locale to the representation used internally in PHP
01165     */
01166     function internalNumber( $number )
01167     {
01168         if ( preg_match( '/^(['.$this->PositiveSymbol.']|['.$this->NegativeSymbol.'])?([0-9]*|[0-9]{1,3}(['.$this->ThousandsSeparator.'][0-9]{3,3})*)(['.$this->DecimalSymbol.'][0-9]+)?$/', trim( $number ) ) )
01169         {
01170             $number = str_replace( ' ', '', $number );
01171             if ( $this->PositiveSymbol )
01172                 $number = str_replace( $this->PositiveSymbol, '', $number );
01173             $number = str_replace( $this->NegativeSymbol, '-', $number );
01174             $number = str_replace( $this->ThousandsSeparator, '', $number );
01175             $number = str_replace( $this->DecimalSymbol, '.', $number );
01176         }
01177         return $number;
01178     }
01179 
01180     /*!
01181      \deprecated
01182      Formats the currency $number according to locale information and returns it. If $as_html
01183      is true all spaces are converted to &nbsp; before being returned.
01184     */
01185     function formatCurrency( $number, $as_html = true )
01186     {
01187         return $this->formatCurrencyWithSymbol( $number, $this->CurrencySymbol );
01188     }
01189 
01190     /*!
01191       Formats the same as formatCurrency, but drops the currency sign
01192 
01193       \param currency input
01194     */
01195     function formatCleanCurrency( $number )
01196     {
01197         $text = $this->formatCurrencyWithSymbol( $number, '' );
01198         return trim( $text );
01199     }
01200 
01201     function formatCurrencyWithSymbol( $number, $symbol )
01202     {
01203         $neg = $number < 0;
01204         $num = $neg ? -$number : $number;
01205         $num_text = number_format( $num, $this->CurrencyFractDigits,
01206                                    $this->CurrencyDecimalSymbol, $this->CurrencyThousandsSeparator );
01207         return str_replace( array( '%c', '%p', '%q' ),
01208                             array( $symbol,
01209                                    $neg ? $this->CurrencyNegativeSymbol : $this->CurrencyPositiveSymbol,
01210                                    $num_text ),
01211                             $neg ? $this->CurrencyNegativeFormat : $this->CurrencyPositiveFormat );
01212     }
01213 
01214     function translatedCountryNames()
01215     {
01216         return $this->CountryNames;
01217     }
01218 
01219     /*!
01220      Formats the currency according locale to the representation used internally in PHP
01221     */
01222     function internalCurrency( $number )
01223     {
01224         if ( preg_match( '/^(['.$this->CurrencyPositiveSymbol.']|['.$this->CurrencyNegativeSymbol.'])?([0-9]*|[0-9]{1,3}(['.$this->ThousandsSeparator.'][0-9]{3,3})*)(['.$this->CurrencyDecimalSymbol.'][0-9]+)?$/', trim( $number ) ) )
01225         {
01226             $number = str_replace( ' ', '', $number );
01227             if ( $this->CurrencyPositiveSymbol )
01228                 $number = str_replace( $this->CurrencyPositiveSymbol, '', $number );
01229             $number = str_replace( $this->CurrencyNegativeSymbol, '-', $number );
01230             $number = str_replace( $this->CurrencyThousandsSeparator, '', $number );
01231             $number = str_replace( $this->CurrencyDecimalSymbol, '.', $number );
01232         }
01233         return $number;
01234     }
01235 
01236     /*!
01237      Returns the short name of the day number $num.
01238      The different numbers for the days are:
01239      Sunday    = 0
01240      Monday    = 1
01241      Tuesday   = 2
01242      Wednesday = 3
01243      Thursday  = 4
01244      Friday    = 5
01245      Saturday  = 6
01246      This functions is usually used together with weekDays().
01247      \sa longDayName()
01248     */
01249     function shortDayName( $num )
01250     {
01251         if ( $num >= 0 and $num <= 6 )
01252         {
01253             $code = $this->DayNames[$num];
01254             $name = $this->ShortDayNames[$code];
01255         }
01256         else
01257         {
01258             $name = null;
01259         }
01260         return $name;
01261     }
01262 
01263     /*!
01264      Returns the long name of the day number $num.
01265      The different numbers for the days are:
01266      Sunday    = 0
01267      Monday    = 1
01268      Tuesday   = 2
01269      Wednesday = 3
01270      Thursday  = 4
01271      Friday    = 5
01272      Saturday  = 6
01273      This functions is usually used together with weekDays().
01274      \sa shortDayName()
01275     */
01276     function longDayName( $num )
01277     {
01278         if ( $num >= 0 and $num <= 6 )
01279         {
01280             $code = $this->DayNames[$num];
01281             $name = $this->LongDayNames[$code];
01282         }
01283         else
01284         {
01285             $name = null;
01286         }
01287         return $name;
01288     }
01289 
01290     /*!
01291      Returns the short name of the month number $num.
01292      The different numbers for the months are:
01293      Januray   = 1
01294      February  = 2
01295      March     = 3
01296      April     = 4
01297      May       = 5
01298      June      = 6
01299      July      = 7
01300      August    = 8
01301      September = 9
01302      October   = 10
01303      November  = 11
01304      December  = 12
01305      This functions is usually used together with months().
01306      \sa longMonthName()
01307     */
01308     function shortMonthName( $num )
01309     {
01310         if ( $num >= 1 and $num <= 12 )
01311         {
01312             $code = $this->MonthNames[$num];
01313             $name = $this->ShortMonthNames[$code];
01314         }
01315         else
01316         {
01317             $name = null;
01318         }
01319         return $name;
01320     }
01321 
01322     /*!
01323      Returns the long name of the month number $num.
01324      The different numbers for the months are:
01325      Januray   = 1
01326      February  = 2
01327      March     = 3
01328      April     = 4
01329      May       = 5
01330      June      = 6
01331      July      = 7
01332      August    = 8
01333      September = 9
01334      October   = 10
01335      November  = 11
01336      December  = 12
01337      This functions is usually used together with months().
01338      \sa shortMonthName()
01339     */
01340     function longMonthName( $num )
01341     {
01342         if ( $num >= 1 and $num <= 12 )
01343         {
01344             $code = $this->MonthNames[$num];
01345             $name = $this->LongMonthNames[$code];
01346         }
01347         else
01348         {
01349             $name = null;
01350         }
01351         return $name;
01352     }
01353 
01354     /*!
01355      \static
01356      \return a list of locale objects which was found in the system.
01357      \param $asObject If \c true it returns each element as an eZLocale object
01358      \param $withVariations If \c true it will include variations of locales (ends with @identifier)
01359     */
01360     static function localeList( $asObject = false, $withVariations = true )
01361     {
01362         $locales =& $GLOBALS['eZLocaleLocaleStringList'];
01363         if ( !is_array( $locales ) )
01364         {
01365             $localeRegexp = eZLocale::localeRegexp( $withVariations, false );
01366             $locales = array();
01367             $dir = opendir( 'share/locale' );
01368             while( ( $file = readdir( $dir ) ) !== false )
01369             {
01370                 if ( preg_match( "/^($localeRegexp)\.ini$/", $file, $regs ) )
01371                 {
01372                     $locales[] = $regs[1];
01373                 }
01374             }
01375             closedir( $dir );
01376             $locales = array_unique( $locales );
01377             sort( $locales );
01378             if ( $asObject )
01379             {
01380                 $localeObjects = array();
01381                 foreach ( $locales as $locale )
01382                 {
01383                     $localeInstance = eZLocale::instance( $locale );
01384                     if ( $localeInstance )
01385                         $localeObjects[] = $localeInstance;
01386                 }
01387                 $locales = $localeObjects;
01388             }
01389         }
01390         return $locales;
01391     }
01392 
01393     /*!
01394      \static
01395      \return a list of countries which was found in the system, the countries are in identifier form,
01396              for instance: NO, GB, US
01397      \param $withVariations If \c true it will include variations of locales (ends with @identifier)
01398     */
01399     static function countryList( $withVariations = true )
01400     {
01401         $countries =& $GLOBALS['eZLocaleCountryList'];
01402         if ( !is_array( $countries ) )
01403         {
01404             $localeRegexp = eZLocale::localeRegexp( $withVariations, false );
01405             $countries = array();
01406             $dir = opendir( 'share/locale' );
01407             while( ( $file = readdir( $dir ) ) !== false )
01408             {
01409                 if ( preg_match( "/^$localeRegexp\.ini$/", $file, $regs ) )
01410                 {
01411                     $countries[] = $regs[3];
01412                 }
01413             }
01414             closedir( $dir );
01415             $countries = array_unique( $countries );
01416             sort( $countries );
01417         }
01418         return $countries;
01419     }
01420 
01421     /*!
01422      \static
01423      \return a list of languages which was found in the system, the languages are in identifier form,
01424              for instance: nor, eng
01425      \param $withVariations If \c true it will include variations of locales (ends with @identifier)
01426     */
01427     static function languageList( $withVariations = true )
01428     {
01429         $languages =& $GLOBALS['eZLocaleLanguageist'];
01430         if ( !is_array( $languages ) )
01431         {
01432             $localeRegexp = eZLocale::localeRegexp( $withVariations, false );
01433             $languages = array();
01434             $dir = opendir( 'share/locale' );
01435             while( ( $file = readdir( $dir ) ) !== false )
01436             {
01437                 if ( preg_match( "/^$localeRegexp\.ini$/", $file, $regs ) )
01438                 {
01439                     $languages[] = $regs[1];
01440                 }
01441             }
01442             closedir( $dir );
01443             $languages = array_unique( $languages );
01444             sort( $languages );
01445         }
01446         return $languages;
01447     }
01448 
01449 
01450     /*!
01451      Returns the eZINI object for the locale ini file.
01452      \warning Do not modify this object.
01453     */
01454     function localeFile( $withVariation = false )
01455     {
01456         $type = $withVariation ? 'variation' : 'default';
01457         if ( !( $this->LocaleINI[$type] instanceof eZINI ) )
01458         {
01459             $country = $this->countryCode();
01460             $countryVariation = $this->countryVariation();
01461             $language = $this->languageCode();
01462             $locale = $language;
01463             if ( $country !== '' )
01464                 $locale .= '-' . $country;
01465             if ( $withVariation )
01466             {
01467                 if ( $countryVariation !== '' )
01468                     $locale .= '@' . $countryVariation;
01469             }
01470             $localeFile = $locale . '.ini';
01471             if ( eZLocale::isDebugEnabled() )
01472             {
01473                 eZDebug::writeNotice( "Requesting $localeFile", __METHOD__ );
01474             }
01475             if ( eZINI::exists( $localeFile, 'share/locale' ) )
01476                 $this->LocaleINI[$type] = eZINI::instance( $localeFile, 'share/locale' );
01477         }
01478         return $this->LocaleINI[$type];
01479     }
01480 
01481     /*!
01482      Returns the eZINI object for the country ini file.
01483      \warning Do not modify this object.
01484     */
01485     function countryFile( $withVariation = false )
01486     {
01487         $type = $withVariation ? 'variation' : 'default';
01488         if ( !( $this->CountryINI[$type] instanceof eZINI ) )
01489         {
01490             $country = $this->countryCode();
01491             $countryVariation = $this->countryVariation();
01492             $locale = $country;
01493             if ( $withVariation )
01494             {
01495                 if ( $countryVariation !== '' )
01496                     $locale .= '@' . $countryVariation;
01497             }
01498             $countryFile = 'country/' . $locale . '.ini';
01499             if ( eZLocale::isDebugEnabled() )
01500             {
01501                 eZDebug::writeNotice( "Requesting $countryFile", __METHOD__ );
01502             }
01503             if ( eZINI::exists( $countryFile, 'share/locale' ) )
01504                 $this->CountryINI[$type] = eZINI::instance( $countryFile, 'share/locale' );
01505         }
01506         return $this->CountryINI[$type];
01507     }
01508 
01509     /*!
01510      Returns the eZINI object for the language ini file.
01511      \warning Do not modify this object.
01512     */
01513     function languageFile( $withVariation = false )
01514     {
01515         $type = $withVariation ? 'variation' : 'default';
01516         if ( !( $this->LanguageINI[$type] instanceof eZINI ) )
01517         {
01518             $language = $this->languageCode();
01519             $countryVariation = $this->countryVariation();
01520             $locale = $language;
01521             if ( $withVariation )
01522             {
01523                 if ( $countryVariation !== '' )
01524                     $locale .= '@' . $countryVariation;
01525             }
01526             $languageFile = 'language/' . $locale . '.ini';
01527             if ( eZLocale::isDebugEnabled() )
01528             {
01529                 eZDebug::writeNotice( "Requesting $languageFile", __METHOD__ );
01530             }
01531             if ( eZINI::exists( $languageFile, 'share/locale' ) )
01532                 $this->LanguageINI[$type] = eZINI::instance( $languageFile, 'share/locale' );
01533         }
01534         return $this->LanguageINI[$type];
01535     }
01536 
01537     /**
01538      * Returns a shared instance of the eZLocale class pr locale string.
01539      * If $localeString is not specified the default local string in site.ini is used.
01540      * Use this instead of newing eZLocale to benefit from speed and unified access.
01541      * note: Use create() if you need to get a new unique copy you can alter.
01542      *
01543      * @param string|false $localeString
01544      * @return eZLocale
01545      */
01546     static function instance( $localeString = false )
01547     {
01548         if ( $localeString === false )
01549         {
01550             $localeStringDefault =& $GLOBALS["eZLocaleStringDefault"];
01551             if ( !isset( $localeStringDefault ) )
01552             {
01553                 $ini = eZINI::instance();
01554                 $localeString = $ini->variable( 'RegionalSettings', 'Locale' );
01555                 /* Cache this answer to prevent countless calls to retrieve this
01556                  * from the INI settings */
01557                 $localeStringDefault = $localeString;
01558             }
01559             else
01560             {
01561                 /* Used cached version */
01562                 $localeString = $localeStringDefault;
01563             }
01564         }
01565 
01566         $globalsKey = "eZLocaleInstance_$localeString";
01567 
01568         if ( !isset( $GLOBALS[$globalsKey] ) ||
01569              !( $GLOBALS[$globalsKey] instanceof eZLocale ) )
01570         {
01571             $GLOBALS[$globalsKey] = new eZLocale( $localeString );
01572         }
01573         return $GLOBALS[$globalsKey];
01574     }
01575 
01576     /*!
01577      \static
01578      Similar to instance() but will always create a new copy.
01579     */
01580     static function create( $localeString = false )
01581     {
01582         if ( $localeString === false )
01583         {
01584             $ini = eZINI::instance();
01585             $localeString = $ini->variable( 'RegionalSettings', 'Locale' );
01586         }
01587         return new eZLocale( $localeString );
01588     }
01589 
01590     /*!
01591      \static
01592      \return true if debugging of internals is enabled, this will display
01593      which files are loaded and when cache files are created.
01594       Set the option with setIsDebugEnabled().
01595     */
01596     static function isDebugEnabled()
01597     {
01598         if ( !isset( $GLOBALS['eZLocaleDebugInternalsEnabled'] ) )
01599              $GLOBALS['eZLocaleDebugInternalsEnabled'] = self::DEBUG_INTERNALS;
01600         return $GLOBALS['eZLocaleDebugInternalsEnabled'];
01601     }
01602 
01603     /*!
01604      \static
01605      Sets whether internal debugging is enabled or not.
01606     */
01607     static function setIsDebugEnabled( $debug )
01608     {
01609         $GLOBALS['eZLocaleDebugInternalsEnabled'] = $debug;
01610     }
01611 
01612     /*!
01613      \static
01614     */
01615     static function resetGlobals( $localeString = false )
01616     {
01617         if ( $localeString === false )
01618         {
01619             $localeStringDefault =& $GLOBALS["eZLocaleStringDefault"];
01620             if ( isset( $localeStringDefault ) )
01621             {
01622                 $localeString = $localeStringDefault;
01623             }
01624         }
01625 
01626         unset( $GLOBALS["eZLocaleInstance_$localeString"] );
01627         unset( $GLOBALS["eZLocaleStringDefault"] );
01628     }
01629 
01630     //@{
01631     public $IsValid;
01632     //@}
01633 
01634     //@{
01635     /// Format of dates
01636     public $DateFormat;
01637     /// Format of short dates
01638     public $ShortDateFormat;
01639     /// Format of times
01640     public $TimeFormat;
01641     /// Format of short times
01642     public $ShortTimeFormat;
01643     /// True if monday is the first day of the week
01644     public $MondayFirst;
01645     /// AM and PM names
01646     public $AM, $PM;
01647     //@}
01648 
01649     //@{
01650     /// Numbers
01651     public $DecimalSymbol;
01652     public $ThousandsSeparator;
01653     public $FractDigits;
01654     public $NegativeSymbol;
01655     public $PositiveSymbol;
01656     //@}
01657 
01658     //@{
01659     /// Currency
01660     public $CurrencyDecimalSymbol;
01661     public $CurrencyThousandsSeparator;
01662     public $CurrencyFractDigits;
01663     public $CurrencyNegativeSymbol;
01664     public $CurrencyPositiveSymbol;
01665     public $CurrencySymbol;
01666     public $CurrencyPositiveFormat;
01667     public $CurrencyNegativeFormat;
01668     //@}
01669 
01670     //@{
01671     /// Help arrays
01672     public $DayNames;
01673     public $ShortDayNames, $LongDayNames;
01674     public $MonthNames;
01675     public $ShortMonthNames, $LongMonthNames;
01676     public $WeekDays, $Months;
01677     public $ShortWeekDayNames, $LongWeekDayNames;
01678 
01679     public $TimeArray;
01680     public $DateArray;
01681     public $TimePHPArray;
01682     public $DatePHPArray;
01683     //@}
01684 
01685     //@{
01686     /// Objects
01687     public $Country;
01688     public $CountryCode;
01689     public $CountryVariation;
01690     public $CountryComment;
01691     public $LanguageComment;
01692     public $LocaleINI;
01693     public $CountryINI;
01694     public $LanguageINI;
01695     /// The language code, for instance nor-NO, or eng-GB
01696     public $LanguageCode;
01697     /// Name of the language
01698     public $LanguageName;
01699     /// Internationalized name of the language
01700     public $IntlLanguageName;
01701     public $CountryNames;
01702     //@}
01703 }
01704 
01705 ?>