Class: CSL::Locale

Inherits:
Node show all
Extended by:
Loader
Includes:
Comparable
Defined in:
lib/csl/locale.rb,
lib/csl/locale/date.rb,
lib/csl/locale/term.rb,
lib/csl/locale/style_options.rb

Overview

CSL::Locales contain locale specific date formatting options, term translations, and a number ordinalizer.

Defined Under Namespace

Classes: Date, DatePart, StyleOptions, Term, Terms

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes included from Loader

#extension, #prefix, #root

Attributes inherited from Node

#attributes

Attributes included from Treelike

#children, #nodename, #parent

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Loader

extend_name, extend_path, list, load

Methods inherited from Node

#attribute?, #attributes?, #attributes_for, constantize, create, create_attributes, #custom_attributes, #deep_copy, #default_attribute?, default_attributes, #default_attributes, #each, #exact_match?, #format_page_ranges?, #formatting_options, #has_attributes?, #has_default_attributes?, #has_language?, hide_default_attributes!, hide_default_attributes?, match?, #match?, matches?, #page_range_format, parse, parse!, #quotes?, #reverse_merge!, #save_to, show_default_attributes!, #strip_periods?, #tags, #textnode?, types

Methods included from Extensions::Nesting

#nesting

Methods included from PrettyPrinter

#pretty_print, #tags, #to_xml

Methods included from Treelike

#<<, #add_child, #add_children, #ancestors, #closest, #delete_child, #delete_children, #depth, #descendants, #each_ancestor, #each_child, #each_descendant, #each_sibling, #empty?, #find_child, #find_children, #has_children?, #root, #root?, #siblings, #unlink

Constructor Details

#initialize(*arguments) {|_self| ... } ⇒ Locale

Returns a new locale. In the first form, the language/regions is set to the default language and region. In the second form the language/region is set by the passed-in IETF tag. The third form additionally accepts a hash of localize style-options. The fourth form is the standard node attribute initialize signature.

Examples:

Locale.new                                         #-> default
Locale.new('en')                                   #-> American English
Locale.new('en', :'punctuation-in-quote' => false) #-> with style-options
Locale.new(:lang => 'en-GB', :version => '1.0')    #-> British English

Yields:

  • (_self)

Yield Parameters:

  • _self (CSL::Locale)

    the object that the method was called on



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/csl/locale.rb', line 123

def initialize(*arguments)
  case arguments.length
  when 0
    locale, attributes, options = nil, {}, nil
  when 1
    if arguments[0].is_a?(Hash)
      arguments[0] = arguments[0].symbolize_keys

      locale = arguments[0].delete(:lang) || arguments[0].delete(:'xml:lang')

      attributes, options = arguments
    else
      attributes, locale, options = {}, *arguments
    end
  when 2
    attributes, locale, options = {}, *arguments
  else
    raise ArgumentError, "wrong number of arguments (#{arguments.length} for 0..2)"
  end

  super(attributes, &nil)

  set(locale) unless locale.blank?

  unless options.nil?
    children[:'style-options'] = StyleOptions.new(options)
  end

  yield self if block_given?
end

Class Attribute Details

.defaultObject

Returns the value of attribute default.



40
41
42
# File 'lib/csl/locale.rb', line 40

def default
  @default
end

.languagesObject (readonly)

Returns the value of attribute languages.



41
42
43
# File 'lib/csl/locale.rb', line 41

def languages
  @languages
end

.regionsObject (readonly)

Returns the value of attribute regions.



41
42
43
# File 'lib/csl/locale.rb', line 41

def regions
  @regions
end

.scriptsObject (readonly)

Returns the value of attribute scripts.



41
42
43
# File 'lib/csl/locale.rb', line 41

def scripts
  @scripts
end

Instance Attribute Details

#regionObject

Returns the value of attribute region.



103
104
105
# File 'lib/csl/locale.rb', line 103

def region
  @region
end

#scriptObject

Returns the value of attribute script.



103
104
105
# File 'lib/csl/locale.rb', line 103

def script
  @script
end

Class Method Details

.load(input = nil) ⇒ Object



43
44
45
46
47
# File 'lib/csl/locale.rb', line 43

def load(input = nil)
  input ||= Locale.default
  input = normalize input if input.to_s =~ @tag_pattern
  super(input)
end

.normalize(tag) ⇒ String

Normalizes an IETF tag; adds default language, region, script.

