Django i18n_patterns - 如何防止非活动语言的前缀添加

3 投票
2 回答
2388 浏览
提问于 2025-04-27 13:57

在我的django设置文件settings.py中,我有六种活跃的语言:

LANGUAGES = (
('de', gettext_noop('German')),
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('fr', gettext_noop('French')),
('nl', gettext_noop('Dutch')),
('pt', gettext_noop('Portuguese')),
)

当我使用国际化的路径时,这些页面运行得很好:

 http://exmaple.com/de/main
 http://exmaple.com/nl/main
 etc...

但是,如果你在谷歌上搜索我的网站,你会看到很多带有语言前缀的页面。有些是我不支持的语言,还有一些甚至根本不存在:

http://examble.com/ch/main
http://exmaple.com/zz/main
etc..

我不太明白这些页面为什么会被搜索引擎收录。它们不在我的网站地图里。不过,Django确实把它们当作页面来处理。

我想问一下,怎么修改i18n_patterns,让它只允许settings.py中定义的有效活跃语言?我希望其他的两位字符前缀都返回404错误。

暂无标签

2 个回答

1

这不是一个直接的解决方案,但可能会对你有所帮助,或者指引你找到一个好的解决办法。

  • 那自定义中间件怎么样?

这里有两个选择:

  1. 一个中间件,用来检查用户的国家,然后把他们重定向到你允许的国家(如果用户的国家不在允许的范围内,你可以重定向到一个自定义的链接,或者显示404错误)

  2. 另一个中间件,用来检查客户端的URL路径,比如你会有 /country_code/url,如果这个路径不被允许,你可以像上面那样重定向到一个自定义的链接,或者显示404错误

简单的例子:

1. 检查国家的中间件

pygeoIP 在这个例子中用来通过IP获取国家

import pygeoip

class CountryMiddleware:
    def process_request(self, request):
        allowed_countries = ['GB','ES', 'FR']  # Add your allowed countries
        gi = pygeoip.GeoIP('/usr/share/GeoIP/GeoIP.dat', pygeoip.MEMORY_CACHE)
        ip = request.META.get('REMOTE_ADDR')
        user_country = gi.country_code_by_addr(ip)

        if user_country not in allowed_countries:
            return HttpResponse... # Here you decide what to do if the url is not allowed
            # Show 404 error
            # or Redirect to other page... 

2. 检查URL的中间件

class DomainMiddleware:
    def process_request(self, request):
        """Parse out the subdomain from the request"""        
        # You especify full path or root paths
        # If you specify '/en' as allowed paths, '/en/whatever' are allowed
        ALLOWED_PATHS = ['/en','/fr', '/es']  # You add here allowed paths'
        path = request.path
        can_access = False
        for url in ALLOWED_PATHS:  # Find if the path is an allowed url 
            if url in path:  # If any allowed url is in path
                can_access=True
                break

        if not can_access:  # If user url is not allowed
            return HttpResponse... # Here you decide what to do if the url is not allowed
            # Show 404 error
            # or Redirect to other page... 

如果你决定使用这些选项中的任何一个,记得:

  • 你需要把中间件文件放在 your_project/middleware/middlewarefile.py 这个路径下
  • 你需要在你的 settings.py 文件中添加中间件:

    MIDDLEWARE_CLASSES = (

    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # etc.....
    'yourproject.middleware.domainmiddleware.DomainMiddleware',
    

    )

  • 我在这里展示的代码并不完整,也没有经过测试,它只是给你一个方向,帮助你找到一个好的解决方案

1

我知道的最好解决方案是使用 solid-i18n-urls

首先,安装这个包:

pip install solid_i18n

然后稍微修改一下设置:

# Default language, that will be used for requests without language prefix
LANGUAGE_CODE = 'en'

# supported languages
LANGUAGES = (
    ('en', 'English'),
    ('ru', 'Russian'),
)

# enable django translation
USE_I18N = True

#Add SolidLocaleMiddleware instead of LocaleMiddleware to MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
   'django.contrib.sessions.middleware.SessionMiddleware',
   'solid_i18n.middleware.SolidLocaleMiddleware',
   'django.middleware.common.CommonMiddleware',
)

用 solid_i18n_patterns 替代 i18n_patterns

from django.conf.urls import patterns, include, url
from solid_i18n.urls import solid_i18n_patterns

urlpatterns = solid_i18n_patterns('',
    url(r'^main/$', 'about.view', name='about'),
)

现在,如果你访问 example.com/en/main,它会正常工作,因为 en 在你的语言列表中有指定。但是如果你访问 example.com/ch/main,就会出现404页面找不到的错误。

撰写回答