You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by bo...@apache.org on 2017/09/16 01:54:20 UTC

svn commit: r1018226 [24/41] - in /websites/production/tapestry/content: ./ cache/ styles/

Modified: websites/production/tapestry/content/limitations.html
==============================================================================
--- websites/production/tapestry/content/limitations.html (original)
+++ websites/production/tapestry/content/limitations.html Sat Sep 16 01:54:19 2017
@@ -27,6 +27,16 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,7 +77,8 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><plain-text-body>{scrollbar}</plain-text-body><h2 id="Limitations-Limitations">Limitations</h2><h3 id="Limitations-HowdoIaddnewcomponentstoanexistingpagedynamically?">How do I add new components to an existing page dynamically?</h3><p>The short answer here is: <strong>you don't</strong>. The long answer here is <strong>you don't have to, to get the behavior you desire</strong>.</p><p>One of Tapestry basic values is high scalability: this is expressed in a number of ways, reflecting scalability concerns within a single server, and within a cluster of servers.</p><p>Although you code Tapestry pages and components as if they were ordinary POJOs (<span style="line-height: 1.4285715;">Plain Old Java Objects -- Tapestry does not require you to extend any base classes or implement any special interfaces)</span><span style="line-height: 1.4285715;">, as deployed by Tapestry they are closer to a traditional servlet: a single instance of each page s
 ervices requests from multiple threads. Behind the scenes, Tapestry transforms you code, rewriting it on the fly.</span></p><p>What this means is that <em>any</em> incoming request must be handled by a <em>single page instance</em>. Therefore, Tapestry enforces the concept of <strong>static structure, dynamic behavior</strong>.</p><p>Tapestry provides quite a number of ways to vary what content is rendered, well beyond simple conditionals and loops. It is possible to "drag in" components from other pages when rendering a page (other FAQs will expand on this concept). The point is, that although a Tapestry page's structure is very rigid, the order in which the components of the page render does not have to be top to bottom.</p><h3 id="Limitations-Whydoesn'tmyserviceimplementationreloadwhenIchangeit?">Why doesn't my service implementation reload when I change it?</h3><p>Main article: <a  href="service-implementation-reloading.html">Service Implementation Reloading</a></p><p>Live servi
 ce reloading has some limitations:</p><ul><li>The service must define a service interface.</li><li>The service implementation must be on the file system (not inside a JAR).</li><li>The implementation must be instantiated by Tapestry, not inside code (even code inside a module class).</li><li>The service must use the default <a  href="defining-tapestry-ioc-services.html">scope</a> (reloading of perthread scopes is not supported).</li></ul><p>Consider the following example module:</p><parameter ac:name="controls">true</parameter><parameter ac:name="linenumbers">true</parameter><plain-text-body>public static void bind(ServiceBinder binder)
+                <div id="ConfluenceContent"><h2 id="Limitations-Limitations">Limitations</h2><h3 id="Limitations-HowdoIaddnewcomponentstoanexistingpagedynamically?">How do I add new components to an existing page dynamically?</h3><p>The short answer here is: <strong>you don't</strong>. The long answer here is <strong>you don't have to, to get the behavior you desire</strong>.</p><p>One of Tapestry basic values is high scalability: this is expressed in a number of ways, reflecting scalability concerns within a single server, and within a cluster of servers.</p><p>Although you code Tapestry pages and components as if they were ordinary POJOs (<span style="line-height: 1.4285715;">Plain Old Java Objects -- Tapestry does not require you to extend any base classes or implement any special interfaces)</span><span style="line-height: 1.4285715;">, as deployed by Tapestry they are closer to a traditional servlet: a single instance of each page services requests from multiple threads. Behind
  the scenes, Tapestry transforms you code, rewriting it on the fly.</span></p><p>What this means is that <em>any</em> incoming request must be handled by a <em>single page instance</em>. Therefore, Tapestry enforces the concept of <strong>static structure, dynamic behavior</strong>.</p><p>Tapestry provides quite a number of ways to vary what content is rendered, well beyond simple conditionals and loops. It is possible to "drag in" components from other pages when rendering a page (other FAQs will expand on this concept). The point is, that although a Tapestry page's structure is very rigid, the order in which the components of the page render does not have to be top to bottom.</p><h3 id="Limitations-Whydoesn'tmyserviceimplementationreloadwhenIchangeit?">Why doesn't my service implementation reload when I change it?</h3><p>Main article: <a  href="service-implementation-reloading.html">Service Implementation Reloading</a></p><p>Live service reloading has some limitations:</p><ul><li>
 The service must define a service interface.</li><li>The service implementation must be on the file system (not inside a JAR).</li><li>The implementation must be instantiated by Tapestry, not inside code (even code inside a module class).</li><li>The service must use the default <a  href="defining-tapestry-ioc-services.html">scope</a> (reloading of perthread scopes is not supported).</li></ul><p>Consider the following example module:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: true; theme: Default" style="font-size:12px;">public static void bind(ServiceBinder binder)
 {
   binder.bind(ArchiveService.class, ArchiveServiceImpl.class);
 }
