7

これらの選択肢を持つ ChoiceField が必要です。

choices = [(1, '1 thing'),
           (2, '2 things'),
           (3, '3 things'),
           ...]

そして翻訳してもらいたいです。

これは動作しません:

choices = [(i, ungettext_lazy('%s thing', '%s things', i) % i) for i in range(1,4)]

遅延オブジェクトが補間されるとすぐに、Unicode オブジェクトになるためです。ChoiceField.choices は起動時に評価されるため、その選択肢は Django の起動時にアクティブな言語になります。

を使用することもできますugettext_lazy('%s things' % i)が、それでは数字ごとに翻訳が必要になり、ばかげています。これを行う正しい方法は何ですか?

4

3 に答える 3

5

Django ドキュメントのTranslationWorking with lazy translation objectsに、ここであなたの懸念に対処しているように見える発言があります。

モデルとユーティリティ関数で文字列をマークするために と を使用することは、一般的な操作ugettext_lazy()です。ungettext_lazy()これらのオブジェクトをコードの他の場所で使用している場合は、誤って文字列に変換しないように注意する必要があります。これは、(正しいロケールが有効になるように) できるだけ遅く変換する必要があるためです。これには、次に説明するヘルパー関数を使用する必要があります。

それから彼らは提示しますが、これは現在モジュールのドキュメントdjango.utils.functional.lazy(func, *resultclasses)でカバーされていません。ただし、ソースコードによると、「任意の callable を遅延評価された callable に変換します。関数はアクセスごとに評価されます。」django.utils.functionaldjango.utils.functional.py

コードを組み込むために遅延翻訳での遅延の他の使用からの例を変更すると、次のコードが機能する可能性があります。

from django.utils import six  # Python 3 compatibility
from django.utils.functional import lazy
from django.utils.safestring import mark_safe

choices = [
    (i, lazy(
        mark_safe(ungettext_lazy('%s thing', '%s things', i) % i),
        six.text_type
    )# lazy()
    for i in range(1,4)
]

また、django.utils.functionalモジュールのドキュメントには関数デコレータについて言及されていますallow_lazy(func, *resultclasses)。これにより、遅延文字列を引数として受け取る独自の関数を作成できます。「関数を変更して、最初の引数として遅延変換を使用して呼び出された場合、文字列に変換する必要があるまで関数の評価を遅らせます。」 lazy(func, *resultclasses)デコレーターではなく、callable を変更します。

注意: Django でこのコードを試したことはありません。ドキュメントで見つけたものを伝えているだけです。うまくいけば、それはあなたが使用できる何かを指し示すでしょう.

于 2012-12-29T05:38:37.773 に答える
2

この質問に遭遇した人のために。残念ながら、@Jim DeLaHunt の回答は完全には機能しません。

重要な違いは次のとおりです。

  1. ワープする必要がlazyあるのは、別の遅延翻訳オブジェクトではなく、テキスト値を返す関数です。そうし<django.utils.functional.__proxy__ at ...>ないと、実際のテキストの代わりに奇妙なものが表示される可能性があります (IIRC Django は、遅延オブジェクトのチェーンを深く掘り下げることはありません) )。したがって、ungettextではなくを使用してくださいungettext_lazy

  2. ラップされた関数の実行時にのみ、文字列補間を行いたい。あなたが書いlazy(f("%d" % 42))た場合、補間が早すぎます - この場合、Python は熱心に評価します。変数のスコープについても忘れないでください。ラップされた関数から反復子を参照することはできません。

ここでlambdaは、数値引数を受け取り、補間を行う a を使用しました。内部のコードlambdaは、遅延オブジェクトが評価されるとき、つまり選択がレンダリングされるときにのみ実行されます。

したがって、作業コードは次のとおりです。

choices = [
    (
        (i, lazy(
            lambda cnt: ungettext(u"%(count)d thing",
                                  u"%(count)d things", cnt)
                        % {"count": cnt},
            six.text_type
        )(i))
    )
    for i in [1, 2, 3]
]

これにより、意図したのと同じ効果が正しく得られます

choices = [
    (1, _("1 thing")),
    (2, _("2 things")),
    (3, _("3 things")),
]

ただし、翻訳データベースには、複数のエントリではなく、このエントリが 1 つだけ存在します。

于 2015-08-06T11:58:52.190 に答える
0
于 2012-12-29T04:51:02.560 に答える