Java, Programming

ZK i18n

zk-i18n

ZK page should be combined with several components. How can I change ZK page language? You can view this tutorial: http://www.zkoss.org/smalltalks/i18n/i18n.dsp, but it is not a good method for implement i18n. If there are 100 components in same page, you should type 100 line of codes and you need write a same code in a different page.

Here is a method for implements i18n with many components. I will show you Border Layout and combine with 5 component.

First, create a folder in WEB-INF and named this folder to component.

Create East.zul in component folder:
/WEB-INF/component/East.zul:

<window id="East" border="none">
    <label id="pageName" value="East" />
    <button id="btn" label="Button" />
</window>

In ZK page, first element ID should be same as page name. It is for program to get the correct language string.

/WEB-INF/component/North.zul:

<window id="North" border="none">
    <label id="pageName" value="North" />
    <button id="btn" label="Button" />
</window>

/WEB-INF/component/South.zul:

<window id="South" border="none">
    <label id="pageName" value="South" />
    <button id="btn" label="Button" />
</window>

/WEB-INF/component/West.zul:

<window id="West" border="none">
    <label id="pageName" value="West" />
    <button id="btn" label="Button" />
</window>

Now, create a index.zul in a root directory.
index.zul:

<?page title="Index Page"?>
<zk>
    <borderlayout>
        <north><include src="/WEB-INF/component/North.zul" /></north>
        <east><include src="/WEB-INF/component/East.zul" /></east>
        <center></center>
        <west><include src="/WEB-INF/component/West.zul" /></west>
        <south><include src="/WEB-INF/component/South.zul" /></south>
    </borderlayout>
</zk>

Use browser to open the index.zul. Is it same as below image?
ZK i18n

Now, create a Java class. This Java class is a ZK i18n core.
com.opentutorial.www.zk.language.I18N:

package com.opentutorial.www.zk.language;
import java.util.List;

import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zul.Button;
import org.zkoss.zul.Label;

public class I18N {

@SuppressWarnings("unchecked")
public static void setLanguage(Component rootComponent) {
List<Component> components = (List<Component>) rootComponent.getChildren();
for (int i = 0; i < components.size(); i++) {
Component component = components.get(i);
setComponentLanguage(component);
if (component.getChildren().size() > 0) {
setLanguage(component);
}
}
}

private static void setComponentLanguage(Component component) {
IdSpace owner = component.getSpaceOwner();
if (owner instanceof Component) {
String ownerId = ((Component)owner).getId();
String i18n = Labels.getLabel(ownerId + "." + component.getId());
if (i18n != null) {
if (component instanceof Label) {
((Label) component).setValue(i18n);
} else if (component instanceof Button) {
((Button) component).setLabel(i18n);
}
}
}
}
}

Create a language file.

/WEB-INF/i3-label.properties:

#i18n
North.pageName=North
North.btn=Button
East.pageName=East
East.btn=Button

South.pageName=South
South.btn=Button

West.pageName=West
West.btn=Button

/WEB-INF/i3-label_zh.properties:
#i18n
North.pageName=北
North.btn=按鈕

East.pageName=東
East.btn=按鈕

South.pageName=南
South.btn=按鈕

West.pageName=西
West.btn=按鈕

/WEB-INF/i3-label_en.properties:

#i18n
North.pageName=North
North.btn=Button

East.pageName=East
East.btn=Button

South.pageName=South
South.btn=Button

West.pageName=West
West.btn=Button

/WEB-INF/i3-label_ja.properties:

#i18n
North.pageName=北
North.btn=ボタン
East.pageName=東
East.btn=ボタン

South.pageName=南
South.btn=ボタン

West.pageName=西
West.btn=ボタン

Total 4 language file. i3-label.properties is a default language file. When program cannot find the correct language file, ZK should be use default language file.

North.pageName=North Front North is a ZK page first element ID. It can ensure same ID in different page also do not have a same key.

Now, create a component for user to change page language.

com.opentutorial.www.zk.component.LanguageCombobox:

package com.opentutorial.www.zk.component;
import java.util.Locale;

import org.zkoss.util.Locales;
import org.zkoss.web.Attributes;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.SimpleListModel;

import com.opentutorial.www.zk.language.I18N;

public class LanguageCombobox extends Combobox {

private static final long serialVersionUID = 1L;

public LanguageCombobox() {
Locale[] model = new Locale[3];
model[0] = Locale.ENGLISH;
model[1] = Locale.CHINESE;
model[2] = Locale.JAPANESE;

setModel(new SimpleListModel(model));
}

public void onInitRenderLater() throws InterruptedException {
Locale locale = Locales.getThreadLocal();
ListModel languages = this.getModel();
setSelectedIndex(0);
for (int i = 0; i < languages.getSize(); i++) {
if (locale.getDisplayLanguage().equals(((Locale) languages.getElementAt(i)).getDisplayLanguage())) {
setSelectedIndex(i);
return;
}
}
}

public void onCreate() {
I18N.setLanguage(getRoot());
}

public void onChange() {
Locale locale = (Locale) this.getModel().getElementAt(this.getSelectedIndex());
setDefaultLanguage(locale);
I18N.setLanguage(getRoot());
}

public void setDefaultLanguage(Locale locale) {
Session session = Sessions.getCurrent();
session.setAttribute(Attributes.PREFERRED_LOCALE, locale);
Locales.setThreadLocal(locale);
}
}

In LanguageCombobox’s constructor set up 3 different language, ENGLISH, CHINESE and JAPANESE.

onInitRenderLater() for display user selected language. If user do not select any language, use browser language for default language.

onCreate() for when LanguageCombobox create success. LanguageCombobox change the page language to user selected language.

onChange() for when user select language, LanguageCombobox immediately change the page language.

setDefaultLanguage() for set a user default language.

Create a Center.zul and put this component in here.
Center.zul:

<window id="Center" border="none">
    <combobox use="com.ctlok.pro.zk.component.LanguageCombobox" />
</window>

Add Center.zulcomponent toindex.zul.

index.zul:

<?page title="Index Page"?>
<zk>
    <borderlayout>
        <north><include src="/WEB-INF/component/North.zul" /></north>
        <east><include src="/WEB-INF/component/East.zul" /></east>
        <center><include src="/WEB-INF/component/Center.zul" /></center>
        <west><include src="/WEB-INF/component/West.zul" /></west>
        <south><include src="/WEB-INF/component/South.zul" /></south>
    </borderlayout>
</zk>

Below image is a index.zul with different language.
ZK i18n

ZK i18n

ZK i18n

ZK i18n Example:zk-i18n-advanced (Eclipse Project)

**** Please manual add ZK 5.01 library in WEB-INF/lib folder.