Toggle navigation
wCMF 4.0
Guides
Getting started
Architecture
Model
Persistence
Presentation
Configuration
Security
I18n & l10n
Tests
API
Code
Support
wcmf_older
wcmf
docs
api-src
framework_description
en
i18n_l10n.doxy
1
/*!
2
\page i18n_l10n I18n & l10n
3
<div class="has-toc"></div>
4
5
# Internationalization & localization # {#i18n_main}
6
7
_Internationalization_ of an application requires to identify all language dependent
8
resources and make them exchangeable for the actual _localization_ into a specific
9
language. This includes __static__ and __dynamic texts__ as well as __images__.
10
Since images are referenced by their filename or represented as text (e.g. _base64_
11
encoded), it is sufficient to focus on text.
12
13
## Static text ## {#i18n_static}
14
15
Static text refers to text used in __application templates__ or __messages__ generated
16
while the application is executed. To keep the application code language agnostic
17
only so called _text identifiers_ are used in these places and the actual
18
translation is retrieved by calling the
19
\link wcmf::lib::i18n::Message::getText `Message::getText`\endlink method:
20
21
~~~~~~~~~~~~~{.php}
22
$textId = 'An error occured';
23
24
// retrieve the translation
25
$message = ObjectFactory::getInstance('Message');
26
$errorText = $message->getText($textId);
27
28
// use the translation
29
$ex = new Exception($errorText);
30
~~~~~~~~~~~~~
31
32
@note Implementations of \link wcmf::lib::i18n::Message `Message`\endlink
33
must return the _text identifier_, if no translation is found or the translation
34
is empty. This helps to simplify the translation process, if the default language
35
is used in _text identifiers_. In this case, no translation is required for the
36
default language.
37
38
If no language parameter is passed to the
39
\link wcmf::lib::i18n::Message::getText `Message::getText`\endlink method, the
40
returned translation will be in the application's __default user interface language__.
41
This language is determined in the following way:
42
43
1. Use the value of the `language` parameter of the `Message` configuration section
44
2. If not defined use the value of the global variable <code>$_SERVER['HTTP_ACCEPT_LANGUAGE']</code>
45
46
If parts of the text vary depending on the application state, it is necessary to
47
put __variables__ into the text identifier. Variable names are `%0%`, `%1%`, ...
48
and they are replaced in the order of the values passed into the
49
\link wcmf::lib::i18n::Message::getText `Message::getText`\endlink method:
50
51
~~~~~~~~~~~~~{.php}
52
$textId = 'Logged in as %0% since %1%';
53
$parameters = array($username, $date);
54
55
// retrieve the translation
56
$message = ObjectFactory::getInstance('Message');
57
$loginMessage = $message->getText($textId, $parameters);
58
59
// use the translation
60
$view->setValue('loginMessage', $loginMessage);
61
~~~~~~~~~~~~~
62
63
### Template text ### {#i18n_static_tpl}
64
65
wCMF provides the `translate` plugin for embedding language dependent text into
66
_Smarty_ templates. The plugin is automatically included and used in the following
67
way:
68
69
~~~~~~~~~~~~~{.php}
70
{translate text="An error occured"}
71
72
{* with variables *}
73
{translate text="Logged in as %0% since %1%" r0=$login r1=$logindate}
74
~~~~~~~~~~~~~
75
76
### Localization ### {#i18n_static_locale}
77
78
Since \link wcmf::lib::i18n::Message `Message`\endlink defines the interface, it
79
needs concrete implementations to actually get the translations. The
80
\link wcmf::lib::i18n::impl::FileMessage `FileMessage`\endlink class retrieves
81
translations from the file system. It expects one file per language defining
82
a language dependent array that maps text identifiers to translations.
83
The language code (e.g. _en_) is used to identify the language of the translation.
84
The file must be named like <em>messages_</em>code.<em>php</em>,
85
the variable like <em>$messages_</em>code.
86
87
The following __examples__ show definitions for English (_en_) and German (_de_)
88
texts, where the array keys are the text identifiers used in the application and
89
the values are the translations in the appropriate language.
90
91
<em>messages_en.php</em>
92
93
~~~~~~~~~~~~~{.php}
94
$messages_en = array();
95
$messages_en['%0% selected'] = '';
96
$messages_en['Author'] = '';
97
$messages_en['Book'] = '';
98
~~~~~~~~~~~~~
99
100
<em>messages_de.php</em>
101
102
~~~~~~~~~~~~~{.php}
103
$messages_de = array();
104
$messages_de['%0% selected'] = '%0% ausgewählt';
105
$messages_de['Author'] = 'Autor';
106
$messages_de['Book'] = 'Buch';
107
~~~~~~~~~~~~~
108
109
@note Note that the text identifiers are in the application's default language
110
(_en_) and therefor no translations need to be provided.
111
112
The default __configuration__ of \link wcmf::lib::i18n::Message `Message`\endlink
113
is as follows:
114
115
~~~~~~~~~~~~~{.ini}
116
[Message]
117
__class = wcmf\lib\i18n\impl\FileMessage
118
localeDir = app/locale/
119
language = en
120
~~~~~~~~~~~~~
121
122
The parameter `localeDir` defines the directory where
123
\link wcmf::lib::i18n::impl::FileMessage `FileMessage`\endlink searchs for
124
translation files and the `language` parameter defines the application's default
125
language.
126
127
### Tools ### {#i18n_static_tools}
128
129
The \ref app "default application" ships with a tool for finding translatable text
130
and generating localization files from it. After installing the application
131
it is available under `http://localhost/wcmf-default-app/tools/locale/`.
132
133
The tool uses \link wcmf::lib::util::I18nUtil `I18nUtil`\endlink internally to
134
search for occurrences of
135
136
- <code>->getText('Text to translate', ...)</code> as used in
137
<code>$message->getText('Text to translate', ...)</code> in PHP code
138
- `{translate:"Text to translate" ...}` as used in Smarty templates
139
- `Dict.translate("Text to translate", ...)` as used in the Javascript code of the
140
\ref app "default application"
141
142
_Text to translate_ is supposed to be the message to be localized. The tool generates
143
one localization file for each language puts it into the appropriate directory.
144
It's capable of merging already existing translations into the newly generated
145
files.
146
147
The tool's configuration is defined in the file _config.ini_ in the tool's directory
148
and defaults to:
149
150
~~~~~~~~~~~~~{.ini}
151
[Application]
152
localeDir = app/locale/
153
154
[I18n]
155
searchDirs = {vendor/wcmf/wcmf/src/wcmf, app/}
156
exclude = {vendor, .git, .svn, test}
157
languages = {de, en}
158
~~~~~~~~~~~~~
159
160
## Model content ## {#i18n_dynamic}
161
162
Model content is initially created in the application's __default model language__,
163
which might differ from the _default user interface language_ (see \ref i18n_static).
164
Localization of the model content is done by using implementations of
165
\link wcmf::lib::i18n::Localization `Localization`\endlink. The interface defines
166
methods for loading and saving localized model content. The following code
167
demonstrates how to use it to get translated content:
168
169
~~~~~~~~~~~~~{.php}
170
$oid = new ObjectId('Book', 1);
171
172
// retrieve a localized entity instance
173
$localization = ObjectFactory::getInstance('localization');
174
$bookDe = $localization->loadTranslatedObject($oid, 'de');
175
~~~~~~~~~~~~~
176
177
### Localization ### {#i18n_dynamic_locale}
178
179
There are several strategies for storing localized versions of the content, all
180
having advantages and disadvantages regarding extensibility and performance. The
181
idea behind the
182
\link wcmf::lib::i18n::impl::DefaultLocalization `DefaultLocalization`\endlink
183
implementation is to keep the domain model clear of localization related attributes
184
by storing translations in a separate entity type. Using one entity type for all
185
content leads to more flexibility when extending the domain model.
186
187
The __translation entity type__ must have the following attributes:
188
189
- `objectid` object id of the translated entity (e.g. _Book:1_)
190
- `attribute` translated attribute (e.g. _title_)
191
- `language` the language code of the translation (e.g. _en_)
192
- `translation` the actual translation
193
194
The supported content languages are either defined in the `Languages` configuration
195
section (see below) or in the language entity type that is used by
196
\link wcmf::lib::i18n::impl::DefaultLocalization `DefaultLocalization`\endlink,
197
if the configuration section does not exist.
198
199
The __language entity type__ must have the following attributes:
200
201
- `code` language code (e.g. _en_)
202
- `name` language name (e.g. _English_)
203
204
The following __example__ demonstrates the creation of localized content
205
using the \link wcmf::lib::i18n::Localization `Localization`\endlink interface:
206
207
~~~~~~~~~~~~~{.php}
208
$oid = new ObjectId('Book', 1);
209
210
// retrieve the original entity instance
211
$persistenceFacade = ObjectFactory::getInstance('persistenceFacade');
212
$book = $persistenceFacade->load($oid);
213
214
// localize the instance
215
$book->setValue('title', 'Übersetzter Titel');
216
217
// save the translation
218
$localization = ObjectFactory::getInstance('localization');
219
$localization->saveTranslation($book, 'de');
220
~~~~~~~~~~~~~
221
222
The localization __configuration__ of the \ref app "default application" is the
223
following:
224
225
~~~~~~~~~~~~~{.ini}
226
[Localization]
227
__class = wcmf\lib\i18n\impl\DefaultLocalization
228
defaultLanguage = en
229
languageType = app.src.model.wcmf.Language
230
translationType = app.src.model.wcmf.Translation
231
232
[Languages]
233
de = Deutsch
234
en = English
235
~~~~~~~~~~~~~
236
237
In this example the _default model language_ is set to English and the
238
_language entity type_ is ignored, because the available languages are defined
239
in the configuration.
240
*/