Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Not understanding i18n of DataSource ds.xml title fields

    I've been trying to get localization (i18n) to work on the DataSource field titles in a DataSource ds.xml files following the steps documented in the SmartClient reference on DataSource localization that been cited as the how-to in other forum threads. I think I am not understanding a key concept since I've not gotten it to work.

    I am using SmartGWT PowerEdition 2.3 (SC_SNAPSHOT-2010-09-04/PowerEdition Deployment (built 2010-09-04)) with Eclipse 3.5 running in development mode with GWT 2.0.4 plugins.

    I can get the GWT approach to localization to work, but I'd prefer to get the localization in the DataSource for the field titles. What am I missing or doing incorrectly? I am guessing that I'm not providing English and Spanish language bundles needed for the translation and it unfortunately will not be using the same i18n mechanism that GWT is using. I've not found hints yet what I should to create the appropriate bundles or where to place them.

    I added the "/shared/ds/*" to the jsp-config in the web.xml, snippet:

    Code:
    	<jsp-config>
    		<!-- Isomorphic JSP tags -->
    		<taglib>
    			<taglib-uri>isomorphic</taglib-uri> 
    			<taglib-location>/WEB-INF/iscTaglib.xml</taglib-location> 
    		</taglib>
    		<!-- For I18N of ds.xml fields, etc. -->
    		<jsp-property-group>
    			<url-pattern>/shared/ds/*</url-pattern>
    		</jsp-property-group>
    	</jsp-config>
    This is the PING.ds.xml:

    Code:
    <!--
    <%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %>
    -->
    
    <DataSource xmlns:fmt="urn:jsptld:/WEB-INF/fmt.tld"  
    	schema="PING"
    	dbName="Oracle"
    	tableName="PING"
    	ID="PING"
    	serverType="sql"
    >
    	<fields>
    		<field sequenceName="PING_SEQ" primaryKey="true" name="id" type="sequence" hidden="true"></field>
    		<field name="name" length="51" type="text">
    			<title><fmt:message key="ping_ds_field_name" /></title>
    			<validators>
    				<validator type="isUnique" requiresServer="true" />
    			</validators>
    		</field>
    		<field name="other" length="21" type="text">
    			<title><fmt:message key="ping_ds_field_other" /></title>
    		</field>
    	</fields>
    	
    	<operationBindings>
    		<operationBinding operationType="fetch" >
    			<orderClause>
    			UPPER(ping.PING.name)
    			</orderClause>
    		</operationBinding>
    	</operationBindings>
    </DataSource>
    Note, I do not have a WEB-INF/fmt.tld file. Should I have this file and is it the one from the jakarta-taglibs-standard-1.1.2?

    This is the html page for the Ping RIA:

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    
    <html>
      <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        
        <meta name="gwt:property" content="locale=es"> 
    
        <title>Ping</title>
        
        <script>var isomorphicDir = "Ping/sc/";</script>
    	
        <script type="text/javascript" language="javascript" src="Ping/Ping.nocache.js"></script>
      </head>
    
      <body>
    
        <!--load the datasources-->
        <script src="Ping/sc/DataSourceLoader?dataSource=PING"></script>
    
        <!-- OPTIONAL: include this if you want history support -->
        <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
    
      </body>
    </html>

    Also note, I'm trying to do this from an html file not a jsp file. Is this translation possible using the DataSourceLoader script method?

    This is the Ping.gwt.xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
    
    <module rename-to="Ping">
    
        <inherits name='com.google.gwt.user.User'/>
    
        <inherits name="com.smartgwtpower.SmartGwtPower"/>
        
        <entry-point class='com.smartgwt.sample.client.Ping'/>
        
        <extend-property name="locale" values="es"/>
        
    	
    </module>
    This is the GWT localization code:

    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.i18n.client.Constants;
    
    public interface ClientConstants extends Constants 
    {
    	
    	@DefaultStringValue("Clear")
    	String clear();
    	
    	@DefaultStringValue("New")
    	String _new();
    
    	@DefaultStringValue("Save")
    	String save();
    
    	
    	@DefaultStringValue("Name")
    	String ping_ds_field_name();
    	
    	@DefaultStringValue("Other")
    	String ping_ds_field_other();
    }
    ClientConstants_es.properties:
    Code:
    clear = Limpiar 
    _new = Crear
    save = Guardar
    
    
    ping_ds_field_name = Nombre
    ping_ds_field_other = Suplemento
    And the code for Ping.java:

    Code:
    package com.smartgwt.sample.client;
    
    import java.util.ArrayList;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.data.Record;
    import com.smartgwt.client.widgets.Canvas;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.form.DynamicForm;
    import com.smartgwt.client.widgets.form.fields.FormItem;
    import com.smartgwt.client.widgets.form.fields.TextItem;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
    import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
    import com.smartgwt.client.widgets.layout.HLayout;
    import com.smartgwt.client.widgets.layout.VStack;
    
    public class Ping implements EntryPoint 
    {
    	private ClientConstants constants = GWT.create(ClientConstants.class);
    
    	private ListGrid grid;
    	private DynamicForm form;
    	private IButton saveBtn;
    	private IButton newBtn;
    
    
    	public void onModuleLoad() 
    	{
    		Canvas mainCanvas = new Canvas();
    		mainCanvas.setHeight100();
    		mainCanvas.setWidth100();
    		mainCanvas.setBackgroundColor("green");
    
    		DataSource ds = DataSource.get("PING");
    
    		VStack vstack = new VStack();
    		vstack.setLeft(10);
    		vstack.setTop(10);
    		vstack.setWidth("80%");
    		vstack.setHeight("80%");
    		vstack.setMembersMargin(10);
    
    		grid = new ListGrid();
    		grid.setDataSource(ds);
    		grid.setWidth(300);
    		grid.setHeight(200);
    		grid.addRecordClickHandler(new RecordClickHandler() {
    			public void onRecordClick(RecordClickEvent event) {
    				Record record = event.getRecord();
    				form.editRecord(record);
    				form.enable();
    				saveBtn.enable();
    				newBtn.disable();
    			}
    		});
    		
    		// Add for I18N
    //		ListGridField nameField = new ListGridField("name", constants.ping_ds_field_name());
    //		ListGridField otherField = new ListGridField("other", constants.ping_ds_field_other());
    //		grid.setFields(nameField, otherField);
    		
    		grid.fetchData();
    
    		vstack.addMember(grid);
    
    		form = new DynamicForm();
    		form.setDataSource(ds);
    		form.setNumCols(2);
    		form.setAutoFocus(false);
    		form.disable();
    		
    		// Add for I18N
    //		ArrayList<FormItem> fields = new ArrayList<FormItem>();
    //		TextItem name = new TextItem("name", constants.ping_ds_field_name());
    //		fields.add(name);
    //		TextItem other = new TextItem("other", constants.ping_ds_field_other());
    //		fields.add(other);
    //		form.setFields(fields.toArray(new FormItem[fields.size()]));
    		
    		vstack.addMember(form);
    
    		HLayout hLayout = new HLayout(10);
    		hLayout.setMembersMargin(10);
    		hLayout.setHeight(22);
    
    		saveBtn = new IButton(constants.save());
    		saveBtn.disable();
    		saveBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				form.saveData();
    			}
    		});
    		hLayout.addMember(saveBtn);
    
    		newBtn = new IButton(constants._new());
    		newBtn.enable();
    		newBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				form.enable();
    				form.editNewRecord();
    				saveBtn.enable();
    				newBtn.disable();
    			}
    		});
    		hLayout.addMember(newBtn);
    
    		IButton clearBtn = new IButton(constants.clear());
    		clearBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				form.disable();
    				form.clearValues();
    				saveBtn.disable();
    				newBtn.enable();
    			}
    		});
    		hLayout.addMember(clearBtn);
    
    		vstack.addMember(hLayout);
    
    
    		mainCanvas.addChild(vstack);
    
    		mainCanvas.draw();
    
    	}
    
    }
    Note, I've commented out the GWT localization that I have working in Ping.java since I am trying to get the embedded DataSource localization method working.

    Also, is there a working example that I missed in the showcase for localization of ds.xml files that I overlooked? If there is a demo project that I can look at it would be really helpful for my understanding of this task.

    #2
    Yes, the "fmt" tag is from that taglib - you'll need to install it.

    When you switch over to JSP-based formatting, you need to replace the DataSourceLoader servlet as well - note the section that talks about this and shows "<isomorphic:XML>" tags.

    Basically, create .jsp with one <jsp:include> per i18n'd DataSource, and use a <script src=> tag to point to that .jsp instead of the DataSourceLoader servlet. If you watch in Firebug, you'll see the .jsp returning a series of JavaScript DataSource definitions (just like the DataSourceLoader servlet).

    Comment


      #3
      Thanks for the advice. I have it working, but I'd like to check to see if I did it correctly since I wasn't able to get the <script src=> the .jsp part working in my Ping.html within GWT development mode in Eclipse. (I've not checked that approach in a deployment environment yet.)

      These are the changes I did in regards to my above code. First, I fixed the web.xml to point to the correct ds directory:
      Code:
              <!-- For I18N of ds.xml fields, etc. -->
              <jsp-property-group>
                  <url-pattern>/ds/*</url-pattern>
              </jsp-property-group>
      Next I changed Ping.html into Ping.jsp, with the following difference:
      Code:
          <!--load the datasources-->
          <jsp:include page="loadpingds.jsp"></jsp:include>
      This is the new loadpingds.jsp:
      Code:
      <%@ taglib uri="/WEB-INF/iscTaglib.xml" prefix="isomorphic" %>
      
      <SCRIPT>
          <isomorphic:XML>
          <jsp:include page="/ds/PING.ds.xml"></jsp:include>            
          </isomorphic:XML>
      </SCRIPT>
      I was unsure where to put the "<jsp:include> per the i18n'd DataSource", but I did modify the ds.xml like this to get the localizations to get appropriately swapped.
      Code:
      <!--
      <%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %>
      
      <fmt:setBundle basename="com.smartgwt.sample.client.ClientConstants" />
      
      -->
      
      <DataSource xmlns:fmt="urn:jsptld:/WEB-INF/fmt.tld"  
      	schema="PING"
      	dbName="Oracle"
      	tableName="PING"
      	ID="PING"
      	serverType="sql"
      >
      	<fields>
      		<field sequenceName="PING_SEQ" primaryKey="true" name="id" type="sequence" hidden="true"></field>
      		<field name="name" length="51" type="text">
      			<title><fmt:message key="ping_ds_field_name" /></title>
      			<validators>
      				<validator type="isUnique" requiresServer="true" />
      			</validators>
      		</field>
      		<field name="other" length="21" type="text">
      			<title><fmt:message key="ping_ds_field_other" /></title>
      		</field>
      	</fields>
      	
      	<operationBindings>
      		<operationBinding operationType="fetch" >
      			<orderClause>UPPER(ping.PING.name)</orderClause>
      		</operationBinding>
      	</operationBindings>
      </DataSource>
      Lastly, I added a new properties file, ClientConstants_en.properties, for English:
      Code:
      clear=Clear 
      _new=New
      save=Save
      
      ping_ds_field_name=Name
      ping_ds_field_other=Other
      If I didn't have the English version of properties, the translations did not use the defaults in the ClientConstants.class file.

      Now it works, but, is this the acceptable, correct approach?

      I note that the localization seems to be driven by the browser's Language preference setting, rather than the meta tag set for GWT that is in the .jsp —
      Code:
          <meta name="gwt:property" content="locale=es">
      This seems to mean as a side effect of not being a pure-Javascript SmartClient app, a SmartGWT app will have two mechanisms for localization if I want ds.xml files are to be localized.

      So, in the Ping.java instead of writing code like this:
      Code:
          private ClientConstants constants = GWT.create(ClientConstants.class);
      
      // ... and so on
              newBtn = new IButton(constants._new());
      Have code like this:
      Code:
      	newBtn = new IButton("<fmt:message key=\"ping_ds_field_other\" />");
      Is there a best practices approach to use the same approach in the .java code?

      Comment


        #4
        By "<jsp:include> per the i18n'd DataSource" we meant that to i18n further DataSources, you can just add more jsp:include lines to your loadpingds.jsp (so it should probably be named loadDataSources.jsp or similar instead).

        You didn't mention what we wrong when you tried to just point a <script src=> tag at this .jsp - is that not working?

        We're not sure what Ping.java is but you don't need any Java code for this localization - this is server-side localization and doesn't involve the GWT compiler. However you may want to use a shared .properties file for the messages you are using server-side and the ones you are using client-side, since they probably overlap - there are multiple GWT localization strategies some of which support using .properties files.

        Finally, yes, since this is .jsp-based localization, the default locale is the one sent from the browser, but could pass it in as an ordinary HTTP parameter to the JSP if you want to provide explicit switching.

        Comment


          #5
          You didn't mention what we wrong when you tried to just point a <script src=> tag at this .jsp - is that not working?
          What I've determined is that DataSource isn't being processed and the page does not load. Here's the error GWT Eclipse plug-in Development Mode:
          Code:
          11:33:43.392 [ERROR] [Ping] Unable to load module entry point class com.smartgwt.sample.client.Ping (see associated exception for details)
          java.lang.NullPointerException: null
              at com.smartgwt.client.widgets.grid.ListGrid.setDataSource(ListGrid.java:11727)
              at com.smartgwt.sample.client.Ping.onModuleLoad(Ping.java:50)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
              at java.lang.reflect.Method.invoke(Unknown Source)
              at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:369)
              at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:185)
              at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:380)
              at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:222)
              at java.lang.Thread.run(Unknown Source)
          Ping.java, line 50 is:
          Code:
                  grid.setDataSource(ds);
          I've not been able to get any additional information about this from the Developer Console.
          We're not sure what Ping.java is but you don't need any Java code for this localization - this is server-side localization and doesn't involve the GWT compiler.
          Ping.java is my 'small reproducer' test program for trying out new-to-me SmartGWT concepts or exploring issues I'm facing in developing a larger application. It is a learning tool for me. I thought I needed Java code for this localization to get the three buttons to localize in the Java code. This is not correct?
          However you may want to use a shared .properties file for the messages you are using server-side and the ones you are using client-side...
          I am sharing or at least believe I am, although my name choice should be better. The ClientConstants_en.properties and ClientConstants_es.properties are shared between the GWT compiled ping app (for the three buttons) and the server-side localization that the jsp is doing for the DataSource.

          Comment


            #6
            That error indicates the DataSource didn't load - almost all of the steps in the FAQ for troubleshooting DataSource loading from the DataSourceLoader apply (eg, look at what the response was in Firebug).

            You want to continue to internationalize your client-side GWT code in the same way - nothing changes there.

            Comment


              #7
              The response Firebug shows for loadpingds.jsp seems okay. Here it is for English:

              Code:
              <SCRIPT>
                  
                  
              
              isc.DataSource.create({
                  ID:"PING",
                  dbName:"Oracle",
                  schema:"PING",
                  serverType:"sql",
                  tableName:"PING",
                  fmt:"urn:jsptld:/WEB-INF/fmt.tld",
                  fields:{
                      id:{
                          hidden:true,
                          name:"id",
                          primaryKey:true,
                          sequenceName:"PING_SEQ",
                          type:"sequence"
                      },
                      name:{
                          length:"51",
                          name:"name",
                          type:"text",
                          title:"Name",
                          validators:[
                              {
                                  requiresServer:"true",
                                  type:"isUnique"
                              }
                          ]
                      },
                      other:{
                          length:"21",
                          name:"other",
                          type:"text",
                          title:"Other"
                      }
                  },
                  operationBindings:[
                      {
                          operationType:"fetch",
                          orderClause:"UPPER(ping.PING.name)"
                      }
                  ]
              })
                       
              </SCRIPT>
              I went back and restepped through the DataSource troubleshooting section of the FAQ and each checkpoint seems okay, but I have a question.

              Even though the DataSourceLoader is in the web.xml, which isn't being used by Ping.html, do I need to also place the loadpingds.jsp in the web.xml as well? I've not done this.

              Other than that, the DataSource ID and file name matches.

              The server.properties' project.datasource is set correctly.

              There are no malformed XML messages associated with loadpingds.jsp (or anything else) in the server log (in this case the Eclipse console output).

              And the <script src="loadpingds.jsp"></script> line comes after the <script type="text/javascript" language="javascript" src="Ping/Ping.nocache.js"></script> in index.html.

              The datasource and Ping app loads fine (minus localization) if I use the DataSourceLoader method, so unless the loadpingds.jsp needs to be somehow in the web.xml I'm not sure what else to try.

              Comment


                #8
                Those are all the right things to check - if you open your Developer Console and type isc.DS.get("PING") into the Evaluate JS Expression area and hit Evaluate, what do you get?

                Comment


                  #9
                  Evaluator: result of 'isc.DS.get("PING")' (0ms):
                  null

                  Comment


                    #10
                    Sorry for the wild goose chase, the problem is that you should not have <script> tags inside loadpingds.jsp because it's supposed to return just pure JavaScript.

                    Comment


                      #11
                      Excellent! That was it. Thank you.

                      Comment


                        #12
                        This thread seems as a good starting point for exploration of i18n. There are however 2 issues which perplex me :

                        1/ What exactly do tags of the kind "<fmt:message key="some_key"/>"? Do they retrieve translated message from a bundle on the server or do they generate JavaScript code which retrieves translated message from a bundle on the client? Or something else?
                        2/ In either case : how do these tags know which bundle to use?

                        Comment


                          #13
                          The "fmt" tag is a standard JSTL tag - try Googling "fmt jsp tag" for usage and samples.

                          Comment


                            #14
                            Thank you! Sorry about being so uneducated on standard JSPs:(

                            Comment


                              #15
                              Hi,

                              i have asked a little bit about this kind of thing in another thread. Just as a gentle question - to me, it would be really neat to be able to somehow use GWT standard i18n for fields in the ds.xml's. This approach (which i just now saw) should work i guess, but it's a bit awkward having to split up my i18n resources in different places.

                              Is this somehow a known issue and/or are there any plans for adding "smoother" i18n features for the datasources?

                              Love the product, cheers.

                              Comment

                              Working...
                              X