2

trans変数をコンテキストからの値としてではなく、(コンテキストを使用せずに) html としてレンダリングすることにより、 の動作を拡張したいと思います。私の目標は、JavaScript を使用してクライアントにこれらの変数を入力できるようにすることです。

Jinja は、この種のカスタマイズを大幅に許可していないようです。または、適切なフックを見つけることができないだけです。

これが私が達成したいことです:

{% etrans name=username %}
My name is {{ name }}
{% endetrans %}

これは次のようにレンダリングする必要があります。

My name is <span id='#username'></span>

もちろん、通常の{% trans %}ディレクティブを使用して自分の html コードを に渡すこともできますtemplate.render(html_code_params)が、その場合、避けたいテンプレートとレンダリング コードでそれらを定義する必要があります。

これまでに得たもの (それほど多くはありません) は、新しいetransタグと、提供するあらゆるグッズを使用できる機能を可能InternationalizationExtensionにします。

from jinja2.ext import InternationalizationExtension
from jinja2.runtime import concat


class JavaScriptVariableExtension(InternationalizationExtension):
    tagname = 'etrans'
    tags = set([tagname])

    def _parse_block(self, parser, allow_pluralize):
        """Parse until the next block tag with a given name.

        Copy from InternationalizationExtension, as this uses hardcoded
        `name:endtrans` instead of relying on tag name
        """
        referenced = []
        buf = []
        while 1:
            if parser.stream.current.type == 'data':
                buf.append(parser.stream.current.value.replace('%', '%%'))
                next(parser.stream)
            elif parser.stream.current.type == 'variable_begin':
                next(parser.stream)
                name = parser.stream.expect('name').value
                referenced.append(name)
                buf.append('%%(%s)s' % name)
                parser.stream.expect('variable_end')
            elif parser.stream.current.type == 'block_begin':
                next(parser.stream)
                # can't use hardcoded "endtrans"
                # if parser.stream.current.test('name:endtrans'):
                if parser.stream.current.test('name:end%s' % self.tagname):
                    break
                elif parser.stream.current.test('name:pluralize'):
                    if allow_pluralize:
                        break
                    parser.fail('a translatable section can have only one '
                                'pluralize section')
                parser.fail('control structures in translatable sections are '
                            'not allowed')
            elif parser.stream.eos:
                parser.fail('unclosed translation block')
            else:
                assert False, 'internal parser error'

        return referenced, concat(buf)


i18n_extended = JavaScriptVariableExtension

より多くのメソッドをオーバーロードしてもかまいません (ただし、上記の理由はおそらくアップストリームで修正する必要があります)。

コードをステップ実行することは、非常に興味深い冒険です。しかし、私は問題を抱えており、誰かがアドバイスをくれるかどうか興味があります.

私が見る問題は、コンパイル中に関数 context.resolve() がコンパイルされたコードに焼き付けられることです。jinja2.jinja2.compiler.CodeGeneratorここで異なる処理を実際に許可することはありません (間違っている場合は修正してください)。理想的には、(変数用に) 別のノードを定義し、このノードがコンパイル中に処理される方法を処理しますが、これがどのように可能かわかりません。私は解決策としてこれに集中しすぎているかもしれないので、誰かが代替案を提供できるかもしれません。

4

1 に答える 1

1

@Garrett のコメントで示唆されているように、はるかに簡単な解決策は、変数を補間するテンプレート レンダラーに関数を渡すことです。私の場合、ターゲットのクライアント側フレームワークは Angular ですが、これは{% trans %}環境内で使用する任意の JS 変数に対しても機能します。構成要素は次のとおりです。

def text_to_javascript(string):
    # modify as needed... 
    return "<span>{{ %s }}</span>" % string

def render():
    tmpl = jinja_env.get_template(template_filename)
    return tmpl.render({'js': text_to_javascript})

そして、これは私がテンプレートファイルでそれをどのように利用するかです:

{% trans username=js('user.name') %}
  My name is {{ username }}
{% endtrans %}

Angular コントローラーでは、変数は次のようにuserバインドされます。$scope

$scope.user = {'name': 'Bugs Bunny'}
于 2016-01-23T07:23:45.480 に答える