| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.locale.introduction">
- <title>Introduction</title>
- <para>
- <classname>Zend_Locale</classname> is the Frameworks answer to the question, "How can the
- same application be used around the whole world?" Most people will say, "That's easy. Let's
- translate all our output to several languages." However, using simple translation tables to
- map phrases from one language to another is not sufficient. Different regions will have
- different conventions for first names, surnames, salutory titles, formatting of numbers,
- dates, times, currencies, etc.
- </para>
- <para>
- We need <ulink
- url="http://en.wikipedia.org/wiki/Internationalization_and_localization">Localization
- and complementary Internationalization</ulink>. Both are often abbreviated to
- <emphasis>L10n</emphasis> and <emphasis>I18n</emphasis>. Internationalization
- refers more to support for use of systems, regardless of special needs unique to groups of
- users related by language, region, number format conventions, financial conventions, time
- and date conventions, etc. Localization involves adding explicit support to systems for
- special needs of these unique groups, such as language translation, and support for local
- customs or conventions for communicating plurals, dates, times, currencies, names, symbols,
- sorting and ordering, etc. <emphasis>L10n</emphasis> and <emphasis>I18n</emphasis>
- compliment each other. Zend Framework provides support for these through a combination of
- components, including <classname>Zend_Locale</classname>, <classname>Zend_Date</classname>,
- <classname>Zend_Measure</classname>, <classname>Zend_Translate</classname>,
- <classname>Zend_Currency</classname>, and <classname>Zend_TimeSync</classname>.
- </para>
- <tip>
- <title>Zend_Locale and setLocale()</title>
- <para>
- <ulink url="http://php.net/setlocale">PHP's documentation</ulink> states that
- <methodname>setlocale()</methodname> is not threadsave because it is maintained per
- process and not per thread. This means that, in multithreaded environments, you can have
- the problem that the locale changes while the script never has changed the locale
- itself. This can lead to unexpected behaviour when you use
- <methodname>setlocale()</methodname> in your scripts.
- </para>
- <para>
- When you are using <classname>Zend_Locale</classname> you will not have this
- limitations, because <classname>Zend_Locale</classname> is not related to or coupled
- with <acronym>PHP</acronym>'s <methodname>setlocale()</methodname>.
- </para>
- </tip>
- <sect2 id="zend.locale.whatislocalization">
- <title>What is Localization</title>
- <para>
- Localization means that an application (or homepage) can be used from different users
- which speak different languages. But as you already have expected Localization means
- more than only translating strings. It includes
- </para>
- <itemizedlist mark='opencircle'>
- <listitem>
- <para>
- <classname>Zend_Locale</classname> - Backend support of locales available for
- localization support within other Zend Framework components.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Translate</classname> - Translating of strings.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Date</classname> - Localization of dates, times.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Calendar</classname> - Localization of calendars (support for
- non-Gregorian calendar systems)
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Currency</classname> - Localization of currencies.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Locale_Format</classname> - Parsing and generating localized
- numbers.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Locale_Data</classname> - Retrieve localized standard strings
- as country names, language names and <ulink
- url="http://unicode.org/cldr/">more from the
- <acronym>CLDR</acronym></ulink>.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.locale.whatis">
- <title>What is a Locale?</title>
- <para>
- Each computer user makes use of Locales, even when they don't know it. Applications
- lacking localization support, normally have implicit support for one particular locale
- (the locale of the author). When a class or function makes use of localization, we say
- it is <emphasis>locale-aware</emphasis>. How does the code know which localization the
- user is expecting?
- </para>
- <para>
- A locale string or object identifying a supported locale gives
- <classname>Zend_Locale</classname> and its subclasses access to information about the
- language and region expected by the user. Correct formatting, normalization, and
- conversions are made based on this information.
- </para>
- </sect2>
- <sect2 id="zend.locale.representation">
- <title>How are Locales Represented?</title>
- <para>
- Locale identifiers consist of information about the user's language and
- preferred/primary geographic region (e.g. state or province of home or workplace). The
- locale identifier strings used in Zend Framework are internationally defined standard
- abbreviations of language and region, written as <emphasis>language_REGION</emphasis>.
- Both the language and region parts are abbreviated to alphabetic,
- <acronym>ASCII</acronym> characters.
- </para>
- <note>
- <para>
- Be aware that there exist not only locales with 2 characters as most people think.
- Also there are languages and regions which are not only abbreviated with 2
- characters. Therefor you should NOT strip the region and language yourself, but use
- <classname>Zend_Locale</classname> when you want to strip language or region from a
- locale string. Otherwise you could have unexpected behaviour within your code when
- you do this yourself.
- </para>
- </note>
- <para>
- A user from USA would expect the language English and the region
- <constant>USA</constant>, yielding the locale identifier "en_US". A user in Germany
- would expect the language German and the region Germany,
- yielding the locale identifier "de_DE". See the <ulink
- url="http://unicode.org/cldr/data/diff/supplemental/languages_and_territories.html">list
- of pre-defined locale and region combinations</ulink>, if you need to select a
- specific locale within Zend Framework.
- </para>
- <example id="zend.locale.representation.example-1">
- <title>Choosing a specific locale</title>
- <programlisting language="php"><![CDATA[
- $locale = new Zend_Locale('de_DE'); // German language _ Germany
- ]]></programlisting>
- </example>
- <para>
- A German user in America might expect the language German and the region
- <constant>USA</constant>, but these non-standard mixes are not supported directly as
- recognized "locales". Instead, if an invalid combination is used, then it will
- automatically be truncated by dropping the region code. For example, "de_IS" would be
- truncated to "de", and "xh_RU" would be truncated to "xh", because neither of these
- combinations are valid. Additionally, if the base language code is not supported (e.g.
- "zz_US") or does not exist, then a default "root" locale will be used. The "root" locale
- has default definitions for internationally recognized representations of dates, times,
- numbers, currencies, etc. The truncation process depends on the requested information,
- since some combinations of language and region might be valid for one type of data (e.g.
- dates), but not for another (e.g. currency format).
- </para>
- <para>
- Beware of historical changes, as Zend Framework components do not know about or attempt
- to track the numerous timezone changes made over many years by many regions. For
- example, <ulink url="http://www.statoids.com/tus.html">we can see a historical
- list</ulink> showing dozens of changes made by governments to when and if a
- particular region observes Daylight Savings Time, and even which timezone a particular
- geographic area belongs. Thus, when performing date math, the math performed by Zend
- Framework components will not adjust for these changes, but instead will give the
- correct time for the timezone using current, modern rules for <acronym>DST</acronym> and
- timezone assignment for geographic regions.
- </para>
- </sect2>
- <sect2 id="zend.locale.selection">
- <title>Selecting the Right Locale</title>
- <para>
- For most situations, <command>new Zend_Locale()</command> will automatically select the
- correct locale, with preference given to information provided by the user's web browser.
- However, if <command>new Zend_Locale(Zend_Locale::ENVIRONMENT)</command> is used, then
- preference will be given to using the host server's environment configuration, as
- described below.
- </para>
- <example id="zend.locale.selection.example-1">
- <title>Automatically selecting a locale</title>
- <programlisting language="php"><![CDATA[
- $locale = new Zend_Locale();
- // default behavior, same as above
- $locale1 = new Zend_Locale(Zend_Locale::BROWSER);
- // prefer settings on host server
- $locale2 = new Zend_Locale(Zend_Locale::ENVIRONMENT);
- // perfer framework app default settings
- $locale3 = new Zend_Locale(Zend_Locale::FRAMEWORK);
- ]]></programlisting>
- </example>
- <para>
- The search algorithm used by <classname>Zend_Locale</classname> for automatic selection
- of a locale uses three sources of information:
- <orderedlist>
- <listitem>
- <para>
- const <constant>Zend_Locale::BROWSER</constant> - The user's Web browser
- provides information with each request, which is published by
- <acronym>PHP</acronym> in the global variable
- <varname>$_SERVER['HTTP_ACCEPT_LANGUAGE']</varname>. if no matching locale
- can be found, then preference is given to <constant>ENVIRONMENT</constant>
- and lastly <constant>FRAMEWORK</constant>.
- </para>
- </listitem>
- <listitem>
- <para>
- const <constant>Zend_Locale::ENVIRONMENT</constant> - <acronym>PHP</acronym>
- publishes the host server's locale via the <acronym>PHP</acronym> internal
- function <methodname>setlocale()</methodname>. If no matching locale can be
- found, then preference is given to <constant>FRAMEWORK</constant> and lastly
- <constant>BROWSER</constant>.
- </para>
- </listitem>
- <listitem>
- <para>
- const <constant>Zend_Locale::FRAMEWORK</constant> - When Zend Framework has
- a standardized way of specifying component defaults (planned, but not yet
- available), then using this constant during instantiation will give
- preference to choosing a locale based on these defaults. If no matching
- locale can be found, then preference is given to
- <constant>ENVIRONMENT</constant> and lastly <constant>BROWSER</constant>.
- </para>
- </listitem>
- </orderedlist>
- </para>
- </sect2>
- <sect2 id="zend.locale.selection.automatic">
- <title>Usage of automatic Locales</title>
- <para>
- <classname>Zend_Locale</classname> provides three additional locales. These locales do
- not belong to any language or region. They are "automatic" locales which means that they
- have the same effect as the method <methodname>getDefault()</methodname> but without the
- negative effects like creating an instance. These "automatic" locales can be used
- anywhere, where also a standard locale and also the definition of a locale, its string
- representation, can be used. This offers simplicity for situations like working with
- locales which are provided by a browser.
- </para>
- <para>
- There are three locales which have a slightly different behaviour:
- <orderedlist>
- <listitem>
- <para>
- '<property>browser</property>' - <classname>Zend_Locale</classname> should
- work with the information which is provided by the user's Web browser. It
- is published by <acronym>PHP</acronym> in the global variable
- <constant>$_SERVER['HTTP_ACCEPT_LANGUAGE']</constant>.
- </para>
- <para>
- If a user provides more than one locale within his browser,
- <classname>Zend_Locale</classname> will use the first found locale. If the
- user does not provide a locale or the script is being called from the
- command line the automatic locale '<property>environment</property>' will
- automatically be used and returned.
- </para>
- </listitem>
- <listitem>
- <para>
- '<property>environment</property>' - <classname>Zend_Locale</classname>
- should work with the information which is provided by the host server. It
- is published by <acronym>PHP</acronym> via the internal function
- <methodname>setlocale()</methodname>.
- </para>
- <para>
- If a environment provides more than one locale,
- <classname>Zend_Locale</classname> will use the first found locale. If the
- host does not provide a locale the automatic locale
- '<property>browser</property>' will automatically be used and returned.
- </para>
- </listitem>
- <listitem>
- <para>
- '<property>auto</property>' - <classname>Zend_Locale</classname> should
- automatically detect any locale which can be worked with. It will first
- search for a users locale and then, if not successful, search for the host
- locale.
- </para>
- <para>
- If no locale can be detected, it will throw an exception and tell you that
- the automatic detection has been failed.
- </para>
- </listitem>
- </orderedlist>
- </para>
- <example id="zend.locale.selection.automatic.example-1">
- <title>Using automatic locales</title>
- <programlisting language="php"><![CDATA[
- // without automatic detection
- //$locale = new Zend_Locale(Zend_Locale::BROWSER);
- //$date = new Zend_Date($locale);
- // with automatic detection
- $date = new Zend_Date('auto');
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.locale.defaultlocale">
- <title>Using a default Locale</title>
- <para>
- In some environments it is not possible to detect a locale automatically. You can expect
- this behaviour when you get an request from command line or the requesting browser has
- no language tag set and additionally your server has the default locale 'C' set or
- another proprietary locale.
- </para>
- <para>
- In such cases <classname>Zend_Locale</classname> will normally throw an exception with a
- message that the automatic detection of any locale was not successful. You have two
- options to handle such a situation. Either through setting a new locale per hand, or
- defining a default locale.
- </para>
- <example id="zend.locale.defaultlocale.example-1">
- <title>Handling locale exceptions</title>
- <programlisting language="php"><![CDATA[
- // within the bootstrap file
- try {
- $locale = new Zend_Locale('auto');
- } catch (Zend_Locale_Exception $e) {
- $locale = new Zend_Locale('de');
- }
- // within your model/controller
- $date = new Zend_Date($locale);
- ]]></programlisting>
- </example>
- <para>
- But this has one big negative effect. You will have to set your locale object within
- every class using <classname>Zend_Locale</classname>. This could become very unhandy if
- you are using multiple classes.
- </para>
- <para>
- Since Zend Framework Release 1.5 there is a much better way to handle this. You can set
- a default locale which the static <methodname>setDefault()</methodname> method. Of
- course, every unknown or not fully qualified locale will also throw an exception.
- <methodname>setDefault()</methodname> should be the first call before you initiate any
- class using <classname>Zend_Locale</classname>. See the following example for details:
- </para>
- <example id="zend.locale.defaultlocale.example-2">
- <title>Setting a default locale</title>
- <programlisting language="php"><![CDATA[
- // within the bootstrap file
- Zend_Locale::setDefault('de');
- // within your model/controller
- $date = new Zend_Date();
- ]]></programlisting>
- </example>
- <para>
- In the case that no locale can be detected, automatically the locale
- <emphasis>de</emphasis> will be used. Otherwise, the detected locale will be used.
- </para>
- </sect2>
- <sect2 id="zend.locale.interoperate">
- <title>ZF Locale-Aware Classes</title>
- <para>
- In the Zend Framework, locale-aware classes rely on <classname>Zend_Locale</classname>
- to automatically select a locale, as explained above. For example, in a Zend Framework
- web application, constructing a date using <classname>Zend_Date</classname> without
- specifying a locale results in an object with a locale based on information provided by
- the current user's web browser.
- </para>
- <example id="zend.locale.interoperate.example-1">
- <title>Dates default to correct locale of web users</title>
- <programlisting language="php"><![CDATA[
- $date = new Zend_Date('2006',Zend_Date::YEAR);
- ]]></programlisting>
- </example>
- <para>
- To override this default behavior, and force locale-aware Zend Framework components to
- use specific locales, regardless of the origin of your website visitors, explicitly
- specify a locale as the third argument to the constructor.
- </para>
- <example id="zend.locale.interoperate.example-2">
- <title>Overriding default locale selection</title>
- <programlisting language="php"><![CDATA[
- $usLocale = new Zend_Locale('en_US');
- $date = new Zend_Date('2006', Zend_Date::YEAR, $usLocale);
- $temp = new Zend_Measure_Temperature('100,10',
- Zend_Measure::TEMPERATURE,
- $usLocale);
- ]]></programlisting>
- </example>
- <para>
- If you know many objects should all use the same default locale, explicitly specify the
- default locale to avoid the overhead of each object determining the default locale.
- </para>
- <example id="zend.locale.interoperate.example-3">
- <title>Performance optimization when using a default locale</title>
- <programlisting language="php"><![CDATA[
- $locale = new Zend_Locale();
- $date = new Zend_Date('2006', Zend_Date::YEAR, $locale);
- $temp = new Zend_Measure_Temperature('100,10',
- Zend_Measure::TEMPERATURE,
- $locale);
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.locale.frameworkwidelocale">
- <title>Application wide locale</title>
- <para>
- Zend Framework allows the usage of an application wide locale. You simply set an
- instance of <classname>Zend_Locale</classname> to the registry with the key
- 'Zend_Locale'. Then this instance will be used within all locale aware classes of
- Zend Framework. This way you set one locale within your registry and then you can forget
- about setting it again. It will automatically be used in all other classes. See the
- below example for the right usage:
- </para>
- <example id="zend.locale.frameworkwidelocale.example">
- <title>Usage of an application wide locale</title>
- <programlisting language="php"><![CDATA[
- // within your bootstrap
- $locale = new Zend_Locale('de_AT');
- Zend_Registry::set('Zend_Locale', $locale);
- // within your model or controller
- $date = new Zend_Date();
- // print $date->getLocale();
- echo $date->getDate();
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.locale.formatoptions">
- <title>Zend_Locale_Format::setOptions(array $options)</title>
- <para>
- The 'precision' option of a value is used to truncate or stretch extra digits. A value
- of '-1' disables modification of the number of digits in the fractional part of the
- value. The 'locale' option helps when parsing numbers and dates using separators and
- month names. The date format 'format_type' option selects between
- <acronym>CLDR</acronym>/ISO date format specifier tokens and <acronym>PHP</acronym>'s
- date() tokens. The 'fix_date' option enables or disables heuristics that attempt to
- correct invalid dates. The 'number_format' option specifies a default number format for
- use with <methodname>toNumber()</methodname> (see <link
- linkend= "zend.locale.number.localize">this section</link>).
- </para>
- <para>
- The 'date_format' option can be used to specify a default date format string, but beware
- of using getDate(), checkdateFormat() and getTime() after using setOptions() with a
- 'date_format'. To use these four methods with the default date format for a locale, use
- array('date_format' => null, 'locale' => $locale) for their options.
- </para>
- <example id="zend.locale.formatoptions.example-1">
- <title>Dates default to correct locale of web users</title>
- <programlisting language="php"><![CDATA[
- Zend_Locale_Format::setOptions(array('locale' => 'en_US',
- 'fix_date' => true,
- 'format_type' => 'php'));
- ]]></programlisting>
- </example>
- <para>
- For working with the standard definitions of a locale the option
- <constant>Zend_Locale_Format::STANDARD</constant> can be used. Setting the option
- <constant>Zend_Locale_Format::STANDARD</constant> for <property>date_format</property>
- uses the standard definitions from the actual set locale. Setting it for
- <property>number_format</property> uses the standard number format for this locale.
- And setting it for locale uses the standard locale for this environment or browser.
- </para>
- <example id="zend.locale.formatoptions.example-2">
- <title>Using STANDARD definitions for setOptions()</title>
- <programlisting language="php"><![CDATA[
- Zend_Locale_Format::setOptions(array('locale' => 'en_US',
- 'date_format' => 'dd.MMMM.YYYY'));
- // overriding the global set date format
- $date = Zend_Locale_Format::getDate('2007-04-20',
- array('date_format' =>
- Zend_Locale_Format::STANDARD);
- // global setting of the standard locale
- Zend_Locale_Format::setOptions(array('locale' => Zend_Locale_Format::STANDARD,
- 'date_format' => 'dd.MMMM.YYYY'));
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.locale.cache">
- <title>Speed up Zend_Locale and its subclasses</title>
- <para>
- <classname>Zend_Locale</classname> and its subclasses can be speeded up by the usage of
- <classname>Zend_Cache</classname>. Use the static method
- <methodname>Zend_Locale::setCache($cache)</methodname> if you are using
- <classname>Zend_Locale</classname>. <classname>Zend_Locale_Format</classname> can be
- speeded up the using the option <property>cache</property> within
- <classname>Zend_Locale_Format::setOptions(array('cache' => $adapter));</classname>.
- If you are using both classes you should only set the cache for
- <classname>Zend_Locale</classname>, otherwise the last set cache will overwrite the
- previous set cache. For convenience there are also the static methods
- <methodname>getCache()</methodname>, <methodname>hasCache()</methodname>,
- <methodname>clearCache()</methodname> and <methodname>removeCache()</methodname>.
- </para>
- <para>
- When no cache is set, then <classname>Zend_Locale</classname> will automatically set a
- cache itself. Sometimes it is wished to prevent that a cache is set, even if this
- degrades performance. In this case the static
- <methodname>disableCache(true)</methodname> method should be used. It does not only
- disable the actual set cache, without erasing it, but also prevents that a cache is
- automatically generated when no cache is set.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|