Java JSF2中每个语言环境的不同facelet(用于模板)

Java JSF2中每个语言环境的不同facelet(用于模板),java,jsf,jsf-2,internationalization,facelets,Java,Jsf,Jsf 2,Internationalization,Facelets,我有一个包含的模板,还有一个定义的页面。例如,您可以定义复合组件,它只是标准ui:include的外观 resources/myComponents/localeInclude.xhtml: <cc:interface> <cc:attribute name="src" required="true" type="java.lang.String"/> </cc:interface> <cc:implementation> <ui:

我有一个包含
的模板,还有一个定义
的页面。例如,您可以定义复合组件,它只是标准
ui:include
的外观

resources/myComponents/localeInclude.xhtml:

<cc:interface>
  <cc:attribute name="src" required="true" type="java.lang.String"/>
</cc:interface>

<cc:implementation>
  <ui:include src="#{myResolver.resolve(cc.attrs.src)}">
    <cc:insertChildren/>
  </ui:inclue>
</cc:implementation>
在这种情况下,只需将
src
放在不带区域设置扩展的页面上,让方法解决这个问题:

<my:localeInclude src="myPage.xhtml/>
根据您的需要配置此
过滤器的映射。

从中可以动态包含内容(检查选中的答案)。在备份文件中,如果您有一个钩子,可以在其中适当地设置文件名,我认为这可以做到

对此不确定,您可以检查,如果您可以在EL中传递参数,即方法的部分路径,则可以在方法内部处理rest,如构造完整路径、附加当前区域设置以及检查文件是否存在

希望这有帮助

更新(回答评论):


是的。您可以查看下面的链接,这是我解决您问题的方法。这本书体积庞大,但内容完整,内容丰富,据我所知,它是完整的。有了它,你将能够从一系列以当前语言为基础的语言后缀视图中包含必要的视图

