我们在 Java 程序中为 I18N 使用 gettext。
有没有办法将 gettext 用于 JSF xhtml 文件?
目前我们在 JSF 中使用 Java 属性文件:
<p:column headerText="#{msg['bargains.columns.percent']}">
你可以这样写一个命名的bean:
import java.io.Serializable;
import java.util.Locale;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import org.xnap.commons.i18n.I18nFactory;
/**
* Injectable version of {@link org.xnap.commons.i18n.I18n}.
*
* @author Falko Menge
* @author nico.rehwaldt
*/
@Named("i18n")
@SessionScoped
public class I18n implements Serializable {
private static final long serialVersionUID = 1L;
private transient org.xnap.commons.i18n.I18n i18n;
public org.xnap.commons.i18n.I18n getI18n() {
if (i18n == null) {
FacesContext context = FacesContext.getCurrentInstance();
String messageBundleName = context.getApplication().getMessageBundle();
Locale locale = context.getViewRoot().getLocale();
setI18n(I18nFactory.getI18n(getClass(), messageBundleName, locale, I18nFactory.FALLBACK));
}
return i18n;
}
public void setI18n(org.xnap.commons.i18n.I18n i18n) {
this.i18n = i18n;
}
public String marktr(String text) {
return org.xnap.commons.i18n.I18n.marktr(text);
}
public String tr(String text, Object o1, Object o2, Object o3, Object o4) {
return getI18n().tr(text, o1, o2, o3, o4);
}
public String tr(String text, Object o1, Object o2, Object o3) {
return getI18n().tr(text, o1, o2, o3);
}
public String tr(String text, Object o1, Object o2) {
return getI18n().tr(text, o1, o2);
}
public String tr(String text, Object o1) {
if (o1 instanceof Object[]) {
return getI18n().tr(text, (Object[]) o1);
}
return getI18n().tr(text, o1);
}
public String tr(String arg0) {
return getI18n().tr(arg0);
}
public String trc(String arg0, String arg1) {
return getI18n().trc(arg0, arg1);
}
public String trn(String text, String pluralText, long n, Object o1, Object o2, Object o3, Object o4) {
return getI18n().trn(text, pluralText, n, o1, o2, o3, o4);
}
public String trn(String text, String pluralText, long n, Object o1, Object o2, Object o3) {
return getI18n().trn(text, pluralText, n, o1, o2, o3);
}
public String trn(String text, String pluralText, long n, Object o1, Object o2) {
return getI18n().trn(text, pluralText, n, o1, o2);
}
public String trn(String text, String pluralText, long n, Object o1) {
if (o1 instanceof Object[]) {
return getI18n().trn(text, pluralText, n, (Object[]) o1);
}
return getI18n().trn(text, pluralText, n, o1);
}
public String trn(String arg0, String arg1, long arg2) {
return getI18n().trn(arg0, arg1, arg2);
}
public String trnc(String comment, String singularText, String pluralText, long n, Object obj1, Object obj2, Object obj3, Object obj4) {
return getI18n().trnc(comment, singularText, pluralText, n, obj1, obj2, obj3, obj4);
}
public String trnc(String comment, String singularText, String pluralText, long n, Object obj1, Object obj2, Object obj3) {
return getI18n().trnc(comment, singularText, pluralText, n, obj1, obj2, obj3);
}
public String trnc(String comment, String singularText, String pluralText, long n, Object obj1, Object obj2) {
return getI18n().trnc(comment, singularText, pluralText, n, obj1, obj2);
}
public String trnc(String comment, String singularText, String pluralText, long n, Object obj) {
if (obj instanceof Object[]) {
return getI18n().trnc(comment, singularText, pluralText, n, (Object[]) obj);
}
return getI18n().trnc(comment, singularText, pluralText, n, obj);
}
public String trnc(String arg0, String arg1, String arg2, long arg3) {
return getI18n().trnc(arg0, arg1, arg2, arg3);
}
}
像这样在 JSF 中使用它:
<h:outputLabel value="#{i18n.tr('Username')}" for="usernameInput" />
并通过 gettext-commons 运行它:
<dependency>
<!-- required for i18n with GNU gettext -->
<groupId>org.xnap.commons</groupId>
<artifactId>gettext-commons</artifactId>
<version>0.9.6</version>
</dependency>
Maven 插件可以与 shellscript 一起使用,以从 JSF 页面中提取密钥:
<plugin>
<!-- required for i18n with GNU gettext -->
<groupId>org.xnap.commons</groupId>
<artifactId>maven-gettext-plugin</artifactId>
<version>1.2.3</version>
<configuration>
<xgettextCmd>${basedir}/src/main/po/xgettext-jsf.sh</xgettextCmd>
<poDirectory>${basedir}/src/main/po</poDirectory>
<targetBundle>i18n.Messages</targetBundle>
<outputDirectory>${basedir}/src/main/resources</outputDirectory>
</configuration>
</plugin>
</plugins>
脚本:
#!/bin/sh
# extract gettext strings from Java sources with options provided by Maven
xgettext --copyright-holder='ACME Inc.' --package-name='ACME Webapp' --package-version='1.0-SNAPSHOT' --msgid-bugs-address='info@example.com' $*
# replace some placeholders
sed -i '1 s/SOME DESCRIPTIVE TITLE/This is the LANGUAGE translation of ACME Webapp/' ../po/keys.pot
sed -i '2 s/YEAR/2011/' ../po/keys.pot
sed -i '3 s/PACKAGE/ACME Webapp/' ../po/keys.pot
# fix Java source file locations
sed -i 's/^#: /#: ..\/java\//' ../po/keys.pot
# add a newline
echo >> ../po/keys.pot
# extract gettext strings from JSF templates
grep "i18n\.[^(]\+('[^']\+'[^)]*)" --recursive --exclude-dir=.svn --include='*.xhtml' --only-matching --with-filename --line-number ../ | sed "s/\(.*\)\:i18n.tr('\(.*\)'.*/#: \1\nmsgid \"\2\"\nmsgstr \"\"\n/" >> ../po/keys.pot
# unify duplicate translations in message catalog
msguniq --sort-by-file --output-file=../po/keys.pot ../po/keys.pot