我正在开发一个Rails 3项目,在该项目中,表单中有日期输入的位置。带有日期的文本字段使用日期选择器,因此无需担心以错误的格式输入日期,但日期显示为:db格式(例如2010-01-21)。
(注意:这特别是在表单字段中 - 例如<%= f.text_field :publish_date %>
,它应该自动使用:默认格式,并且不需要提供值)
我尝试添加具有以下日期配置的自定义区域设置:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d/%m/%Y"
short: "%b %d"
long: "%B %d, %Y"
然后将我的语言环境设置为此(config.i18n.default_locale = "en-AU"
),但这似乎没有采取,而且变得非常令人沮丧。
该应用程序最终将支持多种语言环境,因此在应用程序启动时设置初始化程序以覆盖日期格式并不合适,我知道应该工作 - 我是我在这里猜错了。
语言环境文件是:config/locales/en-AU.yml
,在我的application.rb中,我包括:
config.i18n.load_path += Dir[Rails.root.join("config", "locales", "*.yml").to_s]
config.i18n.default_locale = "en-AU"
在我的application.rb文件中。
答案 0 :(得分:85)
显示日期时,您可以使用I18n.l
所以你会这样做:
I18n.l @entry.created_at
如果你想改变它的格式:
I18n.l @entry.created_at, :format => :short
internationalization rails guide正在记录该内容。
答案 1 :(得分:7)
查看delocalize gem,它可能会帮到你一些。
https://github.com/clemens/delocalize
http://www.railway.at/articles/2009/05/03/new-plugin-delocalize/
答案 2 :(得分:7)
@ damien-mathieu对于使用I18n.localize
显示本地化日期有一个可靠的答案,他的评论提出了一个重要的警告:这打破了表单文本输入。从那以后,rails为我们提供了一个很好的解决方案。
从 Rails 5 开始,您可以使用 Rails attributes API自定义用户输入如何转换为模型或数据库值。实际上,它是available in Rails 4.2,但没有完全记录。
通过Sean Griffin's相当大的努力,所有型号&#39;类型现在定义为ActiveRecord::Type
个对象。这定义了如何处理属性的单一事实来源。该类型定义了属性的序列化方式(从ruby类型到数据库类型),反序列化(从数据库类型到ruby类型)和强制转换(从用户输入到ruby类型)。这是一个大问题,因为搞乱这个曾经是开发人员应该避免的特殊情况的雷区。
首先,浏览attribute
个文档,了解如何覆盖属性的类型。您可能需要阅读文档才能理解这个答案。
这里是Rails属性API的快速浏览。你可以跳过这一部分,但后来你不知道这些东西是如何工作的。这有什么乐趣?
了解Rails如何处理属性的用户输入将让我们只覆盖一种方法,而不是制作更完整的自定义类型。它还可以帮助您编写更好的代码,因为rails&#39;代码非常好。
由于您没有提及模型,我假设您的Post
属性为:publish_date
(有些人更喜欢名称{ {1}},但我离题了。)
找出:published_on
的类型。我们并不关心它是:publish_date
的实例,我们需要知道type_for_attribute返回的内容:
此方法是与模型属性类型相关的唯一有效信息来源。
Date
现在我们知道$ rails c
> post = Post.where.not(publish_date: nil).first
> post.publish_date.class
=> Date
> Post.type_for_attribute('publish_date').type
=> :date
属性是:publish_date
类型。这由ActiveRecord::Type::Date定义,ActiveModel::Type::Date扩展ActiveModel::Type::Value,扩展cast。我已经链接到rails 5.1.3,但您想要阅读您的版本的来源。
因此,当您设置:date
时,该值会传递给cast_value,后者会调用fast_string_to_date。由于表单输入是一个字符串,它将尝试fallback_string_to_date然后使用Date._parse {{3}}。
如果您迷路了,请不要担心。你不需要了解rails&#39;用于自定义属性的代码。
现在我们了解了Rails如何使用属性API,我们可以轻松地创建自己的属性。只需创建一个自定义类型来覆盖:publish_date
以期望本地化的日期字符串:
cast_value
看看我是如何复制rails&#39;代码并进行了一些小调整。简单。您可能希望通过调用class LocalizedDate < ActiveRecord::Type::Date
private
# Convert localized date string to Date object. This takes I18n formatted date strings
# from user input and casts them back to Date objects.
def cast_value(value)
if value.is_a?(::String)
return if value.empty?
format = I18n.translate("date.formats.short")
Date.strptime(value, format) rescue nil
elsif value.respond_to?(:to_date)
value.to_date
else
value
end
end
end
来改进此问题,并将super
格式移至选项或常量。
注册您的类型,以便用符号引用它:
:short
使用您的自定义类型覆盖# config/initializers/types.rb
ActiveRecord::Type.register(:localized_date, LocalizedDate)
类型:
:publish_date
现在,您可以在表单输入中使用本地化值:
class Post < ApplicationRecord
attribute :publish_date, :localized_date
end
答案 3 :(得分:4)
我发现最好的解决方案是:
<%= f.text_field :publish_date, :value => (@model.publish_date.nil? ? nil : l(@model.publish_date)) %>
这不是完美的遗憾,但至少这样我可以将我的表格用于新记录和现有记录。与使用初始化程序更改默认格式相比,该应用程序将与多个语言环境保持兼容。如果你完全想要遵守DRY,你总是可以写一个自定义助手。
答案 4 :(得分:1)
您可以覆盖:publish_date
属性的getter。
即。在你的模型中:
def date( *format)
self[:publish_date].strftime(format.first || default)
end
并且在您的视图中,您可以执行任何操作
@income.date("%d/%m/%Y")
或
@income.date
这会导致strftime使用传递的格式字符串,除非它是nil,在这种情况下它会回退到你的默认字符串。
注意:我使用splat运算符添加了对没有参数的日期的支持。可能有一种更清洁的方法。