9

私のアプリでは、ユーザーはロケール (ページ上のテキストのレンダリングに使用される言語) を切り替えることができるはずです。多くのチュートリアルで FacesContext.getCurrentInstance().getViewRoot().setLocale() が使用されています。例: http://www.mkyong.com/jsf2/jsf-2-internationalization-example/ . しかし、それは JSF 2.0 では機能しません (1.2 では機能しました)。言語が切り替わることはありません。エラーも何もありません。同じコードが JSF 1.2 で正常に機能しました。

正確で決定的なアプローチは何ですか?解決策をまとめましたが、これが正しいかどうかはわかりません。これはうまくいきます。ユーザーが英語またはフランス語をクリックすると、言語が切り替わります。アイデアを提供するためのコード スニペットを次に示します。

@ManagedBean(name = "switcher")
@SessionScoped
public class LanguageSwitcher {
    Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
    public String switchLocale(String lang) {
        locale = new Locale(lang);

        return FacesContext.getCurrentInstance().getViewRoot().getViewId() +
            "?faces-redirect=true";
    }
    //getLocale() etc. omitted for brevity
}

XHTML:

<f:view locale="#{switcher.locale}">
    <h:outputText value="#{msg.greeting}" />
    <h:commandLink value="English" action="#{switcher.switchLocale('en')}" />
    <h:commandLink value="French" action="#{switcher.switchLocale('fr')}" />
</f:view>

詳細情報を提供するために、ここに設定ファイルがあります。

<application>
    <locale-config>
        <supported-locale>en</supported-locale>
        <supported-locale>fr</supported-locale>
    </locale-config>
    <resource-bundle>
        <base-name>com.resources.Messages</base-name>
        <var>msg</var>
    </resource-bundle>
</application>

繰り返しますが、これは機能します。ただし、API を呼び出して JSF 自体のロケールを変更したことはありません。これは私にいくらか不気味な気持ちを与えます。これはユーザーのロケールを変更する正しい方法ですか?

4

3 に答える 3

9

OK、私自身の質問に答える危険を冒して、私が見つけたさまざまなアプローチをすべて要約したいと思います。

基本的なアプローチは、私がすでに行っていることです。つまり、ユーザーのロケールを返すセッション スコープにマネージド Bean を配置します。このロケールは、を使用するすべての XHTML で使用する必要があります<f:view locale="...">。BalusC の投稿からこのテクニックを学んだので、そこに感謝します。

さて、問題は f:view 要素の使用です。これはすべてのページで繰り返される必要があり、誤って省略された場合、潜在的な欠陥の原因となります。この問題を解決する方法をいくつか見つけました。

アプローチ #1: Facelet テンプレートを作成し、そこに f:view 要素を追加します。個々のテンプレート ユーザー ページは、この要素の追加について心配する必要はありません。

アプローチ 2 では、フェーズ リスナーを使用します。@meriton が解決策をここに投稿しました。有難うございます。

アプローチ 3 では、MultiViewHandler を拡張し、calculateLocale() メソッドからユーザーのロケールを返すカスタム ビュー ハンドラーを使用します。これについては、本 Beginning JSF 2 APIs and JBoss Seam By: Kent Ka Iok Tong で説明されています。これは、本からわずかに変更された例です。

public class MyViewHandler extends MultiViewHandler {
    public Locale calculateLocale(FacesContext context) {
        HttpSession session = (HttpSession) context.getExternalContext()
            .getSession(false);
        if (session != null) {
            //Return the locale saved by the managed bean earlier
            Locale locale = (Locale) session.getAttribute("locale");
            if (locale != null) {
                return locale;
            }
        }
       return super.calculateLocale(context);
    }
}

次に、faces config に登録します。

<application>
    <view-handler>com.package.MyViewHandler</view-handler>
<!-- Other stuff ... -->
</application>

これは、フェーズ リスナーよりもいくらか洗練されています。残念ながら、MultiViewHandler は com.sun.faces.application.view パッケージの内部非 API クラスです。そのためには、今後のリスクが伴います。

アプローチ #2 または #3 のいずれでも、ページに f:view 要素は必要ありません。

于 2012-08-23T14:58:45.650 に答える
2

javax.faces.application.ViewHandlerWrappercalculateLocale() メソッドからユーザーのロケールを拡張して返すカスタム ビュー ハンドラーを使用できます。

これは、あなたの提案で言及されている本のBeginning JSF 2 APIsに何が記載されていてもMultiViewHandler、プロプライエタリなSUNパッケージから拡張するよりも間違いなく優れています。それとは別に、元のアプローチはまったく問題ありません。com.sun.faces.application.view

public class MyViewHandler extends ViewHandlerWrapper {

  public Locale calculateLocale(FacesContext context) {
    HttpSession session = (HttpSession) context.getExternalContext()
        .getSession(false);
    if (session != null) {
      //Return the locale saved by the managed bean earlier
      Locale locale = (Locale) session.getAttribute("locale");
      if (locale != null) {
        return locale;
      }
    }
    return super.calculateLocale(context);
  }
}

次に、faces config に登録します。

    <application>
      <view-handler>com.package.MyViewHandler</view-handler>
      <!-- Other stuff ... -->
    </application>
于 2015-09-19T10:38:10.907 に答える