Django模板:在带有HTML的文本块中进行翻译的最佳实践

34
在Django模板中,如果我想翻译一个包含HTML的块,应该怎么做?例如:
{% trans "Please" %}
    <a href="{% url login %}?next={{ currentUrlPath }}">
        {% trans "log in" %}
    </a>
{% trans "in order to use MyApplicationName." %}

将翻译字符串分开使我能够随时更改模板中的HTML,但我想把它放入单个翻译字符串中可能更有意义,如下所示:

{% url login as loginUrl %}
{% blocktrans %}
    Please
    <a href="{{ loginUrl }}?next={{ currentUrlPath }}">
        log in
    </a>
    in order to use MyApplicationName.
{% endblocktrans %}

但是这样翻译字符串中包含了HTML标记,例如如果我想要更改HTML(例如锚点的CSS类),那么我就必须为每种语言重新翻译该字符串。

是否有更好的替代方案?

3个回答

23

来源于文档:

{% trans %}内不允许混合使用模板变量和字符串。如果您的翻译需要带有变量(占位符)的字符串,请使用{% blocktrans %}。

然后,在blocktrans中:

要翻译模板表达式,例如访问对象属性或使用模板过滤器,您需要将表达式绑定到本地变量以在翻译块中使用。示例如下:

{% blocktrans with article.price as amount %}
That will cost $ {{ amount }}.
{% endblocktrans %}

{% blocktrans with value|filter as myvar %}
This will have {{ myvar }} inside.
{% endblocktrans %}

使用这种方式,您的翻译字符串将具有占位符。在您的情况下:

{% blocktrans with login_object.anchor as anchor %}
    Please {{ anchor|safe }}log in</a> in order to use MyApplicationName.
{% endblocktrans %}

您需要在视图函数中生成放入 anchor 中的文本。这样可以避免将其放入翻译字符串中。


这是一个很好的解决方案,谢谢你。我将使用Ned Batchelder的小技巧(仅将属性存储在变量中)。不幸的是,你说得对,使用Django内置的模板语言无法轻松创建anchor变量,所以我必须在我的视图中完成它。 - AndiDog
6
你可以这样做:{% url login as anchor_url %}{% blocktrans with anchor='<a href="'|add:anchor_url|add:'">'|safe %}请{{ anchor </a>登录}}以使用MyApplicationName。{% endblocktrans %} - Pascal Polleunus

14

将整个句子放入一个翻译字符串中不仅更合理,而且当将句子分为多个部分时,翻译者可能无法正确翻译该句子。请记住,句子的不同部分可以相互影响,包括时态、语态、性别等。更不用说其他语言与英语的不同行为方式了。例如,单词“please”在请求和要求时可能不同。

请始终在翻译字符串中使用完整的句子,以便翻译者可以在目标语言中构建正确的句子。

Mike DeSimone提出了正确的建议,我只会对其进行微调:

{% blocktrans with login_object.anchor_attr as anchor_attr %}
    Please <a {{ anchor_attr|safe }}>log in</a> in order to use MyApplicationName.
{% endblocktrans %}

这个做法让翻译字符串中的HTML标签保持平衡。如果字符串中没有起始标签,很容易被误认为是字符串出错了。


1
但在这种情况下,我们的翻译.poh文件中有'tag a'对吧?是否有一种方法可以创建一个没有任何HTML标签的.po文件?谢谢。 - sergzach
1
没有简单的方法。如果您需要在句子中标记几个单词,只有翻译人员才能告诉您这些单词在哪里,因此他们必须以某种方式标记它们。您可以使用HTML或自己编写标记。 - Ned Batchelder

10

对于任何翻译都是固定的部分,我可以提供一个方便的解决方案。

在这种情况下,当使用自定义模板标签如下所示时,您可以避免在.po文件中使用任何HTML或CSS:

@register.filter( name='safewrap' )
def safewrap( val, arg ):
    return val.format( arg )
safewrap.is_safe = True

...

{% blocktrans with sum2="<a href='mysite.com/offer'>{0}</a>"|safewrap:sum %}
    It costs {{sum2}} dollars.
{% endblocktrans %}

所以,在你的.po文件中,你有:

It costs %(sum2)s dollars.

但这是一个难题——对于需要翻译的部分片段该怎么处理(就像你的情况一样)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接