Class: TwitterCldr::Resources::NumberFormats

Inherits:
Object
  • Object
show all
Defined in:
lib/twitter_cldr/resources/number_formats_importer.rb

Constant Summary collapse

TYPES =
%w(decimal scientific percent currency).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(locale, cldr_req) ⇒ NumberFormats

Returns a new instance of NumberFormats.



68
69
70
71
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 68

def initialize(locale, cldr_req)
  @locale = locale
  @cldr_req = cldr_req
end

Instance Attribute Details

#cldr_reqObject (readonly)

Returns the value of attribute cldr_req.



66
67
68
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 66

def cldr_req
  @cldr_req
end

#localeObject (readonly)

Returns the value of attribute locale.



66
67
68
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 66

def locale
  @locale
end

Instance Method Details

#cldr_main_pathObject



217
218
219
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 217

def cldr_main_path
  @cldr_main_path ||= File.join(cldr_req.common_path, 'main')
end

#default_number_systemsObject



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 108

def default_number_systems
  { alternatives: {} }.tap do |result|
    doc.xpath('//ldml/numbers/defaultNumberingSystem').each do |default_ns_node|
      if alt_attr = default_ns_node.attribute('alt')
        result[:alternatives][alt_attr.value] = default_ns_node.content
      else
        result[:default] = default_ns_node.content
      end
    end
  end
end

#docObject



210
211
212
213
214
215
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 210

def doc
  @doc ||= begin
    locale_fs = locale.to_s.gsub('-', '_')
    Nokogiri.XML(File.read(File.join(cldr_main_path, "#{locale_fs}.xml")))
  end
end

#formats_for_type(type) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 120

def formats_for_type(type)
  doc.xpath("//ldml/numbers/#{type}Formats").each_with_object({}) do |formats_node, ret|
    number_system = if ns_node = formats_node.attribute('numberSystem')
      ns_node.value
    else
      :default
    end

    if aliased = formats_node.xpath('alias').first
      alias_number_system = aliased.attribute('path').value[/@numberSystem='(\w+)'/, 1]
      ret[number_system] = :"numbers.formats.#{type}.#{alias_number_system}"
      next
    end

    formats = formats_from_node(formats_node, type, number_system)
    formats[:default] = formats[:default][:default] if formats[:default]
    ret[number_system] = formats

    unit = unit_for(formats_node)

    unless unit.empty?
      ret[number_system][:unit] = unit
    end
  end
end

#formats_from_node(formats_node, type, number_system) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 146

def formats_from_node(formats_node, type, number_system)
  formats_node.xpath("#{type}FormatLength").each_with_object({}) do |format_length_node, format_result|
    format_nodes = format_length_node.xpath("#{type}Format")

    format_key = format_length_node.attribute('type')
    format_key = format_key ? format_key.value : :default

    if format_nodes.size > 0
      format_nodes.each do |format_node|
        format_result[format_key] ||= patterns_from(format_node)
      end
    else
      if aliased = format_length_node.xpath('alias').first
        format_result[format_key] = pattern_xpath_to_redirect(
          aliased.attribute('path').value, number_system
        )
      end
    end
  end
end

#pattern_xpath_to_redirect(xpath, number_system) ⇒ Object



196
197
198
199
200
201
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 196

def pattern_xpath_to_redirect(xpath, number_system)
  length = xpath[/(\w+)FormatLength/, 1]
  type   = xpath[/@type='(\w+)'/, 1]

  :"numbers.formats.#{length}.#{number_system}.#{type}"
end

#patterns_from(format_node) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 167

def patterns_from(format_node)
  format_node.xpath('pattern').each_with_object({}) do |pattern_node, pattern_result|
    # CLDR v42 added a few new alt patterns, alphaNextToNumber and noCurrency.
    # See: https://cldr.unicode.org/index/downloads/cldr-42#h.ocxunccgtf28
    next if pattern_node.attribute('alt')

    pattern_key_node = pattern_node.attribute('type')
    pattern_count_node = pattern_node.attribute('count')

    unless cldr_req.draft?(pattern_node)
      pattern_key = pattern_key_node ? pattern_key_node.value : :default

      if pattern_count_node
        pattern_count = pattern_count_node.value

        if pattern_result[pattern_key].nil?
          pattern_result[pattern_key] ||= {}
        elsif !pattern_result[pattern_key].is_a?(Hash)
          raise "can't parse patterns with and without 'count' attribute in the same section"
        end

        pattern_result[pattern_key][pattern_count] = pattern_node.content
      else
        pattern_result[pattern_key] = pattern_node.content
      end
    end
  end
end

#symbolsObject



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 85

def symbols
  doc.xpath('//ldml/numbers/symbols').each_with_object({}) do |symbols_node, symbols_result|
    number_system = if ns_node = symbols_node.attribute('numberSystem')
      ns_node.value
    else
      :default
    end

    if aliased = symbols_node.xpath('alias').first
      alias_number_system = aliased.attribute('path').value[/@numberSystem='(\w+)'/, 1]
      symbols_result[number_system] = :"numbers.symbols.#{alias_number_system}"
      next
    end

    symbols_result[number_system] = symbols_node.elements.each_with_object({}) do |symbol, symbol_result|
      unless cldr_req.draft?(symbol)
        symbol_name = symbol.name.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2.downcase}"}
        symbol_result[symbol_name] = symbol.content
      end
    end
  end
end

#to_hObject



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 73

def to_h
  {
    numbers: {
      symbols: symbols,
      default_number_systems: default_number_systems,
      formats: TYPES.each_with_object({}) do |type, ret|
        ret[type.to_sym] = formats_for_type(type)
      end
    }
  }
end

#unit_for(format_length_node) ⇒ Object



203
204
205
206
207
208
# File 'lib/twitter_cldr/resources/number_formats_importer.rb', line 203

def unit_for(format_length_node)
  format_length_node.xpath('unitPattern').each_with_object({}) do |unit_node, result|
    count = unit_node.attribute('count').value rescue 'one'
    result[count] = unit_node.content
  end
end