Revision: 6127
Author: rj...@google.com
Date: Fri Sep 11 16:18:26 2009
Log: Moved here from incubator
http://code.google.com/p/google-web-toolkit/source/detail?r=6127

Added:
  /wiki/UiBinderI18n.wiki

=======================================
--- /dev/null
+++ /wiki/UiBinderI18n.wiki     Fri Sep 11 16:18:26 2009
@@ -0,0 +1,366 @@
+#summary GWT UiBinder i18n use cases
+
+= GWT UiBinder Internationalization Use Cases =
+
+Ray Ryan <br />
+freely plagiarizing from the brilliant minds behind  
[http://code.google.com/p/gxp/ gxp]
+
+This document explores internationalization use cases supported the GWT  
UiBinder.
+
+= Background =
+
+The basic idea is that the localizable bits of your ui.xml template file  
are marked up as such. When the UiBinder code generator processes the  
template, it gathers these and creates an interface  extends  
com.google.gwt.i18.client.Messages. You then provide localized versions of  
these messages as you would for any other portion of your app. (See the  
Binding to Properties Files section of the  
[http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/i18n/client/Messages.html
  
Messages javadoc].)
+
+Values for annotations that apply at the Messages interface level are set  
as attributes on the root element. Here is an example with all possible  
values set (normally you'd let some of these default).
+
+{{{
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+
+  ui:defaultLocale="en_us"
+  ui:generateKeys="com.my.app.KeyGenerator"
+  ui:generateFormat="com.my.app.MessageCatalogFormat1,  
com.my.app.MessageCatalogFormat2"
+  ui:generateFilename="myapp_translate_source"
+  ui:generateLocales="default"
+>
+}}}
+
+= Open Issues =
+
+Support for Constants and ConstantsWithLookup is not yet designed.
+
+PluralText is theoretically supported, but untested.
+
+So far, I have found no use for Gxp's <ui:eph/> element. Is it really not  
needed, or do I just lack imagination?
+
+Unannotated user visible text is allowed--a feature is needed to make this  
a compile time error.
+
+= Complete sentence or headline with no internal tags. =
+
+*Original*
+{{{
+<h1>User Account Management.</h1>
+}}}
+
+*Tagged*
+{{{
+<h1>
+  <ui:msg description="Title of UAM page">User Account Management.</ui:msg>
+</h1>
+}}}
+
+
+*Generated*
+{{{
+public class MyUiBinderImpl implements MyUiBinder {
+  static final MyUiMessages messages = GWT.create(MyUiMessages.class);
+
+  void bindUi(MyUi myUi) {
+    HTML html = new HTML();
+    html.setHtml("<h1>" + messages.message1() + "</h1>");
+    myUi.setElement(html.getElement());
+  }
+}
+
+...@defaultlocale("en_US")
+...@generatekeys
+...@generatedfrom("com.foo.bar.MyUi.ul.xml")
+public interface MyUiMessages extends com.google.gwt.i18.client.Messages {
+  @DefaultMessage("User Account Management.")
+  @Description("Title of UAM page")
+  String message1();
+}
+}}}
+
+This is the hello world case‚ a simple, unparametrized string.
+
+= Simple HTML tags inside message =
+
+*Original*
+{{{
+We <b>strongly</b> urge you to reconsider.
+}}}
+
+*Tagged*
+{{{
+<ui:msg>We <b>strongly</b> urge you to reconsider.</ui:msg>
+}}}
+
+*Generated*
+
+As above
+
+Simple formatting is reasonable to put in front of a translator, and
+so UiBinder supports html in messages, not just text.
+
+
+= Messages with unclobberable portions =
+
+*Original*
+{{{
+<!-- Uh oh, don't want translator to mess up brand CSS or the trademark  
span -->
+<div><span class="brand">Colgate</span>, with MFP!<span  
class="tm">TM</span></div>
+}}}
+
+*Tagged*
+{{{
+<div>
+  <ui:msg description="blurb"><span class="brand"  
ui:ph="brandedSpan">Colgate</span>,
+  with MFP!<ui:ph name="trademark"><span  
class="tm">TM</span></ui:ph></ui:msg>
+</div>
+}}}
+
+
+*Generated*
+{{{
+public class MyUiBinderImpl implements MyUiBinder {
+  static final String MESSAGE1_BRANDED_SPAN_OPEN = "<span  
class=\"brand\">";
+  static final String MESSAGE1_BRANDED_SPAN_CLOSE = "</span>";
+  static final String MESSAGE1_TRADEMARK = "<span class='tm'>TM</span>";
+  static final MyUiMessages messages = GWT.create(MyUiMessages.class);
+
+  static final MyUiMessages messages = GWT.create(MyUiMessages.class);
+
+  public void bind(MyUi myUi) {
+    HTML html = new HTML();
+    html.setHtml("<div>"
+      + messages.message1(MESSAGE1_BRANDED_SPAN_OPEN,
+            MESSAGE1_BRANDED_SPAN_CLOSE, MESSAGE1_TRADEMARK)
+      + "</div>");
+  }
+}
+
+...@defaultlocale("en_US")
+...@description("blurb")
+...@generatekeys
+...@generatedfrom("com.foo.bar.MyUi.ul.xml")
+public interface MyUiMessages extends com.google.gwt.i18.client.Messages {
+  @DefaultMessage("{0}Colgate{1}, with MFP!{2}")
+  String message1(
+    @Example(MyUiBinderImpl.MESSAGE1_BRANDED_SPAN_OPEN) String  
brandedSpanOpen,
+    @Example(MyUiBinderImpl.MESSAGE1_BRANDED_SPAN_CLOSE) String  
brandedSpanClose,
+    @Example(MyUiBinderImpl.MESSAGE1_TRADEMARK) String trademark
+  );
+}
+}}}
+
+There are two examples in here. First, you see a {{{ui:ph}}} attribute that
+can be added to any child of a {{{ui:msg}}}, to indicate that placholders
+should be created to protect it from translators. Two placeholders are
+created, for the opening and closing tags of the element (in this
+case, brandedSpanOpen and brandedSpanClose).
+
+Second, we see an element, also named {{{ui:ph}}}, that can surround an
+arbitrary bit of markup to be protected in its entirety (in this case,
+the trademark placeholder).
+
+So, you have both an element *<ui:ph>*to surround untranslatable
+runs*</ui:ph>*, and the <span *ui:ph*>attribute{{{<}}}/span> to put in
+arbitrary elements to hide their begin and end tags from translators,
+but keep their content as part of the message.
+
+
+= Messages with runtime computed values =
+
+*Original*
+{{{
+<!-- Java code will make calls like  
getClosingDate().setInnerText(closingDate()) -->
+
+(closed <span ui:field="closingDate" /> through <span  
ui:field="reopeningDate"/>)
+}}}
+
+*Tagged*
+{{{
+<ui:msg>
+  (closed <span ui:field="closingDate" ui:example="7/12/2008" />
+  through <span ui:field="reopeningDate" ui:example="7/19/2008" />)
+</ui:msg>
+}}}
+
+
+Note that there is no {{{ui:ph}}} attribute here, which would normally
+be used to identify a span as a placeholder, and also to provide its
+name. The {{{ui:field}}} attribute's appearance inside a child of a
+{{{ui:msg}}} element is enough to make it clear that a placeholder is
+required, and the field name can be used as the placeholder name.
+
+The {{{ui:example}}} attribute is optional, and allows more useful
+text to be provided in the {...@example()}}} attribute of the generated
+Mesages interface (and hence to the translator). Without it, the
+parameters here would both be annotated {...@example("<span/>")}}}
+
+
+= Message containing widgets (HTMLPanel only) =
+
+*Original*
+{{{
+<ui:HTMLPanel>
+  Meeting starts at
+    <my:TimePicker ui:field="startPicker"/>
+  and ends at
+    <my:TimePicker ui:field="endPicker"/>.
+</ui:HTMLPanel>
+}}}
+
+*Tagged*
+{{{
+<ui:HTMLPanel>
+  <ui:msg>Meeting starts at
+    <my:TimePicker ui:field="startPicker"/>
+  and ends at
+    <my:TimePicker ui:field="endPicker"/>.
+  </ui:msg>
+</ui:HTMLPanel>
+}}}
+
+
+Note that there is no {{{ui:ph}}} attribute on the widgets. There's no
+need for them, as there is no ambiguity about what must be done when a
+widget shows up in the middle of a message. Note also that you can
+only do this kind of thing (widgets in messages) inside of an
+HTMLPanel, the only widget in the GWT collection that intermixes
+markup and child widgets.
+
+= Message containing widgets with text bodies (HasText or HasHtml inside  
HTMLPanel) =
+
+*Original*
+{{{
+<ui:HTMLPanel>
+  To do the thing,
+  <ui:HyperLink token="/doThe#thing">click
+  here</ui:HyperLink> and massage vigorously.
+</ui:HTMLPanel>
+}}}
+
+*Tagged*
+{{{
+<ui:HTMLPanel>
+  <ui:msg>To do the thing,
+  <ui:HyperLink token="/doThe#thing">click
+  here</ui:HyperLink> and massage vigorously.
+  </ui:msg>
+</ui:HTMLPanel>
+}}}
+
+
+*Generated*
+{{{
+...@default("To do the thing, {0}click here{1} and massage vigorously.")
+String message536(
+  @Example("<span>") String startWidget,
+  @Example("</span>") String endWidget
+);
+
+HTMLPanel panel = ..." + messages.message536("<span id='xyz'>", "</span>")  
+ "...
+HyperLink link = new HyperLink();
+link.setHistoryToken("/doThe#thing");
+link.setText(panel.getElementById("xyz").getInnerText());
+panel.addAndReplace(link, "xyz");
+}}}
+
+Again, only an HTMLPanel can intermix markup and widgets, and so only
+an HTMLPanel can hold a {{{<ui:msg>}}} in this style. Further, only the
+bodies of HasHTML and HasText children can be recognized as part of
+the message.
+
+= HTML attributes that need translation =
+
+*Original*
+{{{
+<th title="Keyword targeted">
+  <ui:msg>Keyword</ui:msg>
+</th>
+}}}
+
+*Tagged*
+{{{
+<th title="Keyword targeted">
+  <ui:attribute ui:name="title" ui:description="Tooltip text for keyword  
column"/>
+  <ui:msg>Keyword</ui:msg>
+</th>
+}}}
+
+
+*Generated*
+{{{
+...@defaultlocale("en_US")
+...@generatekeys
+...@generatedfrom("com.foo.bar.MyUi.ul.xml")
+public class MyUiBinderImpl implements MyUiBinder {
+   static final MyUiMessages messages = GWT.create(MyUiMessages.class);
+
+   void bindUi(MyUi myUi) {
+     HTML html = new HTML();
+     html.setHtml("<th title='" + messages.message1() + ">"
+       + messages.message2()
+       + "</th>");
+     myUi.setElement(html.getElement());
+   }
+}
+
+public interface MyUiMessages extends com.google.gwt.i18.client.Messages {
+  @DefaultMessage("Keyword targetted")
+  @Description("Tooltip text for keyword column")
+  String message1();
+
+  @DefaultMessage("Keyword")
+  String message2();
+}
+}}}
+
+Most common examples of this are the title attribute, for tool-tip
+text, and the alt tag of an <img> element.
+
+= Plural vs. Singular =
+
+*Original*
+{{{
+<!-- Imagine code that shows or hides these spans as appropriate -->
+<span ui:field="plural">
+  You have <span ui:field="pluralFormCount"/> active campaigns.
+</span>
+<span ui:field="singular">
+  You have one active campaign.
+</span>
+}}}
+
+*Tagged*
+{{{
+<ui:msg>
+  You have <ui:ph name="campaignCount" example="5"/> active campaigns.
+  <ui:pluralText key="one">You have one active campaign.</ui:pluralText>
+</ui:msg>
+}}}
+
+= Words with Multiple Meanings =
+
+*Original*
+{{{
+Favorite Color:
+  <ui:RadioButton name="color">Red</ui:RadioButton>
+  <ui:RadioButton name="color">Orange</ui:RadioButton>
+
+Favorite Fruit:
+  <ui:RadioButton name="fruit">Apple</ui:RadioButton>
+  <ui:RadioButton name="fruit">Orange</ui:RadioButton>
+}}}
+
+*Tagged*
+{{{
+Favorite Color:
+  <ui:RadioButton name="color"><ui:msg>Red</ui:msg></ui:RadioButton>
+  <ui:RadioButton name="color"><ui:msg meaning="the  
color"/>Orange</ui:msg></ui:RadioButton>
+
+Favorite Fruit:
+  <ui:RadioButton name="fruit"><ui:msg>Apple</ui:msg></ui:RadioButton>
+  <ui:RadioButton name="fruit"><ui:msg meaning="the  
fruit">Orange</ui:msg></ui:RadioButton>
+}}}
+
+
+The punchline here is that a translator may well be working with no
+more context than the attributes you set on an individual
+message. Post processors that generate unique hashes on the contents
+of the default message can use the optional {{{meaning}}} attribute to
+modify the hash. In this example that ensures that we get two
+different translations of the word "orange" in languages where it's
+needed.

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to