我对您的设置的假设

  • 您正在处理描述语言的语言环境,即
    Locale.ENGLISH
    格式
  • 您选择的语言存储在会话范围的bean中
  • 将国际化页面保持为以下格式:
    page.xhtml
    page\u en.xhtml
    page\u fr.xhtml
    ,等等
  • 默认语言为英语
  • 您的
    FacesServlet
    映射到
    *.xhtml
  • 我的解决方案的标准设置 会话范围bean,包含可用语言和用户选择:

    @ManagedBean
    @SessionScoped
    public class LanguageBean implements Serializable {
    
        private List<Locale> languages;//getter
        private Locale selectedLanguage;//getter + setter
    
        public LanguageBean() {
            languages = new ArrayList<Locale>();
            languages.add(Locale.ENGLISH);
            languages.add(Locale.FRENCH);
            languages.add(Locale.GERMAN);
            selectedLanguage = Locale.ENGLISH;
        }
    
        public Locale findLocale(String value) {
            for(Locale locale : languages) {
                if(locale.getLanguage().equals(new Locale(value).getLanguage())) {
                    return locale;
                }
            }
            return null;
        }
    
        public void languageChanged(ValueChangeEvent e){
            FacesContext.getCurrentInstance().getViewRoot().setLocale(selectedLanguage);
        }
    
    }
    
    主视图(
    Main.xhtml
    ),带有指向国际化页面的链接,并能够通过下拉框更改当前语言:

    <f:view locale="#{languageBean.selectedLanguage}">
        <h:head>
            <title>Links to internationalized pages</title>
        </h:head>
        <h:body>
            <h:form>
                <h:selectOneMenu converter="#{localeConverter}" value="#{languageBean.selectedLanguage}" valueChangeListener="#{languageBean.languageChanged}" onchange="submit()">
                    <f:selectItems value="#{languageBean.languages}"/>
                </h:selectOneMenu>
            </h:form>
            <br/>
            <h:link value="Show me internationalized page (single)" outcome="/international/page-single"/>
            <br/>
            <h:link value="Show me internationalized page (multiple)" outcome="/international/page-multiple"/>
        </h:body>
    </f:view>
    
    国际化页面:

    对于英语(
    page-multiple\u en.xhtml
    ):

    德语(无视图,模拟丢失的文件)

    执行重定向的托管bean:

    @ManagedBean
    @RequestScoped
    public class PageLoader {
    
        @ManagedProperty("#{languageBean}")
        private LanguageBean languageBean;//setter
    
        public PageLoader() {   }
    
        public void loadPage() throws IOException {
            Locale locale = languageBean.getSelectedLanguage();
            FacesContext context = FacesContext.getCurrentInstance();
            ExternalContext external = context.getExternalContext();
            String currentPath = context.getViewRoot().getViewId();
            String resource = currentPath.replace(".xhtml", "_" + locale.toString() + ".xhtml");
            if(external.getResource(resource) == null) {
                resource = currentPath.replace(".xhtml", "_en.xhtml");
            }
            String redirectedResource = external.getRequestContextPath() + resource.replace(".xhtml", ".jsf");
            external.redirect(redirectedResource);
        }
    
    }
    
    每次请求查看
    page multiple.xhtml
    时,都会将其重定向到带有语言后缀的视图,如果找不到目标语言的视图,则会重定向到英语视图。当前语言取自会话作用域bean,所有视图必须位于服务器上的同一文件夹中。当然,这可以根据视图参数中定义的语言重新进行。目标页面可以使用合成。默认数据可以在不带后缀的视图中提供,
    preRenderView
    listener不执行重定向

    作为说明,我的(三)个视图存储在网页的
    international/
    文件夹中

    基于所有语言的单个页面的解决方案 虽然您的问题应该在前面的设置中解决,但我想到了另一个想法,我将在下面描述

    有时,不创建支持的语言所支持的视图(+1用于重定向),而是创建一个基于当前所选语言有条件地呈现其输出的视图可能更容易

    视图(
    page single.xhtml
    ,也位于服务器上的同一文件夹中)可能如下所示:

    <ui:param name="lang" value="#{languageBean.selectedLanguage}"/>
    <ui:fragment rendered="#{lang == 'en'}">
        <h:head>
            <title>Hello - English</title>
            <meta http-equiv="Content-Type" content="text/html;charset=UTF8" />
        </h:head>
        <h:body>
            Internationalized page - English
        </h:body>
    </ui:fragment>
    <ui:fragment rendered="#{lang == 'fr'}">
        <h:head>
            <title>Hello - Français</title>
            <meta http-equiv="Content-Type" content="text/html;charset=UTF8" />
        </h:head>
        <h:body>
            Page internationalisé - Français
        </h:body>
    </ui:fragment>
    <ui:fragment rendered="#{(lang ne 'en') and (lang ne 'fr')}">
        <h:head>
            <title>Hello - Default</title>
            <meta http-equiv="Content-Type" content="text/html;charset=UTF8" />
        </h:head>
        <h:body>
            Internationalized page - Default
        </h:body>
    </ui:fragment>
    
    web.xml
    中启用解析器:

    <h:head>
        <title>Hello - English</title>
    </h:head>
    <h:body>
        Internationalized page - English
    </h:body>
    
    <h:head>
        <title>Hello - Français</title>
    </h:head>
    <h:body>
        Page internationalisé - Français
    </h:body>
    
    <context-param>
        <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
        <param-value>i18n.InternalizationResourceResolver</param-value>
    </context-param>
    
    <h:outputText value="Welcome" />
    
    <h:outputText value="Bienvenue" />
    
    不会有
    页面include.xhtml
    ,但会有每种语言的视图,如:

    page-include_en.xhtml

    <h:head>
        <title>Hello - English</title>
    </h:head>
    <h:body>
        Internationalized page - English
    </h:body>
    
    <h:head>
        <title>Hello - Français</title>
    </h:head>
    <h:body>
        Page internationalisé - Français
    </h:body>
    
    <context-param>
        <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
        <param-value>i18n.InternalizationResourceResolver</param-value>
    </context-param>
    
    <h:outputText value="Welcome" />
    
    <h:outputText value="Bienvenue" />
    


    通过这种方式,解析器将根据当前区域设置选择正确的国际化包含视图。

    在对冗长的问题进行了详细讨论之后,我了解到OP本质上是在询问如何在每个包含/组合的基础上执行该操作,例如
    ,而不是在每个请求的基础上。一个过滤器是完全不适合这种情况的。本质上,OP需要一个自定义资源解析器,或者可能需要一个自定义标记处理程序。如果OP想要按照
    ui:include
    解析,我还不清楚。这是你总结这句话的地方吗:“包括基于地区的作文内容”?我将等待OP的反馈,如果有,我将删除答案。@BalusC完全正确。或者,从托管bean获取xhtml页面名称是否可行?检测文件是否存在(并缓存答案)并不难。另外,很抱歉让问题比本质更长。。。我这样做的原因是,我喜欢为未来的访问者提供答案的上下文,以便他们能够确定他们的挑战是否相同。我输入的是谷歌搜索。@partlov是的,这确实是ui:include的解析。这是基于模板的,因此帮助内容是通过ui:define和内容确定的。但不要删除答案。。。这些评论也很有用。请根据评论编辑并改进问题。我会对这个没有回答的问题投否决票,因为它根本没有回答具体的问题。这可能很有趣,与我在我的链接中的问题的答案类似。但是我不认为包含的内容会通过jsfservlet/controller/任何处理JSF内容并生成(x)html的程序。还是我弄错了?在把这个冗长的问题煮沸之后,我明白OP本质上是在询问如何在每个包含/组合的基础上(如so
    )而不是在每个请求的基础上执行该操作。预渲染视图侦听器完全不适合这种情况。本质上,OP需要一个自定义资源解析器,或者可能需要一个自定义标记处理程序(另请参见我对partlov答案的第一条评论)。顺便说一下,
    是一个视图呈现时间标记,而不是视图构建时间标记。一个
    /
    的组件树就不会那么笨拙/低效了。@BalusC我真的不明白为什么我的解决方案不能满足OP的需要。根据修订后的问题
    <h:outputText value="Bienvenue" />