Examples:

Locale.normalize("en")  #-> "en-US"
Locale.normalize("-BR") #-> "pt-BR"
Locale.normalize("de-at") #-> "de-AT"
Locale.normalize("sr") #-> "sr-Latn-RS"

Parameters:

  • tag (String)

    an IETF tag to be normalized

Returns:

  • (String)

    the normalized IETF tag

Raises:

  • (ArgumentError)

    if the passed-in string is no IETF tag



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
# File 'lib/csl/locale.rb', line 61

def normalize(tag)
  tag = tag.to_s.strip

  unless tag =~ @tag_pattern
    raise ArgumentError, "unsupported IETF tag: #{tag.inspect}"
  end

  language, *rs = tag.split(/-/)
  region, script = rs.reverse

  if language.nil? || language.empty?
    language = languages[region.to_sym]
  else
    language.downcase!
  end

  if region.nil?
    region = regions[language.to_sym]
  else
    region.upcase!
  end

  if script.nil?
    script = scripts[language.to_sym]
  else
    script.capitalize!
  end

  [language, script, region].compact.join('-')
end

Instance Method Details

#<=>(other) ⇒ 1, ...

Locales are sorted first by language, then by region and script; sort order is alphabetical with the following exceptions: the default locale is prioritised; in case of a language match the default region of that language will be prioritised (e.g., de-DE will come before de-AT even though the alphabetical order would be different).

Parameters:

  • other (Locale)

    the locale used for comparison

Returns:

  • (1, 0, -1, nil)

    the result of the comparison



449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# File 'lib/csl/locale.rb', line 449

def <=>(other)
  case
  when !other.is_a?(Locale)
    nil
  when [language, region] == [other.language, other.region]
    script <=> other.script
  when default?
    -1
  when other.default?
    1
  when language == other.language
    case
    when default_region?
      -1
    when other.default_region?
      1
    else
      region.to_s <=> other.region.to_s
    end
  else
    language.to_s <=> other.language.to_s
  end
end

#added_to(node) ⇒ Object

Raises:



159
160
161
162
# File 'lib/csl/locale.rb', line 159

def added_to(node)
  raise ValidationError, "not allowed to add locale to #{node.nodename}" unless
    node.nodename == 'style'
end

#clearself

Sets the locale’s language, script and region to nil.

Returns:

  • (self)


213
214
215
216
# File 'lib/csl/locale.rb', line 213

def clear
  @language, @script, @region = nil
  self
end

#default?Boolean

Returns:

  • (Boolean)


384
385
386
# File 'lib/csl/locale.rb', line 384

def default?
  to_s == Locale.default
end

#default_language?Boolean

Returns whether or not the Locale’s language is the default language for its region.

Returns:

  • (Boolean)

    whether or not the Locale’s language is the default language for its region



396
397
398
# File 'lib/csl/locale.rb', line 396

def default_language?
  language && language == Locale.languages[region]
end

#default_region?Boolean

Returns whehter or not the Locale’s region is the default region for its language.

Returns:

  • (Boolean)

    whehter or not the Locale’s region is the default region for its language



390
391
392
# File 'lib/csl/locale.rb', line 390

def default_region?
  region && region == Locale.regions[language]
end

#each_date(&block) ⇒ Object

Calls block once for each date format defined by the locale. If no block is given, an enumerator is returned instead.

Examples:

locale.each_date { |date_format| block } #-> locale
locale.each_date                         #-> enumerator


371
372
373
374
375
376
377
378
379
380
381
# File 'lib/csl/locale.rb', line 371

def each_date(&block)
  if block_given?
    if date.is_a? CSL::Node
      yield date
    else
      date.each(&block)
    end
  else
    enum_for :each_date
  end
end

#each_term(&block) ⇒ Object

Calls block once for each term defined by the locale. If no block is given, an enumerator is returned instead.

Examples:

locale.each_term { |term| block } #-> locale
locale.each_term                  #-> enumerator


356
357
358
359
360
361
362
363
# File 'lib/csl/locale.rb', line 356

def each_term(&block)
  if block_given?
    terms.each(&block)
    self
  else
    enum_for :each_term
  end
end

#initialize_copy(other) ⇒ Object



154
155
156
157
# File 'lib/csl/locale.rb', line 154

def initialize_copy(other)
  @parent, @ancestors, @descendants, @siblings, @root, @depth = nil
  initialize(other.attributes.to_hash.merge(:lang => other.to_s))
