Django如何处理语言偏好

一旦你准备好了翻译,如果希望在Django中使用,那么只需要激活这些翻译即可。

在这些功能背后,Django拥有一个灵活的模型来确定在安装和使用应用程序的过程中选择使用的语言。

要设定一个安装阶段的语种偏好,请设定LANGUAGE_CODE。如果其他翻译器没有找到一个译文,Django将使用这个语种作为缺省的翻译最终尝试。

如果你只是想要用本地语言来运行Django,并且该语言的语言文件存在,只需要简单地设置 LANGUAGE_CODE 即可。

如果要让每一个使用者各自指定语言偏好,就需要使用 LocaleMiddlewareLocaleMiddleware 使得Django基于请求的数据进行语言选择,从而为每一位用户定制内容。 它为每一个用户定制内容。

使用 LocaleMiddleware 需要在 MIDDLEWARE_CLASSES 设置中增加 'django.middleware.locale.LocaleMiddleware' 。 中间件的顺序是有影响的,最好按照依照以下要求:

  • 保证它是第一批安装的中间件类。

  • 因为 LocalMiddleware 要用到session数据,所以需要放在 SessionMiddleware 之后。

  • 如果你使用CacheMiddleware,把LocaleMiddleware放在它后面。

例如, MIDDLE_CLASSES 可能会是如此:

  1. MIDDLEWARE_CLASSES = (
  2. 'django.contrib.sessions.middleware.SessionMiddleware',
  3. 'django.middleware.locale.LocaleMiddleware',
  4. 'django.middleware.common.CommonMiddleware',
  5. )

(更多关于中间件的内容,请参阅第17章)

LocaleMiddleware 按照如下算法确定用户的语言:

  • 首先,在当前用户的 session 的中查找django_language键;

  • 如未找到,它会找寻一个cookie

  • 还找不到的话,它会在 HTTP 请求头部里查找Accept-Language, 该头部是你的浏览器发送的,并且按优先顺序告诉服务器你的语言偏好。 Django会尝试头部中的每一个语种直到它发现一个可用的翻译。

  • 以上都失败了的话, 就使用全局的 LANGUAGE_CODE 设定值。

备注:

在上述每一处,语种偏好应作为字符串,以标准的语种格式出现。 例如,巴西葡萄牙语是pt-br如果一个基本语种存在而亚语种没有指定,Django将使用基本语种。 比如,如果用户指定了 de-at (澳式德语)但Django只有针对 de 的翻译,那么 de 会被选用。只有在 LANGUAGES 设置中列出的语言才能被选用。 若希望将语言限制为所提供语言中的某些(因为应用程序并不提供所有语言的表示),则将 LANGUAGES 设置为所希望提供语言的列表,例如: 例如:
  1. LANGUAGES = (
  2. ('de', _('German')),
  3. ('en', _('English')),
  4. )
上面这个例子限制了语言偏好只能是德语和英语(包括它们的子语言,如 de-chen-us )。如果自定义了 LANGUAGES ,将语言标记为翻译字符串是可以的,但是,请不要使用 django.utils.translation 中的 gettext() (决不要在settings文件中导入 django.utils.translation ,因为这个模块本身是依赖于settings,这样做会导致无限循环),而是使用一个“虚构的” gettext() 。解决方案就是使用一个“虚假的” gettext() 。以 下是一个settings文件的例子:
  1. ugettext = lambda s: s
  2. LANGUAGES = (
  3. ('de', ugettext('German')),
  4. ('en', ugettext('English')),
  5. )
这样做的话, make-messages.py 仍会寻找并标记出将要被翻译的这些字符串,但翻译不会在运行时进行,故而需要在任何使用 LANGUAGES 的代码中用“真实的” ugettext()LocaleMiddleware 只能选择那些Django已经提供了基础翻译的语言。 如果想要在应用程序中对Django中还没有基础翻译的语言提供翻译,那么必须至少先提供该语言的基本的翻译。 例如,Django使用特定的信息ID来翻译日期和时间格式,故要让系统正常工作,至少要提供这些基本的翻译。以英语的 .po 文件为基础,翻译其中的技术相关的信息,可能还包括一些使之生效的信息。技术相关的信息ID很容易被认出来:它们都是大写的。 这些信息ID的翻译与其他信息不同:你需要提供其对应的本地化内容。 例如,对于 DATETIME_FORMAT (或 DATE_FORMAT 、 TIME_FORMAT ),应该提供希望在该语言中使用的格式化字符串。 格式被模板标签now用来识别格式字符串。

一旦LocaleMiddleware决定用户的偏好,它会让这个偏好作为request.LANGUAGE_CODE对每一个HttpRequest有效。请随意在你的视图代码中读一读这个值。 以下是一个简单的例子:

  1. def hello_world(request):
  2. if request.LANGUAGE_CODE == 'de-at':
  3. return HttpResponse("You prefer to read Austrian German.")
  4. else:
  5. return HttpResponse("You prefer to read another language.")

注意,对于静态翻译(无中间件)而言,此语言在settings.LANGUAGE_CODE中,而对于动态翻译(中间件),它在request.LANGUAGE_CODE中。