Django LocaleMiddleware无法切换至指定中文语言的问题求助
我之前在做独立打包的Django应用时也碰到过一模一样的问题——LocaleMiddleware死活识别不了自定义的cn语言包,调试后发现确实是check_for_language只认Django自带的locale路径,而应用自己的locale目录没被加入LOCALE_PATHS。下面分享几个我亲测好用的方案,完全不用硬编码路径:
方案1:动态收集所有已安装应用的Locale路径(全局配置)
直接在项目的settings.py里用Django的apps模块自动扫描所有已安装应用的locale目录,把存在的路径都加入LOCALE_PATHS:
from django.apps import apps import os # 动态收集所有带locale目录的应用路径 LOCALE_PATHS = [ os.path.join(app_config.path, "locale") for app_config in apps.get_app_configs() if os.path.exists(os.path.join(app_config.path, "locale")) ] # 可选:保留项目根目录的locale路径(如果有的话) PROJECT_LOCALE = os.path.join(os.path.dirname(os.path.dirname(__file__)), "locale") if PROJECT_LOCALE not in LOCALE_PATHS: LOCALE_PATHS.append(PROJECT_LOCALE)
这个方案的好处是一劳永逸,不管你装了多少个独立应用,只要应用里有locale目录,就会被自动识别,完全不用管应用部署在什么路径下。
方案2:让应用自己注册Locale路径(模块化推荐)
如果希望每个应用自己管理locale路径,不用修改项目的settings.py,可以在应用的apps.py里通过AppConfig的ready()方法动态添加:
from django.apps import AppConfig import os from django.conf import settings class YourAppConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "your_app_name" def ready(self): # 获取当前应用的locale目录路径 app_locale_path = os.path.join(self.path, "locale") # 如果路径不在LOCALE_PATHS里,就添加进去 if os.path.exists(app_locale_path) and app_locale_path not in settings.LOCALE_PATHS: settings.LOCALE_PATHS += (app_locale_path,)
这样应用启动时会自动把自己的locale路径注册到全局配置里,非常适合独立打包、需要复用的应用场景。
方案3:重写check_for_language函数(进阶玩法)
如果不想修改LOCALE_PATHS,可以直接重写django.utils.translation.trans_real.check_for_language函数,让它不仅检查默认路径,还检查所有应用的locale目录:
首先创建一个自定义中间件yourapp/middleware.py:
from django.middleware.locale import LocaleMiddleware from django.utils.translation.trans_real import check_for_language as original_check from django.apps import apps import os def custom_check_for_language(lang_code): # 先调用原函数检查Django自带语言 if original_check(lang_code): return True # 遍历所有应用,检查是否有对应语言的locale目录 for app_config in apps.get_app_configs(): locale_dir = os.path.join(app_config.path, "locale") lang_dir = os.path.join(locale_dir, lang_code) if os.path.exists(lang_dir) and os.listdir(lang_dir): return True return False class CustomLocaleMiddleware(LocaleMiddleware): def process_request(self, request): # 替换原有的check_for_language函数 from django.utils.translation import trans_real trans_real.check_for_language = custom_check_for_language super().process_request(request)
然后在项目的settings.py里替换默认的LocaleMiddleware:
MIDDLEWARE = [ # ... 其他中间件 ... # 'django.middleware.locale.LocaleMiddleware', 注释掉原来的 'your_app_name.middleware.CustomLocaleMiddleware', # 换成自定义的 ]
这个方案适合需要更精细控制语言检测逻辑的场景,但相对前两个方案稍复杂一些。
我个人最推荐方案1或方案2,它们既解决了路径多变的问题,又保持了代码的简洁性和可维护性。
内容的提问来源于stack exchange,提问作者dgeorgiev

