15

我有一个现有的多语言 Django 应用程序,我正在移植到 Django 1.4。I18n 支持目前基于一些丑陋的 hack,我想让它使用 Django 的内置 i18n 模块。

一个限制是我不想更改已经存在的 url。该站点已经活跃了一段时间,并且有指向它的外部链接,我不想中断或重定向。urls 方案是这样工作的:英文内容位于网站的根目录,而其他语言在域名中使用前缀:

英文网址:

/
/articles/
/suggestions/

西班牙语网址:

/es/
/es/articulos/
/es/sugerencias/

我已经得到了使用 Django 1.4 的 i18n 模块的翻译页面,但它真的,真的,真的想把所有的英文网址放在 /en/ 下。我尝试了一些不同的技巧,包括为英文版定义非国际化网址:

def build(callback):
  return callback('',
    url(_(r'^$'), home.index, name="home"),
    url(_(r'^articles/$'), content.article_list, name='article_list'),
    url(_(r'^suggestions/$'), suggestions.suggestions, name='suggestions'),
  )

urlpatterns = build(patterns)
urlpatterns += build(i18n_patterns)

这使得 url 可以正确解析,但是用于反向解析的 {% url %} 标记不起作用。

完成无前缀英文网址的最佳方法是什么?

4

3 回答 3

15

我使用solid-i18n-url 来解决类似的问题: https ://github.com/st4lk/django-solid-i18n-urls

很好的描述它是如何工作的:http: //www.lexev.org/en/2013/multilanguage-site-django-without-redirects/

于 2013-06-17T13:07:31.647 回答
12

Django 1.10 原生支持它。正如他们在文档中所说:

i18n_patterns( *urls, prefix_default_language=True )

这个函数可以在根 URLconf 中使用,Django 会自动将当前活动的语言代码添加到i18n_patterns().

将 prefix_default_language 设置为 False 会从默认语言 ( LANGUAGE_CODE) 中删除前缀。这在将翻译添加到现有站点时很有用,这样当前的 URL 就不会改变。

来源:https ://docs.djangoproject.com/en/1.10/topics/i18n/translation/#language-prefix-in-url-patterns

于 2016-06-24T17:29:54.227 回答
10

更新:阅读下面的答案,Django 1.10 原生支持它

我遇到了这个问题并以这种方式解决了:

  • i18n_patterns创建了一个不作为站点主要语言前缀的替代方案(在 中定义settings.LANGUAGE_CODE)。

  • 创建了一个仅使用 URL 前缀语言来激活当前语言的替代中间件。

我没有看到使用这种技术的任何副作用。

编码:

# coding: utf-8
"""
Cauê Thenório - cauelt(at)gmail.com

This snippet makes Django do not create URL languages prefix (i.e. /en/)
for the default language (settings.LANGUAGE_CODE).

It also provides a middleware that activates the language based only on the URL.
This middleware ignores user session data, cookie and 'Accept-Language' HTTP header.

Your urls will be like:

In your default language (english in example):

    /contact
    /news
    /articles

In another languages (portuguese in example):

    /pt/contato
    /pt/noticias
    /pt/artigos

To use it, use the 'simple_i18n_patterns' instead the 'i18n_patterns'
in your urls.py:

    from this_sinppet import simple_i18n_patterns as i18n_patterns

And use the 'SimpleLocaleMiddleware' instead the Django's 'LocaleMiddleware'
in your settings.py:

    MIDDLEWARE_CLASSES = (
    ...
        'this_snippet.SimpleLocaleMiddleware'
    ...
    )

Works on Django >=1.4
"""

import re

from django.conf import settings
from django.conf.urls import patterns
from django.core.urlresolvers import LocaleRegexURLResolver
from django.middleware.locale import LocaleMiddleware
from django.utils.translation import get_language, get_language_from_path
from django.utils import translation


class SimpleLocaleMiddleware(LocaleMiddleware):

    def process_request(self, request):

        if self.is_language_prefix_patterns_used():
            lang_code = (get_language_from_path(request.path_info) or
                         settings.LANGUAGE_CODE)

            translation.activate(lang_code)
            request.LANGUAGE_CODE = translation.get_language()


class NoPrefixLocaleRegexURLResolver(LocaleRegexURLResolver):

    @property
    def regex(self):
        language_code = get_language()

        if language_code not in self._regex_dict:
            regex_compiled = (re.compile('', re.UNICODE)
                              if language_code == settings.LANGUAGE_CODE
                              else re.compile('^%s/' % language_code, re.UNICODE))

            self._regex_dict[language_code] = regex_compiled
        return self._regex_dict[language_code]


def simple_i18n_patterns(prefix, *args):
    """
    Adds the language code prefix to every URL pattern within this
    function, when the language not is the main language.
    This may only be used in the root URLconf, not in an included URLconf.

    """
    pattern_list = patterns(prefix, *args)
    if not settings.USE_I18N:
        return pattern_list
    return [NoPrefixLocaleRegexURLResolver(pattern_list)]

上面的代码可在: https ://gist.github.com/cauethenorio/4948177

于 2013-02-13T23:17:09.440 回答