当前位置: 首页 > 工具软件 > rails365 > 使用案例 >

rails time_ago_in_words翻译

朱鹤轩
2023-12-01

使用

ActionController::Base.helpers.time_ago_in_words(time, :scope=>:"datetime.card", :locale=>:"zh_CN")

源码

module ActionView
  module Helpers
    module DateHelper
  	  MINUTES_IN_YEAR = 525600
      MINUTES_IN_QUARTER_YEAR = 131400
      MINUTES_IN_THREE_QUARTERS_YEAR = 394200

      # Reports the approximate distance in time between two Time, Date, or DateTime objects or integers as seconds.
      # Pass <tt>include_seconds: true</tt> if you want more detailed approximations when distance < 1 min, 29 secs.
      # Distances are reported based on the following table:
      #
      #   0 <-> 29 secs                                                             # => less than a minute
      #   30 secs <-> 1 min, 29 secs                                                # => 1 minute
      #   1 min, 30 secs <-> 44 mins, 29 secs                                       # => [2..44] minutes
      #   44 mins, 30 secs <-> 89 mins, 29 secs                                     # => about 1 hour
      #   89 mins, 30 secs <-> 23 hrs, 59 mins, 29 secs                             # => about [2..24] hours
      #   23 hrs, 59 mins, 30 secs <-> 41 hrs, 59 mins, 29 secs                     # => 1 day
      #   41 hrs, 59 mins, 30 secs  <-> 29 days, 23 hrs, 59 mins, 29 secs           # => [2..29] days
      #   29 days, 23 hrs, 59 mins, 30 secs <-> 44 days, 23 hrs, 59 mins, 29 secs   # => about 1 month
      #   44 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs   # => about 2 months
      #   59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec                    # => [2..12] months
      #   1 yr <-> 1 yr, 3 months                                                   # => about 1 year
      #   1 yr, 3 months <-> 1 yr, 9 months                                         # => over 1 year
      #   1 yr, 9 months <-> 2 yr minus 1 sec                                       # => almost 2 years
      #   2 yrs <-> max time or date                                                # => (same rules as 1 yr)
      #
      # With <tt>include_seconds: true</tt> and the difference < 1 minute 29 seconds:
      #   0-4   secs      # => less than 5 seconds
      #   5-9   secs      # => less than 10 seconds
      #   10-19 secs      # => less than 20 seconds
      #   20-39 secs      # => half a minute
      #   40-59 secs      # => less than a minute
      #   60-89 secs      # => 1 minute
      #
      #   from_time = Time.now
      #   distance_of_time_in_words(from_time, from_time + 50.minutes)                                # => about 1 hour
      #   distance_of_time_in_words(from_time, 50.minutes.from_now)                                   # => about 1 hour
      #   distance_of_time_in_words(from_time, from_time + 15.seconds)                                # => less than a minute
      #   distance_of_time_in_words(from_time, from_time + 15.seconds, include_seconds: true)         # => less than 20 seconds
      #   distance_of_time_in_words(from_time, 3.years.from_now)                                      # => about 3 years
      #   distance_of_time_in_words(from_time, from_time + 60.hours)                                  # => 3 days
      #   distance_of_time_in_words(from_time, from_time + 45.seconds, include_seconds: true)         # => less than a minute
      #   distance_of_time_in_words(from_time, from_time - 45.seconds, include_seconds: true)         # => less than a minute
      #   distance_of_time_in_words(from_time, 76.seconds.from_now)                                   # => 1 minute
      #   distance_of_time_in_words(from_time, from_time + 1.year + 3.days)                           # => about 1 year
      #   distance_of_time_in_words(from_time, from_time + 3.years + 6.months)                        # => over 3 years
      #   distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years
      #
      #   to_time = Time.now + 6.years + 19.days
      #   distance_of_time_in_words(from_time, to_time, include_seconds: true)                        # => about 6 years
      #   distance_of_time_in_words(to_time, from_time, include_seconds: true)                        # => about 6 years
      #   distance_of_time_in_words(Time.now, Time.now)                                               # => less than a minute
      #
      # With the <tt>scope</tt> option, you can define a custom scope for Rails
      # to look up the translation.
      #
      # For example you can define the following in your locale (e.g. en.yml).
      #
      #   datetime:
      #     distance_in_words:
      #       short:
      #         about_x_hours:
      #           one: 'an hour'
      #           other: '%{count} hours'
      #
      # See https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml
      # for more examples.
      #
      # Which will then result in the following:
      #
      #   from_time = Time.now
      #   distance_of_time_in_words(from_time, from_time + 50.minutes, scope: 'datetime.distance_in_words.short') # => "an hour"
      #   distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short')    # => "3 hours"
      def distance_of_time_in_words(from_time, to_time = 0, options = {})
        options = {
          scope: :'datetime.distance_in_words'
        }.merge!(options)

        from_time = normalize_distance_of_time_argument_to_time(from_time)
        to_time = normalize_distance_of_time_argument_to_time(to_time)
        from_time, to_time = to_time, from_time if from_time > to_time
        distance_in_minutes = ((to_time - from_time) / 60.0).round
        distance_in_seconds = (to_time - from_time).round

        I18n.with_options locale: options[:locale], scope: options[:scope] do |locale|
          case distance_in_minutes
          when 0..1
            return distance_in_minutes == 0 ?
                   locale.t(:less_than_x_minutes, count: 1) :
                   locale.t(:x_minutes, count: distance_in_minutes) unless options[:include_seconds]

            case distance_in_seconds
            when 0..4   then locale.t :less_than_x_seconds, count: 5
            when 5..9   then locale.t :less_than_x_seconds, count: 10
            when 10..19 then locale.t :less_than_x_seconds, count: 20
            when 20..39 then locale.t :half_a_minute
            when 40..59 then locale.t :less_than_x_minutes, count: 1
            else             locale.t :x_minutes,           count: 1
            end

          when 2...45           then locale.t :x_minutes,      count: distance_in_minutes
          when 45...90          then locale.t :about_x_hours,  count: 1
            # 90 mins up to 24 hours
          when 90...1440        then locale.t :about_x_hours,  count: (distance_in_minutes.to_f / 60.0).round
            # 24 hours up to 42 hours
          when 1440...2520      then locale.t :x_days,         count: 1
            # 42 hours up to 30 days
          when 2520...43200     then locale.t :x_days,         count: (distance_in_minutes.to_f / 1440.0).round
            # 30 days up to 60 days
          when 43200...86400    then locale.t :about_x_months, count: (distance_in_minutes.to_f / 43200.0).round
            # 60 days up to 365 days
          when 86400...525600   then locale.t :x_months,       count: (distance_in_minutes.to_f / 43200.0).round
          else
            from_year = from_time.year
            from_year += 1 if from_time.month >= 3
            to_year = to_time.year
            to_year -= 1 if to_time.month < 3
            leap_years = (from_year > to_year) ? 0 : (from_year..to_year).count { |x| Date.leap?(x) }
            minute_offset_for_leap_year = leap_years * 1440
            # Discount the leap year days when calculating year distance.
            # e.g. if there are 20 leap year days between 2 dates having the same day
            # and month then based on 365 days calculation
            # the distance in years will come out to over 80 years when in written
            # English it would read better as about 80 years.
            minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
            remainder                   = (minutes_with_offset % MINUTES_IN_YEAR)
            distance_in_years           = (minutes_with_offset.div MINUTES_IN_YEAR)
            if remainder < MINUTES_IN_QUARTER_YEAR
              locale.t(:about_x_years,  count: distance_in_years)
            elsif remainder < MINUTES_IN_THREE_QUARTERS_YEAR
              locale.t(:over_x_years,   count: distance_in_years)
            else
              locale.t(:almost_x_years, count: distance_in_years + 1)
            end
          end
        end
      end

  	  # Like <tt>distance_of_time_in_words</tt>, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
      #
      #   time_ago_in_words(3.minutes.from_now)                 # => 3 minutes
      #   time_ago_in_words(3.minutes.ago)                      # => 3 minutes
      #   time_ago_in_words(Time.now - 15.hours)                # => about 15 hours
      #   time_ago_in_words(Time.now)                           # => less than a minute
      #   time_ago_in_words(Time.now, include_seconds: true) # => less than 5 seconds
      #
      #   from_time = Time.now - 3.days - 14.minutes - 25.seconds
      #   time_ago_in_words(from_time)      # => 3 days
      #
      #   from_time = (3.days + 14.minutes + 25.seconds).ago
      #   time_ago_in_words(from_time)      # => 3 days
      #
      # Note that you cannot pass a <tt>Numeric</tt> value to <tt>time_ago_in_words</tt>.
      #
      def time_ago_in_words(from_time, options = {})
        distance_of_time_in_words(from_time, Time.now, options)
      end

      alias_method :distance_of_time_in_words_to_now, :time_ago_in_words