@@ -80,7 +91,8 @@ public static JobQueue buildJobQueue(Mes
  
   return service;
 }
-</plain-text-body><p>ArchiveService is reloadable, because Tapestry instantiates <code>ArchiveServiceImpl</code> itself. On the other hand, Tapestry invokes <code>buildJobQueue()</code> and it is your code inside the method that instantiates <code>JobQueueImpl</code>, so the JobQueue service will not be reloadable.</p><p>Finally, only classes whose class files are stored directly on the file system, and not packaged inside JARs, are ever reloadable ... generally, only the services of the application being built (and not services from libraries) will be stored on the file system. This reflects the intent of reloading: as an agile development tool, but not something to be used in deployment.</p><h3 id="Limitations-HowdoIrunmultipleTapestryapplicationsinthesamewebapplication?">How do I run multiple Tapestry applications in the same web application?</h3><p>Running multiple Tapestry 5 applications is not supported; there's only one place to identify the application root package, so even 
 configuring multiple filters into multiple folders will not work.</p><p>Support for multiple Tapestry applications in the same web application was a specific non-goal in Tapestry 5 (it needlessly complicated Tapestry 4). Given how loosely connected Tapestry 5 pages are from each other, there doesn't seem to be an advantage to doing so ... and certainly, in terms of memory utilization, there is a significant down side, were it even possible.</p><p>You&#160;<em>can</em>&#160;<span style="color: rgb(0,0,0);">run a Tapestry 4 app and a Tapestry 5 app side-by-side (the package names are different, for just this reason), but they know nothing of each other, and can't interact directly. This is just like the way you could have a single WAR with multiple servlets; the different applications can only communicate via URLs, or shared state in the HttpSession.</span></p><plain-text-body>{scrollbar}</plain-text-body><p>&#160;</p><p>&#160;</p><p>&#160;</p></div>
+</pre>
+</div></div><p>ArchiveService is reloadable, because Tapestry instantiates <code>ArchiveServiceImpl</code> itself. On the other hand, Tapestry invokes <code>buildJobQueue()</code> and it is your code inside the method that instantiates <code>JobQueueImpl</code>, so the JobQueue service will not be reloadable.</p><p>Finally, only classes whose class files are stored directly on the file system, and not packaged inside JARs, are ever reloadable ... generally, only the services of the application being built (and not services from libraries) will be stored on the file system. This reflects the intent of reloading: as an agile development tool, but not something to be used in deployment.</p><h3 id="Limitations-HowdoIrunmultipleTapestryapplicationsinthesamewebapplication?">How do I run multiple Tapestry applications in the same web application?</h3><p>Running multiple Tapestry 5 applications is not supported; there's only one place to identify the application root package, so even config
 uring multiple filters into multiple folders will not work.</p><p>Support for multiple Tapestry applications in the same web application was a specific non-goal in Tapestry 5 (it needlessly complicated Tapestry 4). Given how loosely connected Tapestry 5 pages are from each other, there doesn't seem to be an advantage to doing so ... and certainly, in terms of memory utilization, there is a significant down side, were it even possible.</p><p>You&#160;<em>can</em>&#160;<span style="color: rgb(0,0,0);">run a Tapestry 4 app and a Tapestry 5 app side-by-side (the package names are different, for just this reason), but they know nothing of each other, and can't interact directly. This is just like the way you could have a single WAR with multiple servlets; the different applications can only communicate via URLs, or shared state in the HttpSession.</span></p><p>&#160;</p><p>&#160;</p><p>&#160;</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/link-components-faq.html
