web-dev-qa-db-ja.com

i18n国際化対応のためのJavaScriptでのSpring:メッセージの解決

一部のコードを国際化しようとしています。 JSPXに<spring:message>タグを使用してmessage.propertiesファイルの文字列を解決するページがあります。これは、JSPXページにあるHTMLとCSSに対しては正常に機能しますが、JavaScriptファイルがソースとして提供されており、そこの文字列を<spring:message>タグで置き換えると、そのまま出力されます。

私のJSPXは次のようにJavaScriptを提供しています。

<spring:theme code="jsFile" var="js" />
<script type="text/javascript" src="${js}" />

文字列を置き換える私が探しているJSは以下の通りです:

buildList('settings', [{
    name: '<spring:message code="proj.settings.toggle" javaScriptEscape="true" />',
    id:"setting1",
    description: '<spring:message code="proj.settings.toggle.description" javaScriptEscape="true" />',
    installed: true
}]);

そして最後に、message.propertiesは次のようなものです。

proj.settings.toggle=Click here to toggle
proj.settings.toggle.description=This toggles between on and off

だから私が思っているのは、これでうまくいくのでしょうか?いろいろなフォーラムで集めたものからは、どうやらそうなのですが、どこがいけないのかわかりません。これについてもっと良い方法はありますか?

また、これらのファイルはWEB-INFフォルダーの外にありますが、ReloadableResourceBundleMessageSourceをルートのapplicationContext.xmlに配置すると、Springタグが取得されます。

助けてくれてありがとう!

25
olan

あなたがしたいことはJSファイルのようにJSファイルを扱い、spring:messageタグを介してその内容を解決することです。
私はそれをしません。

通常、JS i18nは次の2つの方法のいずれかで実行されます。

  • JSPページから翻訳文字列の配列を書き出す
  • 変換フィルターを作成し、要求されたクライアントに事前変換されたJSファイルを提供する

クライアント側の翻訳可能な文字列の中心となる場所を1つ作成すると、どちらも最適に機能します。
あなたの文脈では、私は最初の方法をお勧めします(はるかに簡単です)。これは、プロジェクトがかなり大きく、クライアント側に翻訳可能な文字列がたくさんある場合を除きます。したがって、変更は次のようになります。

<script type="text/javascript">
  var strings = new Array();
  strings['settings.toogle'] = "<spring:message code='proj.settings.toggle' javaScriptEscape='true' />";
  strings['settings.toogle.description'] = "<spring:message code='proj.settings.toggle.description' javaScriptEscape='true' />";
</script>
<spring:theme code="jsFile" var="js" />
<script type="text/javascript" src="${js}" />

そしてあなたのJSファイルで:

buildList('settings', [{
    name: strings['settings.toggle'],
    id:"setting1",
    description: strings['settings.toggle.description'],
    installed: true
}]);

翻訳された文字列を書き出すために二重引用符を使用したことを覚えておいてください。これは、アポストロフィを含む可能性のあるフランス語またはイタリア語の単語が原因です。

編集:追加入力

そのため、JSファイルへの翻訳を提供しています。通常は、UIの一部を動的に作成する必要があるためです。一部のサードパーティコンポーネントをローカライズする必要がある場合もあります。上記の私の回答は、それらをかなりうまく処理します。
UIパーツを動的に作成する場合は、JavaScriptでHTMLタグを連結するのではなく、テンプレートを使用するのが実際的です。私はこれを書くことにしました。なぜなら、それがはるかにクリーンな(そしておそらく再利用可能な)ソリューションになるからです。
翻訳をJavaScriptに渡す代わりに、テンプレートを作成してページに配置することができます(私の例では Handlebars.js を使用しますが、他のエンジンを使用することは可能だと思います) ):

<script id="article" type="text/x-handlebars-template">
  <div class="head">
    <p>
      <span>
        <spring:message code="article.subject.header" text="Subject: " />
      </span>{{subject}}</p>
  </div>
  <div class="body">
    {{{body}}}
  </div>
</script>

クライアント側(つまりJavaScript)では、テンプレートにアクセスし(以下の例では明らかにjQueryを使用しています)、コンパイルするだけです。

