Django 模板:获取另一种语言的当前 URL
Posted
技术标签:
【中文标题】Django 模板:获取另一种语言的当前 URL【英文标题】:Django templates: Get current URL in another language 【发布时间】:2012-07-11 08:30:23 【问题描述】:我正在使用 i18n_patterns
在 Django 应用程序中创建语言前缀。
我的网址如下所示:
/de/contact/
/fr/contact/
/it/contact/
在我的基本模板中,我循环遍历所有可用的语言以显示语言切换链接。
% get_available_languages as languages %
<nav id="language_chooser">
<ul>
% for lang_code, lang_name in languages %
% language lang_code %
<li><a href="% url 'home' %" title=" lang_name "> lang_code </a></li
% endlanguage %
% endfor %
</ul>
</nav>
在这种情况下,我正在反转“主页”URL。有没有办法获取当前页面的翻译 URL?
如果我在“联系人”页面的德语版本,我希望“fr”链接指向“联系人”页面的法语版本,而不是“主页”页面。
【问题讨论】:
【参考方案1】:我没有使用语言前缀,而是使用翻译后的网址。但是,这个模板标签也应该可以帮助你:
# This Python file uses the following encoding: utf-8
from django import template
from django.core.urlresolvers import reverse # from django.urls for Django >= 2.0
from django.core.urlresolvers import resolve # from django.urls for Django >= 2.0
from django.utils import translation
register = template.Library()
class TranslatedURL(template.Node):
def __init__(self, language):
self.language = language
def render(self, context):
view = resolve(context['request'].path)
request_language = translation.get_language()
translation.activate(self.language)
url = reverse(view.url_name, args=view.args, kwargs=view.kwargs)
translation.activate(request_language)
return url
@register.tag(name='translate_url')
def do_translate_url(parser, token):
language = token.split_contents()[1]
return TranslatedURL(language)
它以所需语言返回当前 url。像这样使用它:% translate_url de %
欢迎提出改进意见和建议。
【讨论】:
谢谢,您的解决方案对我有用,但几乎没有改进。我在 forloop ...@register.simple_tag(name='translate_url') def do_translate_url(language): return TranslatedURL(language)
... 然后在模板中使用简单标签 ... % get_language_info_list for LANGUAGES as languages % % for language in languages % <a href="% translate_url language.code %"> language.name_local </a> % endfor %
如果 kwarg 依赖于语言,这似乎会失败 - 例如,在 url 中使用依赖于语言的 slug
参数,这会为所有语言呈现相同的 slug。
@Flash 您是否找到了一种使用 slug 参数的方法?我也有这个问题:(
@LuisPalacios 作为临时黑客,在translation.activate
之后,我正在使用view.kwargs['slug'] = MyModel.objects.get(pk=view.kwargs['id']).slug
手动修复蛞蝓 - 我相信有更好的方法。
@LuisPalacios,我已经为 translated url patterns 的项目开发了我的解决方案 - 它有效。无论如何,当 URL 与模型相关时,我们可以在模型上定义一个方法,以所需语言返回 URL。【参考方案2】:
这个 sn-p 应该这样做:
https://djangosnippets.org/snippets/2875/
一旦您拥有added that as a custom template tag,您就可以执行以下操作:
<a href='% change_lang 'fr' %'>View this page in French</a>
【讨论】:
此解决方案的缺点是:与django.conf.urls.i18n.set_language
相比,它不会保留所选语言,因此您应该自己完成,例如,通过添加额外的中间件或特殊的将处理它的视图。【参考方案3】:
我认为值得一提的是,有一个内置函数叫做translate_url
。
from django.urls import translate_url
translate_url(url, lang_code)
【讨论】:
这充其量是一条评论。【参考方案4】:使用django_hreflang:
% load hreflang %
<ul>
<li><a href="% translate_url 'en' %" hreflang="en">English</a></li>
<li><a href="% translate_url 'ru' %" hreflang="ru">Russian</a></li>
</ul>
【讨论】:
【参考方案5】:我认为你给问题增加了不必要的复杂性。您正在寻找的是一个简单的语言选择器。 Django 提供了开箱即用的功能,它总是重定向到当前页面(以另一种语言)。
这在此处记录:
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#django.conf.urls.i18n.set_language
唯一的一点是set_language
视图需要一个POST参数,所以你需要使用<form>
元素;您不能使用简单的<a href="...">
链接。但是,有时您希望语言选择器看起来像一个链接,而不是带有选择小部件的表单。我的建议是使用一个表单,但它的样式看起来像一个链接。
您的模板可能如下所示:
<nav id="language_chooser">
<ul>
% get_language_info_list for LANGUAGES as languages %
% for language in languages %
<form action="% url 'set_language' %" method="post">
% csrf_token %
<input name="next" type="hidden" value=" redirect_to " />
<input name="language" type="hidden" value=" language.code " />
<button type="submit"> language.local_name "</button>
</form>
% endfor %
</ul>
</nav>
然后您使用 CSS 设置表单样式并提交按钮,使其看起来像普通链接:
ul#language_chooser form
display: inline;
margin: 0;
padding: 0;
ul#language_chooser button
margin: 0;
padding: 0;
border: none;
background: none;
color: blue; /* whatever you like */
text-decoration: underline; /* if you like */
【讨论】:
language.local_name
应该是 language.name_local
。
另外,该解决方案与语言前缀并不能很好地配合使用。我们决定不只使用会话或 cookie 来设置和记住语言,而是使用唯一的 URL。因此,这种方法对我来说真的不起作用......(但无论如何感谢您的贡献。)
我也有类似的问题,用表格来解决也没有用。我想使用“alternate language meta tags”向客户端(或机器人)指示“此 url 是当前页面的 x 语言版本”。对此有何建议?
你也可以使用get参数。我有时会这样使用它:<form action="/search/?q=" method="get"><button><img src="/static/images/search_20x20.png" alt="Search Symbol"></button></form>
【参考方案6】:
我使用来自docs的标准语言形式
<form action="% url 'set_language' %" method="post" id="lang_changer">
% csrf_token %
<input name="next" type="hidden" value=" redirect_to " />
<select name="language">
% get_language_info_list for LANGUAGES as languages %
% for language in languages %
<option value=" language.code "% if language.code == LANGUAGE_CODE % selected="selected"% endif %>
language.name_local ( language.code )
</option>
% endfor %
</select>
<input type="submit" value="Go" />
</form>
和 jquery 修复以使用 url lang 前缀:
$('#lang_changer input[name="next"]').attr('value', '/'+window.location.pathname.substring(4));
页面准备就绪时运行。
【讨论】:
在 Django 3.2 中删除 lang 前缀对我有用。我不得不在window.location.pathname
上使用这个函数***.com/a/14482123/329395,因为我有这样的前缀:es-mx
【参考方案7】:
一个简单的解决方案是使用带有模板标签的Django's translate_url
function:
# utils/templatetags/utils.py
from django.template import Library
from django.urls import translate_url as django_translate_url
register = Library()
@register.simple_tag(takes_context=True)
def translate_url(context, lang_code):
path = context.get('request').get_full_path()
return django_translate_url(path, lang_code)
然后在您的 html 中以这种方式使用它来选择语言:
% load i18n utils %
% get_available_languages as languages %
<ul>
% for lang_code, lang_name in languages %
<li><a href="% translate_url lang_code %"> lang_code </a></li>
% endfor %
</ul>
对于hreflangs:
% get_available_languages as languages %
% for lang_code, lang_name in languages %
<link rel="alternate" hreflang="lang_code" href="% translate_url lang_code %" />
% endfor %
希望这会有所帮助。
【讨论】:
【参考方案8】:对于 Django 2.0(基于 Philipp Zedler 的 answer)
自定义模板:
from django import template
from django.urls import reverse
from django.urls import resolve
from django.utils import translation
register = template.Library()
@register.simple_tag(takes_context=True)
def translate_url(context, language):
view = resolve(context['request'].path)
request_language = translation.get_language()
translation.activate(language)
url = reverse(view.app_name+":"+view.url_name, args=view.args, kwargs=view.kwargs, )
translation.activate(request_language)
return url
在模板中:
% get_available_languages as LANGUAGES %
<ul>
% for lang_code, lang_name in LANGUAGES %
<li><a href="% translate_url lang_code %"> lang_name </a></li>
% endfor %
</ul>
【讨论】:
【参考方案9】:自定义模板标签的问题是该函数根据当前 url 计算其他语言等效项,因为我使用的是 modeltranslation package 然后url 之间的 slug 总是相同的。例如:
example.com/en/article/english-slug
example.com/es/articulo/english-slug
为了解决这个问题,我采取了一种稍微不同的方法,在视图级别计算备用 url 并让它们在模板上下文中可用。
为此工作:
1- 使用以下辅助函数创建一个 utils.py 文件
from django.utils.translation import activate, get_language
from django.conf import settings
def getAlternateUrls(object):
#iterate through all translated languages and get its url for alt lang meta tag
cur_language = get_language()
altUrls =
for language in settings.LANGUAGES:
try:
code = language[0]
activate(code)
url = object.get_absolute_url()
altUrls[code] = url
finally:
activate(cur_language)
return altUrls;
2- 让您的模型定义反向 url:get_absolute_url
3- 在你的 views.py
中添加一个包含 urls 字典的上下文变量from .utils import getAlternateUrls
...
def MyView(DetailView):
def get_context_data(self, **kwargs):
context['alt_urls'] = getAlternateUrls(self.object)
4- 在模板的头部生成备用 urls 元标记
<!-- alternate lang -->
% for key, value in alt_urls.items %
<link rel="alternate" hreflang=" key " href="http:// request.get_host value">
% endfor %
% endblock %
在 Django 1.8 中测试
【讨论】:
【参考方案10】:我试图让它尽可能简单 - 将动态 reverse()
与任意数量的 kwargs
一起使用,以便语言切换(或任何其他类似的东西)将重定向到当前视图。
在 templatetags 目录文件中添加了简单的模板标签(例如,templatetags/helpers.py
):
from django.core.urlresolvers import reverse
register = template.Library()
@register.simple_tag
def get_url_with_kwargs(request):
url_name = ''.join([
request.resolver_match.app_name,
':',
request.resolver_match.url_name,
])
url_kwargs = request.resolver_match.kwargs
return reverse(url_name, None, None, url_kwargs)
可以在这样的语言切换模板中使用:
% load helpers %
% get_available_languages as available_languages %
% get_language_info_list for available_languages as language_info_list %
% for language in language_info_list %
% language language.code %
% get_url_with_kwargs request as url_with_kwargs %
<a href=" url_with_kwargs "> language.code </a>
% endlanguage %
% endfor %
非常适合我。
【讨论】:
【参考方案11】:我宁愿评论接受的答案,但不能,所以我发布我自己的。 我正在使用基于以下内容的非常相似的解决方案: https://djangosnippets.org/snippets/2875/
存在resolve
和reverse
方法都可能崩溃的问题:
resolve
会引发 Resolver404 异常,尤其是当您已经显示 404 页面时(反而会导致 500 错误,非常烦人且难以检测,尤其是在 DEBUG=True 不显示真正的 404 时)
reverse
可能会在您尝试使用不同语言但实际上没有翻译的页面时崩溃。
也许反向更多地取决于您使用哪种翻译方法或其他什么,但解决 404 页面内的崩溃非常明显。
如果出现异常,您可能希望返回相同的 url 或返回索引页面的 url,而不是在模板中引发异常。代码可能如下所示:
from django.core.urlresolvers import resolve, reverse
from django.utils.translation import activate, get_language
@register.simple_tag(takes_context=True, name="change_lang")
def change_lang(context, lang=None, *args, **kwargs):
url = context['request'].path
cur_language = get_language()
try:
url_parts = resolve(url)
activate(lang)
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
except:
url = reverse("index") #or whatever page you want to link to
# or just pass if you want to return same url
finally:
activate(cur_language)
return "%s" % url
【讨论】:
【参考方案12】:在 Django 2.2 中为我工作
创建自定义模板标签
from django import template
from django.urls import translate_url
register = template.Library()
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path
return translate_url(path, lang)
在模板中
% load change_lang %
<a href="% change_lang 'en' %">English</a>
<a href="% change_lang 'es' %">Español</a>
【讨论】:
【参考方案13】:Django 3 解决方案,基于Jonhatan's answer:
文件:App/templatetags.py
或 App/templatetags/change_lang.py
:
from django.template.defaultfilters import register
from django.urls import translate_url
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path
return translate_url(path, lang)
模板:
% load trans change_lang %
% trans 'View page in other languages:' %
<a href="% change_lang 'en' %">English</a>
| <a href="% change_lang 'de' %">Deutsch</a>
【讨论】:
以上是关于Django 模板:获取另一种语言的当前 URL的主要内容,如果未能解决你的问题,请参考以下文章