1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.translate.using">
4 <title>Using Translation Adapters</title>
7 The next step is to use the adapter within your code.
10 <example id="zend.translate.using.example1">
11 <title>Example of single-language PHP code</title>
13 <programlisting language="php"><![CDATA[
16 print "Here is line one\n";
17 print "Today is the " . date("d.m.Y") . "\n";
19 print "Here is line two\n";
24 The example above shows some output with no support for translation.
25 You probably write your code in your native language.
26 Generally you need to translate not only the output,
27 but also error and log messages.
31 The next step is to integrate <classname>Zend_Translate</classname> into your existing code.
32 Of course it is much easier if you had already written your code with
33 translation in mind, than changing your code afterwards.
36 <example id="zend.translate.using.example2">
37 <title>Example of multi-lingual PHP code</title>
39 <programlisting language="php"><![CDATA[
40 $translate = new Zend_Translate(
42 'adapter' => 'gettext',
43 'content' => '/my/path/source-de.mo',
47 $translate->addTranslation(
49 'content' => '/path/to/translation/fr-source.mo',
54 print $translate->_("Example") . "\n";
56 print $translate->_("Here is line one") . "\n";
57 printf($translate->_("Today is the %1\$s") . "\n", date('d.m.Y'));
60 $translate->setLocale('fr');
61 print $translate->_("Here is line two") . "\n";
66 Now let's take a deeper look into what has been done and how to
67 integrate <classname>Zend_Translate</classname> into your own code.
71 Create a new <classname>Zend_Translate</classname> object and define the base adapter:
74 <programlisting language="php"><![CDATA[
75 $translate = new Zend_Translate
77 'adapter' => 'gettext',
78 'content' => '/path/to/translation/source-de.mo',
85 In this example we chose the
86 <emphasis>Gettext Adapter</emphasis>.
87 We place our file <emphasis>source-de.mo</emphasis>
88 into the directory <emphasis>/path/to/translation</emphasis>.
89 The gettext file will have German translation included,
90 and we also added another language source for French.
94 The next step is to wrap all strings which are to be translated.
95 The simplest approach is to have only simple strings or sentences
99 <programlisting language="php"><![CDATA[
100 print $translate->_("Example") . "\n";
102 print $translate->_("Here is line one") . "\n";
106 Some strings do not needed to be translated.
107 The separating line is always a separating line,
108 even in other languages.
112 Having data values integrated into a translation string is also
113 supported through the use of embedded parameters.
116 <programlisting language="php"><![CDATA[
117 printf($translate->_("Today is the %1\$s") . "\n", date("d.m.Y"));
121 Instead of <methodname>print()</methodname>, use the <methodname>printf()</methodname>
122 function and replace all parameters with <code>%1\$s</code> parts.
123 The first is <code>%1\$s</code>, the second is <code>%2\$s</code>,
124 and so on. This way a translation can be done without knowing
125 the exact value. In our example, the date is always the actual day,
126 but the string can be translated without the knowledge of the actual
131 Each string is identified in the translation storage by a message ID.
132 You can use message IDs instead of strings in your code, like this:
135 <programlisting language="php"><![CDATA[
136 print $translate->_(1) . "\n";
138 print $translate->_(2) . "\n";
142 But doing this has several disadvantages:
146 You can not see what your code should output just by viewing your code.
150 Also you will have problems if some strings are not translated.
151 You must always keep in mind how translation works.
152 First <classname>Zend_Translate</classname> checks whether the specified language has a
153 translation for the given message ID or string.
154 If no translation string has been found it refers to the next lower
155 level language as defined within <classname>Zend_Locale</classname>.
156 So "<emphasis>de_AT</emphasis>" becomes
157 "<emphasis>de</emphasis>" only.
158 If there is no translation found for
159 "<emphasis>de</emphasis>" either,
160 then the original message is returned.
161 This way you always have an output, even in case the message translation
162 does not exist in your message storage.
163 <classname>Zend_Translate</classname> never throws an error or exception when translating
167 <sect2 id="zend.translate.using.structure">
168 <title>Translation Source Structures</title>
171 Your next step is to create the translation sources for the
172 languages you want to translate.
173 Every adapter is created its own way as described here,
174 but there are common features applicable for all adapters.
178 You have to decide where to store your translation source files.
179 Using <classname>Zend_Translate</classname> you are not restricted in any way.
180 The following structures are preferable:
186 Single structured source
189 <programlisting language="txt"><![CDATA[
198 Positive: all source files for every languages are stored
199 in one directory. No splitting of related files.
205 Language structured source
208 <programlisting language="txt"><![CDATA[
212 /languages/en/first.en
213 /languages/en/second.en
215 /languages/de/first.de
216 /languages/de/second.de
221 Positive: Every language is stored in their own directories.
222 Easy translation, as every language team has to translate
223 only one directory. Also the usage of multiple files is transparent.
229 Application structured source
232 <programlisting language="txt"><![CDATA[
234 /application/languages/
235 /application/languages/first.en
236 /application/languages/first.de
237 /application/languages/second.en
238 /application/languages/second.de
243 Positive: all source files for every language are stored
244 in one directory. No splitting of related files.
248 Negative: having multiple files for the same language can be
255 Gettext structured source
258 <programlisting language="txt"><![CDATA[
262 /languages/de/LC_MESSAGES/
263 /languages/de/LC_MESSAGES/first.mo
264 /languages/de/LC_MESSAGES/second.mo
266 /languages/en/LC_MESSAGES/
267 /languages/en/LC_MESSAGES/first.mo
268 /languages/en/LC_MESSAGES/second.mo
273 Positive: existing gettext sources can be used without changing
278 Negative: having sub-sub directories may be confusing
279 for people who have not used gettext before.
285 File structured source
288 <programlisting language="txt"><![CDATA[
291 /application/models/MyModel.php
292 /application/models/MyModel.de
293 /application/models/MyModel.en
294 /application/controllers/
295 /application/controllers/MyController.php
296 /application/controllers/MyController.de
297 /application/controllers/MyController.en
302 Positive: translation files are localted near their source.
306 Negative: too many and also small translation files result in
307 being tedious to translate.
308 Also every file has to be added as translation source.
314 Single structured and language structured source files are most
315 usable for <classname>Zend_Translate</classname>.
319 So now, that we know which structure we want to have,
320 we should create our translation source files.