Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StockWatcher: errors when translating contents to german

I'm following the internationalization chapter. After finishing the steps to translate content to german, I getting this errors when I try to load the page in the browser:

11:26:27.142 [ERROR] [stockwatcher] Error while executing the JavaScript provider for property 'locale'
com.google.gwt.core.client.JavaScriptException: (TypeError): Property 'locale' of object  is not a function
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:248)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.ModuleSpacePropertyOracle.computePropertyValue(ModuleSpacePropertyOracle.java:193)
    at com.google.gwt.dev.shell.ModuleSpacePropertyOracle.getSelectionProperty(ModuleSpacePropertyOracle.java:130)
    at com.google.gwt.i18n.rebind.LocaleUtils.getInstance(LocaleUtils.java:85)
    at com.google.gwt.i18n.rebind.LocaleInfoGenerator.generate(LocaleInfoGenerator.java:101)
    at com.google.gwt.core.ext.GeneratorExtWrapper.generate(GeneratorExtWrapper.java:48)
    at com.google.gwt.core.ext.GeneratorExtWrapper.generateIncrementally(GeneratorExtWrapper.java:60)
    at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:647)
    at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)
    at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:78)
    at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:268)
    at com.google.gwt.dev.shell.ShellModuleSpaceHost.rebind(ShellModuleSpaceHost.java:141)
    at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:585)
    at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:455)
    at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:49)
    at com.google.gwt.core.client.GWT.create(GWT.java:97)
    at com.google.gwt.i18n.client.LocaleInfo.<clinit>(LocaleInfo.java:37)
    at com.google.gwt.user.client.ui.HasHorizontalAlignment.<clinit>(HasHorizontalAlignment.java:123)
    at com.google.gwt.user.client.ui.VerticalPanel.<init>(VerticalPanel.java:31)
    at com.google.gwt.sample.stockwatcher.client.StockWatcher.<init>(StockWatcher.java:29)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:465)
    at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:375)
    at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:525)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
    at java.lang.Thread.run(Thread.java:722)

11:26:27.640 [ERROR] [stockwatcher] Unable to load module entry point class com.google.gwt.sample.stockwatcher.client.StockWatcher (see associated exception for details)
com.google.gwt.dev.shell.BrowserChannel$RemoteDeathError: Remote connection lost
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:356)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:289)
    at com.google.gwt.dev.shell.ModuleSpace.displayErrorGlassPanel(ModuleSpace.java:616)
    at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:401)
    at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:525)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
    at java.lang.Thread.run(Thread.java:722)
Caused by: com.google.gwt.dev.shell.BrowserChannelException: Invalid message type PROTOCOL_VERSION received waiting for return.
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:350)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:289)
    at com.google.gwt.dev.shell.ModuleSpace.displayErrorGlassPanel(ModuleSpace.java:616)
    at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:401)
    at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:525)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
    at java.lang.Thread.run(Thread.java:722)

11:26:27.959 [ERROR] [stockwatcher] Failed to load module 'stockwatcher' from user agent 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2' at localhost:52343

This is the code of StockWatcher.java:

package com.google.gwt.sample.stockwatcher.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

import java.util.ArrayList;
import java.util.Date;

public class StockWatcher implements EntryPoint {



private static final int REFRESH_INTERVAL = 5000;
  private VerticalPanel mainPanel = new VerticalPanel(); //line 29
  private FlexTable stocksFlexTable = new FlexTable();
  private HorizontalPanel addPanel = new HorizontalPanel();
  private TextBox newSymbolTextBox = new TextBox();
  private Button addStockButton = new Button("Add");
  private Label lastUpdatedLabel = new Label();
  private ArrayList<String> stocks = new ArrayList<String>();
  private StockWatcherConstants constants = GWT.create(StockWatcherConstants.class);

