i18n for GWT SimplePager

Nowadays, internationalization (i18n) is virtually indispensable in most applications. Therefore, GWT also provides a powerful and commonly used i18n mechanism to meet this requirement. Unfortunately, even in the GWT source code itself, there are components which still contain hard-coded text.

The problem

The SimplePager, which can be used as a navigation within paginated tables, shows texts like “1-10 of 14” or “1-20 of over 1000”. This is implemented in SimplePager’s createText()-method:

protected String createText() {
    // Default text is 1 based.
    NumberFormat formatter = NumberFormat.getFormat("#,###");
    HasRows display = getDisplay();
    Range range = display.getVisibleRange();
    int pageStart = range.getStart() + 1;
    int pageSize = range.getLength();
    int dataSize = display.getRowCount();
    int endIndex = Math.min(dataSize, pageStart + pageSize - 1);
    endIndex = Math.max(pageStart, endIndex);
    boolean exact = display.isRowCountExact();
    return formatter.format(pageStart) + "-" + formatter.format(endIndex)
        + (exact ? " of " : " of over ") + formatter.format(dataSize);
}

Fortunately, this method is protected so we can overwrite it according to our needs. The calculation of the pages’ start and end, the data size and exact flag (see line 558 to 565) need to be copied. But what about the rest?

Primitive approach

One way to achieve the i18n-ability is to create Constants (or parameterless Messages) for the texts “of”, “of over” and maybe also for the dash, which can then be used instead of the hard-coded ones, e.g. like this:

public class I18nSimplePager extends SimplePager {

    private final I18nMessages i18n = GWT.create(I18nMessages.class);
    private final NumberFormat formatter = NumberFormat.getFormat("#,###");

    protected String createText() {
        HasRows display = getDisplay();
        Range range = display.getVisibleRange();
        int pageStart = range.getStart() + 1;
        int pageSize = range.getLength();
        int dataSize = display.getRowCount();
        int endIndex = Math.min(dataSize, pageStart + pageSize - 1);
        endIndex = Math.max(pageStart, endIndex);
        boolean exact = display.isRowCountExact();
        return formatter.format(pageStart) 
            + i18n.rangeSeparator()
            + formatter.format(endIndex) 
            + (exact ? i18n.ofText() : i18n.ofOverText()) 
            + formatter.format(dataSize);
}

This solution would possibly meet your requirements, even if it requires at least 3 constants/messages and multiple manual calls to NumberFormat. But what if you want to translate your application to a language where this static format ([start]-[end] of [total]) is not appropriate?

Advanced approach

A more flexible solution would be desirable, and GWT provides mechanisms to do so:

  1. Using a single parameterized message, instead of separate constants/messages, allows a flexible, language-specific format.
  2. With GWT-specific formats for the message parameter, manual calls to the NumberFormat are no longer required.
  3. Using Select Forms to evaluate the exact flag provides the possibility to show a different message based on its value.

With this improvement, the code snippets and properties would look like this:

public interface I18nMessages extends Messages {
    // ...
    String pagerText(int start, int end, int size, @Select boolean exact);
    // ...
}
# ...
pagerText={0,number,#,###}-{1,number,#,###} of {2,number,#,###}
pagerText[false]={0,number,#,###}-{1,number,#,###} of over {2,number,#,###}
# ...
public class I18nSimplePager extends SimplePager {

    private final I18nMessages i18n = GWT.create(I18nMessages.class);

    protected String createText() {
        HasRows display = getDisplay();
        Range range = display.getVisibleRange();
        int pageStart = range.getStart() + 1;
        int pageSize = range.getLength();
        int dataSize = display.getRowCount();
        int endIndex = Math.min(dataSize, pageStart + pageSize - 1);
        endIndex = Math.max(pageStart, endIndex);
        boolean exact = display.isRowCountExact();
        return i18n.pagerText(pageStart, endIndex, dataSize, exact);
}
Short URL for this post: http://wp.me/p4nxik-2Dg
This entry was posted in Java and Quality and tagged , , , , , , . Bookmark the permalink.

Leave a Reply