| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| |
| <html> |
| <head> |
| <meta name="author" content="troy.giunipero@sun.com"> |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
| <meta name="description" content="This tutorial unit describes how to create multilingual pages for web applications"> |
| |
| <meta name="keywords" content="NetBeans, IDE, integrated development environment, |
| Java, Java EE, open source, web technology, e-commerce, resource bundle, locale, internationalization, |
| localization"> |
| |
| <link rel="stylesheet" type="text/css" href="../../../../netbeans.css"> |
| <link rel="stylesheet" type="text/css" href="../../../../print.css" media="print"> |
| <link rel="stylesheet" type="text/css" href="../../../../lytebox.css" media="screen"> |
| <script type="text/javascript" src="../../../../images_www/js/lytebox-compressed.js"></script> |
| |
| <title>The NetBeans E-commerce Tutorial - Adding Language Support</title> |
| </head> |
| |
| <body> |
| |
| <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> |
| |
| <h1>The NetBeans E-commerce Tutorial - Adding Language Support</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="intro.html">Introduction</a></li> |
| <li><a href="design.html">Designing the Application</a></li> |
| <li><a href="setup-dev-environ.html">Setting up the Development Environment</a></li> |
| <li><a href="data-model.html">Designing the Data Model</a></li> |
| <li><a href="page-views-controller.html">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="connect-db.html">Connecting the Application to the Database</a></li> |
| <li><a href="entity-session.html">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="manage-sessions.html">Managing Sessions</a></li> |
| <li><a href="transaction.html">Integrating Transactional Business Logic</a></li> |
| <li><strong>Adding Language Support</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#resourceBundles">Understanding Resource Bundles</a></li> |
| <li><a href="#multilingual">Making Pages Multilingual</a></li> |
| <li><a href="#toggle">Implementing a Language Toggle</a></li> |
| <li><a href="#seeAlso">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="security.html">Securing the Application</a></li> |
| <li><a href="test-profile.html">Testing and Profiling</a></li> |
| <li><a href="conclusion.html">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>The goal of this tutorial unit is to demonstrate how to enable language support |
| for a web application. "Language support" here refers to the ability |
| to display page views according to the customer-specified languages. Within the |
| context of the <code>AffableBean</code> application, we have agreed to provide |
| support for both English and Czech, as per the previously outlined |
| <a href="design.html#requirements">customer requirements</a>.</p> |
| |
| <p>In order to accomplish this, you rely on Java's support for internationalization. |
| You create a <em>resource bundle</em> for each language and let the Java runtime |
| environment determine the appropriate language for incoming client requests. You |
| also implement a 'language toggle' to enable users to switch the languages manually.</p> |
| |
| <p>The NetBeans IDE provides special support for localizing application content. This |
| includes a Customizer dialog that enables you to add new locales to an existing |
| resource bundle base name, as well as a special Properties editor that lets you |
| view and edit key-value pairs for all locales in a table layout. These are both |
| utilized in this tutorial.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFish">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 8</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 9</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFish">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="setup.html">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="resourceBundles">Understanding Resource Bundles</h2> |
| |
| <p>In Java, a resource bundle is a representation of the |
| <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/ResourceBundle.html" target="_blank"><code>java.util.ResourceBundle</code></a> |
| class. As stated in the Javadoc,</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>Resource bundles contain locale-specific objects. When your program needs |
| a locale-specific resource, a String for example, your program can load it |
| from the resource bundle that is appropriate for the current user's locale. |
| In this way, you can write program code that is largely independent of the |
| user's locale isolating most, if not all, of the locale-specific information |
| in resource bundles. |
| |
| <br><br> |
| This allows you to write programs that can:</em> |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><em>be easily localized, or translated, into different languages</em></li> |
| <li><em>handle multiple locales at once</em></li> |
| <li><em>be easily modified later to support even more locales</em></li> |
| </ul> |
| </blockquote> |
| |
| <p>From the Javadoc, you can also note that the <code>ResourceBundle</code> is parent |
| to both <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/ListResourceBundle.html" target="_blank"><code>ListResourceBundle</code></a> |
| and <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/PropertyResourceBundle.html" target="_blank"><code>PropertyResourceBundle</code></a>. |
| In this tutorial we utilize the <code>PropertyResourceBundle</code>, which manages |
| resources as text files that use the <code>.properties</code> extension and contain |
| locale-specific information in the form of key-value pairs. With new each translation, |
| a new version of the resource bundle is created by appending the locale identifier |
| to the base name using an underscore ('<code>_</code>'). For example, snippets from |
| two of the resource bundles you create in this tutorial look as follows:</p> |
| |
| <p><strong>messages_en.properties</strong></p> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| meats=meats |
| bakery=bakery</pre> |
| |
| <p><strong>messages_cs.properties</strong></p> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| meats=maso |
| bakery=pečivo</pre> |
| |
| <p>In the above example, '<code>messages</code>' represents the base name, and the locale |
| identifier is the two-letter code which is appended using an underscore. (i.e., '<code>en</code>' |
| for English, '<code>cs</code>' for Czech). The two-letter codes are derived from the |
| international <a href="http://en.wikipedia.org/wiki/ISO_639" target="_blank">ISO 639</a> |
| standard, which lists codes that represent the names of languages. The ISO 639 standard |
| is adopted by the <a href="http://www.w3.org/International/" target="_blank">W3C |
| Internationalization Activity</a> and is used by all major browsers (these are the codes |
| understood in the <code>Accept-Language</code> HTTP header). It is also internalized in the |
| <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/Locale.html" target="_blank"><code>java.util.Locale</code></a> |
| class.</p> |
| |
| |
| <br> |
| <h2 id="multilingual">Making Pages Multilingual</h2> |
| |
| <p>Returning to the <code>AffableBean</code> application, after continued discussions with |
| the customer you've agreed on the following implementation details:</p> |
| |
| <ul style="margin: 0 0 0 -.7em" id="impDeets"> |
| <li>The website initially displays based on the preferred language of the user's |
| browser.</li> |
| |
| <li>If the browser's preferred language is neither English nor Czech, the site |
| displays text in English.</li> |
| |
| <li>The user has the option of changing the language by means of a 'language toggle' |
| in the page header.</li> |
| |
| <li>When using the language toggle to change the language, the user remains in the |
| same page view.</li> |
| |
| <li>The language toggle should not appear for the confirmation page, as a user will |
| already have selected his or her language prior to checkout.</li> |
| </ul> |
| |
| <p>In order to implement the above points, divide the task into two parts. Start by |
| creating basic bilingual support for page views. Once bilingual support is in place, |
| implement the language toggle that enables users to manually switch languages.</p> |
| |
| <p>There are three basic steps that you need to follow to incorporate multilingual support |
| into your web pages.</p> |
| |
| <ol style="margin: 0"> |
| <li>Create a resource bundle for each language you plan to support.</li> |
| |
| <li>Register the resource bundle with the application by setting a context parameter |
| in the <code>web.xml</code> deployment descriptor.</li> |
| |
| <li>In page views, replace 'hard-coded' text with <code><fmt:message></code> tags |
| that reference keys in the resource bundles.</li> |
| </ol> |
| |
| <p>The following exercise demonstrates how to integrate English and Czech language support |
| into the <code>AffableBean</code> welcome page by applying the above three steps, and |
| finishes by showing how to test for browser language support using Firefox.</p> |
| |
| <ol> |
| <li><a href="#createResource">Create Resource Bundles</a></li> |
| <li><a href="#register">Register the Resource Bundle with the Application</a></li> |
| <li><a href="#replace">Replace 'Hard-Coded' Text with <code><fmt:message></code> Tags</a></li> |
| <li><a href="#test">Test Supported Languages</a></li> |
| </ol> |
| |
| <div class="indent"> |
| <h3 id="createResource">Create Resource Bundles</h3> |
| |
| <ol> |
| <li>Open the <code>AffableBean</code> project <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">snapshot |
| 8</a> in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project.</li> |
| |
| <li>Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button to run the project and ensure that it is properly |
| configured with your database and application server. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="setup.html">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Begin by creating a default resource bundle to contain text used in page views. Click |
| the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.)</li> |
| |
| <li>Under Categories select Other, then under File Types select Properties File. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/new-file-wzd.png" |
| class="margin-around b-all" alt="New File wizard" |
| title="Create a new resource bundle using the File wizard"> |
| |
| <br> |
| Note that the wizard provides a description for the selected file type: |
| |
| <blockquote> |
| <em>Creates a resource bundle (<code>.properties</code>) file suitable for internationalizing |
| applications by separating out all human-visible text strings from your code. Resource |
| bundle files can also be used to collect other types of strings, such as properties for |
| Ant scripts. The created resource bundle contains only one locale, but you can add additional |
| locales from the created file's contextual menu. The bundle can be edited in a text file |
| (property-file format) for a specific locale or in a table that displays information for |
| all locales.</em> |
| </blockquote></li> |
| |
| <li>Click Next. In the Name and Location step, name the file <code>messages</code> and type |
| in <code>src/java/resources</code> in the Folder field. This will instruct the wizard |
| to place the resource bundle in a new package named <code>resources</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/new-properties-file-wzd.png" |
| class="margin-around b-all" alt="New Properties File wizard" |
| title="Specify the name and location of the resource bundle"></li> |
| |
| <li>Click Finish. The <code>messages.properties</code> resource bundle is generated and opens |
| in the editor. |
| |
| <br><br> |
| Note that the new <code>messages.properties</code> file name does not have a language |
| code appended to it, as was previously described. This is because this file will be used |
| as the <em>default</em> resource bundle. The default resource bundle is applied when the |
| Java runtime environment does not find a direct match for the requested locale.</li> |
| |
| <li>Open the project's <code>index.jsp</code> file in the editor and note that the following |
| text is currently used: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Greeting:</strong> <code>Welcome to the online home of the Affable Bean Green Grocer.</code></li> |
| |
| <li><strong>Introductory Message:</strong> <code>Enjoy browsing and learning more about our |
| unique home delivery service bringing you fresh organic produce, dairy, meats, breads |
| and other delicious and healthy items to your doorstep.</code></li> |
| </ul> |
| |
| Also, note that we'll need language-specific names for the four categories that display |
| when <code>index.jsp</code> renders in the browser. Since these names are currently taken |
| from the database, we can use them as keys in the resource bundle. |
| |
| <br><br> |
| Recall that one of the <a href="#impDeets">implementation details</a> outlined above states |
| that "<em>if the browser's preferred language is neither English nor Czech, the site |
| displays text in English.</em>" Therefore, the values that we apply to the |
| <code>messages.properties</code> file will be in English.</li> |
| |
| <li>In the <code>messages.properties</code> file, begin adding key-value pairs for the text used |
| in the welcome page. Add the following content. |
| |
| <pre class="examplecode"> |
| # welcome page |
| greeting=Welcome to the online home of the Affable Bean Green Grocer. |
| introText=Our unique home delivery service brings you fresh organic produce, dairy, meats, breads and other delicious and healthy items direct to your doorstep. |
| |
| # categories |
| dairy=dairy |
| meats=meats |
| bakery=bakery |
| fruit\ &\ veg=fruit & veg</pre> |
| |
| Comments are added using a number sign ('<code>#</code>'). Also, because the <code>fruit & veg</code> |
| category name contains spaces, it is necessary to escape the space characters using a backslash |
| ('<code>\</code>') in order to apply the name as a resource bundle key. |
| |
| <br><br> |
| We are now finished with the default resource bundle for the application's welcome page. |
| Let's continue by creating resource bundles for the customer-specified languages.</li> |
| |
| <li>In the Projects window, expand the Source Packages node, then right-click the <code>resources</code> |
| > <code>messages.properties</code> file node and choose Customize. The Customizer dialog |
| opens.</li> |
| |
| <li>In the Customizer dialog, click the Add Locale button. In the New Locale dialog that |
| displays, enter '<code>en</code>' in the Language Code combo box, then click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/new-locale-dialog.png" |
| class="margin-around b-all" alt="New Locale dialog" |
| title="The New Locale dialog enables you to add a new locale to an existing resource bundle base name"> |
| |
| <br> |
| <p class="tips">A <em>locale</em> can be defined by both a language and a geographic region. |
| The optional country code which can be used to specify the region can be applied to define |
| formatting for dates, time, numbers, and currency. For more information, see the technical |
| article, <a href="http://java.sun.com/developer/technicalArticles/J2SE/locale/" target="_blank">Understanding |
| Locale in the Java Platform</a>.</p></li> |
| |
| <li>Click the Add Locale button again, then enter '<code>cs</code>' in the Language Code combo |
| box and click OK. The Customizer dialog displays as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/customizer-dialog.png" |
| class="margin-around b-all" alt="New Locale dialog" |
| title="The New Locale dialog enables you to add a new locale to an existing resource bundle base name"></li> |
| |
| <li>Click Close. In the Projects window, note that your resource bundles look as follows. You can |
| expand a resource bundle to view the keys it contains. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/projects-window.png" |
| class="margin-around b-all" alt="Resource bundles displayed in Projects window" |
| title="View resource bundles and the keys they contain in the Projects window"></li> |
| |
| <li>Right-click any of the three resource bundles and choose Open. The Properties editor opens, |
| enabling you to view and edit key-value pairs for all locales in a table layout. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/language/properties-editor.png" |
| rel="lytebox" title="Use the Properties editor to view and edit key-value pairs for all locales"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/properties-editor.png" |
| class="margin-around b-all" alt="Properties editor for resource bundles" style="width:688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">Press Shift-Esc to maximize the window in the IDE.</p> |
| |
| Note that when you add a new locale using the Customizer dialog, as you did for English and |
| Czech in the previous steps, the keys and values of the default resource bundle are copied |
| to the new locale.</li> |
| |
| <li>Modify the values for the Czech resource bundle. You can do this by <em>either</em> clicking |
| into the table cells for each row and typing your entries directly <em>or</em> selecting the |
| cell you want to edit and typing into the <strong>Value</strong> field located at the bottom |
| of the Properties editor. |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>greeting:</strong> <code>Vítejte v našem domácím on-line obchodě Affable Bean Green Grocer.</code></li> |
| <li><strong>introText:</strong> <code>Naše jedinečná dodávková služba Vám zajistí dopravu čerstvých organických produktů, mléčných výrobků, uzenin, pečiva a dalších delikates a zdravých výroků až ke dveřím.</code></li> |
| <li><strong>dairy:</strong> <code>mléčné výrobky</code></li> |
| <li><strong>meats:</strong> <code>maso</code></li> |
| <li><strong>bakery:</strong> <code>pečivo</code></li> |
| <li><strong>fruit & veg:</strong> <code>ovoce a zeleniny</code></li> |
| </ul> |
| |
| <p class="tips">You can also add a comment to each key-value pair. Any text you enter into |
| the <strong>Comment</strong> field in the Properties editor is added to the resource |
| bundle text file above the key-value pair as a comment (i.e., following a '<code>#</code>' |
| sign).</p></li> |
| |
| <li>Double-click the <code>messages_cs.properties</code> file node in the Projects window. Note |
| that the text file has been updated according to your changes in the Properties editor. |
| |
| <pre class="examplecode"> |
| # welcome page |
| greeting=Vítejte v našem domácím on-line obchodě Affable Bean Green Grocer. |
| introText=Naše jedinečná dodávková služba Vám zajistí dopravu čerstvých organických produktů, mléčných výrobků, uzenin, pečiva a dalších delikates a zdravých výroků až ke dveřím. |
| |
| # categories |
| dairy=mléčné výrobky |
| meats=maso |
| bakery=pečivo |
| fruit\ &\ veg=ovoce a zeleniny</pre></li> |
| </ol> |
| |
| <p>We now have the following resource bundles defined:</p> |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>default (English)</li> |
| <li>Czech</li> |
| <li>English</li> |
| </ul> |
| |
| <p>You might assume that if the default bundle is in English, then there is no need to |
| create a resource bundle explicitly for English. However, consider the following scenario: |
| a client browser's list of preferred languages includes both Czech and English, with |
| English taking precedence over Czech. If the application doesn't provide a resource |
| bundle for English but does for Czech, pages sent to that browser will be in Czech |
| (since a Czech bundle was defined). This is clearly not the desired behavior for that |
| browser.</p> |
| |
| |
| <h3 id="register">Register the Resource Bundle with the Application</h3> |
| |
| <p>The purpose of this step is to inform JSTL's format (i.e., |
| <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/fmt/tld-summary.html" target="_blank"><code>fmt</code></a>) |
| tag library where it can locate any resource bundles existing in the application. You |
| accomplish this by instructing the application to create a |
| <a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/jstl/1.1/docs/api/javax/servlet/jsp/jstl/fmt/LocalizationContext.html" target="_blank"><code>LocalizationContext</code></a> |
| using the existing resource bundles. This can be done by setting a context parameter |
| in the application's <code>web.xml</code> deployment descriptor.</p> |
| |
| <p class="tips">The topic of setting context parameters is also covered in |
| <a href="connect-db.html#param">Connecting the Application to the Database</a>.</p> |
| |
| <ol> |
| <li>In the Projects window, expand the Configuration Files node, then double-click |
| <code>web.xml</code> to open it in the editor.</li> |
| |
| <li>Under the deployment descriptor's General tab, expand the Context Parameters |
| category.</li> |
| |
| <li>Click the Add button, then in the Add Context Parameter dialog enter the following |
| values. |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Parameter Name:</strong> <code>javax.servlet.jsp.jstl.fmt.localizationContext</code></li> |
| <li><strong>Parameter Value:</strong> <code>resources.messages</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/add-context-parameter.png" |
| class="margin-around b-all" alt="Add Context Parameter dialog" |
| title="Add context parameters under the General tab for web.xml"> |
| |
| <p class="tips">The <code>LocalizationContext</code> class belongs to the |
| <code>javax.servlet.jsp.jstl.fmt</code> package. You can verify this by viewing |
| the <a href="http://java.sun.com/products/jsp/jstl/1.1/docs/api/index.html" target="_blank">JSTL |
| 1.1 API Reference</a> online.</p></li> |
| |
| <li>Click OK. The new context parameter is added to the table of existing context parameters |
| under the General tab.</li> |
| |
| <li>Click the deployment descriptor's XML tab. Note that the following entry has been |
| added to the file: |
| |
| <pre class="examplecode"> |
| <context-param> |
| <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> |
| <param-value>resources.messages</param-value> |
| </context-param></pre></li> |
| </ol> |
| |
| |
| <h3 id="replace">Replace Hard-Coded Text with <code><fmt:message></code> Tags</h3> |
| |
| <p>In order to apply the localized text of resource bundles to your web pages, you reference |
| the keys from the key-value pairs you created. You can reference the keys using JSTL's |
| <code><fmt:message></code> tags.</p> |
| |
| <ol> |
| <li>Open the project's <code>index.jsp</code> page in the editor. (If already opened, |
| press Ctrl-Tab to switch to the file.)</li> |
| |
| <li>Delete instances of hard-coded text that display in the page's left column, and |
| in their place enter <code><fmt:message></code> tags using the <code>key</code> |
| attribute to specify the resource bundle key. The page's left column will look as |
| follows. |
| |
| <pre class="examplecode"> |
| <div id="indexLeftColumn"> |
| <div id="welcomeText"> |
| <p style="font-size: larger"><strong><fmt:message key='greeting'/></strong></p> |
| |
| <p><strong><fmt:message key='introText'/></strong></p> |
| </div> |
| </div></pre></li> |
| |
| <li>Add <code><fmt:message></code> tags for the four category names, but use |
| the <code>${category.name}</code> expression as the value for the <code>key</code> |
| attribute. Since the category name is also used as the value for the <code><img></code> |
| tag's <code>alt</code> attribute, follow the same procedure. The page's right |
| column will look as follows. |
| |
| <pre class="examplecode"> |
| <div id="indexRightColumn"> |
| <c:forEach var="category" items="${categories}"> |
| <div class="categoryBox"> |
| <a href="<c:url value='category?${category.id}'/>"> |
| <span class="categoryLabel"></span> |
| <span class="categoryLabelText"><strong><fmt:message key='${category.name}'/></strong></span> |
| |
| <img src="${initParam.categoryImagePath}${category.name}.jpg" |
| alt="<strong><fmt:message key='${category.name}'/></strong>" class="categoryImage"> |
| </a> |
| </div> |
| </c:forEach> |
| </div></pre></li> |
| |
| <li>Finally, ensure that you have the <code>fmt</code> tag library declared in the |
| web page. Enter the following at the top of the file: |
| |
| <pre class="examplecode"><%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %></pre> |
| |
| <p class="notes"><strong>Note:</strong> Here you add the tag library declaration |
| to the top of the <code>index.jsp</code> file. However, when you begin using |
| <code><fmt></code> tags elsewhere in the project, it may make more sense |
| to remove the tag library declaration from individual page views, and add it |
| to the header (<code>header.jspf</code>) file. This practice is adopted in |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">snapshot |
| 9</a> (and later snapshots).</p> |
| </li> |
| </ol> |
| |
| <p>You've now completed the tasks necessary for providing bilingual support for the |
| application's welcome page. The following step demonstrates how to test the language |
| support in your browser.</p> |
| |
| |
| <h3 id="test">Test Supported Languages</h3> |
| |
| <p>You could theoretically test for the following scenarios involving the application's |
| supported languages, as well as an unsupported language (e.g., Korean):</p> |
| |
| <div class="indent"> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Use-case</th> |
| <th class="tblheader" scope="col">Outcome</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 1. Browser has no preferred language</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 2. Browser prefers only English</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 3. Browser prefers only Czech</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 4. Browser prefers only Korean</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 5. Browser prefers Korean and English; Korean takes precedence</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 6. Browser prefers Korean and English; English takes precedence</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 7. Browser prefers Korean and Czech; Korean takes precedence</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 8. Browser prefers Korean and Czech; Czech takes precedence</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 9. Browser prefers English and Czech; English takes precedence</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">10. Browser prefers English and Czech; Czech takes precedence</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">11. Browser prefers, in the following order, English, Czech, Korean</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">12. Browser prefers, in the following order, English, Korean, Czech</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">13. Browser prefers, in the following order, Czech, English, Korean</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">14. Browser prefers, in the following order, Czech, Korean, English</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">15. Browser prefers, in the following order, Korean, English, Czech</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">16. Browser prefers, in the following order, Korean, Czech, English</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <br> |
| <p>Rather than stepping through all 16 scenarios, we'll demonstrate how to examine scenario 3 above, in which |
| the browser's preferred language is Czech, using the Firefox browser.</p> |
| |
| <ol> |
| <li>In Firefox, choose Tools > Options (Firefox > Preferences on Mac). In the window that |
| displays, click the Content tab. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/firefox-content.png" |
| class="margin-around b-all" alt="Firefox options - Content tab" |
| title="Examine your browser's preferred languages"></li> |
| |
| <li>Under the Languages heading, click Choose.</li> |
| |
| <li>Select any language that is currently listed in the provided text area, then click Remove. |
| (You should remember your language list and reinstate languages after completing this tutorial.)</li> |
| |
| <li>Click the 'Select Language to Add' drop-down and select <code>Czech [cs]</code>. Then |
| click the Add button. The Czech language is added to the text area. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/firefox-languages.png" |
| class="margin-around b-all" alt="Firefox options - General tab" |
| title="Specify your browser's preferred languages"></li> |
| |
| <li>Click OK, then press Esc to close Firefox' Options window.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ). When the welcome page opens in your browser, note |
| that text is displayed in Czech. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/czech-text.png" |
| class="margin-around b-all" alt="Czech text displayed in welcome page" style="width:688px" |
| title="The displayed language is determined by your browser's language preferences"></li> |
| </ol> |
| </div> |
| |
| |
| <br> |
| <h2 id="toggle">Implementing a Language Toggle</h2> |
| |
| <p>Now that basic Czech-English language support is in place, continue by implementing the language |
| toggle in the application's page views. We can divide this task into three parts:</p> |
| |
| <ul> |
| <li><a href="#toggleDisplay">Create Toggle Display and Synchronize with the Browser's Preferred Language</a></li> |
| <li><a href="#handleRequest">Implement Functionality to Handle a Request from the Language Toggle</a></li> |
| <li><a href="#keepTrack">Enable the Application to Keep Track of the Originating Page View</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="toggleDisplay">Create Toggle Display and Synchronize with the Browser's Preferred Language</h3> |
| |
| <ol> |
| <li>Use the Go to File dialog to open the <code>header</code> JSP fragment in the editor. Press |
| Alt-Shift-O (Ctrl-Shift-O on Mac), then type '<code>h</code>' in the dialog and click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/go-to-file-dialog.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="Use the Go to File dialog to quickly open project resources in the editor"></li> |
| |
| <li>In the <code>header.jspf</code> file, locate the first <code><div class="headerWidget"></code> |
| tag (line 56), and replace the <code>[ language toggle ]</code> placeholder text with the |
| following HTML markup. |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <strong><%-- language selection widget --%> |
| english | <div class="bubble"><a href="chooseLanguage?language=cs">česky</a></div></strong> |
| </div></pre> |
| |
| This markup implements the language toggle's appearance when English is the displayed |
| language. In other words, the toggle provides a link allowing the user to select the |
| Czech (i.e., '<code>česky</code>') option. The link is used to send a request for |
| <code>chooseLanguage</code>, and creates a query string (<code>?language=cs</code>) that |
| specifies the requested language code. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> Recall that in Unit 5, <a href="page-views-controller.html#controller">Preparing |
| the Page Views and Controller Servlet</a>, you set the <code>ControllerServlet</code> |
| to handle the <code>/chooseLanguage</code> URL pattern.</p> |
| |
| <p class="tips">Snapshot 8 includes the <a href="http://jquery.com/" target="_blank">jQuery</a> |
| JavaScript library and takes advantage of various UI effects to enhance the appearance |
| and behavior of the website. Aside from a |
| <a href="http://plugins.jquery.com/project/validate" target="_blank">jQuery plugin |
| for client-side validation</a> (discussed in the <a href="transaction.html#client">previous |
| tutorial unit</a>), the snapshot implements an easing effect for category headings in |
| the welcome page, as well as for category buttons in the category page. Configuration |
| is included in <code>header.jspf</code> of the project snapshot. Rounded corners are |
| implemented using CSS3's <a href="http://www.w3.org/TR/css3-background/#corners" |
| target="_blank">border-radius</a> property (applied in <code>affablebean.css</code>).</p></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to see what the toggle looks like in the browser. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/language-toggle.png" |
| class="margin-around b-all" alt="Language toggle in browser" |
| title="Run the project to view the language toggle"> |
| |
| <br> |
| Currently, the language toggle appears as in the above image regardless of what language |
| the page displays in. In the next step, you integrate JSTL logic into the toggle so that |
| it renders according to the language displayed on the page.</li> |
| |
| <li id="step4">Modify the toggle implementation as follows. |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <%-- language selection widget --%> |
| <strong><c:choose> |
| <c:when test="${pageContext.request.locale.language ne 'cs'}"> |
| english |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="en"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">english</a></div> |
| </c:otherwise> |
| </c:choose> | |
| |
| <c:choose> |
| <c:when test="${pageContext.request.locale.language eq 'cs'}"> |
| česky |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="cs"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">česky</a></div> |
| </c:otherwise> |
| </c:choose></strong> |
| </div></pre> |
| |
| In the above implementation, you rely on conditional tags from JSTL's <code>core</code> |
| tag library to display the left and right portions of the toggle according to the language |
| used by the request locale. What is the "language used by the request locale"? |
| When a request is made, the browser passes a list of preferred locales in the <code>Accept-Language</code> |
| HTTP header. The Java runtime environment on the server reads the list and determines |
| the best match based on the locales defined by the application's resource bundles. This |
| match is then recorded in the <code>ServletRequest</code> object, and can be accessed |
| using the <code>getLocale</code> method. For example, you could access the preferred |
| locale from a servlet with the following statement. |
| |
| <pre class="examplecode">request.getLocale();</pre> |
| |
| <p class="tips">You can use the IDE's HTTP Monitor (Window > Debugging > HTTP |
| Server Monitor) to examine HTTP headers for client requests. In order to use the |
| HTTP Monitor, you need to first activate it for the server you are using. Unit 8, |
| <a href="manage-sessions.html">Managing Sessions</a> provides a demonstration |
| under the sub-section, <a href="manage-sessions.html#http-monitor">Examining |
| Client-Server Communication with the HTTP Monitor</a>.</p> |
| |
| <p>To determine the language of the preferred locale, you use the <code>Locale</code> |
| class' <code>getLanguage</code> method. Again, from a servlet you could access the |
| language of the client request's preferred locale with the following.</p> |
| |
| <pre class="examplecode">request.getLocale().getLanguage();</pre> |
| |
| <p>Returning to the code you just added to the <code>header.jspf</code> fragment, |
| you utilize the <code>pageContext.request</code> implicit object to access the |
| <code>ServletRequest</code> for the given client request. Using dot notation, you |
| then proceed to call the same methods as you would from a servlet. In the above |
| example, accessing the "language used by the request locale" is as simple |
| as:</p> |
| |
| <pre class="examplecode">${pageContext.request.locale.language}</pre> |
| |
| <p class="notes"><strong>Note:</strong> The above implementation uses <code><c:url></code> |
| tags to set up the toggle link. This is done in order to properly encode the request |
| URL in the event that URL rewriting is used as a means for session tracking. Unit 8, |
| <a href="manage-sessions.html#encodeUrl">Managing Sessions</a> provides a brief |
| explanation of how the <code><c:url></code> tags can be used.</p></li> |
| |
| <li>Add a basic language test to the <code>header.jspf</code> file. This will enable us to |
| check whether the toggle is properly rendering according to the client request's preferred |
| language. Enter the following after the page's <code><body></code> tag. |
| |
| <pre class="examplecode"> |
| <body> |
| |
| <strong><%-- Language test --%> |
| <p style="text-align: left;"><strong>tests:</strong> |
| <br> |
| <code>\${pageContext.request.locale.language}</code>: ${pageContext.request.locale.language} |
| </p></strong> |
| |
| <div id="main"></pre></li> |
| |
| <li>Ensure that you have set Czech as your browser's preferred language. (If you are |
| following this tutorial unit sequentially, you've already done this. If not, refer |
| to the steps outlined above in <a href="#test">Test Supported Languages</a>.)</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) and examine the application welcome page in the browser. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/language-test.png" |
| class="margin-around b-all" style="width:688px" alt="Language test and welcome page displayed in browser" |
| title="Language toggle displays according to request's preferred language"> |
| |
| <br> |
| If your browser's preferred language is set to Czech, you can note the following: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>The test that we introduced in the previous step indicates that '<code>cs</code>' |
| is the preferred language.</li> |
| |
| <li>Czech text is displayed in the page.</li> |
| |
| <li>The language toggle provides a link enabling the user to select English.</li> |
| </ul> |
| </li> |
| </ol> |
| |
| |
| <h3 id="handleRequest">Implement Functionality to Handle a Request from the Language Toggle</h3> |
| |
| <p>Now that the toggle is in place and it appears according to the language displayed |
| in the page, let's continue by adding code to the <code>ControllerServlet</code> |
| that handles the request sent when a user clicks the link in the language toggle.</p> |
| |
| <p>As indicated in the current language toggle implementation from <a href="#step4">step 4</a> |
| above, the requested URL with query string looks as follows:</p> |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>English:</strong> <code>chooseLanguage?language=en</code></li> |
| <li><strong>Czech:</strong> <code>chooseLanguage?language=cs</code></li> |
| </ul> |
| |
| <p>Our goal is to register the language choice, and then display both the page view and |
| language toggle based on the chosen language. We can accomplish this by extracting |
| the <code>language</code> parameter from the query string and creating a session-scoped |
| <code>language</code> attribute that remembers the language selected by the user. Then |
| we'll return to the <code>header.jspf</code> fragment and apply the |
| <a href="http://download-llnw.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/fmt/setLocale.html" target="_blank"><code><fmt:setLocale></code></a> |
| tag to set the page language based on the user's choice. With the <code><fmt:setLocale></code> |
| tag we can manually switch the language used in the page display. We'll also modify |
| the language toggle so that if the <code>language</code> attribute has been set, the |
| toggle's appearance is determined according to the <code>language</code> attribute's |
| value.</p> |
| |
| <ol> |
| <li>Open the <code>ControllerServlet</code> in the editor. Use the Go To File dialog |
| - press Alt-Shift-O (Ctrl-Shift-O on Mac), then type '<code>controller</code>' and |
| click OK. In the opened file, locate the portion of the <code>doGet</code> method |
| that handles the <code>chooseLanguage</code> request (line 126).</li> |
| |
| <li>Delete the <code>// TODO: Implement language request</code> comment and enter code |
| to extract the <code>language</code> parameter from the request query string. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| <strong>// get language choice |
| String language = request.getParameter("language");</strong> |
| }</pre></li> |
| |
| <li>Place the <code>language</code> parameter in the request scope. Add the following. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| <strong>// place in request scope |
| request.setAttribute("language", language);</strong> |
| }</pre></li> |
| |
| <li>As a temporary measure, have the application forward the response to the |
| <code>index.jsp</code> welcome page when the language toggle link is clicked. |
| Add the following code. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| // place in request scope |
| request.setAttribute("language", language); |
| |
| <strong>// forward request to welcome page |
| try { |
| request.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return;</strong> |
| }</pre> |
| Naturally, forwarding the user to the welcome page regardless of what page |
| he or she is on is not an ideal way to handle the language toggle's behavior. |
| We'll return to this matter in the next sub-section, <a href="#keepTrack">Enable |
| the Application to Keep Track of the Originating Page View</a>. For the meantime |
| however, this will allow us to examine the results of the current language |
| toggle implementation when running the project.</li> |
| |
| <li>Switch to the <code>header.jspf</code> fragment (If the file is already opened |
| in the editor, press Ctrl-Tab and choose the file.) and apply the |
| <a href="http://download-llnw.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/fmt/setLocale.html" target="_blank"><code><fmt:setLocale></code></a> |
| tag to set the page language based on the new <code>language</code> variable. |
| Add the following. |
| |
| <pre class="examplecode"> |
| <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
| <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> |
| <strong><%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> |
| |
| <%-- Set language based on user's choice --%> |
| <c:if test="${!empty language}"> |
| <fmt:setLocale value="${language}" scope="session" /> |
| </c:if></strong> |
| |
| |
| <%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"></pre> |
| |
| Since the <code>language</code> variable is only created when the user clicks the |
| link in the language toggle, you perform a test using |
| <a href="http://download-llnw.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/c/if.html" target="_blank"><code><c:if></code></a> |
| tags to determine whether the variable exists before attempting to set the language. |
| When applying the <code><fmt:setLocale></code> tag, you set its scope to |
| <code>session</code> as you want the user-selected language to take precedence |
| for the remainder of his or her session on the website. Also, since this is the |
| first time the <code>fmt</code> library is used in the header, you declare the tag |
| library. |
| |
| <br><br> |
| <p class="tips">You can read the EL expression <code>${!empty language}</code> as, |
| "False if the <code>language</code> variable is null or an empty string." |
| See the |
| <a href="http://download-llnw.oracle.com/javaee/5/tutorial/doc/bnahq.html#bnaim" target="_blank">Java |
| EE 5 Tutorial: Examples of EL Expressions</a> for other available examples.</p></li> |
| |
| <li>Modify the language toggle implementation so that if a value has been set by the |
| <code><fmt:setLocale></code> tag, the toggle displays according to the language |
| specified by that value. (You can determine this value using the |
| <code>${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</code> expression.) |
| |
| <br><br> |
| Enclose the current implementation within <code><c:choose></code> tags, and |
| create logic similar to the current implementation in the event that the locale has |
| been manually set. (Changes are displayed in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <%-- language selection widget --%> |
| <strong><c:choose> |
| <%-- When user hasn't explicitly set language, |
| render toggle according to browser's preferred locale --%> |
| <c:when test="${empty sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}"></strong> |
| <c:choose> |
| <c:when test="${pageContext.request.locale.language ne 'cs'}"> |
| english |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="en"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">english</a></div> |
| </c:otherwise> |
| </c:choose> | |
| |
| <c:choose> |
| <c:when test="${pageContext.request.locale.language eq 'cs'}"> |
| česky |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="cs"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">česky</a></div> |
| </c:otherwise> |
| </c:choose> |
| <strong></c:when> |
| |
| <%-- Otherwise, render widget according to the set locale --%> |
| <c:otherwise> |
| <c:choose> |
| <c:when test="${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session'] ne 'cs'}"> |
| english |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="en"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">english</a></div> |
| </c:otherwise> |
| </c:choose> | |
| |
| <c:choose> |
| <c:when test="${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session'] eq 'cs'}"> |
| česky |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="cs"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">česky</a></div> |
| </c:otherwise> |
| </c:choose> |
| </c:otherwise> |
| </c:choose></strong> |
| |
| </div></pre></li> |
| |
| <li>Before examining the project in a browser, add another test that displays the |
| value set by the <code><fmt:setLocale></code> tag. Add the following code |
| beneath the test you created earlier. |
| |
| <pre class="examplecode"> |
| <p style="text-align: left;"><strong>tests:</strong> |
| <br> |
| <code>\${pageContext.request.locale.language}</code>: ${pageContext.request.locale.language} |
| <strong><br> |
| <code>\${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</code>: ${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</strong> |
| </p></pre> |
| |
| <p class="tips"><code>javax.servlet.jsp.jstl.fmt.locale.session</code> is the <em>string |
| literal</em> key for the <code>Locale</code> set by the <code><fmt:setLocale></code> |
| tag. You can verify this by clicking in the editor's left margin to set a breakpoint ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/breakpoint-badge.png" |
| alt="Breakpoint badge"> ) on the new test, then running the debugger ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) on the project. When you click the toggle link to change |
| languages in the browser, examine the Variables window (Alt-Shift-1; Ctrl-Shift-1 on |
| Mac) when the debugger suspends on the breakpoint. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/language/variables-window.png" |
| rel="lytebox" title="Run debugger and view variable and expression values in the Variables window"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/variables-window.png" |
| class="margin-around b-all" style="width:654px" alt="Variables window" |
| title="Click to enlarge"></a> |
| |
| <br> |
| EL expressions presented in this tutorial primarily use dot (<code>.</code>) notation. The |
| format depicted in the expression above is known as <em>bracket</em> (<code>[]</code>) notation |
| whereby you enter the string literal key within quotes in order to extract the object's value: |
| |
| <div style="margin:-10px 0 0 43px"> |
| <pre class="examplecode" style="width:637px">${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</pre> |
| </div> |
| |
| <p style="margin-left:34px">Numerous EL resolver classes exist for the purpose of resolving expressions. |
| For example, when the above expression is encountered at runtime, the |
| <a href="http://download-llnw.oracle.com/javaee/6/api/javax/servlet/jsp/el/ImplicitObjectELResolver.html" target="_blank"><code>ImplicitObjectResolver</code></a> |
| first returns a <code>Map</code> that maps session-scoped attribute names to their values. (In the |
| above image of the Variables window, you can verify that session attributes are maintained in a |
| <a href="http://download-llnw.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html" target="_blank"><code>ConcurrentHashMap</code></a>.) |
| In order to resolve the remainder of the expression, the |
| <a href="http://download-llnw.oracle.com/javaee/6/api/javax/el/MapELResolver.html" target="_blank"><code>MapELResolver</code></a> |
| is used to get the value of the key named '<code>javax.servlet.jsp.jstl.fmt.locale.session</code>'. |
| |
| <br><br> |
| For more information, refer to the Java EE 5 Tutorial: |
| <a href="http://download-llnw.oracle.com/javaee/5/tutorial/doc/bnahq.html#bnaif" target="_blank">Unified |
| Expression Language: Resolving Expressions</a>.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) and examine the application welcome page in the browser. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/toggle-page1.png" |
| class="margin-around b-all" style="width:688px" alt="Welcome page displayed in browser" |
| title="Welcome page displays according to browser's preferred language"> |
| |
| <br> |
| In the above image, the server identifies Czech (<code>cs</code>) as the browser's preferred |
| language from the <code>Accept-Language</code> HTTP header. This is indicated from the first |
| test. The page displays in Czech, and the language toggle enables the user to choose English. |
| The second test remains blank as the <code><fmt:setLocale></code> tag has not yet been |
| called.</li> |
| |
| <li>Click the toggle link for English. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/toggle-page2.png" |
| class="margin-around b-all" style="width:688px" alt="Welcome page displayed in browser" |
| title="Welcome page displays in English, according to toggle selection"> |
| |
| <br> |
| When clicking the toggle link, the default Czech language is overridden by means of the |
| <code><fmt:setLocale></code> tag implemented in the <code>header.jspf</code> file. |
| Although the browser's preferred language remains Czech, you see that the page now displays |
| according to the new language made available by the language toggle.</li> |
| |
| <li>Click the toggle link for Czech. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/toggle-page3.png" |
| class="margin-around b-all" style="width:688px" alt="Welcome page displayed in browser" |
| title="Welcome page displays in Czech, according to toggle selection"> |
| |
| <br> |
| Changing the language back to the browser's preferred language works as expected, however |
| note that the deciding factor is no longer the language detected from the <code>Accept-Language</code> |
| HTTP header, but is the language specified from the <code><fmt:setLocale></code> tag.</li> |
| |
| <li>Before continuing, remove the tests you added to the <code>header.jspf</code> file. |
| (Deleted code in <strong><strike>strike-through</strike></strong> text.) |
| |
| <pre class="examplecode"> |
| <body> |
| |
| <strong><strike><%-- Language tests --%></strike> |
| <strike><p style="text-align: left;"><strong>tests:</strong></strike> |
| <strike><br></strike> |
| <strike><code>\${pageContext.request.locale.language}</code>: ${pageContext.request.locale.language}</strike> |
| <strike><br></strike> |
| <strike><code>\${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</code>: ${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</strike> |
| <strike></p></strike></strong> |
| |
| <div id="main"></pre></li> |
| </ol> |
| |
| |
| <h3 id="keepTrack">Enable the Application to Keep Track of the Originating Page View</h3> |
| |
| <p>One of the <a href="#impDeets">implementation details</a> which you have agreed on with |
| the Affable Bean staff is that when the language toggle is used to change the language, |
| the user remains in the same page view. In our current implementation, the welcome page |
| is returned whenever the language toggle is clicked. A more user-friendly approach would |
| be to provide the application with a means of tracking the request page view, and forwarding |
| the request to that page view when the language toggle link is clicked.</p> |
| |
| <p>We can accomplish this by setting a session-scoped <code>view</code> attribute within each |
| of the page views, then referencing this attribute in the <code>ControllerServlet</code> |
| in order to determine where to forward the request. There are however several caveats |
| to consider when dealing with the language toggle in the confirmation page. These are |
| discussed and dealt with in steps 7-11 below.</p> |
| |
| <p>Begin this exercise with <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">snapshot |
| 9</a> of the <code>AffableBean</code> project. This snapshot includes completed English |
| and Czech resource bundles for all page views, all page views have been modified to use |
| text from the resource bundles, and the language toggle is presented in a state corresponding |
| to this point in the tutorial.</p> |
| |
| <ol> |
| <li>Open <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">snapshot |
| 9</a> in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project.</li> |
| |
| <li>Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button to run the project. When navigating through the site, |
| note that when you click the language toggle from any of the page views, you are returned |
| to the application's welcome page. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="setup.html">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Use <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/c/set.html" target="_blank"><code><c:set></code></a> |
| tags to set a session-scoped <code>view</code> attribute for each of the page views. |
| Open each of the page views in the editor and add the following code to the top of |
| each file. |
| |
| <h4>index.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/index' scope='session' /></pre> |
| |
| <h4>category.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/category' scope='session' /></pre> |
| |
| <h4>cart.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/cart' scope='session' /></pre> |
| |
| <h4>checkout.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/checkout' scope='session' /></pre> |
| |
| Based on customer-agreed <a href="#impDeets">implementation details</a>, we |
| do not need to provide a means of switching languages on the confirmation page |
| view. From a usability perspective, a user will have already selected his or |
| her preferred language prior to checkout. From an implementation perspective, |
| recall that we destroy the user session upon a successfully completed order. |
| (Refer back to the final paragraph in <a href="manage-sessions.html">Managing |
| Sessions</a>, which describes how to apply the <code>invalidate</code> method |
| to explicitly terminate a user session.) If the Affable Bean staff were to insist |
| on allowing customers to view their orders bilingually, you would need to consider |
| the following scenarios, dependent on whether you destroy the user session |
| upon displaying the confirmation page: |
| |
| <ol style="margin: 5px 0 0 0em; list-style-type:lower-alpha"> |
| <li><strong>Session destroyed:</strong> Would be necessary to take |
| extra measures to ensure that a <code>chooseLanguage</code> request |
| from the confirmation page refers to the appropriate order, and can |
| display customer-sensitive details in a secure fashion.</li> |
| |
| <li><strong>Session maintained:</strong> Would risk enabling users |
| to mistakenly place double orders on their shopping cart. Also, by |
| not terminating user sessions when they are no longer needed, an |
| unnecessary load may be placed on the server.</li> |
| </ol></li> |
| |
| <li>Open the <code>ControllerServlet</code> in the editor. (If already opened, |
| press Ctrl-Tab and choose the file.) In the opened file, locate the portion |
| of the <code>doGet</code> method that handles the <code>chooseLanguage</code> |
| request (line 126). |
| |
| <br><br> |
| Note that currently <code>chooseLanguage</code> requests are forwarded to |
| the <code>index.jsp</code> welcome page. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| // place in session scope |
| session.setAttribute("language", language); |
| |
| <strong>// forward request to welcome page |
| try { |
| request.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return;</strong> |
| }</pre></li> |
| |
| <li>Use the <code>view</code> session attribute to forward the request back |
| to the originating page view. Make the following changes (in <strong>bold</strong>). |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| // place in request scope |
| request.setAttribute("language", language); |
| |
| <strong>String userView = (String) session.getAttribute("view"); |
| |
| if ((userView != null) && |
| (!userView.equals("/index"))) { // index.jsp exists outside 'view' folder |
| // so must be forwarded separately |
| userPath = userView; |
| } else { |
| |
| // if previous view is index or cannot be determined, send user to welcome page</strong> |
| try { |
| request.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return; |
| <strong>}</strong> |
| }</pre> |
| |
| In the above implementation, you extract the value of the <code>view</code> attribute |
| and, provided that the view: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>can be identified (i.e., the value is not null),</li> |
| |
| <li>does not originate from the welcome page (<code>index.jsp</code> does not |
| reside in the same location as other page views, and therefore cannot be |
| resolved using the <code>doGet</code> method's way of forwarding requests)</li> |
| </ul> |
| |
| <span class="indent">...you set it to the <code>doGet</code> method's <code>userPath</code> |
| variable, and forward the request using the method's existing <code>RequestDispatcher</code>:</span> |
| |
| <pre class="examplecode"> |
| // use RequestDispatcher to forward request internally |
| String url = "/WEB-INF/view" + userPath + ".jsp"; |
| |
| try { |
| request.getRequestDispatcher(url).forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| }</pre></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to test it in the browser. When you navigate to the |
| category, cart or checkout pages, switch languages using the language toggle. |
| When you do so, you now remain within the same page view.</li> |
| |
| <li>In the browser, complete an order so that the application forwards you to the |
| confirmation page. When you click the language toggle from the confirmation page, |
| note that you are sent back to the website's welcome page. |
| |
| <br><br> |
| Implementation-wise, you may consider this to be sufficient. However, the Affable |
| Bean staff have explicitly asked you to remove the language toggle from this page |
| view. One way to accomplish this is to perform a test to determine whether the request |
| <em>servlet path</em> contains '<code>/confirmation</code>'. |
| |
| <br><br> |
| Switch to the <code>header.jspf</code> file in the editor and surround the language |
| toggle with the following test. You can use JSTL's functions (i.e., |
| <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/fn/tld-summary.html" target="_blank"><code>fn</code></a>) |
| library to perform string operations. |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <strong><%-- If servlet path contains '/confirmation', do not display language toggle --%> |
| <c:if test="${!fn:contains(pageContext.request.servletPath,'/confirmation')}"></strong> |
| |
| <%-- language selection widget --%> |
| <c:choose> |
| |
| ... |
| </c:choose> |
| |
| <strong></c:if></strong> |
| </div></pre> |
| |
| Examine the above code snippet and note the following points: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>The servlet path can be accessed from the <code>HttpServletRequest</code> |
| using the <a href="http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getServletPath%28%29" target="_blank"><code>getServletPath</code></a> |
| method. Because we use a <code>RequestDispatcher</code> to forward the request |
| to the confirmation page (<code>ControllerServlet</code>, line 158), the servlet |
| path becomes: |
| |
| <pre class="examplecode" style="width: 651px">/WEB-INF/view/confirmation.jsp</pre></li> |
| |
| <li>Using the <code>pageContext.request.servletPath</code> EL expression is |
| comparable to calling <code>request.getServletPath()</code> from a servlet.</li> |
| |
| <li>The <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/fn/contains.fn.html" target="_blank"><code>fn:contains()</code></a> |
| function allows you to test if an input string contains the specified substring.</li> |
| |
| <li>The <code>fn</code> tag library has already been declared for you at the top of |
| in the <code>header.jspf</code> file in snapshot 9: |
| |
| <pre class="examplecode" style="width: 651px"><%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %></pre></li> |
| </ul></li> |
| |
| <li>Run the project again and step through to the confirmation page. Note that the page |
| no longer displays the language toggle. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/confirmation-page.png" |
| class="margin-around b-all" style="width:688px" alt="Confirmation page displayed in browser" |
| title="Language toggle no longer displays in confirmation page"></li> |
| |
| <li>In the browser, step through to the confirmation page but switch languages once along the |
| way using the language toggle. Note that when you complete an order, the confirmation page |
| inadvertently switches back to the originally displayed language. You may rightly identify |
| the cause: upon a successfully completed order, the <code>ControllerServlet</code> destroys |
| the user session and consequently the session-scoped locale that was set using the |
| <code><fmt:setLocale></code> tag is also lost. |
| |
| <br><br> |
| To remedy this, open the <code>ControllerServlet</code> and locate the <code>invalidate()</code> |
| method which is used to destroy user sessions (approximately line 259). |
| |
| <br><br> |
| <p class="tips">Use the editor's quick search facility: press Ctrl-F (⌘-F on Mac) |
| and type in '<code>invalidate</code>'.</p></li> |
| |
| <li>Add code that extracts the session-scoped locale value prior to destroying the user session |
| and resets the request-scoped <code>language</code> attribute to the locale value after the |
| session has been destroyed. (Changes in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| // if order processed successfully send user to confirmation page |
| if (orderId != 0) { |
| |
| <strong>// in case language was set using toggle, get language choice before destroying session |
| Locale locale = (Locale) session.getAttribute("javax.servlet.jsp.jstl.fmt.locale.session"); |
| String language = ""; |
| |
| if (locale != null) { |
| |
| language = (String) locale.getLanguage(); |
| }</strong> |
| |
| // dissociate shopping cart from session |
| cart = null; |
| |
| // end session |
| session.invalidate(); |
| |
| <strong>if (!language.isEmpty()) { // if user changed language using the toggle, |
| // reset the language attribute - otherwise |
| request.setAttribute("language", language); // language will be switched on confirmation page! |
| }</strong> |
| |
| // get order details |
| Map orderMap = orderManager.getOrderDetails(orderId); |
| |
| ... |
| userPath = "/confirmation"; |
| }</pre></li> |
| |
| <li>Run the project and again, step through to the confirmation page but switch languages |
| once along the way using the language toggle. Note that when you complete an order, |
| the confirmation page now displays in the language you selected.</li> |
| </ol> |
| </div> |
| |
| <p>You have now successfully integrated language support into the <code>AffableBean</code> |
| application according to customer specification. You've factored out all text from page views, |
| placed it into resource bundles, and have applied JSTL's <code>fmt</code> tag library to |
| use resource bundle content based on the user's preferred language. You also implemented |
| a language toggle that enables users to switch between English and Czech, and override their |
| browser's default language choice. Download and examine |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot10.zip">snapshot |
| 10</a> to compare your work with the state of the project at the end of this tutorial unit.</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Adding Language Support">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <br> |
| <h2 id="seeAlso">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>External Resources</h3> |
| |
| <ul> |
| <li><a href="http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/i18n/index.html" target="_blank">The Java Tutorials: Internationalization</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnaxu.html" target="_blank">Java EE 5 Tutorial: Internationalizing and Localizing Web Applications</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/Intl/MultilingualJSP/index.html" target="_blank">Developing Multilingual Web Applications Using JavaServer Pages Technology</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/J2SE/locale/" target="_blank">Internationalization: Understanding Locale in the Java Platform</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/" target="_blank">Java Internationalization: Localization with ResourceBundles</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0415/" target="_blank">A JSTL primer, Part 3: Presentation is everything</a></li> |
| <li><a href="http://java.sun.com/javase/technologies/core/basic/intl/" target="_blank">Java Internationalization</a> [Technology Homepage]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">Internationalization and localization</a> [Wikipedia]</li> |
| <li><a href="http://www.loc.gov/standards/iso639-2/php/code_list.php" target="_blank">ISO 639-2 Language Code List</a> [Library of Congress]</li> |
| <li><a href="http://www.w3.org/International/articlelist#language" target="_blank">W3C Internationalization Activity: Articles, best practices & tutorials: Language</a></li> |
| <li><a href="http://jquery.com/" target="_blank">jQuery</a></li> |
| </ul> |
| </div> |
| |
| </body> |
| </html> |