| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.translate.additional">
- <title>Additional features for translation</title>
- <para>
- There are several additional features which are supported by
- <classname>Zend_Translate</classname>. Read here for these additional informations.
- </para>
- <sect2 id="zend.translate.additional.options">
- <title>Options for adapters</title>
- <para>
- Options can be used with all adapters. Of course the options are different for all
- adapters. You can set options when you create the adapter. Actually there is one option
- which is available to all adapters: '<code>clear</code>' sets if translation data
- should be added to existing one or not. Standard behaviour is to add new translation
- data to existing one. But the translation data is only cleared for the selected
- language. So other languages remain untouched.
- </para>
- <para>
- You can set options temporarily when using <code>addTranslation($data, $locale, array
- $options = array())</code> as third and optional parameter. And you can use the method
- <methodname>setOptions()</methodname> to set the options permanently.
- </para>
- <example id="zend.translate..additional.options.example">
- <title>Using translation options</title>
- <programlisting language="php"><![CDATA[
- // define ':' as separator for the translation source files
- $options = array('delimiter' => ':');
- $translate = new Zend_Translate(
- 'csv',
- '/path/to/mytranslation.csv',
- 'de',
- $options);
- ...
- // clear the defined language and use new translation data
- $options = array('clear' => true);
- $translate->addTranslation('/path/to/new.csv', 'fr', $options);
- ]]></programlisting>
- </example>
- <para>
- Here you can find all available options for the different adapters with a description
- of their usage:
- </para>
- <table id="zend.translate.additional.options.alloptions">
- <title>Options for translation adapters</title>
- <tgroup cols="4">
- <thead>
- <row>
- <entry>Option</entry>
- <entry>Adapter</entry>
- <entry>Description</entry>
- <entry>Default value</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>clear</entry>
- <entry>all</entry>
- <entry>
- If set to true, the already read translations will be cleared. This can
- be used instead of creating a new instance when reading new translation
- data
- </entry>
- <entry><emphasis>false</emphasis></entry>
- </row>
- <row>
- <entry>disableNotices</entry>
- <entry>all</entry>
- <entry>
- If set to true, all notices regarding not available translations will
- be disabled. You should set this option to true in production
- environment
- </entry>
- <entry><emphasis>false</emphasis></entry>
- </row>
- <row>
- <entry>ignore</entry>
- <entry>all</entry>
- <entry>
- All directories and files beginning with this prefix will be ignored
- when searching for files. This value defaults to
- <emphasis>'.'</emphasis> which leads to the behavior that all hidden
- files will be ignored. Setting this value to <code>'tmp'</code> would
- mean that directories and files like <code>'tmpImages'</code> and
- <code>'tmpFiles'</code> would be ignored as well as all subsequent
- directories
- </entry>
- <entry><emphasis>.</emphasis></entry>
- </row>
- <row>
- <entry>log</entry>
- <entry>all</entry>
- <entry>
- An instance of <classname>Zend_Log</classname> where untranslated
- messages and notices will be written to
- </entry>
- <entry><emphasis>null</emphasis></entry>
- </row>
- <row>
- <entry>logMessage</entry>
- <entry>all</entry>
- <entry>
- The message which will be written into the log
- </entry>
- <entry>
- <emphasis>Untranslated message within '%locale%': %message%</emphasis>
- </entry>
- </row>
- <row>
- <entry>logUntranslated</entry>
- <entry>all</entry>
- <entry>
- When this option is set to true, all message IDs which can not be
- translated will be written into the attached log
- </entry>
- <entry><emphasis>false</emphasis></entry>
- </row>
- <row>
- <entry>reload</entry>
- <entry>all</entry>
- <entry>
- When this option is set to true, then files are reloaded into the cache.
- This option can be used to recreate the cache, or to add translations
- to already cached data after the cache has already been created.
- </entry>
- <entry><emphasis>false</emphasis></entry>
- </row>
- <row>
- <entry>scan</entry>
- <entry>all</entry>
- <entry>
- If set to null, no scanning of the directory structure will be done.
- If set to <constant>Zend_Translate::LOCALE_DIRECTORY</constant> the
- locale will be detected within the directory. If set to
- <constant>Zend_Translate::LOCALE_FILENAME</constant> the locale will
- be detected within the filename. See <xref
- linkend="zend.translate.additional.detection" /> for details
- </entry>
- <entry><emphasis>null</emphasis></entry>
- </row>
- <row>
- <entry>delimiter</entry>
- <entry>Csv</entry>
- <entry>
- Defines which sign is used as delimiter for separating source and
- translation
- </entry>
- <entry><emphasis>;</emphasis></entry>
- </row>
- <row>
- <entry>enclosure</entry>
- <entry>Csv</entry>
- <entry>
- Defines the enclosure character to be used. Defaults to a doublequote
- </entry>
- <entry><emphasis>"</emphasis></entry>
- </row>
- <row>
- <entry>length</entry>
- <entry>Csv</entry>
- <entry>
- Defines the maximum length of a csv line. When set to 0 it will be
- detected automatically
- </entry>
- <entry><emphasis>0</emphasis></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- When you want to have self defined options, you are also able to use them within all
- adapters. The <methodname>setOptions()</methodname> method can be used to define your option.
- <methodname>setOptions()</methodname> needs an array with the options you want to set. If an given
- option exists it will be signed over. You can define as much options as needed as they
- will not be checked by the adapter. Just make sure not to overwrite any existing option
- which is used by an adapter.
- </para>
- <para>
- To return the option you can use the <methodname>getOptions()</methodname> method. When
- <methodname>getOptions()</methodname> is called without a parameter it will return all options set.
- When the optional parameter is given you will only get the specified option.
- </para>
- </sect2>
- <sect2 id="zend.translate.additional.languages">
- <title>Handling languages</title>
- <para>
- When working with different languages there are a few methods which will be useful.
- </para>
- <para>
- The <methodname>getLocale()</methodname> method can be used to get the currently set language. It
- can either hold an instance of <classname>Zend_Locale</classname> or the identifier of
- a locale.
- </para>
- <para>
- The <methodname>setLocale()</methodname> method sets a new standard language for translation. This
- prevents the need of setting the optional language parameter more than once to the
- <methodname>translate()</methodname> method. If the given language does not exist, or no
- translation data is available for the language, <methodname>setLocale()</methodname> tries to
- downgrade to the language without the region if any was given. A language of
- <code>en_US</code> would be downgraded to <code>en</code>. When even the downgraded
- language can not be found an exception will be thrown.
- </para>
- <para>
- The <methodname>isAvailable()</methodname> method checks if a given language is already available.
- It returns <constant>TRUE</constant> if data for the given language exist.
- </para>
- <para>
- And finally the <methodname>getList()</methodname> method can be used to get all currently set
- languages for an adapter returned as array.
- </para>
- <example id="zend.translate.additional.languages.example">
- <title>Handling languages with adapters</title>
- <programlisting language="php"><![CDATA[
- // returns the currently set language
- $actual = $translate->getLocale();
- // you can use the optional parameter while translating
- echo $translate->_("my_text", "fr");
- // or set a new language
- $translate->setLocale("fr");
- echo $translate->_("my_text");
- // refer to the base language
- // fr_CH will be downgraded to fr
- $translate->setLocale("fr_CH");
- echo $translate->_("my_text");
- // check if this language exist
- if ($translate->isAvailable("fr")) {
- // language exists
- }
- ]]></programlisting>
- </example>
- <sect3 id="zend.translate.additional.languages.automatic">
- <title>Automatical handling of languages</title>
- <para>
- Note that as long as you only add new translation sources with the
- <methodname>addTranslation()</methodname> method <classname>Zend_Translate</classname> will
- automatically set the best fitting language for your environment when you use one
- of the automatic locales which are '<code>auto</code>' or '<code>browser</code>'.
- So normally you will not need to call <methodname>setLocale()</methodname>. This should only be
- used in conjunction with automatic source detection.
- </para>
- <para>
- The algorithm will search for the best fitting locale depending on the user's
- browser and your environment. See the following example for details:
- </para>
- <example id="zend.translate.additional.languages.automatic.example">
- <title>Automatically language detection</title>
- <programlisting language="php"><![CDATA[
- // Let's expect the browser returns these language settings:
- // HTTP_ACCEPT_LANGUAGE = "de_AT=1;fr=1;en_US=0.8";
- // Example 1:
- // When no fitting language is found, the message ID is returned
- $translate = new Zend_Translate(
- 'gettext',
- 'my_it.mo',
- 'auto',
- array('scan' => Zend_Translate::LOCALE_FILENAME));
- // Example 2:
- // Best found fitting language is 'fr'
- $translate = new Zend_Translate(
- 'gettext',
- 'my_fr.mo',
- 'auto',
- array('scan' => Zend_Translate::LOCALE_FILENAME));
- // Example 3:
- // Best found fitting language is 'de' ('de_AT' will be degraded)
- $translate = new Zend_Translate(
- 'gettext',
- 'my_de.mo',
- 'auto',
- array('scan' => Zend_Translate::LOCALE_FILENAME));
- // Example 4:
- // Returns 'it' as translation source and overrides the automatic settings
- $translate = new Zend_Translate(
- 'gettext',
- 'my_it.mo',
- 'auto',
- array('scan' => Zend_Translate::LOCALE_FILENAME));
- $translate->addTranslation('my_ru.mo', 'ru');
- $translate->setLocale('it_IT');
- ]]></programlisting>
- </example>
- <para>
- After setting a language manually with the <methodname>setLocale()</methodname> method the
- automatic detection will be switched off and overridden.
- </para>
- <para>
- If you want to use it again, you can set the language
- <emphasis>auto</emphasis> with <methodname>setLocale()</methodname> which will reactivate
- the automatic detection for <classname>Zend_Translate</classname>.
- </para>
- <para>
- Since Zend Framework 1.7.0 <classname>Zend_Translate</classname> also recognises an
- application wide locale. You can simply set a <classname>Zend_Locale</classname>
- instance to the registry like shown below. With this notation you can forget about
- setting the locale manually with each instance when you want to use the same locale
- multiple times.
- </para>
- <programlisting language="php"><![CDATA[
- // in your bootstrap file
- $locale = new Zend_Locale();
- Zend_Registry::set('Zend_Locale', $locale);
- // default language when requested language is not available
- $defaultlanguage = 'en';
- // somewhere in your application
- $translate = new Zend_Translate('gettext', 'my_de.mo');
- if (!$translate->isAvailable($locale->getLanguage())) {
- // not available languages are rerouted to another language
- $translate->setLocale($defaultlanguage);
- }
- $translate->getLocale();
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.translate.additional.detection">
- <title>Automatic source detection</title>
- <para>
- <classname>Zend_Translate</classname> can detect translation sources automatically. So
- you don't have to declare each source file manually. You can let
- <classname>Zend_Translate</classname> do this job and scan the complete directory
- structure for source files.
- </para>
- <note>
- <para>
- Automatic source detection is available since Zend Framework version 1.5 .
- </para>
- </note>
- <para>
- The usage is quite the same as initiating a single translation source with one
- difference. You must give a directory which has to be scanned instead a file.
- </para>
- <example id="zend.translate.additional.languages.directory.example">
- <title>Scanning a directory structure for sources</title>
- <programlisting language="php"><![CDATA[
- // assuming we have the following structure
- // /language/
- // /language/login/login.tmx
- // /language/logout/logout.tmx
- // /language/error/loginerror.tmx
- // /language/error/logouterror.tmx
- $translate = new Zend_Translate('tmx', '/language');
- ]]></programlisting>
- </example>
- <para>
- So <classname>Zend_Translate</classname> does not only search the given directory, but
- also all subdirectories for translation source files. This makes the usage quite
- simple. But <classname>Zend_Translate</classname> will ignore all files which are not
- sources or which produce failures while reading the translation data. So you have to
- make sure that all of your translation sources are correct and readable because you
- will not get any failure if a file is bogus or can not be read.
- </para>
- <note>
- <para>
- Depending on how deep your directory structure is and how much files are within
- this structure it can take a long time for <classname>Zend_Translate</classname>
- to complete.
- </para>
- </note>
- <para>
- In our example we have used the TMX format which includes the language to be used
- within the source. But many of the other source formats are not able to include the
- language within the file. Even this sources can be used with automatic scanning if you
- do some pre-requisits as described below:
- </para>
- <sect3 id="zend.translate.additional.detection.directory">
- <title>Language through naming directories</title>
- <para>
- One way to include automatic language detection is to name the directories related
- to the language which is used for the sources within this directory. This is the
- easiest way and is used for example within standard gettext implementations.
- </para>
- <para>
- <classname>Zend_Translate</classname> needs the '<code>scan</code>' option to know
- that it should search the names of all directories for languages. See the following
- example for details:
- </para>
- <example id="zend.translate.additional.detection.directory.example">
- <title>Directory scanning for languages</title>
- <programlisting language="php"><![CDATA[
- // assuming we have the following structure
- // /language/
- // /language/de/login/login.mo
- // /language/de/error/loginerror.mo
- // /language/en/login/login.mo
- // /language/en/error/loginerror.mo
- $translate = new Zend_Translate(
- 'gettext',
- '/language',
- null,
- array('scan' => Zend_Translate::LOCALE_DIRECTORY));
- ]]></programlisting>
- </example>
- <note>
- <para>
- This works only for adapters which do not include the language within the
- source file. Using this option for example with TMX will be ignored. Also
- language definitions within the filename will be ignored when using this
- option.
- </para>
- </note>
- <note>
- <para>
- You should be aware if you have several subdirectories under the same
- structure. Assuming we have a structure like
- <code>/language/module/de/en/file.mo</code>. In this case the path contains
- multiple strings which would be detected as locale. It could be either
- <code>de</code> or <code>en</code>. In such a case the behaviour is
- undefined and it is recommended to use file detection in such situations.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.translate.additional.detection.filename">
- <title>Language through filenames</title>
- <para>
- Another way to detect the language automatically is to use special filenames. You
- can either name the complete file or parts of a file after the used language. To
- use this way of detection you will have to set the '<code>scan</code>' option at
- initiation. There are several ways of naming the sourcefiles which are described
- below:
- </para>
- <example id="zend.translate.additional.detection.filename.example">
- <title>Filename scanning for languages</title>
- <programlisting language="php"><![CDATA[
- // assuming we have the following structure
- // /language/
- // /language/login/login_en.mo
- // /language/login/login_de.mo
- // /language/error/loginerror_en.mo
- // /language/error/loginerror_de.mo
- $translate = new Zend_Translate(
- 'gettext',
- '/language',
- null,
- array('scan' => Zend_Translate::LOCALE_FILENAME));
- ]]></programlisting>
- </example>
- <sect4 id="zend.translate.additional.detection.filename.complete">
- <title>Complete filename</title>
- <para>
- Having the whole file named after the language is the simplest way but only
- viable if you have only one file per language.
- </para>
- <programlisting><![CDATA[
- /languages/
- /languages/en.mo
- /languages/de.mo
- /languages/es.mo
- ]]></programlisting>
- </sect4>
- <sect4 id="zend.translate.additional.detection.filename.extension">
- <title>Extension of the file</title>
- <para>
- Another simple way to use the extension of the file for language detection.
- But this may be confusing since you will no longer have an idea which extension
- the file originally had.
- </para>
- <programlisting><![CDATA[
- /languages/
- /languages/view.en
- /languages/view.de
- /languages/view.es
- ]]></programlisting>
- </sect4>
- <sect4 id="zend.translate.additional.detection.filename.token">
- <title>Filename tokens</title>
- <para>
- <classname>Zend_Translate</classname> is also capable of detecting the language
- if it is included within the filename. But if you go this way you will have to
- separate the language with a token. There are three supported tokens which can
- be used: a dot '.', an underscore '_', or a hyphen '-'.
- </para>
- <programlisting><![CDATA[
- /languages/
- /languages/view_en.mo -> detects english
- /languages/view_de.mo -> detects german
- /languages/view_it.mo -> detects italian
- ]]></programlisting>
- <para>
- The first found string delimited by a token which can be interpreted as a
- locale will be used. See the following example for details.
- </para>
- <programlisting><![CDATA[
- /languages/
- /languages/view_en_de.mo -> detects english
- /languages/view_en_es.mo -> detects english and overwrites the first file
- /languages/view_it_it.mo -> detects italian
- ]]></programlisting>
- <para>
- All three tokens are used to detect the locale. When the filename contains
- multiple tokens, the first found token depends on the order of the tokens
- which are used. See the following example for details.
- </para>
- <programlisting><![CDATA[
- /languages/
- /languages/view_en-it.mo -> detects english because '_' will be used before '-'
- /languages/view-en_it.mo -> detects italian because '_' will be used before '-'
- /languages/view_en.it.mo -> detects italian because '.' will be used before '_'
- ]]></programlisting>
- </sect4>
- </sect3>
- </sect2>
- <sect2 id="zend.translate.additional.istranslated">
- <title>Checking for translations</title>
- <para>
- Normally text will be translated without any computation. But sometimes it is necessary
- to know if a text is translated or not, therefor the <methodname>isTranslated()</methodname>
- method can be used.
- </para>
- <para>
- <methodname>isTranslated($messageId, $original = false, $locale = null)</methodname> takes
- the text you want to check as its first parameter, and as optional third parameter the
- locale for which you want to do the check. The optional second parameter declares
- whether translation is fixed to the declared language or a lower set of translations
- can be used. If you have a text which can be returned for 'en' but not for 'en_US' you
- will normally get the translation returned, but by setting <varname>$original</varname> to
- true, <methodname>isTranslated()</methodname> will return false.
- </para>
- <example id="zend.translate.additional.istranslated.example">
- <title>Checking if a text is translatable</title>
- <programlisting language="php"><![CDATA[
- $english = array(
- 'message1' => 'Nachricht 1',
- 'message2' => 'Nachricht 2',
- 'message3' => 'Nachricht 3');
- $translate = new Zend_Translate('array', $english, 'de_AT');
- if ($translate->isTranslated('message1')) {
- print "'message1' can be translated";
- }
- if (!($translate->isTranslated('message1', true, 'de'))) {
- print "'message1' can not be translated to 'de'"
- . " as it's available only in 'de_AT'";
- }
- if ($translate->isTranslated('message1', false, 'de')) {
- print "'message1' can be translated in 'de_AT' as it falls back to 'de'";
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.translate.additional.logging">
- <title>How to log not found translations</title>
- <para>
- When you have a bigger site or you are creating the translation files manually, you
- often have the problem that some messages are not translated. But there is an easy
- solution for you when you are using <classname>Zend_Translate</classname>.
- </para>
- <para>
- You have to follow two or three simple steps. First, you have to create an instance of
- <classname>Zend_Log</classname>. Then you have to attach this instance to
- <classname>Zend_Translate</classname>. See the following example:
- </para>
- <example id="zend.translate.additional.logging.example">
- <title>Log translations</title>
- <programlisting language="php"><![CDATA[
- $translate = new Zend_Translate('gettext', $path, 'de');
- // Create a log instance
- $writer = new Zend_Log_Writer_Stream('/path/to/file.log');
- $log = new Zend_Log($writer);
- // Attach it to the translation instance
- $translate->setOptions(array(
- 'log' => $log,
- 'logUntranslated' => true));
- $translate->translate('unknown string');
- ]]></programlisting>
- </example>
- <para>
- Now you will have a new notice in the log: <code>Untranslated message within 'de':
- unknown string</code>.
- </para>
- <note>
- <para>
- You should note that any translation which can not be found will be logged. This
- means all translations when a user requests a language which is not supported. Also
- every request for a message which can not be translated will be logged. Be aware,
- that 100 people requesting the same translation, will result 100 logged notices.
- </para>
- </note>
- <para>
- This feature can not only be used to log messages but also to attach this untranslated
- messages into an empty translation file. To do so you will have to write your own log
- writer which writes the format you want to have and strips the prepending "Untranslated
- message".
- </para>
- <para>
- You can also set the '<code>logMessage</code>' option when you want to have your own
- log message. Use the '<code>%message%</code>' token for placing the messageId within
- your log message, and the '<code>%locale%</code>' token for the requested locale. See
- the following example for a self defined log message:
- </para>
- <example id="zend.translate.additional.logging.example2">
- <title>Self defined log messages</title>
- <programlisting language="php"><![CDATA[
- $translate = new Zend_Translate('gettext', $path, 'de');
- // Create a log instance
- $writer = new Zend_Log_Writer_Stream('/path/to/file.log');
- $log = new Zend_Log($writer);
- // Attach it to the translation instance
- $translate->setOptions(array(
- 'log' => $log,
- 'logMessage' => "Missing '%message%' within locale '%locale%'",
- 'logUntranslated' => true));
- $translate->translate('unknown string');
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.translate.additional.sourcedata">
- <title>Accessing source data</title>
- <para>
- Sometimes it is useful to have access to the translation source data. Therefor
- the following two functions are provided.
- </para>
- <para>
- The <methodname>getMessageIds($locale = null)</methodname> method returns all known message IDs as
- array.
- </para>
- <para>
- The <methodname>getMessages($locale = null)</methodname> method returns the complete translation
- source as an array. The message ID is used as key and the translation data as value.
- </para>
- <para>
- Both methods accept an optional parameter <varname>$locale</varname> which, if set, returns
- the translation data for the specified language. If this parameter is not given, the
- actual set language will be used. Keep in mind that normally all translations should be
- available in all languages. Which means that in a normal situation you will not have to
- set this parameter.
- </para>
- <para>
- Additionally the <methodname>getMessages()</methodname> method can be used to return the complete
- translation dictionary using the pseudo-locale 'all'. This will return all available
- translation data for each added locale.
- </para>
- <note>
- <para>
- Attention: the returned array can be <emphasis>very big</emphasis>,
- depending on the number of added locales and the amount of translation data.
- </para>
- </note>
- <example id="zend.translate.additional.sourcedata.example">
- <title>Handling languages with adapters</title>
- <programlisting language="php"><![CDATA[
- // returns all known message IDs
- $messageIds = $translate->getMessageIds();
- print_r($messageIds);
- // or just for the specified language
- $messageIds = $translate->getMessageIds('en_US');
- print_r($messageIds);
- // returns all the complete translation data
- $source = $translate->getMessages();
- print_r($source);
- ]]></programlisting>
- </example>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|