  /**
   * Entry point method.
   */
  public void onModuleLoad() {
    // Set the window title, the header text, and the Add button text.
    Window.setTitle(constants.stockWatcher());
    RootPanel.get("appTitle").add(new Label(constants.stockWatcher()));
    addStockButton = new Button(constants.add());  

    // Create table for stock data.
    stocksFlexTable.setText(0, 0, constants.symbol());
    stocksFlexTable.setText(0, 1, constants.price());
    stocksFlexTable.setText(0, 2, constants.change());
    stocksFlexTable.setText(0, 3, constants.remove());

    // Add styles to elements in the stock list table.
    stocksFlexTable.setCellPadding(6);
    stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader");
    stocksFlexTable.addStyleName("watchList");
    stocksFlexTable.getCellFormatter().addStyleName(0, 1, "watchListNumericColumn");
    stocksFlexTable.getCellFormatter().addStyleName(0, 2, "watchListNumericColumn");
    stocksFlexTable.getCellFormatter().addStyleName(0, 3, "watchListRemoveColumn");

    // Assemble Add Stock panel.
    addPanel.add(newSymbolTextBox);
    addPanel.add(addStockButton);
    addPanel.addStyleName("addPanel");

    // Assemble Main panel.
    mainPanel.add(stocksFlexTable);
    mainPanel.add(addPanel);
    mainPanel.add(lastUpdatedLabel);

    // Associate the Main panel with the HTML host page.
    RootPanel.get("stockList").add(mainPanel);

    // Move cursor focus to the input box.
    newSymbolTextBox.setFocus(true);

    // Setup timer to refresh list automatically.
    Timer refreshTimer = new Timer() {
      @Override
      public void run() {
        refreshWatchList();
      }
    };
    refreshTimer.scheduleRepeating(REFRESH_INTERVAL);

    // Listen for mouse events on the Add button.
    addStockButton.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        addStock();
      }
    });

    // Listen for keyboard events in the input box.
    newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
      public void onKeyPress(KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
          addStock();
        }
      }
    });

  }

  /**
   * Add stock to FlexTable. Executed when the user clicks the addStockButton or
   * presses enter in the newSymbolTextBox.
   */
  private void addStock() {
    final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
    newSymbolTextBox.setFocus(true);

    // Stock code must be between 1 and 10 chars that are numbers, letters, or dots.
    if (!symbol.matches("^[0-9a-zA-Z\\.]{1,10}$")) {
      Window.alert("'" + symbol + "' is not a valid symbol.");
      newSymbolTextBox.selectAll();
      return;
    }

    newSymbolTextBox.setText("");

    // Don't add the stock if it's already in the table.
    if (stocks.contains(symbol))
      return;

    // Add the stock to the table.
    int row = stocksFlexTable.getRowCount();
    stocks.add(symbol);
    stocksFlexTable.setText(row, 0, symbol);
    stocksFlexTable.setWidget(row, 2, new Label());
    stocksFlexTable.getCellFormatter().addStyleName(row, 1, "watchListNumericColumn");
    stocksFlexTable.getCellFormatter().addStyleName(row, 2, "watchListNumericColumn");
    stocksFlexTable.getCellFormatter().addStyleName(row, 3, "watchListRemoveColumn");

    // Add a button to remove this stock from the table.
    Button removeStockButton = new Button("x");
    removeStockButton.addStyleDependentName("remove");
    removeStockButton.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        int removedIndex = stocks.indexOf(symbol);
        stocks.remove(removedIndex);
        stocksFlexTable.removeRow(removedIndex + 1);
      }
    });
    stocksFlexTable.setWidget(row, 3, removeStockButton);

    // Get the stock price.
    refreshWatchList();

  }

  /**
   * Generate random stock prices.
   */
  private void refreshWatchList() {
    final double MAX_PRICE = 100.0; // $100.00
    final double MAX_PRICE_CHANGE = 0.02; // +/- 2%

    StockPrice[] prices = new StockPrice[stocks.size()];
    for (int i = 0; i < stocks.size(); i++) {
      double price = Random.nextDouble() * MAX_PRICE;
      double change = price * MAX_PRICE_CHANGE
          * (Random.nextDouble() * 2.0 - 1.0);

      prices[i] = new StockPrice(stocks.get(i), price, change);
    }

    updateTable(prices);
  }

  /**
   * Update the Price and Change fields all the rows in the stock table.
   *
   * @param prices Stock data for all rows.
   */
  private void updateTable(StockPrice[] prices) {
    for (int i = 0; i < prices.length; i++) {
      updateTable(prices[i]);
    }

//    // Display timestamp showing last refresh.
//    lastUpdatedLabel.setText("Last update : "
//        + DateTimeFormat.getMediumDateTimeFormat().format(new Date()));

  }

  /**
   * Update a single row in the stock table.
   *
   * @param price Stock data for a single row.
   */
  private void updateTable(StockPrice price) {
    // Make sure the stock is still in the stock table.
    if (!stocks.contains(price.getSymbol())) {
      return;
    }

    int row = stocks.indexOf(price.getSymbol()) + 1;

    // Format the data in the Price and Change fields.
    String priceText = NumberFormat.getFormat("#,##0.00").format(
        price.getPrice());
    NumberFormat changeFormat = NumberFormat.getFormat("+#,##0.00;-#,##0.00");
    String changeText = changeFormat.format(price.getChange());
    String changePercentText = changeFormat.format(price.getChangePercent());

    // Populate the Price and Change fields with new data.
    stocksFlexTable.setText(row, 1, priceText);
    Label changeWidget = (Label)stocksFlexTable.getWidget(row, 2);
    changeWidget.setText(changeText + " (" + changePercentText + "%)");

    // Change the color of text in the Change field based on its value.
    String changeStyleName = "noChange";
    if (price.getChangePercent() < -0.1f) {
      changeStyleName = "negativeChange";
    }
    else if (price.getChangePercent() > 0.1f) {
      changeStyleName = "positiveChange";
    }

    changeWidget.setStyleName(changeStyleName);
  }

}

