Author: buildbot Date: Sun Dec 22 15:11:52 2024 New Revision: 1088327 Log: Production update by buildbot for tapestry
Modified: websites/production/tapestry/content/cache/main.pageCache websites/production/tapestry/content/localization.html Modified: websites/production/tapestry/content/cache/main.pageCache ============================================================================== Binary files - no diff available. Modified: websites/production/tapestry/content/localization.html ============================================================================== --- websites/production/tapestry/content/localization.html (original) +++ websites/production/tapestry/content/localization.html Sun Dec 22 15:11:52 2024 @@ -143,7 +143,7 @@ <!-- /// Content Start --> <div id="content"> - <div id="ConfluenceContent"><p><strong>Localization</strong> (aka L10n) is all about getting the right text to the user, in the right language.</p><div class="aui-label" style="float:right" title="Related Articles"> + <div id="ConfluenceContent"><p></p><p><strong>Localization</strong> (aka L10n) is all about getting the right text to the user, in the right language.</p><div class="aui-label" style="float:right" title="Related Articles"> @@ -196,7 +196,7 @@ </div> -<p>Localization support is well integrated into Tapestry. Tapestry allows you to easily separate the text you present to your users from the rest of your application ... pull it out of your Java code and even out of your component templates. You can then translate your messages into other languages and let Tapestry put everything together.</p><h2 id="Localization-ComponentMessageCatalogs">Component Message Catalogs</h2><p>Each component class may have a component message catalog. A component message catalog is a set of files with the extension ".properties". These property files are the same format used by java.util.ResourceBundle, just lines of <code>key=value</code>. These files are stored on the classpath, in the same package folder as the page or component's compiled Java class.</p><p>So for a class named <code>org.example.myapp.pages.MyPage</code>, you would have a main properties file as <code>org/example/myapp/pages/MyPage.properties</code>.</p><p>If you have a translations o f these values, you provide additional properties file, adding an <a class="external-link" href="http://www.loc.gov/standards/iso639-2/englangn.html" rel="nofollow">ISO language code</a> before the extension. Thus, if you have a French translation, you could create a file <code>MyPage_fr.properties</code>.</p><p>Any values in the more language specific file will <em>override</em> values from the main properties file. If you had an even more specific localization for just French as spoken in France, you could create <code>MyPage_fr_FR.properties</code> (that's a language code plus a country code, and you can even go further and add variants ... but its unlikely that you'll ever need to go beyond just language codes in practice).</p><p>The messages in the catalog are accessed by keys. Tapestry ignores the case of the keys when accessing messages in the catalog.</p><h3 id="Localization-ComponentMessageCatalogInheritance">Component Message Catalog Inheritance</h3><p>If a component class is a subclass of another component class, then it inherits that base class' message catalog. Its own message catalog extends and overrides the values inherited from the base class.</p><p>In this way, you could have a base component class that contained common messages, and extend or override those messages in subclasses (just as you would extend or override the methods of the base component class). This, of course, works for as many levels of inheritance as you care to support.</p><h2 id="Localization-Application-wideMessageCatalog">Application-wide Message Catalog</h2><p>If the file <code>WEB-INF/</code><em>AppName</em><code>.properties</code> exists in the context, it will be used as an application-wide message catalog. The <em>AppName</em> is derived from the name of the filter inside the web.xml file; this is most often just "app", thus <code>WEB-INF/app.properties</code>. The search for the file is case sensitive. The properties files may be localized.</p><p>Individual pages a nd components can override the values defined in the message catalog.</p><div class="confluence-information-macro confluence-information-macro-warning"><p class="title conf-macro-render">Avoid BOMs</p><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Make sure that your properties files don't contain <a class="external-link" href="http://en.wikipedia.org/wiki/Byte_order_mark" rel="nofollow">byte order marks (BOM)</a>, because Java – and thus Tapestry – doesn't support BOM in properties files (see <a class="external-link" href="http://bugs.sun.com/view_bug.do?bug_id=4508058" rel="nofollow">http://bugs.sun.com/view_bug.do?bug_id=4508058</a>). Some editors write them out when saving a file in UTF-8, so watch out.</p></div></div><h2 id="Localization-PropertiesFileCharset">Properties File Charset</h2><p>Tapestry uses the <code>UTF-8</code> character set (charset) w hen reading the properties files in a message catalog. This means that you don't have to use the Java <code>native2ascii</code> tool.</p><h2 id="Localization-LocalizedComponentTemplates">Localized Component Templates</h2><p>The same lookup mechanism applies to component templates. Tapestry will search for a localized version of each component template and use the closest match. Thus you could have <code>MyPage_fr.html</code> for French users, and <code>MyPage.html</code> for all other users.</p><h2 id="Localization-AccessingLocalizedMessages">Accessing Localized Messages</h2><p>The above discusses what files to create and where to store them, but doesn't address how to make use of that information.</p><p>Messages can be accessed in one of two ways:</p><ul><li>Using the "message:" <a href="component-parameters.html">binding expression</a> in a component template</li><li>By injecting the component's Messages object In the first case, you may use the message: binding prefix with compon ent parameters, or with template expansions:</li></ul><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> +<p>Localization support is well integrated into Tapestry. Tapestry allows you to easily separate the text you present to your users from the rest of your application ... pull it out of your Java code and even out of your component templates. You can then translate your messages into other languages and let Tapestry put everything together.</p><h2 id="Localization-ComponentMessageCatalogs">Component Message Catalogs</h2><p>Each component class may have a component message catalog. A component message catalog is a set of files with the extension ".properties". These property files are the same format used by java.util.ResourceBundle, just lines of <code>key=value</code>. These files are stored on the classpath, in the same package folder as the page or component's compiled Java class.</p><p>So for a class named <code>org.example.myapp.pages.MyPage</code>, you would have a main properties file as <code>org/example/myapp/pages/MyPage.properties</code>.</p><p>If you have a translations o f these values, you provide additional properties file, adding an <a class="external-link" href="http://www.loc.gov/standards/iso639-2/englangn.html" rel="nofollow">ISO language code</a> before the extension. Thus, if you have a French translation, you could create a file <code>MyPage_fr.properties</code>.</p><p>Any values in the more language specific file will <em>override</em> values from the main properties file. If you had an even more specific localization for just French as spoken in France, you could create <code>MyPage_fr_FR.properties</code> (that's a language code plus a country code, and you can even go further and add variants ... but its unlikely that you'll ever need to go beyond just language codes in practice).</p><p>The messages in the catalog are accessed by keys. Tapestry ignores the case of the keys when accessing messages in the catalog.</p><h3 id="Localization-ComponentMessageCatalogInheritance">Component Message Catalog Inheritance</h3><p>If a component class is a subclass of another component class, then it inherits that base class' message catalog. Its own message catalog extends and overrides the values inherited from the base class.</p><p>In this way, you could have a base component class that contained common messages, and extend or override those messages in subclasses (just as you would extend or override the methods of the base component class). This, of course, works for as many levels of inheritance as you care to support.</p><h2 id="Localization-Application-wideMessageCatalog">Application-wide Message Catalog</h2><p>If the file <code>WEB-INF/</code><em>AppName</em><code>.properties</code> exists in the context, it will be used as an application-wide message catalog. The <em>AppName</em> is derived from the name of the filter inside the web.xml file; this is most often just "app", thus <code>WEB-INF/app.properties</code>. The search for the file is case sensitive. The properties files may be localized.</p><p>Individual pages a nd components can override the values defined in the message catalog.</p><div class="confluence-information-macro confluence-information-macro-warning"><p class="title conf-macro-render">Avoid BOMs</p><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Make sure that your properties files don't contain <a class="external-link" href="http://en.wikipedia.org/wiki/Byte_order_mark" rel="nofollow">byte order marks (BOM)</a>, because Java – and thus Tapestry – doesn't support BOM in properties files (see <a class="external-link" href="http://bugs.sun.com/view_bug.do?bug_id=4508058" rel="nofollow">http://bugs.sun.com/view_bug.do?bug_id=4508058</a>). Some editors write them out when saving a file in UTF-8, so watch out.</p></div></div><p></p><h2 id="Localization-PropertiesFileCharset">Properties File Charset</h2><p>Tapestry uses the <code>UTF-8</code> character set (cha rset) when reading the properties files in a message catalog. This means that you don't have to use the Java <code>native2ascii</code> tool.</p><h2 id="Localization-LocalizedComponentTemplates">Localized Component Templates</h2><p>The same lookup mechanism applies to component templates. Tapestry will search for a localized version of each component template and use the closest match. Thus you could have <code>MyPage_fr.html</code> for French users, and <code>MyPage.html</code> for all other users.</p><h2 id="Localization-AccessingLocalizedMessages">Accessing Localized Messages</h2><p>The above discusses what files to create and where to store them, but doesn't address how to make use of that information.</p><p>Messages can be accessed in one of two ways:</p><ul><li>Using the "message:" <a href="component-parameters.html">binding expression</a> in a component template</li><li>By injecting the component's Messages objectIn the first case, you may use the message: binding prefix with component parameters, or with template expansions:</li></ul><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> <pre><code class="language-java"><t:layout title="message:page-title"> ${message:greeting}, ${user.name}! @@ -204,7 +204,7 @@ . . . </t:layout> </code></pre> -</div></div><p>Here, the <code>page-title</code> message is extracted from the catalog and passed to the Border component's title parameter.</p><p>In addition, the <code>greeting</code> message is extracted and written into the response as part of the template.</p><p>As usual, "prop:" is the default binding prefix, thus <code>user.name</code> is a property path, not a message key.</p><p>You would extend this with a set of properties files:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> +</div></div><p>Here, the <code>page-title</code> message is extracted from the catalog and passed to the Layout component's <code>title</code> parameter.</p><p>In addition, the <code>greeting</code> message is extracted and written into the response as part of the template.</p><p>As usual, "prop:" is the default binding prefix, thus <code>user.name</code> is a property path, not a message key.</p><p>You would extend this with a set of properties files:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> <pre><code class="language-java">page-title=Your Account greeting=Welcome back </code></pre> @@ -245,7 +245,7 @@ public String getDisplayLanguage() { return persistentLocale.get().getDisplayLanguage(); } </code></pre> -</div></div><p>Once a persistent locale is set, you will see the locale name as the first virtual folder in page render and component event requests URLs. In this way, a persistent locale will, in fact, persist from request to request, or in a user's bookmarks.</p><p>You will see the new locale take effect on the next request. If it is changed in a component event request (which is typical), the new locale will be used in the subsequent page render request.</p><p>Note that the locale for a page is fixed (it can't change once the page instance is created). In addition, a page may only be attached to a request once. In other words, if code in your page changes the persistent locale, you won't see a change to the page's locale (or localized messages) <em>in that request</em>.</p><h2 id="Localization-Built-inLocales">Built-in Locales</h2><p>While your application can support any locale (and thus any language) that you want, Tapestry provides only a limited set of translations for its ow n built-in messages. As of Tapestry 5.3, the following locales have translations provided:</p><div class="table-wrap"><table class="table table-bordered table-responsive"><tbody><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>en (English)</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>el (Greek)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>it (Italian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>pl (Polish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span><span>sv (Swedish)</span></span></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>bg (Bulgarian)</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>es (Spanish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>ja (Japanese)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>pt (Portuguese)</span></p></td><td colspan="1" rowspan="1" class="conflue nceTd"><p><span><span>vi (Vietnamese)</span></span></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>cs (Czech)<sup>1</sup></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>fi (Finnish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>mk (Macedonian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>ru (Russian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>zh (Chinese)</span></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><span>da (Danish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>fr (French)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>nl (Dutch)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd">sl (Slovenian)<sup>2</sup></td><td colspan="1" rowspan="1" class="confluenceTd"></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><span>de (German)</span></p></td><td col span="1" rowspan="1" class="confluenceTd"><p><span>hr (Croatian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>no (Norwegian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>sr (Serbian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"></td></tr></tbody></table></div><p><sup>1 </sup><span>as of Tapestry 5.3.8</span></p><p><span> </span><sup>2 </sup><span>as of Tapestry 5.4</span></p><h3 id="Localization-ProvidingtranslationsforTapestrybuilt-inmessages">Providing translations for Tapestry built-in messages</h3><p>Fortunately, Tapestry uses all the same mechanisms for its own locale support as it provides for your application. So, to support other locales, just translate the built-in message catalog (property) files yourself:</p><style type="text/css">table.sectionMacro { width: auto; }</style> +</div></div><p>Once a persistent locale is set, you will see the locale name as the first virtual folder in page render and component event requests URLs. In this way, a persistent locale will, in fact, persist from request to request, or in a user's bookmarks.</p><p>You will see the new locale take effect on the next request. If it is changed in a component event request (which is typical), the new locale will be used in the subsequent page render request.</p><p>Note that the locale for a page is fixed (it can't change once the page instance is created). In addition, a page may only be attached to a request once. In other words, if code in your page changes the persistent locale, you won't see a change to the page's locale (or localized messages) <em>in that request</em>.</p><h2 id="Localization-Built-inLocales">Built-in Locales</h2><p>While your application can support any locale (and thus any language) that you want, Tapestry provides only a limited set of translations for its ow n built-in messages. As of Tapestry 5.3, the following locales have translations provided:</p><div class="table-wrap"><table class="table table-bordered table-responsive"><tbody><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>en (English)</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>el (Greek)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>it (Italian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>pl (Polish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span><span>sv (Swedish)</span></span></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>bg (Bulgarian)</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>es (Spanish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>ja (Japanese)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>pt (Portuguese)</span></p></td><td colspan="1" rowspan="1" class="conflue nceTd"><p><span><span>vi (Vietnamese)</span></span></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>cs (Czech)<sup>1</sup></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>fi (Finnish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>mk (Macedonian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>ru (Russian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>zh (Chinese)</span></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><span>da (Danish)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>fr (French)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>nl (Dutch)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd">sl (Slovenian)<sup>2</sup></td><td colspan="1" rowspan="1" class="confluenceTd"><p></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><span>de (German)</span></p></td> <td colspan="1" rowspan="1" class="confluenceTd"><p><span>hr (Croatian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>no (Norwegian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><span>sr (Serbian)</span></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p></p></td></tr></tbody></table></div><p><sup>1 </sup><span>as of Tapestry 5.3.8</span></p><p><span> </span><sup>2 </sup><span>as of Tapestry 5.4</span></p><h3 id="Localization-ProvidingtranslationsforTapestrybuilt-inmessages">Providing translations for Tapestry built-in messages</h3><p>Fortunately, Tapestry uses all the same mechanisms for its own locale support as it provides for your application. So, to support other locales, just translate the built-in message catalog (property) files yourself:</p><p></p><style type="text/css">table.sectionMacro { width: auto; }</style> <div class="sectionColumnWrapper"><div class="sectionMacro"><div class="sectionMacroRow"><div class="columnMacro"><div class="table-wrap"><table class="table table-bordered table-responsive"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Tapestry 5.4 and later</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=tree;f=tapestry-core/src/main/resources/org/apache/tapestry5">core.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=tree;f=tapestry-kaptcha/src/main/resources/org/apache/tapestry5/kaptcha">tapestry-kaptcha.properties</a></p></td></tr></tbody></table></div></div><div class="columnMacro"><div class="table-wrap"><table class="table table-bordered table-responsive"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Tapestry 5.3.x</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanEditForm.properties?view=markup">BeanEditForm.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/DateField.properties?view=markup">DateField.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Errors.properties?view=markup">Errors.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.a pache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/GridColumns.properties?view=markup">GridColumns.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/GridPager.properties?view=markup">GridPager.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Palette.properties?view=markup">Palette.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-core/src/main/resources/org/apache/tapestry5/internal/Valida tionMessages.properties?view=markup">ValidationMessages.properties</a></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" href="http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.3/tapestry-kaptcha/src/main/resources/org/apache/tapestry5/kaptcha/tapestry-kaptcha.properties?view=markup">tapestry-kaptcha.properties</a></p></td></tr></tbody></table></div></div></div></div></div><p>To have Tapestry use these new files, just put them in the corresponding package-named directory within your own app (for example, src/main/resources/org/apache/tapestry5/core.properties).</p><p>Finally, please open a new feature request <a class="external-link" href="https://issues.apache.org/jira/browse/TAP5">here</a> and attach the translated files so that they can be included in the next release of Tapestry.</p><div class="confluence-information-macro confluence-information-macro-information"><span class="aui-icon aui-icon-small aui-iconfont-info confluen ce-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Please note that a patch is always preferred over an archive of properties files.</p></div></div></div> </div> <!-- /// Content End -->