如何让Rails 3本地化我的日期格式?

时间:2010-10-07 07:52:24

标签: ruby-on-rails localization internationalization ruby-on-rails-3

我正在开发一个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文件中。

5 个答案:

答案 0 :(得分:85)

显示日期时,您可以使用I18n.l

所以你会这样做:

I18n.l @entry.created_at

如果你想改变它的格式:

I18n.l @entry.created_at, :format => :short

internationalization rails guide正在记录该内容。

答案 1 :(得分:7)

答案 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如何转换属性

这里是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,但您想要阅读您的版本的来源。

如何通过ActiveRecord :: Type :: Date?

转换用户输入

因此,当您设置: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运算符添加了对没有参数的日期的支持。可能有一种更清洁的方法。