You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django CMS的i18n_patterns中为语言Slug添加地域前缀并保留原有语言设置?

如何在Django CMS的i18n_patterns中为语言Slug添加域名相关前缀?

这个需求完全可行,而且不需要修改现有的LANGUAGES配置——我们只需要在URL解析和生成层面做一层前缀映射,让自定义前缀(比如ch-de)对应到原有的语言代码(比如de)即可,这样CMS、modeltranslation等依赖原有语言配置的模块完全不受影响。

下面是具体的实现步骤:

1. 配置域名与前缀的映射关系

首先在settings.py中添加域名到自定义前缀的映射,以及反向的前缀到语言代码的映射:

# settings.py
# 域名 -> 自定义语言前缀
DOMAIN_LANGUAGE_PREFIX = {
    "example.ch": "ch-de",
    "example.us": "us-en",
    "example.fr": "fr-fr",  # 按需添加其他域名
}
# 反向映射:自定义前缀 -> 原语言代码
PREFIX_TO_LANGUAGE = {v: k.split("-")[1] for k, v in DOMAIN_LANGUAGE_PREFIX.items()}

同时确保你已经启用了django.contrib.sites应用(Django CMS通常已经依赖它),并在后台为每个域名创建对应的Site实例。

2. 自定义语言前缀模式

我们需要替换Django默认的LocalePrefixPattern,让它根据当前站点的域名生成对应的自定义前缀。在项目的urls.py中添加以下代码:

# urls.py
from django.conf import settings
from django.conf.urls.i18n import LocalePrefixPattern
from django.urls import path, include
from django.contrib.sites.models import Site

class DomainLocalePrefixPattern(LocalePrefixPattern):
    def __init__(self):
        # 根据你的需求设置是否为默认语言添加前缀
        super().__init__(prefix_default_language=False)

    @property
    def prefix(self):
        # 获取当前站点的域名
        current_site = Site.objects.get_current()
        # 匹配对应的自定义前缀,默认用原语言代码兜底
        custom_prefix = settings.DOMAIN_LANGUAGE_PREFIX.get(current_site.domain, self.language_code)
        return f"{custom_prefix}/"

    def reverse(self, viewname, args=None, kwargs=None, current_app=None):
        # 生成URL时替换默认语言前缀为自定义前缀
        original_url = super().reverse(viewname, args, kwargs, current_app)
        current_site = Site.objects.get_current()
        custom_prefix = settings.DOMAIN_LANGUAGE_PREFIX.get(current_site.domain, self.language_code)
        return original_url.replace(f"/{self.language_code}/", f"/{custom_prefix}/", 1)

# 自定义i18n_patterns函数,使用我们的前缀模式
def domain_i18n_patterns(*args, **kwargs):
    pattern = DomainLocalePrefixPattern()
    return [path(pattern, include(args))]

3. 替换URL配置中的i18n_patterns

把原来urls.py中的i18n_patterns替换为我们自定义的domain_i18n_patterns:

# urls.py
urlpatterns = [
    # 这里放不需要国际化的URL,比如admin、static等
    path("admin/", admin.site.urls),
] + domain_i18n_patterns(
    # 这里放所有需要国际化的URL,包括Django CMS的URL
    path("", include("cms.urls")),
    # 其他应用的国际化URL也放在这里
)

4. 自定义Locale中间件解析前缀

我们需要让Django能识别自定义前缀,并映射到正确的语言代码。创建一个middleware.py文件,添加以下中间件:

# middleware.py
from django.conf import settings
from django.middleware.locale import LocaleMiddleware

class DomainLocaleMiddleware(LocaleMiddleware):
    def process_request(self, request):
        # 从URL路径中提取第一个部分(自定义前缀)
        path_parts = request.path_info.lstrip("/").split("/")
        if path_parts and path_parts[0]:
            custom_prefix = path_parts[0]
            # 检查是否是我们配置的前缀
            language_code = settings.PREFIX_TO_LANGUAGE.get(custom_prefix)
            if language_code:
                # 设置正确的语言代码
                request.LANGUAGE_CODE = language_code
                # 移除前缀,让后续URL解析正常工作
                request.path_info = "/" + "/".join(path_parts[1:])
        # 调用父类方法完成剩余的语言处理逻辑
        super().process_request(request)

然后在settings.py中替换默认的LocaleMiddleware:

# settings.py
MIDDLEWARE = [
    # 保持其他中间件顺序不变,替换LocaleMiddleware
    # ... 其他中间件 ...
    "your_project.middleware.DomainLocaleMiddleware",  # 替换 django.middleware.locale.LocaleMiddleware
    # ... 其他中间件 ...
]

5. 测试验证

完成以上配置后,你可以:

  • 访问https://example.ch/ch-de/your-page/,系统会识别语言为de,并加载对应的CMS内容
  • 调用reverse生成URL时,会自动根据当前域名生成对应的自定义前缀
  • 所有依赖LANGUAGE_CODE和LANGUAGES配置的模块(比如modeltranslation、CMS)都能正常工作,因为我们没有修改核心的语言配置

这样就完美实现了你的需求:URL使用带域名前缀的语言slug,但系统内部仍使用原语言代码,完全兼容现有内容体系。

内容的提问来源于stack exchange,提问作者benzkji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 05:07:43