Django - 如何根据语言环境重写默认日期格式?

5
我们在 Speedy Net 中使用 Django 1.11。我想要覆盖默认的 DATE_FORMATMONTH_DAY_FORMAT 的英文值,但在希伯来语中保留默认值(或重新定义)。这样它们就不会相同,也不会与 Django 的默认值相同。在英文中,我们将有:
DATE_FORMAT = 'j F Y'
MONTH_DAY_FORMAT = 'j F'
YEAR_FORMAT = 'Y'

并用希伯来语:

DATE_FORMAT = 'j בF Y'
MONTH_DAY_FORMAT = 'j בF'

(而YEAR_FORMAT将保持不变)。

模板目前看起来像这样:

{% if can_view_profile and user.date_of_birth %}
    {% if can_view_dob_day_month or can_view_dob_year %}
        <tr>
            <th>{% if can_view_dob_day_month %}{% trans 'Birth Date' %}{% elif can_view_dob_year %}{% trans 'Birth Year' %}{% endif %}</th>
            <td>
                {% if can_view_dob_day_month and can_view_dob_year %}
                    {{ user.date_of_birth|date:settings.DATE_FORMAT }}
                {% elif can_view_dob_day_month %}
                    {{ user.date_of_birth|date:settings.MONTH_DAY_FORMAT }}
                {% elif can_view_dob_year %}
                    {{ user.date_of_birth|date:settings.YEAR_FORMAT }}
                {% endif %}
            </td>
        </tr>
    {% endif %}
{% endif %}

我希望它能在每种语言中以这些格式显示日期。我该怎么做?
更新:我发现可以在this link中按语言环境覆盖格式,并添加了enhe语言环境的格式,但它们不起作用。我添加了调试代码,您可以在here中看到,但它不起作用。它显示的日期是Jan. 1, 2018,而不是我期望的。
我也不知道在模板中是否应该在DATE_FORMAT前加上settings.,但如果没有它,它不会显示任何内容。
我还希望在特定语言环境未定义某个格式或我根本没有定义的语言环境中保留默认设置。
3个回答

5
您覆盖本地环境的方式看起来很好。问题在于您在模板中指定格式的方式:
{{ user.date_of_birth|date:settings.DATE_FORMAT }}

我不确定settings的来源,但无论如何,那样做是不可行的——它将使用在您的主设置文件中定义的格式(如果正在传递给模板上下文),而这将不会本地化。相反,您需要传递一个描述您想要使用的格式的字符串。

{{ user.date_of_birth|date:"DATE_FORMAT" }}

这将导致date过滤器去查找当前语言环境中适当的格式,并应用它。需要在此处传递一个字符串的事实在文档中通过示例暗示,但没有明确说明。


谢谢你的回答,它有效。我不知道Django期望一个字符串。但是如果在特定语言环境中没有定义默认设置,我该如何定义呢?例如YEAR_FORMAT或任何其他格式。 - Uri
你定义的 settings.py 应该成为默认设置,你可以覆盖 formats.py 中的设置。 - Tarun Lalwani
@TarunLalwani 这在我的Django 1.11上不是真的。我在设置中定义的内容并没有被用作默认值。 - Uri
据我所知,您只能选择DATE_FORMATDATETIME_FORMATSHORT_DATE_FORMATSHORT_DATETIME_FORMAT中的一个 - 我认为不可能指定自己的格式,除非你硬编码实际格式(这样就不会随着地区而改变)。如果您需要更多的灵活性,可以编写自己的模板标签来完成此操作。 - solarissmoke
@solarissmoke 好的,我接受这个回答作为被悬赏的采纳答案,尽管它没有解决我的默认问题。 - Uri

1

定义默认日期格式

如果特定语言环境未定义这些格式之一,或者对于我根本没有定义的语言环境,我也希望保留默认设置。

据我所知,您只能选择 DATE_FORMATDATETIME_FORMATSHORT_DATE_FORMATSHORT_DATETIME_FORMAT 中的一个,除非您硬编码实际格式(这样将不随语言环境而变化)。- solarissmoke

您可以修补 django.utils.formats.FORMAT_SETTINGS,使其查找您的 Django 设置:

from django.conf import settings as django_settings
from django.utils import formats

formats.FORMAT_SETTINGS = formats.FORMAT_SETTINGS.union(django_settings.FORMAT_SETTINGS)

在你的 DJANGO_SETTINGS_MODULE 中(或者,在 Speedy Net 的情况下为 speedy/core/settings/base.py):
YEAR_FORMAT = 'Y'

FORMAT_SETTINGS = (
    'YEAR_FORMAT',
)

关于打补丁

只需要运行一次,就可以应用到所有视图(模板)中,因此我会将其放在 speedy/core/patches/locale_patches.pydef patch 中,并调用 locale_patches.patch(),不需要在 wsgi.py 中进行操作。

但问题是,由于测试失败,我不得不打14个文件的补丁,还必须打补丁来修复测试。你可以看到我的提交 https://github.com/speedy-net/speedy-net/commit/f5dc4896c136a816ab9fe0dc360d3fd59d0a5f33。有没有可能在不打这么多文件的补丁的情况下应用它?

我找到了另一种方法:https://docs.djangoproject.com/en/2.2/ref/applications/#configuring-applications

在`speedy/core/apps.py`中,创建一个名为`AppConfig`的子类:
from django.apps import AppConfig

from .patches import locale_patches


class SpeedyCoreConfig(AppConfig):
    name = 'speedy.core'

    def ready(self):
        locale_patches.patch()

speedy/core/settings/base.py 中的 INSTALLED_APPS 中添加该子类的点路径:
INSTALLED_APPS = [
    ...

    'speedy.core.apps.SpeedyCoreConfig',  # Add this line
    'speedy.core.base',
    ...
]

感谢您的建议。我决定在speedy.core.base的配置中添加def ready,而不是添加另一个新应用程序。我还使用了default_app_config,尽管我知道这是Django开发人员不鼓励的。您可以在https://github.com/speedy-net/speedy-net/commit/c1549acf17fa3d1742563e2c2248682ff43fb502 上看到我的提交。我接受了这个答案。 - Uri

0

我已经查看了你的项目,有一些问题需要注意:

  • 你使用了locale文件夹来覆盖区域设置而不是格式。这是不正确的,你应该只使用格式。

  • 现在的格式不允许在语言之间共享,因此你不能有默认值。

所以,如果你希望所有设置都来自于你的设置模块,那么你需要在formats.py中使用它们。

speedy/core/locales/he/formats.py

from django.utils import formats
from django.conf import settings

local_variables = locals()
for format in formats.FORMAT_SETTINGS:
    if hasattr(settings, format):
        local_variables[format] = getattr(settings, format)

DATE_FORMAT = 'j בF Y'
MONTH_DAY_FORMAT = 'j בF'
YEAR_FORMAT = 'Y'


DATE_INPUT_FORMATS = [
    '%Y-%m-%d',                           # '2006-10-25',
]

这种方法是先使用在设置中定义的所有格式,然后覆盖任何特定于语言的内容


Speedy Net使用类似的formats.py文件,例如在https://github.com/speedy-net/speedy-net/blob/staging/speedy/core/locale/en/formats.py - Uri
是的,但如果在您的语言环境中找不到它,则仍将从django.conf.locale中定义的默认区域设置中获取值。 - Tarun Lalwani
你可以看到,例如 FIRST_DAY_OF_WEEK 在 https://github.com/django/django/blob/stable/1.11.x/django/conf/locale/he/formats.py 中没有被定义,它的值来自于默认值(如果我没记错的话,是在 https://github.com/django/django/blob/stable/1.11.x/django/conf/global_settings.py 中)。我想用自己的默认格式扩展这些设置。我该怎么做? - Uri
无论如何,您都需要定义它们,可以在每个本地化文件中单独定义,也可以按照我在答案中添加的方式进行定义。如果您单独定义它们,则它们不再是默认值。 - Tarun Lalwani
默认设置应包括一个我没有定义的区域设置。例如,如果我正在使用“de”区域设置,则需要从我的默认设置中获取“YEAR_FORMAT”,并从Django区域设置中获取其他格式,或者如果我在那里定义了它们,则从我的默认设置中获取。 - Uri
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接