var template = Handlebars.compile($("#article").html());
var html = template({subject: "It is really clean",
  body: "<p>Don't you agree?</p><p>It looks much better than usual spaghetti with JavaScript variables.</p>"
});
$("#someDOMReference").html(html);

ここで注意すべきいくつかのこと:

  • <spring:message />タグは、デフォルトでHTMLとJSの両方をエスケープします。javaScriptEscape属性を指定する必要はありません
  • <spring:message />タグのtext属性を提供することは、コメント(この要素の意味)だけでなくフォールバック(特定の言語の翻訳がない場合)としても使用できるため、意味があります。 )。 <spring:message />タグのファイルをスキャンし、プロパティファイルを自動的に生成するツールを作成することもできます
  • ハンドルバーがHTMLコンテンツをエスケープしないようにするために、トリプル{{{curly braces}}}を使用しました

基本的にはそれだけです。可能であれば、テンプレートを使用することをお勧めします。

38
Paweł Dyda

ご回答有難うございます。これはより一般的なソリューションです。

アイデアは、現在のユーザー言語を使用して、Javaリソースバンドルに登録されたメッセージの連想配列を含む、 "string.js"という名前の動的javascriptファイルを提供することです。

1)Springでメソッドを作成しますControllerリソースバンドルからすべてのリソースキーをロードし、ビュー "spring.jsp"を返します

@RequestMapping(value="strings.js")
public ModelAndView strings(HttpServletRequest request) {
    // Retrieve the locale of the User
    Locale locale = RequestContextUtils.getLocale(request);
    // Use the path to your bundle
    ResourceBundle bundle = ResourceBundle.getBundle("WEB-INF.i18n.messages", locale);  
    // Call the string.jsp view
    return new ModelAndView("strings.jsp", "keys", bundle.getKeys());
}

2)View "strings.jsp"を実装します

<%@page contentType="text/javascript" pageEncoding="UTF-8"
%><%@taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core"
%><%@taglib prefix="spring" uri="http://www.springframework.org/tags"
%>var messages = new Array();

<c:forEach var="key" items="${keys}">messages["<spring:message text='${key}' javaScriptEscape='true'/>"] = "<spring:message code='${key}' javaScriptEscape='true' />";
</c:forEach>

3)HTMLソースコードに「spring.js」をインポートします。メッセージ配列が利用可能で、適切な言語で読み込まれています。

考えられる問題:ユーザーが言語を変更した場合、ナビゲーターが「spring.js」をリロードする必要がありますが、キャッシュされます。ユーザーが言語を変更した場合(またはファイルをリロードするためのその他のトリック)には、キャッシュをクリアする必要があります。

20
Toilal

@Toilalの回答に加えて、strings.jspにヘルパー関数を追加して、翻訳配列をより効果的に使用できます。

<%@page contentType="text/javascript" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core"%>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>
var messages = new Array();

<c:forEach var="key" items="${keys}">messages["<spring:message text='${key}' javaScriptEscape='true'/>"] = "<spring:message code='${key}' javaScriptEscape='true' />";
</c:forEach>

/**
 * Tranlate a String by key, if key is not defined return the key.
 *  
 * @author Pedro Peláez <aaaaa976 at gmail dot com>, Drupal/Wordpress authors, and others
 * @param {String} key
 * @returns {String}
 */
function t(key) {
    if (messages[key]) {
        return messages[key];
    }
    return key;
}

次に、必要なときに使用します:

alert(t("menu.section.main"));
1
Pedro Pelaez

Springのmessage.propertiesをJavaScriptオブジェクトに変換し、そのオブジェクトを他のJavaScriptファイルで使用するのは非常に簡単です。変換できる node module があります

  app.name=Application name
  app.description=Application description

const messages = { app: { name: 'Application name', description: 'Application description' } };

次に、messages。{lang} .propertiesごとにmessages_ {lang} .jsファイルを作成し、テンプレートで参照する必要があります。 thymeleafテンプレートでは、次のようになります。

  <script th:src="@{'/js/messages_' + ${#locale}  + '.js'}"></script> 
  <script>
    console.log(messages.app.name, messages.app.description);
  </script>

この目的のために、簡単な gruntプラグイン を作成しました。

0
devilcius