==============================================================================
--- websites/production/tapestry/content/link-components-faq.html (original)
+++ websites/production/tapestry/content/link-components-faq.html Sat Sep 16 01:54:19 2017
@@ -27,6 +27,16 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,8 +77,11 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><plain-text-body>{scrollbar}</plain-text-body><h2 id="LinkComponentsFAQ-LinkComponents">Link Components</h2><h3 id="LinkComponentsFAQ-HowdoIaddqueryparameterstoaPageLinkorActionLink?">How do I add query parameters to a PageLink or ActionLink?</h3><p>These components do not have parameters to allow you to specify query parameters for the link; they both allow you to specify a <em>context</em> (one or more values to encode into the request path).</p><p>However, you can accomplish the same thing with a little code and markup. For example, to create a link to another page and pass a query parameter, you can replace your PageLink component with a standard <code>&lt;a&gt;</code> tag:</p><parameter ac:name="controls">true</parameter><parameter ac:name="language">xml</parameter><plain-text-body>&lt;a href="${profilePageLink}"&gt;Display Profile (w/ full details)&lt;/a&gt;
-</plain-text-body><p>In the matching Java class, you can create the Link programmatically:</p><parameter ac:name="controls">true</parameter><parameter ac:name="language">java</parameter><plain-text-body>  @Inject
+                <div id="ConfluenceContent"><h2 id="LinkComponentsFAQ-LinkComponents">Link Components</h2><h3 id="LinkComponentsFAQ-HowdoIaddqueryparameterstoaPageLinkorActionLink?">How do I add query parameters to a PageLink or ActionLink?</h3><p>These components do not have parameters to allow you to specify query parameters for the link; they both allow you to specify a <em>context</em> (one or more values to encode into the request path).</p><p>However, you can accomplish the same thing with a little code and markup. For example, to create a link to another page and pass a query parameter, you can replace your PageLink component with a standard <code>&lt;a&gt;</code> tag:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;a href="${profilePageLink}"&gt;Display Profile (w/ full details)&lt;/a&gt;
+</pre>
+</div></div><p>In the matching Java class, you can create the Link programmatically:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Inject
   private PageRenderLinkSource linkSource;
 
   public Link getProfilePageLink()
@@ -77,22 +90,27 @@
     link.addParameterValue("detail", true);
     return link;
   }
-</plain-text-body><p>... and in the DisplayProfile page:</p><parameter ac:name="controls">true</parameter><parameter ac:name="language">java</parameter><plain-text-body>public class DisplayProfile
+</pre>
+</div></div><p>... and in the DisplayProfile page:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class DisplayProfile
 {
   void onActivate(@RequestParameter("detail") boolean detail)
   {
     . . .
   }
 }
-</plain-text-body><p>The @RequestParameter annotation directs Tapestry to extract the query parameter from the request and coerce it to type boolean. You can use any reasonable type for such a parameter (int, long and Date are common).</p><p>A similar technique can be used to add query parmeters to component event URLs (the type generated by the ActionLink or EventLink components), by injecting the ComponentResources, and invoking method <code>createEventLink()</code>.</p>
+</pre>
+</div></div><p>The @RequestParameter annotation directs Tapestry to extract the query parameter from the request and coerce it to type boolean. You can use any reasonable type for such a parameter (int, long and Date are common).</p><p>A similar technique can be used to add query parmeters to component event URLs (the type generated by the ActionLink or EventLink components), by injecting the ComponentResources, and invoking method <code>createEventLink()</code>.</p>
 
 <div class="confluence-information-macro confluence-information-macro-information"><p class="title">Added in 5.3</p><span class="aui-icon aui-icon-small aui-iconfont-info confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
 </div></div>
 <div class="error"><span class="error">Unknown macro: {div}</span> 
 <p>You may also bind a link component's <code>parameters</code> parameter; this is a Map of additional query parameters to add to the URL.  The Map keys should be strings, and the Map values will be encoded to strings.  Tapestry 5.3 also adds a literal map syntax to the <a  href="property-expressions.html" title="Property Expressions">property expression language</a>.</p>
 
