Methods 如何用EL在ZK中实现翻译功能

Methods 如何用EL在ZK中实现翻译功能,methods,el,zk,Methods,El,Zk,我的webapp有一个智能的Java转换器,所以我不能在ZK中使用简单的基于标签的i18n。取而代之的是,应该调用我的带有两个参数(key和language)的smart translator方法,但是当前的语言应该从一些webapp范围中获取 有一个EL函数是非常有用的 <textbox value="${x:translate('some.i18n.key')}"/> 并将其用作 <textbox value="${x:translate('qqq',sessionSc

我的webapp有一个智能的Java转换器,所以我不能在ZK中使用简单的基于标签的i18n。取而代之的是,应该调用我的带有两个参数(key和language)的smart translator方法,但是当前的语言应该从一些webapp范围中获取

有一个EL函数是非常有用的

<textbox value="${x:translate('some.i18n.key')}"/>
并将其用作

 <textbox value="${x:translate('qqq',sessionScope.get('LANGUAGE'))}"/>

但是,每次编写第二个参数并不是一个好的解决方案。它可以写得短一点,如下所示

 <textbox value="${x:translate('qqq',LANGUAGE)}"/>

或者选择一个较短的键而不是
语言
,但我对更紧凑的形式感兴趣


是否可以定义这样一个隐式获取第二个参数的函数?或者从EL调用会话/桌面/页面范围中对象的方法?

自定义标记库是您需要的解决方案。 它存在于ZK中:

我们将模式与ZK结合使用,而转换是ZK引用进入视图模型的一个领域。为了减少其影响,我们采取了以下措施:

创建了转换器接口:

public interface Translator {
    String translate(String key);

    // used where the string to be translation includes placeholders
    // total_qty=Total qty: {1}
    String translate(String key, String... params);
}
和转换器实现:

public class ZKTranslator implements Translator {

    @Override
    public String translate(String s) {
        String translation = Labels.getLabel(s);
        if (translation == null)
            return s;
        return translation;
    }

    @Override
    public String translate(String key, String... params) {
        String translation = Labels.getLabel(key, params);
        if (translation == null)
            return key;
        return translation;
    }
}
此实现可以引用会话来检索语言,或者(更可取的是)在初始化时将语言传递给ZKTranslator

然后按如下方式使用它。在视图模型中:

public class SomeScreenVM {
    private Translator translator;

    @Init
    public void init() {
        // get language from session possibly
        translator = new ZKTranslator(); // or new ZKTtanslator(language);
    }

    public String translate(String s) {
        return translator.translate(s);
    }
}
在zul文件中:

<window viewModel="@id('vm')" @init('com.example.SomeScreenVM')>
    <label value="@load(vm.translate('hello'))"/>
</window>

我可以(错过)使用EL的映射支持来调用对象的非静态单参数方法

首先,我需要一个实现
java.util.Map
的translator对象,它可以在其
get()
方法中翻译字符串:

    public class Translator implements Map<String, String> {

        private String language;

        public Translator(String language) {
            super();
            this.language = language;
        }

        @Override
        public String get(Object arg0) {
            return translate(arg0.toString(), language);
        }
        ...
    }
公共类转换器实现映射{
私有字符串语言;
公共翻译器(字符串语言){
超级();
这种语言=语言;
}
@凌驾
获取公共字符串(对象arg0){
返回translate(arg0.toString(),语言);
}
...
}
然后我可以将翻译器放入桌面范围,并在EL中使用它:

<zscript>
    desktopScope.put("tr",new mypackage.Translator(sessionScope.get("language")));
</zscript>

 <textbox value="${tr.some_key}"/>
 <textbox value="${tr['some.hierarchical.key']}"/>

desktopScope.put(“tr”,新的mypackage.Translator(sessionScope.get(“语言”));

这确实不是一个明确的解决方案,但使使用ZUL文件变得相当简单。

感谢您的回答!我的应用程序是一个使用GenericForwardComposer的旧应用程序,没有MVVM。也许我应该切换到MVVM,然后我可以使用这种方法。如果您有选择的话,我强烈建议您切换到MVVM。当然,如果你在处理遗留代码,说起来容易做起来难。谢谢你的回答。不幸的是,我不是JSP标记库的专家,而且相当简短且唯一的文档只描述了公共静态方式。静态方法对您来说不可用吗?如果您需要一个Springbean,那么您可以始终使用servicelocator()模式。我知道有关于它是模式还是反模式的讨论,但除此之外,它可以帮助您。公共静态的问题是我必须提供一个语言参数,但我不想在每次调用时都提供它。所以我需要调用堆栈中的某个存储状态。如何使用自定义taglibs.Sessions.getCurrent始终为您提供当前会话。
<zscript>
    desktopScope.put("tr",new mypackage.Translator(sessionScope.get("language")));
</zscript>

 <textbox value="${tr.some_key}"/>
 <textbox value="${tr['some.hierarchical.key']}"/>