/
advanced.rb
132 lines (119 loc) · 6.12 KB
/
advanced.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- encoding: utf-8 -*-
module I18n
module Backend
# "Продвинутый" бекэнд для I18n.
#
# Наследует Simple бекэнд и полностью с ним совместим. Добаляет поддержку
# для отдельностоящих/контекстных названий дней недели и месяцев.
# Также позволяет каждому языку использовать собственные правила плюрализации,
# объявленные как Proc (<tt>lambda</tt>).
#
#
# Advanced I18n backend.
#
# Extends Simple backend. Allows usage of "standalone" keys
# for DateTime localization and usage of user-defined Proc (lambda) pluralization
# methods in translation tables.
class Advanced < Simple
LOCALIZE_ABBR_MONTH_NAMES_MATCH = /(%d|%e)?(\s*)(%b)/
LOCALIZE_MONTH_NAMES_MATCH = /(%d|%e)?(\s*)(%B)/
LOCALIZE_STANDALONE_ABBR_DAY_NAMES_MATCH = /^%a/
LOCALIZE_STANDALONE_DAY_NAMES_MATCH = /^%A/
# Acts the same as +strftime+, but returns a localized version of the
# formatted date string. Takes a key from the date/time formats
# translations as a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>).
#
#
# Метод отличается от <tt>localize</tt> в Simple бекэнде поддержкой
# отдельностоящих/контекстных названий дней недели и месяцев.
#
#
# Note that it differs from <tt>localize</tt> in Simple< backend by checking for
# "standalone" month name/day name keys in translation and using them if available.
def localize(locale, object, format = :default)
raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
type = object.respond_to?(:sec) ? 'time' : 'date'
# TODO only translate these if format is a String?
formats = translate(locale, :"#{type}.formats")
format = formats[format.to_sym] if formats && formats[format.to_sym]
# TODO raise exception unless format found?
format = format.to_s.dup
# TODO only translate these if the format string is actually present
# TODO check which format strings are present, then bulk translate then, then replace them
if lookup(locale, :"date.standalone_abbr_day_names")
format.gsub!(LOCALIZE_STANDALONE_ABBR_DAY_NAMES_MATCH,
translate(locale, :"date.standalone_abbr_day_names")[object.wday])
end
format.gsub!(/%a/, translate(locale, :"date.abbr_day_names")[object.wday])
if lookup(locale, :"date.standalone_day_names")
format.gsub!(LOCALIZE_STANDALONE_DAY_NAMES_MATCH,
translate(locale, :"date.standalone_day_names")[object.wday])
end
format.gsub!(/%A/, translate(locale, :"date.day_names")[object.wday])
if lookup(locale, :"date.standalone_abbr_month_names")
format.gsub!(LOCALIZE_ABBR_MONTH_NAMES_MATCH) do
$1 ? $1 + $2 + translate(locale, :"date.abbr_month_names")[object.mon] :
$2 + translate(locale, :"date.standalone_abbr_month_names")[object.mon]
end
else
format.gsub!(/%b/, translate(locale, :"date.abbr_month_names")[object.mon])
end
if lookup(locale, :"date.standalone_month_names")
format.gsub!(LOCALIZE_MONTH_NAMES_MATCH) do
$1 ? $1 + $2 + translate(locale, :"date.month_names")[object.mon] :
$2 + translate(locale, :"date.standalone_month_names")[object.mon]
end
else
format.gsub!(/%B/, translate(locale, :"date.month_names")[object.mon])
end
format.gsub!(/%p/, translate(locale, :"time.#{object.hour < 12 ? :am : :pm}")) if object.respond_to? :hour
object.strftime(format)
end
protected
# Использует правила плюрализации из таблицы переводов для языка (если присутствуют),
# иначе использует правило плюрализации по умолчанию (английский язык).
#
# Пример задания правила в таблице переводов:
#
# store_translations :'en', {
# :pluralize => lambda { |n| n == 1 ? :one : :other }
# }
#
# Правило должно возвращать один из символов для таблицы переводов:
# :zero, :one, :two, :few, :many, :other
#
#
# Picks a pluralization rule specified in translation tables for a language or
# uses default pluralization rules.
#
# This is how pluralization rules are defined in translation tables, English
# language for example:
#
# store_translations :'en', {
# :pluralize => lambda { |n| n == 1 ? :one : :other }
# }
#
# Rule must return a symbol to use with pluralization, it must be one of:
# :zero, :one, :two, :few, :many, :other
def pluralize(locale, entry, count)
return entry unless entry.is_a?(Hash) and count
key = :zero if count == 0 && entry.has_key?(:zero)
locale_pluralize = lookup(locale, :pluralize)
if locale_pluralize && locale_pluralize.respond_to?(:call)
key ||= locale_pluralize.call(count)
else
key ||= default_pluralizer(count)
end
raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key)
entry[key]
end
# Default pluralizer, used if pluralization rule is not defined in translations.
#
# Uses English pluralization rules -- it will pick the first translation if count is not equal to 1
# and the second translation if it is equal to 1.
def default_pluralizer(count)
count == 1 ? :one : :other
end
end
end
end