Javier

like image 483
ziiweb Avatar asked Nov 25 '11 10:11

ziiweb


1 Answers

The reference to line 29 in the stack trace could indicate that

private StockWatcherConstants constants =
  GWT.create(StockWatcherConstants.class);

cannot be instantiated. I could not find the text for StockWatcherConstants in your posting.

As a German who uses GWT with localization—usually with Messages rather than Constants—I do not recall seeing exactly the same error, but there are some common pitfalls.

Please ensure that your properties files are really encoded with UTF-8. As the GWT documentation states, it does not conform with standard Java.

Also, please make sure your Module.gwt.xml is set up properly. Your application should inherit the internationalization module.

<inherits name="com.google.gwt.i18n.I18N"/>

In addition, you should declare the available locales, and pick a default.

<extend-property name="locale" values="de"/>
<!--  <extend-property name="locale" values="en"/> -->
<!--  <extend-property name="locale" values="zh"/> -->
<set-property-fallback name="locale" value="de"/>

To change the locale, one must reload the application. Locales are compiled into separate JavaScript files.

If you do not wish to rely on the HTTP header for localization, you can set the locale from a cookie.

String localeCookie = Cookies.getCookie(LocaleInfo.getLocaleCookieName());

if(localeCookie != null) {
  setLocale(localeCookie);
}

The following declaration is then required elsewhere.

protected void setLocale(String targetLocale) {

  if (LocaleInfo.getCurrentLocale().getLocaleName().equals(targetLocale))
    return;

  Set<String> availableLocales =
    new HashSet<String>(Arrays.asList(LocaleInfo.getAvailableLocaleNames()));
  if (! availableLocales.contains(targetLocale))
    return;

  Cookies.setCookie(LocaleInfo.getLocaleCookieName(), targetLocale,
    new Date(new Date().getTime() + COOKIE_LIFETIME));

  Window.Location.reload();
}

Just make sure you also declare the locale cookie in your Module.gwt.xml.

<set-configuration-property name="locale.cookie" value="GWTlocale"/>

You can use this setLocale() function to change locales in response to a UI event. Because of the reloading, however, you will lose all state information.

If you use Places, you can use a second cookie to get back to where you were.

eventBus.addHandler(PlaceChangeEvent.TYPE, new PlaceChangeEvent.Handler() {
    @Override
    public void onPlaceChange(PlaceChangeEvent event) {
      Cookies.setCookie(HISTORY_COOKIE,
        historyMapper.getToken(event.getNewPlace()),
        new Date(new Date().getTime() + COOKIE_LIFETIME));
    }
});

When starting up, your application would look at the cookie and, presto, you see the same place in the new locale.

String lastToken = Cookies.getCookie(HISTORY_COOKIE);
Place defaultPlace =
  (lastToken != null ? historyMapper.getPlace(lastToken) : Place.NOWHERE);

if (defaultPlace == Place.NOWHERE)
  defaultPlace = new BestPlaceToStartYourApplication();

historyHandler.register(placeController, eventBus, defaultPlace);
historyHandler.handleCurrentHistory();

This response is a little bit more comprehensive since your question went unanswered for so long. Hope it gets you started with internationalization in GWT.

like image 152
Felix Lechner Avatar answered Oct 08 '22 01:10

Felix Lechner