翻译时间config/locales/zh_CN.yml

zh_CN:
  datetime:
    card:
      half_a_minute: "1分钟前"
      less_than_x_seconds:
        one:   "1分钟前"
        other: "1分钟前"
      x_seconds:
        one:   "1分钟前"
        other: "1分钟前"
      less_than_x_minutes:
        one:   "1分钟前"
        other: "%{count}分钟前"
      x_minutes:
        one:   "1分钟前"
        other: "%{count}分钟前"
      about_x_hours:
        one:   "1小时前"
        other: "%{count}小时前"
      x_days:
        one:   "1天前"
        other: "%{count}天前"
      about_x_months:
        one:   "1个月前"
        other: "%{count}个月前"
      x_months:
        one:   "1个月前"
        other: "%{count}个月前"
      about_x_years:
        one:   "1年前"
        other: "%{count}年前"
      over_x_years:
        one:   "1年前"
        other: "%{count}年前"
      almost_x_years:
        one:   "1年前"
        other: "%{count}年前"

测试 rails c

def f(time)
  puts ActionController::Base.helpers.time_ago_in_words(time, :scope=>:"datetime.card", :locale=>:"zh_CN")
end

pry(main)> f(Time.now-10.seconds)
1分钟前
=> nil
pry(main)> f(Time.now-150.seconds)
3分钟前
=> nil
(main)> f(Time.now-3600.seconds)
1小时前
=> nil
pry(main)> f(Time.now-3600.days)
10年前
=> nil
pry(main)> f(Time.now-2.days)
2天前
=> nil
 类似资料: