forked from seam2/jboss-seam
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathI18n.xml
executable file
·342 lines (339 loc) · 18.3 KB
/
I18n.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<?xml version='1.0'?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
<chapter id="i18n">
<title>Internationalization, localization and themes</title>
<para>Seam makes it easy to build internationalized applications.
First, let's walk through all the stages needed to
internationalize and localize your app. Then we'll take a look at
the components Seam bundles.</para>
<section>
<title>Internationalizing your app</title>
<para>A JEE application consists of many components and all of them
must be configured properly for your application to be
localized.</para>
<note>
<para>Note that all i18n features in Seam work only in JSF
context.</para>
</note>
<para>Starting at the bottom, the first step is to ensure that your
database server and client is using the correct character encoding
for your locale. Normally you'll want to use UTF-8. How to do
this is outside the scope of this tutorial.</para>
<section>
<title>Application server configuration</title>
<para>To ensure that the application server receives the request
parameters in the correct encoding from client requests you have to
configure the tomcat connector. If you use JBoss AS, add the system
properties <property>
org.apache.catalina.connector.URI_ENCODING</property> and <property>
org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING</property>
to the server configuration. For JBoss AS 7.1.1 change <filename>
${JBOSS_HOME}/standalone/configuration/standalone.xml</filename>:</para>
<programlisting role="XML">
<system-properties>
<property name="org.apache.catalina.connector.URI_ENCODING" value="UTF-8"/>
<property name="org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING" value="true"/>
</system-properties>
</programlisting>
</section>
<section>
<title>Translated application strings</title>
<para>You'll also need localized strings for all the <emphasis>
messages</emphasis> in your application (for example field labels on
your views). First you need to ensure that your resource bundle is
encoded using the desired character encoding. By default ASCII is
used. Although ASCII is enough for many languages, it doesn't
provide characters for all languages.</para>
<para>Resource bundles must be created in ASCII, or use Unicode
escape codes to represent Unicode characters. Since you don't
compile a property file to byte code, there is no way to tell the
JVM which character set to use. So you must use either ASCII
characters or escape characters not in the ASCII character set. You
can represent a Unicode character in any Java file using \uXXXX,
where XXXX is the hexadecimal representation of the character.</para>
<para>You can write your translation of labels (
<xref linkend="labels"/>) to your messages resource bundle in the
native encoding and then convert the content of the file into the
escaped format through the tool <literal>native2ascii</literal>
provided in the JDK. This tool will convert a file written in your
native encoding to one that represents non-ASCII characters as
Unicode escape sequences.</para>
<para>Usage of this tool is described
<ulink url="http://java.sun.com/j2se/1.5.0/docs/tooldocs/index.html#intl">
here for Java 5</ulink> or
<ulink url="http://java.sun.com/javase/6/docs/technotes/tools/#intl">
here for Java 6</ulink>. For example, to convert a file from
UTF-8:</para>
<programlisting><prompt>$ native2ascii -encoding UTF-8 messages_cs.properties > messages_cs_escaped.properties</prompt></programlisting>
</section>
<section>
<title>Other encoding settings</title>
<para>We need to make sure that the view displays your localized
data and messages using the correct character set and also any data
submitted uses the correct encoding.</para>
<para>To set the display character encoding, you need to use the
<literal><f:view locale="cs_CZ"/></literal> tag
(here we tell JSF to use the Czech locale). You may want to change
the encoding of the xml document itself if you want to embed
localized strings in the xml. To do this alter the encoding
attribute in xml declaration <literal><?xml
version="1.0" encoding="UTF-8"?></literal> as
required.</para>
<para>Also JSF/Facelets should submit any requests using the
specified character encoding, but to make sure any requests that
don't specify an encoding you can force the request encoding
using a servlet filter. Configure this in <literal>
components.xml</literal>:</para>
<programlisting role="XML"><web:character-encoding-filter encoding="UTF-8"
override-client="true"
url-pattern="*.seam" /></programlisting>
</section>
</section>
<section id="locales">
<title>Locales</title>
<para>Each user login session has an associated instance of <literal>
java.util.Locale</literal> (available to the application as a
component named <literal>locale</literal>). Under normal
circumstances, you won't need to do any special configuration to
set the locale. Seam just delegates to JSF to determine the active
locale:</para>
<itemizedlist>
<listitem>
<para>If there is a locale associated with the HTTP request (the
browser locale), and that locale is in the list of supported
locales from <literal>faces-config.xml</literal>, use that locale
for the rest of the session.</para>
</listitem>
<listitem>
<para>Otherwise, if a default locale was specified in the <literal>
faces-config.xml</literal>, use that locale for the rest of the
session.</para>
</listitem>
<listitem>
<para>Otherwise, use the default locale of the server.</para>
</listitem>
</itemizedlist>
<para>It is <emphasis>possible</emphasis> to set the locale manually
via the Seam configuration properties <literal>
org.jboss.seam.international.localeSelector.language</literal>,
<literal>
org.jboss.seam.international.localeSelector.country</literal> and
<literal>
org.jboss.seam.international.localeSelector.variant</literal>, but we
can't think of any good reason to ever do this.</para>
<para>It is, however, useful to allow the user to set the locale
manually via the application user interface. Seam provides built-in
functionality for overriding the locale determined by the algorithm
above. All you have to do is add the following fragment to a form in
your JSP or Facelets page:</para>
<programlisting role="XHTML"><h:selectOneMenu value="#{localeSelector.language}">
<f:selectItem itemLabel="English" itemValue="en"/>
<f:selectItem itemLabel="Deutsch" itemValue="de"/>
<f:selectItem itemLabel="Francais" itemValue="fr"/>
</h:selectOneMenu>
<h:commandButton action="#{localeSelector.select}"
value="#{messages['ChangeLanguage']}"/></programlisting>
<para>Or, if you want a list of all supported locales from <literal>
faces-config.xml</literal>, just use:</para>
<programlisting role="XHTML"><h:selectOneMenu value="#{localeSelector.localeString}">
<f:selectItems value="#{localeSelector.supportedLocales}"/>
</h:selectOneMenu>
<h:commandButton action="#{localeSelector.select}"
value="#{messages['ChangeLanguage']}"/></programlisting>
<para>When the user selects an item from the drop-down, then clicks
the command button, the Seam and JSF locales will be overridden for
the rest of the session.</para>
<para>The brings us to the question of where the supported locales
are defined. Typically, you provide a list of locales for which you
have matching resource bundles in the <literal>
<locale-config></literal> element of the JSF configuration file
(/META-INF/faces-config.xml). However, you have learned to appreciate
that Seam's component configuration mechanism is more powerful
than what is provided in Java EE. For that reason, you can configure
the supported locales, and the default locale of the server, using
the built-in component named <literal>
org.jboss.seam.international.localeConfig</literal>. To use it, you
first declare an XML namespace for Seam's international package
in the Seam component descriptor. You then define the default locale
and supported locales as follows:</para>
<programlisting role="XML"><international:locale-config default-locale="fr_CA" supported-locales="en fr_CA fr_FR"/></programlisting>
<para>Naturally, if you pronounce that you support a locale, you
better provide a resource bundle to match it! Up next, you'll
learn how to define the language-specific labels.</para>
</section>
<section id="labels">
<title>Labels</title>
<para>JSF supports internationalization of user interface labels and
descriptive text via the use of <literal><f:loadBundle
/></literal>. You can use this approach in Seam applications.
Alternatively, you can take advantage of the Seam <literal>
messages</literal> component to display templated labels with
embedded EL expressions.</para>
<section>
<title>Defining labels</title>
<para>Seam provides a <literal>java.util.ResourceBundle</literal>
(available to the application as a <literal>
org.jboss.seam.core.resourceBundle</literal>). You'll need to
make your internationalized labels available via this special
resource bundle. By default, the resource bundle used by Seam is
named <literal>messages</literal> and so you'll need to define
your labels in files named <literal>messages.properties</literal>,
<literal>messages_en.properties</literal>, <literal>
messages_en_AU.properties</literal>, etc. These files usually belong
in the <literal>WEB-INF/classes</literal> directory.</para>
<para>So, in <literal>messages_en.properties</literal>:</para>
<programlisting>Hello=Hello</programlisting>
<para>And in <literal>messages_en_AU.properties</literal>:</para>
<programlisting>Hello=G'day</programlisting>
<para>You can select a different name for the resource bundle by
setting the Seam configuration property named <literal>
org.jboss.seam.core.resourceLoader.bundleNames</literal>. You can
even specify a list of resource bundle names to be searched (depth
first) for messages.</para>
<programlisting role="XML"><core:resource-loader>
<core:bundle-names>
<value>mycompany_messages</value>
<value>standard_messages</value>
</core:bundle-names>
</core:resource-loader></programlisting>
<para>If you want to define a message just for a particular page,
you can specify it in a resource bundle with the same name as the
JSF view id, with the leading <literal>/</literal> and trailing file
extension removed. So we could put our message in <literal>
welcome/hello_en.properties</literal> if we only needed to display
the message on <literal>/welcome/hello.jsp</literal>.</para>
<para>You can even specify an explicit bundle name in <literal>
pages.xml</literal>:</para>
<programlisting role="XML"><page view-id="/welcome/hello.jsp" bundle="HelloMessages"/></programlisting>
<para>Then we could use messages defined in <literal>
HelloMessages.properties</literal> on <literal>
/welcome/hello.jsp</literal>.</para>
</section>
<section>
<title>Displaying labels</title>
<para>If you define your labels using the Seam resource bundle,
you'll be able to use them without having to type <literal>
<f:loadBundle ... /></literal> on every page. Instead, you can
simply type:</para>
<programlisting role="XHTML"><h:outputText value="#{messages['Hello']}"/></programlisting>
<para>or:</para>
<programlisting role="XHTML"><h:outputText value="#{messages.Hello}"/></programlisting>
<para>Even better, the messages themselves may contain EL
expressions:</para>
<programlisting>Hello=Hello, #{user.firstName} #{user.lastName}</programlisting>
<programlisting>Hello=G'day, #{user.firstName}</programlisting>
<para>You can even use the messages in your code:</para>
<programlisting role="JAVA">@In private Map<String, String> messages;</programlisting>
<programlisting role="JAVA">@In("#{messages['Hello']}") private String helloMessage;</programlisting>
</section>
<section>
<title>Faces messages</title>
<para>The <literal>facesMessages</literal> component is a
super-convenient way to display success or failure messages to the
user. The functionality we just described also works for faces
messages:</para>
<programlisting role="JAVA">@Name("hello")
@Stateless
public class HelloBean implements Hello {
@In FacesMessages facesMessages;
public String sayIt() {
facesMessages.addFromResourceBundle("Hello");
}
}</programlisting>
<para>This will display <literal>Hello, Gavin King</literal> or
<literal>G'day, Gavin</literal>, depending upon the user's
locale.</para>
</section>
</section>
<section>
<title>Timezones</title>
<para>There is also a session-scoped instance of <literal>
java.util.Timezone</literal>, named <literal>
org.jboss.seam.international.timezone</literal>, and a Seam component
for changing the timezone named <literal>
org.jboss.seam.international.timezoneSelector</literal>. By default,
the timezone is the default timezone of the server. Unfortunately,
the JSF specification says that all dates and times should be assumed
to be UTC, and displayed as UTC, unless a timezone is explicitly
specified using <literal><f:convertDateTime></literal>. This is
an extremely inconvenient default behavior.</para>
<note>
<para>
You can use application parameter to set up different default time
zone for JSF 2 in
<filename>web.xml</filename>.
</para>
<programlisting role="XML"><context-param>
<param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
<param-value>true</param-value>
</context-param></programlisting>
</note>
<para>Seam overrides this behavior, and defaults all dates and times
to the Seam timezone. </para>
<para>Seam also provides a default date converter to convert a string
value to a date. This saves you from having to specify a converter on
input fields that are simply capturing a date. The pattern is
selected according the the user's locale and the time zone is
selected as described above.</para>
</section>
<section>
<title>Themes</title>
<para>Seam applications are also very easily skinnable. The theme API
is very similar to the localization API, but of course these two
concerns are orthogonal, and some applications support both
localization and themes.</para>
<para>First, configure the set of supported themes:</para>
<programlisting role="XML"><theme:theme-selector cookie-enabled="true">
<theme:available-themes>
<value>default</value>
<value>accessible</value>
<value>printable</value>
</theme:available-themes>
</theme:theme-selector></programlisting>
<para>Note that the first theme listed is the default theme.</para>
<para>Themes are defined in a properties file with the same name as
the theme. For example, the <literal>default</literal> theme is
defined as a set of entries in <literal>default.properties</literal>.
For example, <literal>default.properties</literal> might
define:</para>
<programlisting>css ../screen.css
template /template.xhtml</programlisting>
<para>Usually the entries in a theme resource bundle will be paths to
CSS styles or images and names of facelets templates (unlike
localization resource bundles which are usually text).</para>
<para>Now we can use these entries in our JSP or facelets pages. For
example, to theme the stylesheet in a facelets page:</para>
<programlisting role="XHTML"><link href="#{theme.css}" rel="stylesheet" type="text/css" /></programlisting>
<para>Or, when the page definition resides in a subdirectory:</para>
<programlisting role="XHTML"><link href="#{facesContext.externalContext.requestContextPath}#{theme.css}"
rel="stylesheet" type="text/css" /></programlisting>
<para>Most powerfully, facelets lets us theme the template used by a
<literal><ui:composition></literal>:</para>
<programlisting role="XHTML"><ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
template="#{theme.template}"></programlisting>
<para>Just like the locale selector, there is a built-in theme
selector to allow the user to freely switch themes:</para>
<programlisting role="XHTML"><h:selectOneMenu value="#{themeSelector.theme}">
<f:selectItems value="#{themeSelector.themes}"/>
</h:selectOneMenu>
<h:commandButton action="#{themeSelector.select}" value="Select Theme"/></programlisting>
</section>
<section>
<title>Persisting locale and theme preferences via cookies</title>
<para>The locale selector, theme selector and timezone selector all
support persistence of locale and theme preference to a cookie.
Simply set the <literal>cookie-enabled</literal> property in <literal>
components.xml</literal>:</para>
<programlisting role="XML"><theme:theme-selector cookie-enabled="true">
<theme:available-themes>
<value>default</value>
<value>accessible</value>
<value>printable</value>
</theme:available-themes>
</theme:theme-selector>
<international:locale-selector cookie-enabled="true"/></programlisting>
</section>
</chapter>