001    package hirondelle.web4j.ui.translate;
002    
003    import hirondelle.web4j.request.LocaleSource;
004    
005    import java.util.Locale;
006    
007    /**
008     Translate base text into a localized form. 
009     
010     <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
011     {@link hirondelle.web4j.BuildImpl#forTranslator()} returns the configured implementation of this interface.
012     
013     <P>Here, "<b>base text</b>" refers to either :
014     <ul>
015     <li>a snippet of user-presentable text in the language being used to build the application
016     <li>a "coder key", such as <tt>"image.title"</tt> or <tt>"button.label"</tt>. 
017     Coder keys are never presented to the end user, and serve as an alias or shorthand 
018     for something else. They are intended for the exclusive use of the programmer, and may 
019     be thought of as being in a special "language" understood only by the programmer.
020     </ul>
021    
022     <P><span class="highlight">In code, it is likely best to use user-presentable text 
023     instead of coder keys, whenever possible - since lookups are never needed, it makes 
024     code clearer at the point of call.</span>
025     
026     <P>Please see the package <a href="package-summary.html">overview</a> for an interesting way of 
027     evolving the implementation of this interface during development, allowing applications to assist in their 
028     own translation.
029    
030     <P>One might validly object to a framework which requires an implementation of this 
031     interface even for single-language applications. However, arguments in favor of 
032     such a style include : 
033    <ul>
034     <li>providing a do-nothing implementation for a single-language application is trivial.
035     <li>changing from a single language to multiple languages is a common requirement for 
036     web applications. The presence of this implementation makes it clear to the maintainer 
037     where such changes are made, if they become necessary. 
038     <li>some programmers might prefer to name items as <tt>'emailAddr'</tt> instead of 
039     <tt>'Email Address'</tt>, for instance. In this case, a {@link Translator} can also  
040     be used, even in a single-language application, to translate from such 'coder keys' 
041     to user-presentable text. 
042    </ul> 
043     
044     <P>The recommended style is to implement this interface with a database, and to 
045     <a href="http://www.javapractices.com/Topic208.cjp">avoid <tt>ResourceBundle</tt></a>.
046      
047     <P><b>Guidance For Implementing With A Database</b><br>
048     Example of a web application with the following particular requirements 
049     (see the example application for further illustration): 
050     <ul>
051     <li>English is the base development language, used by the programmers and development team
052     <li>the user interface needs to be in both English and French
053     <li>in source code, the programmers use both regular text snippets in  
054     user-presentable English, and (occasionally) 'coder keys', according to the needs of each particular case 
055     </ul> 
056     
057     Here is a style of <tt>ResultSet</tt> that can be used to implement this interface :
058     <P><table border=1 cellspacing=0 cellpadding=3>
059      <tr>
060       <th>BaseText</th><th>Locale</th><th>Translation</th> 
061      </tr>
062      <tr><td>Fish And Chips</td><td>en</td><td>Fish And Chips</td></tr>
063      <tr><td>Fish And Chips</td><td>fr</td><td>Poisson et Frites</td></tr>
064      <tr><td>delete</td><td>en</td><td>delete</td></tr>
065      <tr><td>delete</td><td>fr</td><td>supprimer</td></tr>
066      <tr><td>add.edit.button</td><td>en</td><td>Add/Edit</td></tr>
067      <tr><td>add.edit.button</td><td>fr</td><td>Ajouter/Changer</td></tr>
068     </table> 
069     
070     <P>Only the last two rows use a "coder key".
071     The <tt>BaseText</tt> column holds either the coder key, or the user-presentable English. 
072     The <tt>BaseText</tt> is the lookup key. The fact that there is 
073     repetition of data between the <tt>BaseText</tt> and <tt>English</tt> columns is not a real duplication problem, 
074     since <em>this is a <tt>ResultSet</tt>, not a table</em> - the underlying tables will not have such 
075     repetition (if designed properly, of course). 
076      
077     <P>For example, such a <tt>ResultSet</tt> can be constructed from three underlying tables - 
078     <tt>BaseText</tt>, <tt>Locale</tt>, and <tt>Translation</tt>. <tt>Translation</tt> is a cross-reference 
079     table, with foreign keys to both <tt>BaseText</tt> and <tt>Locale</tt>. When such a scheme is 
080     normalized, it will have no repeated data. (In underlying queries, however, the base 
081     language will be necessarily treated differently than the other languages.)
082     
083     <P>Upon startup, the tables are read, the above <tt>ResultSet</tt> is created and  
084     stored in a <tt>private static Map</tt>, represented schematically as 
085     <tt>Map[BaseText, Map[Locale, Translation]]</tt>. When a translation is required, 
086     this <tt>Map</tt> is used as an in-memory lookup table. This avoids 
087     repeated fetching from the database of trivial data that rarely changes. 
088    
089     <P><b>Note on Thread Safety</b>
090     <br>In the suggested implementation style, the <tt>private static Map</tt> that stores translation data is 
091     <tt>static</tt>, and thus shared by multiple threads. Implementations are free to implement 
092     any desired policy regarding thread safety, from relaxed to strict. A relaxed implementation 
093     might completely ignore the possibility of a mistaken read/write, since no writes are expected in 
094     production, or simply because the consequences are usually trivial. A strict implementation would 
095     take the opposite approach, and demand that the <tt>private static Map</tt> be used in an fully 
096     thread-safe manner.   
097    */
098    public interface Translator {
099      
100      /**
101       Translate <tt>aBaseText</tt> into text appropriate for <tt>aLocale</tt>.
102       
103       <P><tt>aBaseText</tt> is either user-presentable text in the base language of 
104       development, or a "coder key" known only to the programmer.
105       
106       <P>If <tt>aBaseText</tt> is unknown, then the implementation is free to define 
107       any desired behavior. For example, this method might return  
108      <ul>
109       <li><tt>aBaseText</tt> passed to this method, in its raw, untranslated form
110       <li><tt>aBaseText</tt> with special surrounding text, such as <tt>???some text???</tt>, with 
111       leading and trailing characters
112       <li>a fixed <tt>String</tt> such as <tt>'???'</tt> or <tt>'?untranslated?'</tt>
113       <li>it is also possible for an implementation to throw a {@link RuntimeException} when 
114       an item is missing, but this is not recommended for applications in production
115      </ul>
116      
117       <P>If <tt>aBaseText</tt> is known, but there is no explicit translation for the 
118       given {@link Locale}, then an implementation might choose to mimic the behavior of 
119       {@link java.util.ResourceBundle}, and choose a translation from the "nearest available" 
120       {@link Locale} instead.
121      
122       @param aBaseText is not <tt>null</tt>, but may be empty
123       @param aLocale comes from the configured {@link LocaleSource}.
124      */
125      String get(String aBaseText, Locale aLocale);
126      
127    }