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