-</div><h3 id="LinkComponentsFAQ-HowdoIcreateaLinkbacktothecurrentpagefromacomponent?">How do I create a Link back to the current page from a component?</h3><p>Sometimes it is useful to create a link back to the current page, but you don't always know the name of the page (the link may appear inside a deeply nested subcomponent). Fortunately, this is easy.</p><parameter ac:name="language">xml</parameter><plain-text-body>&lt;t:pagelink page="prop:componentResources.pageName"&gt;refresh page&lt;/t:pagelink&gt;
-</plain-text-body><p>Every component has an extra property, componentResources, added to it: it's the instance of <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html">ComponentResources</a> that represents the link between your code and all of Tapestry's structure around your class. One of the properties of ComponentResources is pageName, the name of the page. By binding the PageLink's page parameter with the "prop:" binding prefix, we ensure that we bind to a computed property; this is necessary because the PageLink.page parameter defaults to the "literal:" binding prefix.</p><p>As an added benefit, if the page class is ever renamed or moved to a different package, the pageName property will automatically adjust to the new name.</p><plain-text-body>{scrollbar}</plain-text-body></div>
+</div><h3 id="LinkComponentsFAQ-HowdoIcreateaLinkbacktothecurrentpagefromacomponent?">How do I create a Link back to the current page from a component?</h3><p>Sometimes it is useful to create a link back to the current page, but you don't always know the name of the page (the link may appear inside a deeply nested subcomponent). Fortunately, this is easy.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;t:pagelink page="prop:componentResources.pageName"&gt;refresh page&lt;/t:pagelink&gt;
+</pre>
+</div></div><p>Every component has an extra property, componentResources, added to it: it's the instance of <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html">ComponentResources</a> that represents the link between your code and all of Tapestry's structure around your class. One of the properties of ComponentResources is pageName, the name of the page. By binding the PageLink's page parameter with the "prop:" binding prefix, we ensure that we bind to a computed property; this is necessary because the PageLink.page parameter defaults to the "literal:" binding prefix.</p><p>As an added benefit, if the page class is ever renamed or moved to a different package, the pageName property will automatically adjust to the new name.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/localization.html
==============================================================================
--- websites/production/tapestry/content/localization.html (original)
+++ websites/production/tapestry/content/localization.html Sat Sep 16 01:54:19 2017
@@ -27,6 +27,16 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,32 +77,94 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>&#160;</p><p><strong>Localization</strong> (aka L10n) is all about getting the right text to the user, in the right language.</p><parameter ac:name="style">float:right</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="class">aui-label</parameter><rich-text-body><parameter ac:name="showLabels">false</parameter><parameter ac:name="showSpace">false</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="cql">label in ("component-templates","localization") and space = currentSpace()</parameter></rich-text-body><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-Compon
 entMessageCatalogs">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 of 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>ov
 erride</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 method
 s 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 and components can override the values defined in the message catalog.<plain-text-body>{float:right|width=45%}