end

#inspectString

Returns a string representation of the Locale.

Returns:

  • (String)

    a string representation of the Locale



479
480
481
# File 'lib/csl/locale.rb', line 479

def inspect
  "#<#{self.class.name} #{to_s}>"
end

#legacy?Boolean

Returns whether or not the Locale’s version is less than CSL-Ruby’s default version.

Returns:

  • (Boolean)

    whether or not the Locale’s version is less than CSL-Ruby’s default version



186
187
188
# File 'lib/csl/locale.rb', line 186

def legacy?
  version < Schema.major_version
end

#like?(other) ⇒ Boolean

Returns:

  • (Boolean)


400
401
402
403
404
405
# File 'lib/csl/locale.rb', line 400

def like?(other)
  return false unless other.is_a? Locale
  return true  if other.universal?

  language == other.language
end

#limit_day_ordinals!Object



290
291
292
293
294
295
296
# File 'lib/csl/locale.rb', line 290

def limit_day_ordinals!
  unless has_options?
    children[:'style-options'] = StyleOptions.new
  end

  options[:'limit-day-ordinals-to-day-1'] = true
end

#limit_day_ordinals?Boolean

Returns true when the option limit-day-ordinals-to-day-1 is true.

Returns:

  • (Boolean)

    true when the option limit-day-ordinals-to-day-1 is true



285
286
287
288
# File 'lib/csl/locale.rb', line 285

def limit_day_ordinals?
  return false unless has_options? && options.attribute?(:'limit-day-ordinals-to-day-1')
  !!(options[:'limit-day-ordinals-to-day-1'].to_s =~ /^true$/i)
end

#merge(*others) ⇒ Locale

Returns:



420
421
422
# File 'lib/csl/locale.rb', line 420

def merge(*others)
  deep_copy.merge!(*others)
end

#merge!(*others) ⇒ self

Returns:

  • (self)


425
426
427
428
429
430
431
432
433
# File 'lib/csl/locale.rb', line 425

def merge!(*others)
  others.each do |other|
    merge_options other
    merge_dates other
    merge_terms other
  end

  self
end

#ordinalize(number, options = {}) ⇒ String

Note:

For CSL 1.0 (and older) locales that do not define an “ordinal-00” term the algorithm specified by CSL 1.0 is used; otherwise uses the CSL 1.0.1 algorithm with improved support for languages other than English.

Ordinalizes the passed-in number using either the ordinal or long-ordinal forms defined by the locale. If a long-ordinal form is requested but not available, the regular ordinal will be returned instead.

Examples:

Locale.load('en').ordinalize(13)
#-> "13th"

de = Locale.load('de')
de.ordinalize(13)
#-> "13."

de.ordinalize(3, :form => :long, :gender => :feminine)
#-> "dritte"

