package hirondelle.web4j.ui.translate;

import hirondelle.web4j.request.LocaleSource;

import java.util.Locale;

/**
 Translate base text into a localized form. 
 
 <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
 {@link hirondelle.web4j.BuildImpl#forTranslator()} returns the configured implementation of this interface.
 
 <P>Here, "<b>base text</b>" refers to either :
 <ul>
 <li>a snippet of user-presentable text in the language being used to build the application
 <li>a "coder key", such as <tt>"image.title"</tt> or <tt>"button.label"</tt>. 
 Coder keys are never presented to the end user, and serve as an alias or shorthand 
 for something else. They are intended for the exclusive use of the programmer, and may 
 be thought of as being in a special "language" understood only by the programmer.
 </ul>

 <P><span class="highlight">In code, it is likely best to use user-presentable text 
 instead of coder keys, whenever possible - since lookups are never needed, it makes 
 code clearer at the point of call.</span>
 
 <P>Please see the package <a href="package-summary.html">overview</a> for an interesting way of 
 evolving the implementation of this interface during development, allowing applications to assist in their 
 own translation.

 <P>One might validly object to a framework which requires an implementation of this 
 interface even for single-language applications. However, arguments in favor of 
 such a style include : 
<ul>
 <li>providing a do-nothing implementation for a single-language application is trivial.
 <li>changing from a single language to multiple languages is a common requirement for 
 web applications. The presence of this implementation makes it clear to the maintainer 
 where such changes are made, if they become necessary. 
 <li>some programmers might prefer to name items as <tt>'emailAddr'</tt> instead of 
 <tt>'Email Address'</tt>, for instance. In this case, a {@link Translator} can also  
 be used, even in a single-language application, to translate from such 'coder keys' 
 to user-presentable text. 
</ul> 
 
 <P>The recommended style is to implement this interface with a database, and to 
 <a href="http://www.javapractices.com/Topic208.cjp">avoid <tt>ResourceBundle</tt></a>.
  
 <P><b>Guidance For Implementing With A Database</b><br>
 Example of a web application with the following particular requirements 
 (see the example application for further illustration): 
 <ul>
 <li>English is the base development language, used by the programmers and development team
 <li>the user interface needs to be in both English and French
 <li>in source code, the programmers use both regular text snippets in  
 user-presentable English, and (occasionally) 'coder keys', according to the needs of each particular case 
 </ul> 
 
 Here is a style of <tt>ResultSet</tt> that can be used to implement this interface :
 <P><table border=1 cellspacing=0 cellpadding=3>
  <tr>
   <th>BaseText</th><th>Locale</th><th>Translation</th> 
  </tr>
  <tr><td>Fish And Chips</td><td>en</td><td>Fish And Chips</td></tr>
  <tr><td>Fish And Chips</td><td>fr</td><td>Poisson et Frites</td></tr>
  <tr><td>delete</td><td>en</td><td>delete</td></tr>
  <tr><td>delete</td><td>fr</td><td>supprimer</td></tr>
  <tr><td>add.edit.button</td><td>en</td><td>Add/Edit</td></tr>
  <tr><td>add.edit.button</td><td>fr</td><td>Ajouter/Changer</td></tr>
 </table> 
 
 <P>Only the last two rows use a "coder key".
 The <tt>BaseText</tt> column holds either the coder key, or the user-presentable English. 
 The <tt>BaseText</tt> is the lookup key. The fact that there is 
 repetition of data between the <tt>BaseText</tt> and <tt>English</tt> columns is not a real duplication problem, 
 since <em>this is a <tt>ResultSet</tt>, not a table</em> - the underlying tables will not have such 
 repetition (if designed properly, of course). 
  
 <P>For example, such a <tt>ResultSet</tt> can be constructed from three underlying tables - 
 <tt>BaseText</tt>, <tt>Locale</tt>, and <tt>Translation</tt>. <tt>Translation</tt> is a cross-reference 
 table, with foreign keys to both <tt>BaseText</tt> and <tt>Locale</tt>. When such a scheme is 
 normalized, it will have no repeated data. (In underlying queries, however, the base 
 language will be necessarily treated differently than the other languages.)
 
 <P>Upon startup, the tables are read, the above <tt>ResultSet</tt> is created and  
 stored in a <tt>private static Map</tt>, represented schematically as 
 <tt>Map[BaseText, Map[Locale, Translation]]</tt>. When a translation is required, 
 this <tt>Map</tt> is used as an in-memory lookup table. This avoids 
 repeated fetching from the database of trivial data that rarely changes. 

 <P><b>Note on Thread Safety</b>
 <br>In the suggested implementation style, the <tt>private static Map</tt> that stores translation data is 
 <tt>static</tt>, and thus shared by multiple threads. Implementations are free to implement 
 any desired policy regarding thread safety, from relaxed to strict. A relaxed implementation 
 might completely ignore the possibility of a mistaken read/write, since no writes are expected in 
 production, or simply because the consequences are usually trivial. A strict implementation would 
 take the opposite approach, and demand that the <tt>private static Map</tt> be used in an fully 
 thread-safe manner.   
*/
public interface Translator {
  
  /**
   Translate <tt>aBaseText</tt> into text appropriate for <tt>aLocale</tt>.
   
   <P><tt>aBaseText</tt> is either user-presentable text in the base language of 
   development, or a "coder key" known only to the programmer.
   
   <P>If <tt>aBaseText</tt> is unknown, then the implementation is free to define 
   any desired behavior. For example, this method might return  
  <ul>
   <li><tt>aBaseText</tt> passed to this method, in its raw, untranslated form
   <li><tt>aBaseText</tt> with special surrounding text, such as <tt>???some text???</tt>, with 
   leading and trailing characters
   <li>a fixed <tt>String</tt> such as <tt>'???'</tt> or <tt>'?untranslated?'</tt>
   <li>it is also possible for an implementation to throw a {@link RuntimeException} when 
   an item is missing, but this is not recommended for applications in production
  </ul>
  
   <P>If <tt>aBaseText</tt> is known, but there is no explicit translation for the 
   given {@link Locale}, then an implementation might choose to mimic the behavior of 
   {@link java.util.ResourceBundle}, and choose a translation from the "nearest available" 
   {@link Locale} instead.
  
   @param aBaseText is not <tt>null</tt>, but may be empty
   @param aLocale comes from the configured {@link LocaleSource}.
  */
  String get(String aBaseText, Locale aLocale);
  
}