-{note:title=Avoid BOMs}
-Make sure that your properties files don't contain [byte order marks (BOM)|http://en.wikipedia.org/wiki/Byte_order_mark], because Java -- and thus Tapestry -- doesn't support BOM in properties files (see http://bugs.sun.com/view_bug.do?bug_id=4508058). Some editors write them out when saving a file in UTF-8, so watch out.
-{note}
-{float}</plain-text-body></p><h2 id="Localization-PropertiesFileCharset">Properties File Charset</h2><p>Tapestry uses the <code>UTF-8</code> character set (charset) 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">bin
 ding expression</a> in a component template</li><li>By injecting the component's Messages object<br clear="none"> In the first case, you may use the message: binding prefix with component parameters, or with template expansions:</li></ul><parameter ac:name="">java</parameter><plain-text-body>&lt;t:layout title="message:page-title"&gt;
+                <div id="ConfluenceContent"><p>&#160;</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">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="templating-and-markup-faq.html">Templating and Markup FAQ</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-classes.html">Component Classes</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="localization.html">Localization</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-parameters.html">Component Parameters</a>
+                
+                        
+                    </div>
+    </li></ul>
+</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 clas
 s 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 
 and components can override the values defined in the message catalog.</p><div class="navmenu" style="float:right; width:45%; background:white; margin:3px; padding:3px">
+<div class="confluence-information-macro confluence-information-macro-note"><p class="title">Avoid BOMs</p><span class="aui-icon aui-icon-small aui-iconfont-warning 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 &#8211; and thus Tapestry &#8211; 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></div><h2 id="Localization-PropertiesFileCharset">Properties File Charset</h2><p>Tapestry uses the <code>UTF-8</code> character set (charset) 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 object<br clear="none"> In 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 class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;t:layout title="message:page-title"&gt;
 
   ${message:greeting}, ${user.name}!
   
   . . .
 &lt;/t:layout&gt;
-</plain-text-body><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><parameter ac:name="">java</parameter><plain-text-body>page-title=Your Account
+</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">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">page-title=Your Account
 greeting=Welcome back
-</plain-text-body><p>Or, perhaps, a French version:</p><parameter ac:name="">java</parameter><plain-text-body>page-title=Votre Compte
+</pre>
+</div></div><p>Or, perhaps, a French version:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">page-title=Votre Compte
 greeting=Bienvenue en arriere
-</plain-text-body><p>Programatically, you may inject your component message catalog into your class, as an instance of the Messages interface:</p><parameter ac:name="">java</parameter><plain-text-body>  @Inject
+</pre>
+</div></div><p>Programatically, you may inject your component message catalog into your class, as an instance of the Messages interface:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Inject
   private Messages messages;
-</plain-text-body><p>You could then <code>get()</code> messages, or <code>format()</code> them:</p><parameter ac:name="">java</parameter><plain-text-body>  public String getCartSummary()     
+</pre>
+</div></div><p>You could then <code>get()</code> messages, or <code>format()</code> them:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  public String getCartSummary()     
   {
     if (items.isEmpty())
       return messages.get("no-items");
       
     return messages.format("item-summary", _items.size());
   }
-</plain-text-body><p>The format() option works using a <code>java.util.Formatter</code>, with all the printf-style loveliness you've come to expect:</p><parameter ac:name="">java</parameter><plain-text-body>no-items=Your shopping cart is empty.     
+</pre>
+</div></div><p>The format() option works using a <code>java.util.Formatter</code>, with all the printf-style loveliness you've come to expect:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">no-items=Your shopping cart is empty.     
 item-summary=You have %d items in your cart.
-</plain-text-body><p>As easy as conditionals are to use inside a Tapestry template, sometimes it's even easier to do it in Java code.</p><h2 id="Localization-MissingKeys">Missing Keys</h2><p>If you reference a key that is not in the message catalog, Tapestry does not throw an exception (because that would make initially developing an application very frustrating). When a key can not be located, a "placeholder" message is generated, such as "[[missing key: key-not-found]]".</p><h2 id="Localization-Reloading">Reloading</h2><p>If you change a property file in a message catalog, you'll see the change immediately, just as with component classes and component templates (provided you're not running in <a  href="configuration.html">production mode</a>).</p><h2 id="Localization-AssetLocalization">Asset Localization</h2><p>When <a  href="injection.html">injecting assets</a>, the injected asset will be localized as well. A search for the closest match for the active locale is made, and the fin
 al Asset will reflect that.</p><h2 id="Localization-LocaleSelection">Locale Selection</h2><p>The locale for each request is determined from the HTTP request headers. The request locale reflects the environment of the web browser and possibly even the keyboard selection of the user on the client. It can be highly specific, for example, identifying British English (as en_GB) vs. American English (en).</p><p>Tapestry "narrows" the raw request locale, as specified in the request, to a known quantity. It uses the <a  href="configuration.html">configuration symbol</a> <code>tapestry.supported-locales</code> to choose the effective locale for each request. This value is a comma-separated list of locale names. Tapestry searches the list for the best match for the request locale; for example, a request locale of "fr_FR" would match "fr" but not "de". If no match is found, then the first locale name in the list is used as the effective locale (that is, the first locale is used as the default 
 for non-matching requests). Thus a site that primarily caters to French speakers would want to list "fr" as the first locale in the list.</p><h2 id="Localization-ChangingtheLocale">Changing the Locale</h2><p>The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PersistentLocale.html">PersistentLocale service</a> can be used to programmatically override the locale. Note: You should be careful to only set the persistent locale to a supported locale.</p><parameter ac:name="">java</parameter><parameter ac:name="title">Toggle between English and German</parameter><plain-text-body>@Inject 
+</pre>
+</div></div><p>As easy as conditionals are to use inside a Tapestry template, sometimes it's even easier to do it in Java code.</p><h2 id="Localization-MissingKeys">Missing Keys</h2><p>If you reference a key that is not in the message catalog, Tapestry does not throw an exception (because that would make initially developing an application very frustrating). When a key can not be located, a "placeholder" message is generated, such as "[[missing key: key-not-found]]".</p><h2 id="Localization-Reloading">Reloading</h2><p>If you change a property file in a message catalog, you'll see the change immediately, just as with component classes and component templates (provided you're not running in <a  href="configuration.html">production mode</a>).</p><h2 id="Localization-AssetLocalization">Asset Localization</h2><p>When <a  href="injection.html">injecting assets</a>, the injected asset will be localized as well. A search for the closest match for the active locale is made, and the final Ass
 et will reflect that.</p><h2 id="Localization-LocaleSelection">Locale Selection</h2><p>The locale for each request is determined from the HTTP request headers. The request locale reflects the environment of the web browser and possibly even the keyboard selection of the user on the client. It can be highly specific, for example, identifying British English (as en_GB) vs. American English (en).</p><p>Tapestry "narrows" the raw request locale, as specified in the request, to a known quantity. It uses the <a  href="configuration.html">configuration symbol</a> <code>tapestry.supported-locales</code> to choose the effective locale for each request. This value is a comma-separated list of locale names. Tapestry searches the list for the best match for the request locale; for example, a request locale of "fr_FR" would match "fr" but not "de". If no match is found, then the first locale name in the list is used as the effective locale (that is, the first locale is used as the default for no
 n-matching requests). Thus a site that primarily caters to French speakers would want to list "fr" as the first locale in the list.</p><h2 id="Localization-ChangingtheLocale">Changing the Locale</h2><p>The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PersistentLocale.html">PersistentLocale service</a> can be used to programmatically override the locale. Note: You should be careful to only set the persistent locale to a supported locale.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Toggle between English and German</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Inject 
 private PersistentLocale persistentLocale;
 
 void onActionFromLocaleToggle() {
@@ -106,8 +178,9 @@ void onActionFromLocaleToggle() {
 public String getDisplayLanguage() {
     return persistentLocale.get().getDisplayLanguage();
 }
-</plain-text-body><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 own built-in messages. As of Tapestry 5.3, the following locales have translations provided:</p><div class="table-wrap"><table class="confluenceTable"><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="confluenceTd"><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>&#160;</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><span>de (German)</span></p></td><td colspa
 n="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>&#160;</p></td></tr></tbody></table></div><p><sup>1&#160;</sup><span style="line-height: 1.4285715;">as of Tapestry 5.3.8</span></p><p><span style="line-height: 1.4285715;">&#160;</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>&#160;</p><parameter ac:name="atlassian-macro-output-type">BLOCK</parameter><plain-text-body>&lt;style typ
 e="text/css"&gt;table.sectionMacro { width: auto; }&lt;/style&gt;
-</plain-text-body><parameter ac:name="width">auto</parameter><rich-text-body><rich-text-body><div class="table-wrap"><table class="confluenceTable"><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></rich-text-body><rich-text-body><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Tapestry 5.3.x</p></th></tr><tr><td colspan="1" rowspan="1" class="con
 fluenceTd"><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.apache.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/ValidationMessages.properties?view=markup">ValidationMessage
 s.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></rich-text-body></rich-text-body><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><rich-text-body><p>Please note that a patch is always preferred over an archive of properties files.</p></rich-text-body></div>
+</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="confluenceTable"><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="confluenceTd"><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>&#160;</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>&#160;</p></td></tr></tbody></table></div><p><sup>1&#160;</sup><span style="line-height: 1.4285715;">as of Tapestry 5.3.8</span></p><p><span style="line-height: 1.4285715;">&#160;</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>&#160;</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="confluenceTable"><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="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Tapestry 5.3.x</p></th></tr><tr><td colspan="1" row
 span="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.apache.org/viewvc/tapestry/tapestry5/br
 anches/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/ValidationMessages.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 confluence-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>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/logging-in-tapestry.html
==============================================================================
--- websites/production/tapestry/content/logging-in-tapestry.html (original)
+++ websites/production/tapestry/content/logging-in-tapestry.html Sat Sep 16 01:54:19 2017
@@ -27,6 +27,14 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -36,26 +44,13 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  href="index.html">Home</a></li><li><a  href="getting-started.html">Getting Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  href="download.html">Download</a></li><li><a  href="about.html">About</a></li><li><a  class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a  href="community.html">Community</a></li><li><a  class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a  class="external-link" href="http://www.apache.org/">Apache</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div>
-
-</div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  href="index.html">Home</a></li><li><a  href="getting-started.html">Getting Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  href="download.html">Download</a></li><li><a  href="about.html">About</a></li><li><a  class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a  href="community.html">Community</a></li><li><a  class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a  class="external-link" href="http://www.apache.org/">Apache</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
-<form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html">
-  <input type="text" name="q">
-  <input type="submit" value="Search">
-</form>
-
-</div>
-
-
-<div class="emblem" style="float:left"><p><a  href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div>
-
-
-<div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">Logging in Tapestry</h1></div>
-
-</div>
+            <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> 
+ <input type="text" name="q"> 
+ <input type="submit" value="Search"> 
+</form></div><div class="emblem" style="float:left"><p><a  href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">Logging in Tapestry</h1></div></div>
       <div class="clearer"></div>
       </div>
 
@@ -67,7 +62,20 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p><strong>Logging in Tapestry</strong> is based on the <a  class="external-link" href="http://www.slf4j.org/" rel="nofollow">Simple Logging Facade for Java (SLF4J)</a>. You can think of SLF4J as a leaner, meaner replacement for <a  class="external-link" href="http://commons.apache.org/logging/">commons-logging</a>.</p><parameter ac:name="style">float:right</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="class">aui-label</parameter><rich-text-body><parameter ac:name="showLabels">false</parameter><parameter ac:name="showSpace">false</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="cql">label = "logging" and space = currentSpace()</parameter></rich-text-body><p>In theory, SLF4J is a wrapper around any of a number of logging systems, including <a  class="external-link" href="http://logging.apache.org/log4j/1.2/">Log4J</a> or the built-in JDK logging. In practice, it is
  almost always used with Log4J and no additional build configuration is needed.</p><p>Your application <em>will</em> need to provide a <strong>log4j.properties</strong> file (or its XML equivalent). See <a  class="external-link" href="http://logging.apache.org/log4j/1.2/manual.html">the Log4J manual</a> for more information.</p><h1 id="LogginginTapestry-AccessingLoggers">Accessing Loggers</h1><p>Loggers are a special kind of resource that is injected into a service. In Tapestry IoC, Loggers an be injected into service constructors, or into service builder methods.</p><p>In Tapestry Core (the web framework), Loggers for components can be injected into component fields.</p><p>This often confuses people, because the standard idiom is to create a Logger based on the class name and inject it into a static field. In Tapestry, the Logger is created on your code's behalf and provided to you, and stored into a final private field.</p><p>In terms of separation of concerns, Tapestry's approach
  is superior ... the concern of creating loggers is offloaded into the framework, and you code retains the concern of actually logging useful information. However this is largely theoretical.</p><p>For a pragmatic standpoint, injecting Loggers makes it easier to test <em>logging</em> code using the same techniques used to test other code: via the injection of Mock Object implementations of the Logger interface. This is something to consider when writing your own services, components and test.</p><h1 id="LogginginTapestry-ServiceLogging">Service Logging</h1><p>Tapestry uses the same loggers that are injected into services; it logs, at debug level, details about the construction of the service (and the proxy for the service), including details such as methods invoked.</p><h1 id="LogginginTapestry-OperationTracker">Operation Tracker</h1><p>The OperationTracker is a resource available throughout Tapestry that is used to track what Tapestry is doing at any given time. Normally, this info
 rmation is only used when reporting errors, as it gives an indication of what Tapestry was doing leading up to the point where the exception occurred.</p><p>Starting in Tapestry 5.3, you may also enable debug logging for <code>org.apache.tapestry5.ioc.Registry</code> to see voluminous details on creation of proxies, services, injections, and so forth. It also tracks creation of pages and components, triggering of component events, handling of return values from event handler methods, and many (many!) other details.</p><p>The logging even identifies how long each operation takes. This can be useful for understanding what is going on in a Tapestry application during the processing of the request, it can also be useful when tracking down performance issues.</p><p>An example from the startup of a Tapestry application:</p><plain-text-body>[INFO] RegistryBuilder Adding module definition for class org.apache.tapestry5.services.TapestryModule
+                <div id="ConfluenceContent"><p><strong>Logging in Tapestry</strong> is based on the <a  class="external-link" href="http://www.slf4j.org/" rel="nofollow">Simple Logging Facade for Java (SLF4J)</a>. You can think of SLF4J as a leaner, meaner replacement for <a  class="external-link" href="http://commons.apache.org/logging/">commons-logging</a>.</p><div class="aui-label" style="float:right" title="Related Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="logging-in-tapestry.html">Logging in Tapestry</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="logging.html">Logging</a> 
+  </div> </li></ul></div><p>In theory, SLF4J is a wrapper around any of a number of logging systems, including <a  class="external-link" href="http://logging.apache.org/log4j/1.2/">Log4J</a> or the built-in JDK logging. In practice, it is almost always used with Log4J and no additional build configuration is needed.</p><p>Your application <em>will</em> need to provide a <strong>log4j.properties</strong> file (or its XML equivalent). See <a  class="external-link" href="http://logging.apache.org/log4j/1.2/manual.html">the Log4J manual</a> for more information.</p><h1 id="LogginginTapestry-AccessingLoggers">Accessing Loggers</h1><p>Loggers are a special kind of resource that is injected into a service. In Tapestry IoC, Loggers an be injected into service constructors, or into service builder methods.</p><p>In Tapestry Core (the web framework), Loggers for components can be injected into component fields.</p><p>This often confuses people, because the standard idiom is to create a Logger
  based on the class name and inject it into a static field. In Tapestry, the Logger is created on your code's behalf and provided to you, and stored into a final private field.</p><p>In terms of separation of concerns, Tapestry's approach is superior ... the concern of creating loggers is offloaded into the framework, and you code retains the concern of actually logging useful information. However this is largely theoretical.</p><p>For a pragmatic standpoint, injecting Loggers makes it easier to test <em>logging</em> code using the same techniques used to test other code: via the injection of Mock Object implementations of the Logger interface. This is something to consider when writing your own services, components and test.</p><h1 id="LogginginTapestry-ServiceLogging">Service Logging</h1><p>Tapestry uses the same loggers that are injected into services; it logs, at debug level, details about the construction of the service (and the proxy for the service), including details such as
  methods invoked.</p><h1 id="LogginginTapestry-OperationTracker">Operation Tracker</h1><p>The OperationTracker is a resource available throughout Tapestry that is used to track what Tapestry is doing at any given time. Normally, this information is only used when reporting errors, as it gives an indication of what Tapestry was doing leading up to the point where the exception occurred.</p><p>Starting in Tapestry 5.3, you may also enable debug logging for <code>org.apache.tapestry5.ioc.Registry</code> to see voluminous details on creation of proxies, services, injections, and so forth. It also tracks creation of pages and components, triggering of component events, handling of return values from event handler methods, and many (many!) other details.</p><p>The logging even identifies how long each operation takes. This can be useful for understanding what is going on in a Tapestry application during the processing of the request, it can also be useful when tracking down performance is
 sues.</p><p>An example from the startup of a Tapestry application:</p><div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
+<pre>[INFO] RegistryBuilder Adding module definition for class org.apache.tapestry5.services.TapestryModule
 [INFO] RegistryBuilder Adding module definition for class org.apache.tapestry5.internal.services.InternalModule
 [INFO] RegistryBuilder Adding module definition for class org.apache.tapestry5.services.assets.AssetsModule
 [INFO] RegistryBuilder Adding module definition for class org.apache.tapestry5.services.pageload.PageLoadModule
@@ -111,7 +119,9 @@
 [DEBUG] Registry [ 11] &lt;-- Determining injection value for parameter #1 (org.apache.tapestry5.ioc.OrderedConfiguration) [0.11 ms]
 [DEBUG] Registry [ 11] --&gt; Determining injection value for parameter #2 (org.apache.tapestry5.ioc.ObjectProvider)
 . . .
-</plain-text-body><h1 id="LogginginTapestry-ConfiguringTapestryforotherLoggingToolkits">Configuring Tapestry for other Logging Toolkits</h1><p>The default configuration uses Log4J.</p><p>If you need to use another logging system, that can be accomplished using Maven dependency control.</p><p>You can exclude some of the dependencies that Tapestry introduces, and replace them with your own. For example, to switch over to JDK logging, update your pom as follows:</p><parameter ac:name="language">xml</parameter><plain-text-body> 
+</pre>
+</div></div><h1 id="LogginginTapestry-ConfiguringTapestryforotherLoggingToolkits">Configuring Tapestry for other Logging Toolkits</h1><p>The default configuration uses Log4J.</p><p>If you need to use another logging system, that can be accomplished using Maven dependency control.</p><p>You can exclude some of the dependencies that Tapestry introduces, and replace them with your own. For example, to switch over to JDK logging, update your pom as follows:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;"> 
   &lt;dependencies&gt;
     &lt;dependency&gt;
       &lt;groupId&gt;org.apache.tapestry&lt;/groupId&gt;
@@ -138,7 +148,8 @@
           &lt;version&gt;1.4.3&lt;/version&gt;
     &lt;/dependency&gt;
   &lt;/dependencies&gt;
-</plain-text-body><p>This pulls out the log4j support normally included with Tapestry, and replaces it with the SLF4J library that wraps around JDK 1.4 logging.</p><p>In all likelihood, you'll replace <em>tapestry-ioc</em> with <em>tapestry-core</em> (assuming you are building a web application using Tapestry, rather than using Tapestry IoC as part of some other application). And, of course, version numbers change all the time!</p><p>&#160;</p><p></p></div>
+</pre>
+</div></div><p>This pulls out the log4j support normally included with Tapestry, and replaces it with the SLF4J library that wraps around JDK 1.4 logging.</p><p>In all likelihood, you'll replace <em>tapestry-ioc</em> with <em>tapestry-core</em> (assuming you are building a web application using Tapestry, rather than using Tapestry IoC as part of some other application). And, of course, version numbers change all the time!</p><p>&#160;</p><p></p></div>
       </div>
 
       <div class="clearer"></div>