Parameters:

  • number (#to_i)

    the number to ordinalize

  • options (Hash) (defaults to: {})

    formatting options

Options Hash (options):

  • :form (:short, :long) — default: :short

    which ordinals form to use

  • :gender (:feminine, :masculine, :neutral) — default: :neutral

    which ordinals gender-form to use

Returns:

  • (String)

    the ordinal for the passed-in number

Raises:

  • (ArgumentError)

    if number cannot be converted to an integer



271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/csl/locale.rb', line 271

def ordinalize(number, options = {})
  raise ArgumentError, "unable to ordinalize #{number}; integer expected" unless
    number.respond_to?(:to_i)

  number = number.to_i
  ordinal = terms.ordinalize number, options

  return number.to_s if ordinal.nil?
  return ordinal.to_s(options) if ordinal.long_ordinal?

  [number, ordinal.to_s(options)].join
end

#punctuation_in_quote!Object Also known as: punctuation_in_quotes!



305
306
307
308
309
310
311
# File 'lib/csl/locale.rb', line 305

def punctuation_in_quote!
  unless has_options?
    children[:'style-options'] = StyleOptions.new
  end

  options[:'punctuation-in-quote'] = true
end

#punctuation_in_quote?Boolean Also known as: punctuation_in_quotes?

Returns true when the option punctuation-in-quote is true.

Returns:

  • (Boolean)

    true when the option punctuation-in-quote is true



299
300
301
302
# File 'lib/csl/locale.rb', line 299

def punctuation_in_quote?
  return false unless has_options? && options.attribute?(:'punctuation-in-quote')
  !!(options[:'punctuation-in-quote'].to_s =~ /^true$/i)
end

#quote(string, escape = false) ⇒ String

Puts localized quotes around the passed-in string.

Returns:

  • (String)

    the quoted string



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/csl/locale.rb', line 316

def quote(string, escape = false)
  oq, cq = t('open-quote'), t('close-quote')

  return string if oq.nil? || cq.nil? || (oq.empty? && cq.empty?)

  if escape
    oq = CSL.encode_xml_text(oq)
    cq = CSL.encode_xml_text(cq)
  end

  string = replace_with_inner_quotes(string, oq, cq, escape)

  if punctuation_in_quotes?
    "#{oq}#{string}#{cq}"
  else
    string, punctuation = string.split(/([\.,])$/, 2)

    "#{oq}#{string}#{cq}#{punctuation}"
  end
end

#replace_with_inner_quotes(string, open, close, escape = false) ⇒ Object



337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/csl/locale.rb', line 337

def replace_with_inner_quotes(string, open, close, escape = false)
  oq, cq = t('open-inner-quote'), t('close-inner-quote')

  return string if oq.nil? || cq.nil? || (oq.empty? && cq.empty?)

  if escape
    oq = CSL.encode_xml_text(oq)
    cq = CSL.encode_xml_text(cq)
  end

  string.gsub(/(#{open}|"\b)/, oq).gsub(/(#{close}|\b")/, cq)
end

#reverse_merge(other) ⇒ Object



435
436
437
# File 'lib/csl/locale.rb', line 435

def reverse_merge(other)
  other.merge(self)
end

#set(locale) ⇒ self

Sets language and region according to the passed-in locale string. If the region part is not defined by the string, this method will set the region to the default region for the given language.

Examples:

locale.set('en')    #-> sets language to :en, region to :US
locale.set('de-AT') #-> sets language to :de, region to :AT
locale.set('-DE')   #-> sets langauge to :de, region to :DE

Returns:

  • (self)

Raises:

  • (ArgumentError)

    if the argument is no valid locale string. A valid locale string is based on the syntax of IETF language tags; it consists of either a language or region tag (or both), separated by a hyphen.



205
206
207
208
209
# File 'lib/csl/locale.rb', line 205

def set(locale)
  @language, *rs = Locale.normalize(locale).split(/-/).map(&:to_sym)
  @region, @script = rs.reverse
  self
end

#store(*arguments) ⇒ Object Also known as: learn

Stores a translation in the locale’s term registry.



229
230
231
232
233
234
235
236
# File 'lib/csl/locale.rb', line 229

def store(*arguments)
  unless has_terms?
    self << CSL::Locale::Terms.new
  end

  terms.store(*arguments)
  self
end

#to_sString

Returns the Locale’s IETF tag.

Returns:

  • (String)

    the Locale’s IETF tag



474
475
476
# File 'lib/csl/locale.rb', line 474

def to_s
  [language, script, region].compact.join('-')
end

#translate(name, options = {}) ⇒ String? Also known as: t

Returns the term’s translation.

Returns:

  • (String, nil)

    the term’s translation



219
220
221
222
223
224
# File 'lib/csl/locale.rb', line 219

def translate(name, options = {})
  return unless has_terms?

  term = terms.lookup name, options
  term && term.to_s(options)
end

#universal?Boolean

Returns:

  • (Boolean)


407
408
409
# File 'lib/csl/locale.rb', line 407

def universal?
  language.nil?
end

#valid?Boolean

Returns:

  • (Boolean)


415
416
417
# File 'lib/csl/locale.rb', line 415

def valid?
  validate.empty?
end

#validateObject



411
412
413
# File 'lib/csl/locale.rb', line 411

def validate
  Schema.validate self
end

#versionObject



165
166
167
# File 'lib/csl/locale.rb', line 165

def version
  attributes[:version]
end

#version=(version) ⇒ Object

Raises:

  • (ArgumentError)


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/csl/locale.rb', line 169

def version=(version)
  raise ArgumentError, "failed to set version to #{version}" unless
    version.respond_to?(:to_s)

  version = version.to_s.strip

  raise ArgumentError, "failed to set version to #{version}: not a version string" unless
    version =~ /^\d[\d\.]+$/

  if version > Schema.version
    warn "setting version to #{version}; latest supported version is #{Schema.version}"
  end

  attributes[:version] = version
end