本地化时间单位

时间:2013-05-15 23:15:01

标签: ruby-on-rails internationalization

考虑名为ActiveRecord的{​​{1}}模型,其持续时间属性以分钟为单位表示电影的长度。在我的视图中打印此属性的最佳方法是什么?

我希望能够写出这样的内容:

Movie

但如果我能写一下,那就更棒了:

= l(@movie.duration, unit: :minutes) # Should return "105 minutes"

甚至

= l(@movie.duration)

但是,这需要某种方式来声明持续时间属性中使用的单位,该属性只是数据库中的整数。

似乎Rails I18n有一种翻译属性的方法,但只有他们的名字,而不是他们的价值。

最好与I18n配合使用的解决方案。

3 个答案:

答案 0 :(得分:2)

Rails不知道该值是以分钟为单位。

此功能属于帮助器,或(我的偏好)装饰器,带有I18N标签。

答案 1 :(得分:0)

我认为没有理由让这里的事情复杂化;你甚至不在不同的单位之间转换:

在您看来:

<%= t :'models.movie.duration', :count => @movie.duration %>

config/locales/en.yml

en:
  models:
    movie:
      duration:
        one: '%{count} minute'
        other: '%{count} minutes'

答案 2 :(得分:0)

大约7年前,我问了这个问题,但是仍然偶尔有活动。

因此对于那些像我一样思考此主题的(初级)开发人员,我想补充一些想法。

我认为这个问题试图解决多个问题。第一个问题是PostgreSQL没有本地数据类型来存储持续时间(至少我不熟悉)。

结果,当使用持续时间时,我们被迫在持续时间和PostgreSQL提供的数据类型之间进行转换。就我而言,我使用了整数类型。

因此,有两个后续问题。

在没有本机持续时间类型的情况下应该使用什么数据类型?

我会说整数或十进制。这取决于应用程序的需求和数据的质量。如果您希望以分钟为单位存储,但需要(milli)秒精度,请使用十进制。但总的来说,我发现使用整数更容易,因此最好使用足够小的单位,以使整数足够精确。

在应用程序中如何在数字类型(整数/十进制)和持续时间类型之间进行转换?

根据您要如何使用数据,我认为最好封装有关持续时间如何转换为数据库数据类型的知识,而不是将其泄漏到应用程序的视图(和其他地方)中。如果这些知识泄漏了,那么以后更改基础数据类型将变得更加困难-例如,如果PostgreSQL / Rails添加了更好的数据类型。

所以我可能会制作一个value class。这意味着制作一个使用数据库值初始化的持续时间类,但可以将其查询和修改为持续时间。

简单的例子:

class Duration

  attr_accessor :seconds
  def initialize(seconds)
    @seconds = seconds
  end

  def minutes
    (seconds / 60.0).round
  end

  def minutes=(minutes)
    self.seconds = minutes * 60
  end

  def hours
    (seconds / (60.0 * 60)).round
  end

  def hours=(hours)
    self.seconds = hours * 60 * 60
  end

  def to_s(unit = :minutes) # Valid values are :seconds, :minutes and :hours.
    I18n.t("value_classes.duration.units.#{unit}", value: send(unit))
  end

end

如果将其与ActiveRecord类上的自定义访问器结合使用,那么您将获得相当可靠的封装。

class Movie < ApplicationRecord

  def duration
    Duration.new(duration_in_seconds) # Name of database attribute
  end

  def duration=(duration_instance)
    self.duration_in_seconds = duration_instance.seconds
  end

end

在视图中:

<p>Duration: <%= @movie.duration %></p>

您可能希望向Duration类添加一些其他格式设置方法,因此可以根据设计者在特定情况下的需要,在“ 127分钟”,“ 2小时7分钟”和“ 2:07”之间进行选择。视图。

此解决方案还包含访问器,因此您的控制器可以执行类似的操作

@movie.duration = Duration.new.tap do |duration|
  duration.minutes = params[:movie][:duration_as_minutes]
end