如何在我的 jinja 过滤器中使用 babel 启用时区?
我想根据 babel 语言环境使用时区。我怎样才能实现这个目标?我的具体情况是目标以人性化和本地化的方式显示文章的日期和时间,例如:
昨天
13:21
或者如果设置了瑞典语语言参数则会显示
伊加尔
13:21
如果日期不是昨天或今天,它将打印日期和 24 小时时间。我认为除了处理时区之外,我一切都成功了:
from webapp2_extras import i18n
from webapp2_extras.i18n import lazy_gettext as _
import datetime
from datetime import date, datetime, time
from babel.dates import format_date, format_datetime, format_time
from babel.numbers import format_number, format_decimal, format_percent
def datetimeformat_jinja(value, format='%H:%M / %d-%m-%Y', locale='en'):
now= datetime.now()
info = None
if datetime.date(value) == datetime.date(now):
info= _('Today')
elif (now - value).days < 2:
info= _('Yesterday')
else:
month = value.month
if month == 1:
info = str(value.day)+' '+_('Jan')
elif month == 2:
info = str(value.day)+' '+_('Feb')
elif month == 3:
info = str(value.day)+' '+_('Mar')
elif month == 4:
info = str(value.day)+' '+_('April')
elif month == 5:
info = str(value.day)+' '+_('May')
elif month == 6:
info = str(value.day)+' '+_('June')
elif month == 7:
info = str(value.day)+' '+_('July')
elif month == 8:
info = str(value.day)+' '+_('Aug')
elif month == 9:
info = str(value.day)+' '+_('Sep')
elif month == 10:
info = str(value.day)+' '+_('Oct')
elif month == 11:
info = str(value.day)+' '+_('Nov')
else:
info = str(value.day)+' '+_('Dec')
return info+'<br>'+format_time(value, 'H:mm', locale=locale)
上面的代码本地化并人性化输出:
我可以还可以将语言切换为巴西葡萄牙语:
其中“Hoje”表示“今天”,因此过滤器似乎可以工作。
您能否告诉我如何使我的代码也允许时区?我使用 babel 进行本地化,使用 Jinja2 进行渲染。时区应该是文章的时区还是查看者的时区?例如,巴西的巴西用户发布消息,瑞典的瑞典查看者查看该消息。那么应该使用哪个时区?
我可以尝试处理时区的方法是导入 pytz 库(如文档状态)并使用 I timezone 对象。我可以通过模板代码传递时区参数,但如何从文章或语言环境中了解时区参数?在这种情况下,语言环境和时区将有所不同,因为它适用于印度,语言环境为英语,时区为印度:
{{ article.modified|datetimeformat_jinja(locale='en') }}
然后我还可以像此过滤器一样传递时区参数
{{ article.modified|datetimeformat_jinja(locale='en') }}
:
def datetimeformat_jinja(value, format='%H:%M / %d-%m-%Y', locale='en', tzinfo=timezone('India')):
now= datetime.now()
info = None
if datetime.date(value) == datetime.date(now):
info= _('Today')
elif (now - value).days < 2:
info= _('Yesterday')
else:
month = value.month
if month == 1:
info = str(value.day)+' '+_('Jan')
elif month == 2:
info = str(value.day)+' '+_('Feb')
elif month == 3:
info = str(value.day)+' '+_('Mar')
elif month == 4:
info = str(value.day)+' '+_('April')
elif month == 5:
info = str(value.day)+' '+_('May')
elif month == 6:
info = str(value.day)+' '+_('June')
elif month == 7:
info = str(value.day)+' '+_('July')
elif month == 8:
info = str(value.day)+' '+_('Aug')
elif month == 9:
info = str(value.day)+' '+_('Sep')
elif month == 10:
info = str(value.day)+' '+_('Oct')
elif month == 11:
info = str(value.day)+' '+_('Nov')
else:
info = str(value.day)+' '+_('Dec')
return info+'<br>'+format_time(value, 'H:mm', tzinfo=tzinfo, locale=locale)
所以至少看起来我可以本地化一个时区,但我想知道如何使其动态化。
I want to use timezones according to the babel locale. How can I achieve this? The specific situation I have is the goal of displaying the date and time of an article and a humanized and localized way eg:
Yesterday
13:21
or if the Swedish language parameter is set it will display
Igår
13:21
And if the date wasn't yesterday or today, it will print the date and 24 hrs time. I think I succeeded with everything except handling the timezone:
from webapp2_extras import i18n
from webapp2_extras.i18n import lazy_gettext as _
import datetime
from datetime import date, datetime, time
from babel.dates import format_date, format_datetime, format_time
from babel.numbers import format_number, format_decimal, format_percent
def datetimeformat_jinja(value, format='%H:%M / %d-%m-%Y', locale='en'):
now= datetime.now()
info = None
if datetime.date(value) == datetime.date(now):
info= _('Today')
elif (now - value).days < 2:
info= _('Yesterday')
else:
month = value.month
if month == 1:
info = str(value.day)+' '+_('Jan')
elif month == 2:
info = str(value.day)+' '+_('Feb')
elif month == 3:
info = str(value.day)+' '+_('Mar')
elif month == 4:
info = str(value.day)+' '+_('April')
elif month == 5:
info = str(value.day)+' '+_('May')
elif month == 6:
info = str(value.day)+' '+_('June')
elif month == 7:
info = str(value.day)+' '+_('July')
elif month == 8:
info = str(value.day)+' '+_('Aug')
elif month == 9:
info = str(value.day)+' '+_('Sep')
elif month == 10:
info = str(value.day)+' '+_('Oct')
elif month == 11:
info = str(value.day)+' '+_('Nov')
else:
info = str(value.day)+' '+_('Dec')
return info+'<br>'+format_time(value, 'H:mm', locale=locale)
The above code localizes and humanizes the output:
I can also switch languages to eg Brazilian Portuguese:
Where "Hoje" means "today" so the filter appears to work.
Could you please tell me how I can enable my code to also allow timezones? I use babel for localization and Jinja2 for rendering. Should the timezone be the timezone of the article or the timezone of the viewer? For instance, a Brazilian user in Brazil posts a message and a Swedish viewer in Sweden views the message. Which timezone should then be used?
The way I can try to handle timezones is by importing the pytz library like the documentation states and using I timezone object. I can pass the timezone parameter via the template code but how to know the timezone parameter, from the article or from the locale? In this case the locale and the timezone will be different since it's for India and locale is English and timezone India:
{{ article.modified|datetimeformat_jinja(locale='en') }}
Then I can also pass I timezone parameter like this
{{ article.modified|datetimeformat_jinja(locale='en') }}
filter:
def datetimeformat_jinja(value, format='%H:%M / %d-%m-%Y', locale='en', tzinfo=timezone('India')):
now= datetime.now()
info = None
if datetime.date(value) == datetime.date(now):
info= _('Today')
elif (now - value).days < 2:
info= _('Yesterday')
else:
month = value.month
if month == 1:
info = str(value.day)+' '+_('Jan')
elif month == 2:
info = str(value.day)+' '+_('Feb')
elif month == 3:
info = str(value.day)+' '+_('Mar')
elif month == 4:
info = str(value.day)+' '+_('April')
elif month == 5:
info = str(value.day)+' '+_('May')
elif month == 6:
info = str(value.day)+' '+_('June')
elif month == 7:
info = str(value.day)+' '+_('July')
elif month == 8:
info = str(value.day)+' '+_('Aug')
elif month == 9:
info = str(value.day)+' '+_('Sep')
elif month == 10:
info = str(value.day)+' '+_('Oct')
elif month == 11:
info = str(value.day)+' '+_('Nov')
else:
info = str(value.day)+' '+_('Dec')
return info+'<br>'+format_time(value, 'H:mm', tzinfo=tzinfo, locale=locale)
So at least it seems I can localize one timezone but I'm wondering how to make it dynamic.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我总是将时间显示为“挂钟时间”,这意味着使用您的观看者在办公桌上的常规时钟上看到的时区。不过,这取决于你。
丑陋的事实是,时区和区域设置是两种不同的野兽,它们之间只有非常松散的联系。例如,瑞典的印度人仍然想阅读英语(印地语,...),但处于瑞典时区。
当然,您可以针对特定用途对其进行硬编码,但更明智的做法是将语言环境与时区分离,并让用户控制时区设置。
至于您的代码,您可能需要从简单的日期时间切换到 tz 感知的日期时间。
I would always display time as "wall clock time" which means use the timezone your viewer would see on a regular clock on his desk. However that's up to you.
The ugly truth is that timezones and locales are two different beasts with only a very loose connection between them. For example an Indian in Sweden still wants to read English (Hindi, ...) but in a Swedish timezone.
Of course you can hard-code it for specific uses but a more sensible thing would be to decouple locale from timezone and let the user control the timezone setting.
As for your code you probably need to switch from naive datetimes to tz-aware datetimes.