csl 1.0.0.pre12 → 1.0.0.pre13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/AGPL CHANGED
@@ -631,7 +631,7 @@ the "copyright" line and a pointer to where the full notice is found.
631
631
 
632
632
  CSL-Ruby. A Ruby CSL parser and library.
633
633
  Copyright 2012 President and Fellows of Harvard College.
634
- Copyright 2009-2012 Sylvester Keil. All rights reserved.
634
+ Copyright 2009-2013 Sylvester Keil. All rights reserved.
635
635
 
636
636
  This program is free software: you can redistribute it and/or modify
637
637
  it under the terms of the GNU Affero General Public License as published by
data/BSDL CHANGED
@@ -1,7 +1,7 @@
1
1
  CSL-Ruby. A Ruby CSL parser and library.
2
2
 
3
3
  Copyright 2012 President and Fellows of Harvard College.
4
- Copyright 2009-2012 Sylvester Keil. All rights reserved.
4
+ Copyright 2009-2013 Sylvester Keil. All rights reserved.
5
5
 
6
6
  Redistribution and use in source and binary forms, with or without
7
7
  modification, are permitted provided that the following conditions are met:
data/README.md CHANGED
@@ -45,7 +45,7 @@ Copyright
45
45
  ---------
46
46
  Copyright 2012 President and Fellows of Harvard College.
47
47
 
48
- Copyright 2009-2012 Sylvester Keil. All rights reserved.
48
+ Copyright 2009-2013 Sylvester Keil. All rights reserved.
49
49
 
50
50
  License
51
51
  -------
@@ -66,11 +66,9 @@ Feature: Converting numbers to ordinals using CSL locales
66
66
  <locale xmlns="http://purl.org/net/xbiblio/csl" version="1.0.1" xml:lang="en">
67
67
  <terms>
68
68
  <term name="ordinal">th</term>
69
-
70
69
  <term name="ordinal-01">st</term>
71
70
  <term name="ordinal-02">nd</term>
72
71
  <term name="ordinal-03">rd</term>
73
-
74
72
  <term name="ordinal-11">th</term>
75
73
  <term name="ordinal-12">th</term>
76
74
  <term name="ordinal-13">th</term>
@@ -97,9 +95,9 @@ Feature: Converting numbers to ordinals using CSL locales
97
95
  | 112 | | | |
98
96
  | 113 | | | |
99
97
  | -102 | | | |
100
- # | 1 | | masculine | |
101
- # | 2 | | feminine | |
102
- # | 3 | | | plural |
98
+ | 1 | | masculine | |
99
+ | 2 | | feminine | |
100
+ | 3 | | | plural |
103
101
  Then the ordinals should be:
104
102
  | ordinal |
105
103
  | 0th |
@@ -120,9 +118,9 @@ Feature: Converting numbers to ordinals using CSL locales
120
118
  | 112th |
121
119
  | 113th |
122
120
  | -102nd |
123
- # | 1st |
124
- # | 2nd |
125
- # | 3rd |
121
+ | 1st |
122
+ | 2nd |
123
+ | 3rd |
126
124
 
127
125
  @v1.0.1 @locale @ordinals @i18n @gender @lang-de
128
126
  Scenario: Gendered German CSL 1.0.1 locales
@@ -196,7 +194,6 @@ Feature: Converting numbers to ordinals using CSL locales
196
194
  <single>e</single>
197
195
  <multiple>es</multiple>
198
196
  </term>
199
-
200
197
  <term name="ordinal-01" match="whole-number">
201
198
  <single>re</single>
202
199
  <multiple>res</multiple>
@@ -268,24 +265,23 @@ Feature: Converting numbers to ordinals using CSL locales
268
265
 
269
266
  <term name="ordinal-00" match="whole-number">de</term>
270
267
 
271
- <term name="ordinal-02" match="2-digits">de</term>
272
- <term name="ordinal-03" match="2-digits">de</term>
273
- <term name="ordinal-04" match="2-digits">de</term>
274
- <term name="ordinal-05" match="2-digits">de</term>
275
- <term name="ordinal-06" match="2-digits">de</term>
276
- <term name="ordinal-07" match="2-digits">de</term>
277
- <term name="ordinal-09" match="2-digits">de</term>
278
-
279
- <term name="ordinal-10" match="2-digits">de</term>
280
- <term name="ordinal-11" match="2-digits">de</term>
281
- <term name="ordinal-12" match="2-digits">de</term>
282
- <term name="ordinal-13" match="2-digits">de</term>
283
- <term name="ordinal-14" match="2-digits">de</term>
284
- <term name="ordinal-15" match="2-digits">de</term>
285
- <term name="ordinal-16" match="2-digits">de</term>
286
- <term name="ordinal-17" match="2-digits">de</term>
287
- <term name="ordinal-18" match="2-digits">de</term>
288
- <term name="ordinal-19" match="2-digits">de</term>
268
+ <term name="ordinal-02" match="last-two-digits">de</term>
269
+ <term name="ordinal-03" match="last-two-digits">de</term>
270
+ <term name="ordinal-04" match="last-two-digits">de</term>
271
+ <term name="ordinal-05" match="last-two-digits">de</term>
272
+ <term name="ordinal-06" match="last-two-digits">de</term>
273
+ <term name="ordinal-07" match="last-two-digits">de</term>
274
+ <term name="ordinal-09" match="last-two-digits">de</term>
275
+ <term name="ordinal-10">de</term>
276
+ <term name="ordinal-11">de</term>
277
+ <term name="ordinal-12">de</term>
278
+ <term name="ordinal-13">de</term>
279
+ <term name="ordinal-14">de</term>
280
+ <term name="ordinal-15">de</term>
281
+ <term name="ordinal-16">de</term>
282
+ <term name="ordinal-17">de</term>
283
+ <term name="ordinal-18">de</term>
284
+ <term name="ordinal-19">de</term>
289
285
  </terms>
290
286
  </locale>
291
287
  """
@@ -375,24 +371,23 @@ Feature: Converting numbers to ordinals using CSL locales
375
371
  <terms>
376
372
  <term name="ordinal">ste</term>
377
373
 
378
- <term name="ordinal-02" match="2-digits">de</term>
379
- <term name="ordinal-03" match="2-digits">de</term>
380
- <term name="ordinal-04" match="2-digits">de</term>
381
- <term name="ordinal-05" match="2-digits">de</term>
382
- <term name="ordinal-06" match="2-digits">de</term>
383
- <term name="ordinal-07" match="2-digits">de</term>
384
- <term name="ordinal-09" match="2-digits">de</term>
385
-
386
- <term name="ordinal-10" match="2-digits">de</term>
387
- <term name="ordinal-11" match="2-digits">de</term>
388
- <term name="ordinal-12" match="2-digits">de</term>
389
- <term name="ordinal-13" match="2-digits">de</term>
390
- <term name="ordinal-14" match="2-digits">de</term>
391
- <term name="ordinal-15" match="2-digits">de</term>
392
- <term name="ordinal-16" match="2-digits">de</term>
393
- <term name="ordinal-17" match="2-digits">de</term>
394
- <term name="ordinal-18" match="2-digits">de</term>
395
- <term name="ordinal-19" match="2-digits">de</term>
374
+ <term name="ordinal-02" match="last-two-digits">de</term>
375
+ <term name="ordinal-03" match="last-two-digits">de</term>
376
+ <term name="ordinal-04" match="last-two-digits">de</term>
377
+ <term name="ordinal-05" match="last-two-digits">de</term>
378
+ <term name="ordinal-06" match="last-two-digits">de</term>
379
+ <term name="ordinal-07" match="last-two-digits">de</term>
380
+ <term name="ordinal-09" match="last-two-digits">de</term>
381
+ <term name="ordinal-10">de</term>
382
+ <term name="ordinal-11">de</term>
383
+ <term name="ordinal-12">de</term>
384
+ <term name="ordinal-13">de</term>
385
+ <term name="ordinal-14">de</term>
386
+ <term name="ordinal-15">de</term>
387
+ <term name="ordinal-16">de</term>
388
+ <term name="ordinal-17">de</term>
389
+ <term name="ordinal-18">de</term>
390
+ <term name="ordinal-19">de</term>
396
391
  </terms>
397
392
  </locale>
398
393
  """
@@ -641,171 +636,3 @@ Feature: Converting numbers to ordinals using CSL locales
641
636
  | 21º |
642
637
  | 21º |
643
638
  | 1001º |
644
-
645
- # @v1.0.1 @locale @ordinals @i18n @gender @lang-sv
646
- # Scenario: Gendered Swedish CSL 1.0.1 locales
647
- # Given the locale:
648
- # """
649
- # <?xml version="1.0" encoding="utf-8"?>
650
- # <locale xmlns="http://purl.org/net/xbiblio/csl" version="1.0.1" xml:lang="sv">
651
- # <terms>
652
- # <term name="ordinal-00">:e</term>
653
- #
654
- # <term name="ordinal-01">:a</term>
655
- # <term name="ordinal-01" gender-form="masculine">:e</term>
656
- # <term name="ordinal-01" gender-form="feminine">:a</term>
657
- #
658
- # <term name="ordinal-02">:a</term>
659
- # <term name="ordinal-02" gender-form="masculine">:e</term>
660
- # <term name="ordinal-02" gender-form="feminine">:a</term>
661
- #
662
- # <term name="ordinal-11">:e</term>
663
- # <term name="ordinal-11" gender-form="feminine">:e</term>
664
- # <term name="ordinal-12">:e</term>
665
- # <term name="ordinal-12" gender-form="feminine">:e</term>
666
- #
667
- # <term name="ordinal-21">:e</term>
668
- # <term name="ordinal-21" gender-form="feminine">:e</term>
669
- # <term name="ordinal-22">:e</term>
670
- # <term name="ordinal-22" gender-form="feminine">:e</term>
671
- #
672
- # <term name="ordinal-31">:e</term>
673
- # <term name="ordinal-32">:e</term>
674
- #
675
- # <term name="ordinal-41">:e</term>
676
- # <term name="ordinal-42">:e</term>
677
- #
678
- # <term name="ordinal-51">:e</term>
679
- # <term name="ordinal-52">:e</term>
680
- #
681
- # <term name="ordinal-61">:e</term>
682
- # <term name="ordinal-62">:e</term>
683
- #
684
- # <term name="ordinal-71">:e</term>
685
- # <term name="ordinal-72">:e</term>
686
- #
687
- # <term name="ordinal-81">:e</term>
688
- # <term name="ordinal-82">:e</term>
689
- #
690
- # <term name="ordinal-91">:e</term>
691
- # <term name="ordinal-92">:e</term>
692
- # </terms>
693
- # </locale>
694
- # """
695
- # When I ordinalize these numbers:
696
- # | num | form | gender | number |
697
- # | 0 | | | |
698
- # | 1 | | | |
699
- # | 2 | | | |
700
- # | 3 | | | |
701
- # | 4 | | | |
702
- # | 5 | | | |
703
- # | 6 | | | |
704
- # | 7 | | | |
705
- # | 8 | | | |
706
- # | 9 | | | |
707
- # | 10 | | | |
708
- # | 1 | | feminine | |
709
- # | 1 | | masculine | |
710
- # | 2 | | feminine | |
711
- # | 2 | | masculine | |
712
- # | 23 | | | |
713
- # | 999 | | | |
714
- # | 11 | | | |
715
- # | 11 | | feminine | |
716
- # | 11 | | masculine | |
717
- # | 21 | | | |
718
- # # | 101 | | | |
719
- # # | 1001 | | feminine | |
720
- # # | 301 | | | |
721
- # | 21 | | masculine | singular |
722
- # | 21 | | masculine | plural |
723
- # # | 1001 | | masculine | |
724
- # Then the ordinals should be:
725
- # | ordinal |
726
- # | 0:e |
727
- # | 1:a |
728
- # | 2:a |
729
- # | 3:e |
730
- # | 4:e |
731
- # | 5:e |
732
- # | 6:e |
733
- # | 7:e |
734
- # | 8:e |
735
- # | 9:e |
736
- # | 10:e |
737
- # | 1:a |
738
- # | 1:e |
739
- # | 2:a |
740
- # | 2:e |
741
- # | 23:e |
742
- # | 999:e |
743
- # | 11:e |
744
- # | 11:e |
745
- # | 11:e |
746
- # | 21:e |
747
- # # | 101:e |
748
- # # | 1001:e |
749
- # # | 301:e |
750
- # | 21:e |
751
- # | 21:e |
752
- # # | 1001:e |
753
-
754
- # @v1.0.1 @locale @ordinals @i18n @gender @lang-pl
755
- # Scenario: Gendered Polish CSL 1.0.1 locales
756
- # Given the locale:
757
- # """
758
- # <?xml version="1.0" encoding="utf-8"?>
759
- # <locale xmlns="http://purl.org/net/xbiblio/csl" version="1.0.1" xml:lang="pl">
760
- # <terms>
761
- # <term name="ordinal-00">:e</term>
762
- #
763
- # </terms>
764
- # </locale>
765
- # """
766
- # When I ordinalize these numbers:
767
- # | num | form | gender | number |
768
- # | 0 | | | |
769
- # | 1 | | | |
770
- # | 2 | | | |
771
- # | 3 | | | |
772
- # | 4 | | | |
773
- # | 5 | | | |
774
- # | 6 | | | |
775
- # | 7 | | | |
776
- # | 8 | | | |
777
- # | 9 | | | |
778
- # | 10 | | | |
779
- # | 1 | | feminine | |
780
- # | 1 | | masculine | |
781
- # | 2 | | feminine | |
782
- # | 2 | | masculine | |
783
- # | 23 | | | |
784
- # | 999 | | | |
785
- # | 11 | | | |
786
- # | 11 | | feminine | |
787
- # | 11 | | masculine | |
788
- # | 21 | | | |
789
- # Then the ordinals should be:
790
- # | ordinal |
791
- # | 0:e |
792
- # | 1:a |
793
- # | 2:a |
794
- # | 3:e |
795
- # | 4:e |
796
- # | 5:e |
797
- # | 6:e |
798
- # | 7:e |
799
- # | 8:e |
800
- # | 9:e |
801
- # | 10:e |
802
- # | 1:a |
803
- # | 1:e |
804
- # | 2:a |
805
- # | 2:e |
806
- # | 23:e |
807
- # | 999:e |
808
- # | 11:e |
809
- # | 11:e |
810
- # | 11:e |
811
- # | 21:e |
@@ -7,7 +7,7 @@ When /^I load the locale from the string$/ do |string|
7
7
  end
8
8
 
9
9
  When /^I ordinalize the number (\d+)(?: using the (long) form(?: and (feminine|masculine) gender))?$/ do |num, form, gender|
10
- @ordinal = @locale.ordinalize(num, :form => form, :gender => gender)
10
+ @ordinal = @locale.ordinalize(num, :form => form, :'gender-form' => gender)
11
11
  end
12
12
 
13
13
  Then /^the ordinal should (?:be|equal) "([^"]*)"$/ do |ord|
@@ -17,7 +17,7 @@ end
17
17
  When /^I ordinalize these numbers:?$/ do |table|
18
18
  @ordinals = table.rows.map do |row|
19
19
  num, form, gender, number = *row
20
- @csl.ordinalize(num, :form => form, :gender => gender, :number => number)
20
+ @csl.ordinalize(num, :form => form, :'gender-form' => gender, :number => number)
21
21
  end
22
22
  end
23
23
 
data/lib/csl.rb CHANGED
@@ -25,7 +25,6 @@ require 'csl/node'
25
25
  require 'csl/info'
26
26
 
27
27
  require 'csl/locale'
28
- require 'csl/locale/ordinalize'
29
28
  require 'csl/locale/date'
30
29
  require 'csl/locale/term'
31
30
  require 'csl/locale/style_options'
data/lib/csl/locale.rb CHANGED
@@ -202,6 +202,51 @@ module CSL
202
202
  end
203
203
  alias t translate
204
204
 
205
+ # Ordinalizes the passed-in number using either the ordinal or
206
+ # long-ordinal forms defined by the locale. If a long-ordinal form is
207
+ # requested but not available, the regular ordinal will be returned
208
+ # instead.
209
+ #
210
+ # @example
211
+ # Locale.load('en').ordinalize(13)
212
+ # #-> "13th"
213
+ #
214
+ # de = Locale.load('de')
215
+ # de.ordinalize(13)
216
+ # #-> "13."
217
+ #
218
+ # de.ordinalize(3, :form => :long, :gender => :feminine)
219
+ # #-> "dritte"
220
+ #
221
+ # @note
222
+ # For CSL 1.0 (and older) locales that do not define an "ordinal-00"
223
+ # term the algorithm specified by CSL 1.0 is used; otherwise uses the
224
+ # CSL 1.0.1 algorithm with improved support for languages other than
225
+ # English.
226
+ #
227
+ # @param number [#to_i] the number to ordinalize
228
+ # @param options [Hash] formatting options
229
+ #
230
+ # @option options [:short,:long] :form (:short) which ordinals form to use
231
+ # @option options [:feminine,:masculine,:neutral] :gender (:neutral)
232
+ # which ordinals gender-form to use
233
+ #
234
+ # @raise [ArgumentError] if number cannot be converted to an integer
235
+ #
236
+ # @return [String] the ordinal for the passed-in number
237
+ def ordinalize(number, options = {})
238
+ raise ArgumentError, "unable to ordinalize #{number}; integer expected" unless
239
+ number.respond_to?(:to_i)
240
+
241
+ number = number.to_i
242
+ ordinal = terms.ordinalize number, options
243
+
244
+ return number.to_s if ordinal.nil?
245
+ return ordinal.to_s(options) if ordinal.long_ordinal?
246
+
247
+ [number, ordinal.to_s(options)].join
248
+ end
249
+
205
250
  # @example
206
251
  # locale.each_term { |term| block } #-> locale
207
252
  # locale.each_term #-> enumerator
@@ -23,58 +23,107 @@ module CSL
23
23
 
24
24
  # @return [Term, nil] the first term that matches the query
25
25
  def lookup(name, options = {})
26
+ options = Term.specialize(options)
26
27
  options[:name] = name = name.to_s
27
28
 
28
- # specialize search conditions
29
- conditions = options.select { |k,_| Term::Attributes.keys.include?(k.to_sym) }
29
+ term = registry[name].detect { |t| t.match?(options) }
30
+ return term unless term.nil? && options.delete(:'gender-form')
30
31
 
31
- term = registry[name].detect { |t| t.match?(conditions) }
32
- return term unless term.nil? && conditions.delete(:'gender-form')
33
-
34
- registry[name].detect { |t| t.match?(conditions) }
32
+ registry[name].detect { |t| t.match?(options) }
35
33
  end
36
34
  alias [] lookup
37
35
 
38
- def ordinalize_modulo(number, divisor, options = {})
39
- ordinal = ordinalize(number, options)
40
- return unless ordinal && ordinal.match_modulo?(divisor)
41
- ordinal
42
- end
43
-
44
36
  def ordinalize(number, options = {})
45
37
  return unless has_ordinals?
46
38
 
47
- if number == :default
48
- options[:name] = 'ordinal'
39
+ options = Term.specialize(options)
40
+ number = number.to_i.abs
41
+
42
+ # try to match long-ordinals first
43
+ if options.delete(:form).to_s =~ /^long/i
44
+ ordinal = lookup_long_ordinal_for number, options
45
+ return ordinal unless ordinal.nil?
46
+ end
47
+
48
+ # select CSL 1.0 or 1.0.1 algorithm
49
+ algorithm = ordinalizer
50
+
51
+ ordinal = send algorithm, number, options
52
+ return ordinal unless ordinal.nil?
53
+
54
+ # fallback to non-gendered version
55
+ if options.delete(:'gender-form')
56
+ ordinal = send algorithm, number, options
57
+ end
58
+
59
+ ordinal
60
+ end
61
+
62
+ def ordinalizer
63
+ if has_legacy_ordinals?
64
+ :lookup_legacy_ordinals_for
49
65
  else
50
- options[:name] = 'ordinal-%02d' % number
66
+ :lookup_ordinals_for
67
+ end
68
+ end
69
+
70
+ def lookup_long_ordinal_for(number, options = {})
71
+ ordinals[number].detect { |t| t.long_ordinal? && t.match?(options) }
72
+ end
73
+
74
+ def lookup_ordinals_for(number, options = {})
75
+ ordinal = lookup_ordinal_for(number, nil, options)
76
+ return ordinal unless ordinal.nil?
77
+
78
+ unless number < 100
79
+ ordinal = lookup_ordinal_for(number, 100, options)
80
+ return ordinal unless ordinal.nil?
51
81
  end
52
82
 
53
- if options[:form].to_s =~ /^long/i
54
- options.delete :form
55
- options[:name][0,0] = 'long-'
83
+ unless number < 10
84
+ ordinal = lookup_ordinal_for(number, 10, options)
85
+ return ordinal unless ordinal.nil?
56
86
  end
57
87
 
58
- ordinal = ordinals[number].detect { |t| t.match?(options) }
59
- return ordinal unless ordinal.nil? && options.delete(:'gender-form')
88
+ default_ordinals.detect { |t| t.match?(options) }
89
+ end
90
+
91
+ def lookup_ordinal_for(number, divisor, options = {})
92
+ modulus = divisor ? (number % divisor) : number
93
+ ordinals[modulus].detect do |t|
94
+ t.short_ordinal? && t.match?(options) && t.match_modulo?(number)
95
+ end
96
+ end
60
97
 
61
- ordinals[number].detect { |t| t.match?(options) }
98
+ def lookup_legacy_ordinals_for(number, options = {})
99
+ case
100
+ when (11..13).include?(number.abs % 100)
101
+ ordinals[4].detect { |t| t.match?(options) }
102
+ when (1..3).include?(number.abs % 10)
103
+ ordinals[number.abs % 10].detect { |t| t.match?(options) }
104
+ else
105
+ ordinals[4].detect { |t| t.match?(options) }
106
+ end
62
107
  end
63
108
 
64
109
  # @return [Boolean] whether or not regular terms are registered at this node
65
110
  def has_terms?
66
- not registry.empty?
111
+ !registry.empty?
67
112
  end
68
113
 
69
114
  # @return [Boolean] whether or not ordinal terms are registered at this node
70
115
  def has_ordinals?
71
- not ordinals.empty?
116
+ !ordinals.empty?
72
117
  end
73
118
 
74
119
  def has_legacy_ordinals?
75
120
  has_ordinals? && !ordinals.key?(:default)
76
121
  end
77
122
 
123
+ def default_ordinals
124
+ ordinals[:default]
125
+ end
126
+
78
127
  def drop_ordinals
79
128
  tmp = ordinals.values.flatten(1)
80
129
  ordinals.clear
@@ -128,25 +177,39 @@ module CSL
128
177
 
129
178
  def_delegators :attributes, :hash, :eql?, :name, :form, :gender
130
179
 
180
+ class << self
181
+ def specialize(options)
182
+ options = options.select do |k,v|
183
+ !v.nil? && Term::Attributes.keys.include?(k.to_sym)
184
+ end
185
+
186
+ options.delete :'gender-form' unless
187
+ options[:'gender-form'].to_s =~ /^masculine|feminine$/
188
+
189
+ options
190
+ end
191
+ end
192
+
131
193
  # This method returns whether or not the ordinal term matchs the
132
194
  # passed-in modulus. This is determined by the ordinal term's match
133
- # attribute: a value of '2-digits' matches a divisor of 100, '1-digit'
134
- # matches a divisor of 10 and 'whole-number' matches a divisor of 1.
195
+ # attribute: a value of 'last-two-digits' matches a modulus of 100,
196
+ # 'last-digit' matches a modulus of 10 and 'whole-number' matches
197
+ # only if the number is identical to the ordinal value.
135
198
  #
136
199
  # If the term is no ordinal term, this methods always returns false.
137
200
  #
138
201
  # @return [Boolean] whether or not the ordinal term matches the
139
- # passed-in divisor.
140
- def match_modulo?(divisor)
202
+ # passed-in number.
203
+ def match_modulo?(number)
141
204
  return false unless ordinal?
142
205
 
143
206
  case attributes.match
144
- when '2-digits'
145
- divisor.to_i == 100
146
- when '1-digit'
147
- divisor.to_i == 10
207
+ when 'last-two-digits'
208
+ ordinal == number % 100
209
+ when 'last-digit'
210
+ ordinal == number % 10
148
211
  when 'whole-number'
149
- divisor.to_i == 1
212
+ ordinal == number
150
213
  else
151
214
  true
152
215
  end
@@ -158,13 +221,27 @@ module CSL
158
221
  /^(long-)?ordinal(-\d\d+)?$/ === attributes.name
159
222
  end
160
223
 
224
+ # @return [Boolean] whether or not this term is a long-ordinal term
225
+ def long_ordinal?
226
+ /^long-ordinal(-\d\d+)?$/ === attributes.name
227
+ end
228
+
229
+ # @return [Boolean] whether or not this term is a regular ordinal term
230
+ def short_ordinal?
231
+ /^ordinal(-\d\d+)?$/ === attributes.name
232
+ end
233
+
234
+ def default_ordinal?
235
+ attributes.name == 'ordinal'
236
+ end
237
+
161
238
  # @return [Fixnum, :default, nil]
162
239
  def ordinal
163
240
  return unless ordinal?
164
241
  return :default if attributes.name == 'ordinal'
165
242
  attributes.name[/\d+/].to_i
166
243
  end
167
-
244
+
168
245
  def gendered?
169
246
  !attributes.gender.blank?
170
247
  end
data/lib/csl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CSL
2
- VERSION = '1.0.0.pre12'.freeze
2
+ VERSION = '1.0.0.pre13'.freeze
3
3
  end
@@ -81,6 +81,10 @@ module CSL
81
81
 
82
82
  it { should be_neutral }
83
83
 
84
+ it { should_not be_ordinal }
85
+ it { should_not be_short_ordinal }
86
+ it { should_not be_long_ordinal }
87
+
84
88
  it 'is not a textnode by default' do
85
89
  subject.should_not be_textnode
86
90
  end
@@ -22,7 +22,7 @@
22
22
  <term name="anonymous">ohne Autor</term>
23
23
  <term name="anonymous" form="short">o. A.</term>
24
24
  <term name="at">auf</term>
25
- <term name="available at">available at</term>
25
+ <term name="available at">verfügbar unter</term>
26
26
  <term name="by">von</term>
27
27
  <term name="circa">circa</term>
28
28
  <term name="circa" form="short">ca.</term>
@@ -54,8 +54,8 @@
54
54
  <multiple>Ref.</multiple>
55
55
  </term>
56
56
  <term name="retrieved">abgerufen</term>
57
- <term name="scale">scale</term>
58
- <term name="version">version</term>
57
+ <term name="scale">Maßstab</term>
58
+ <term name="version">Version</term>
59
59
 
60
60
  <!-- ANNO DOMINI; BEFORE CHRIST -->
61
61
  <term name="ad">n. Chr.</term>
@@ -190,13 +190,9 @@
190
190
  </term>
191
191
 
192
192
  <!-- LONG ROLE FORMS -->
193
- <term name="author">
194
- <single/>
195
- <multiple/>
196
- </term>
197
193
  <term name="director">
198
- <single>director</single>
199
- <multiple>directors</multiple>
194
+ <single>Regisseur</single>
195
+ <multiple>Regisseure</multiple>
200
196
  </term>
201
197
  <term name="editor">
202
198
  <single>Herausgeber</single>
@@ -207,8 +203,8 @@
207
203
  <multiple>Herausgeber</multiple>
208
204
  </term>
209
205
  <term name="illustrator">
210
- <single>illustrator</single>
211
- <multiple>illustrators</multiple>
206
+ <single>Illustrator</single>
207
+ <multiple>illustratoren</multiple>
212
208
  </term>
213
209
  <term name="translator">
214
210
  <single>Übersetzer</single>
@@ -220,13 +216,9 @@
220
216
  </term>
221
217
 
222
218
  <!-- SHORT ROLE FORMS -->
223
- <term name="author" form="short">
224
- <single/>
225
- <multiple/>
226
- </term>
227
219
  <term name="director" form="short">
228
- <single>dir.</single>
229
- <multiple>dirs.</multiple>
220
+ <single>Reg.</single>
221
+ <multiple>Reg..</multiple>
230
222
  </term>
231
223
  <term name="editor" form="short">
232
224
  <single>Hrsg.</single>
@@ -237,8 +229,8 @@
237
229
  <multiple>Hrsg.</multiple>
238
230
  </term>
239
231
  <term name="illustrator" form="short">
240
- <single>ill.</single>
241
- <multiple>ills.</multiple>
232
+ <single>Ill.</single>
233
+ <multiple>Ill.</multiple>
242
234
  </term>
243
235
  <term name="translator" form="short">
244
236
  <single>Übers.</single>
@@ -253,19 +245,19 @@
253
245
  <term name="director" form="verb">directed by</term>
254
246
  <term name="editor" form="verb">herausgegeben von</term>
255
247
  <term name="editorial-director" form="verb">herausgegeben von</term>
256
- <term name="illustrator" form="verb">illustrated by</term>
248
+ <term name="illustrator" form="verb">illustriert von</term>
257
249
  <term name="interviewer" form="verb">interviewt von</term>
258
250
  <term name="recipient" form="verb">an</term>
259
- <term name="reviewed-author" form="verb">by</term>
251
+ <term name="reviewed-author" form="verb">von</term>
260
252
  <term name="translator" form="verb">übersetzt von</term>
261
253
  <term name="editortranslator" form="verb">herausgegeben und übersetzt von</term>
262
254
 
263
255
  <!-- SHORT VERB ROLE FORMS -->
264
256
  <term name="container-author" form="verb-short">von</term>
265
- <term name="director" form="verb-short">dir.</term>
257
+ <term name="director" form="verb-short">Reg.</term>
266
258
  <term name="editor" form="verb-short">hg. von</term>
267
259
  <term name="editorial-director" form="verb-short">hg. von</term>
268
- <term name="illustrator" form="verb-short">illus.</term>
260
+ <term name="illustrator" form="verb-short">illus. von</term>
269
261
  <term name="translator" form="verb-short">übers. von</term>
270
262
  <term name="editortranslator" form="verb-short">hg. &amp; übers. von</term>
271
263
 
@@ -196,10 +196,6 @@
196
196
  </term>
197
197
 
198
198
  <!-- LONG ROLE FORMS -->
199
- <term name="author">
200
- <single/>
201
- <multiple/>
202
- </term>
203
199
  <term name="director">
204
200
  <single>director</single>
205
201
  <multiple>directors</multiple>
@@ -226,10 +222,6 @@
226
222
  </term>
227
223
 
228
224
  <!-- SHORT ROLE FORMS -->
229
- <term name="author" form="short">
230
- <single/>
231
- <multiple/>
232
- </term>
233
225
  <term name="director" form="short">
234
226
  <single>dir.</single>
235
227
  <multiple>dirs.</multiple>
@@ -268,11 +260,11 @@
268
260
 
269
261
  <!-- SHORT VERB ROLE FORMS -->
270
262
  <term name="container-author" form="verb-short">by</term>
271
- <term name="director" form="verb-short">dir.</term>
272
- <term name="editor" form="verb-short">ed.</term>
273
- <term name="editorial-director" form="verb-short">ed.</term>
274
- <term name="illustrator" form="verb-short">illus.</term>
275
- <term name="translator" form="verb-short">trans.</term>
263
+ <term name="director" form="verb-short">dir. by</term>
264
+ <term name="editor" form="verb-short">ed. by</term>
265
+ <term name="editorial-director" form="verb-short">ed. by</term>
266
+ <term name="illustrator" form="verb-short">illus. by</term>
267
+ <term name="translator" form="verb-short">trans. by</term>
276
268
  <term name="editortranslator" form="verb-short">ed. &amp; trans. by</term>
277
269
 
278
270
  <!-- LONG MONTH FORMS -->
@@ -7,7 +7,7 @@
7
7
  <style-options punctuation-in-quote="true"/>
8
8
  <date form="text">
9
9
  <date-part name="month" suffix=" "/>
10
- <date-part name="day" form="numeric-leading-zeros" suffix=", "/>
10
+ <date-part name="day" suffix=", "/>
11
11
  <date-part name="year"/>
12
12
  </date>
13
13
  <date form="numeric">
@@ -196,10 +196,6 @@
196
196
  </term>
197
197
 
198
198
  <!-- LONG ROLE FORMS -->
199
- <term name="author">
200
- <single/>
201
- <multiple/>
202
- </term>
203
199
  <term name="director">
204
200
  <single>director</single>
205
201
  <multiple>directors</multiple>
@@ -226,10 +222,6 @@
226
222
  </term>
227
223
 
228
224
  <!-- SHORT ROLE FORMS -->
229
- <term name="author" form="short">
230
- <single/>
231
- <multiple/>
232
- </term>
233
225
  <term name="director" form="short">
234
226
  <single>dir.</single>
235
227
  <multiple>dirs.</multiple>
@@ -268,11 +260,11 @@
268
260
 
269
261
  <!-- SHORT VERB ROLE FORMS -->
270
262
  <term name="container-author" form="verb-short">by</term>
271
- <term name="director" form="verb-short">dir.</term>
272
- <term name="editor" form="verb-short">ed.</term>
273
- <term name="editorial-director" form="verb-short">ed.</term>
274
- <term name="illustrator" form="verb-short">illus.</term>
275
- <term name="translator" form="verb-short">trans.</term>
263
+ <term name="director" form="verb-short">dir. by</term>
264
+ <term name="editor" form="verb-short">ed. by</term>
265
+ <term name="editorial-director" form="verb-short">ed. by</term>
266
+ <term name="illustrator" form="verb-short">illus. by</term>
267
+ <term name="translator" form="verb-short">trans. by</term>
276
268
  <term name="editortranslator" form="verb-short">ed. &amp; trans. by</term>
277
269
 
278
270
  <!-- LONG MONTH FORMS -->
@@ -27,11 +27,15 @@
27
27
  <category citation-format="author-date"/>
28
28
  <category field="psychology"/>
29
29
  <category field="generic-base"/>
30
- <updated>2012-09-04T02:31:02+00:00</updated>
31
- <rights>This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/</rights>
30
+ <updated>2012-09-27T22:06:38+00:00</updated>
31
+ <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
32
32
  </info>
33
33
  <locale xml:lang="en">
34
34
  <terms>
35
+ <term name="editortranslator" form="short">
36
+ <single>ed. &amp; trans.</single>
37
+ <multiple>eds. &amp; trans.</multiple>
38
+ </term>
35
39
  <term name="translator" form="short">
36
40
  <single>trans.</single>
37
41
  <multiple>trans.</multiple>
@@ -41,12 +45,9 @@
41
45
  <macro name="container-contributors">
42
46
  <choose>
43
47
  <if type="chapter paper-conference" match="any">
44
- <names variable="editor" delimiter=", " suffix=", ">
48
+ <names variable="editor translator" delimiter=", " suffix=", ">
45
49
  <name and="symbol" initialize-with=". " delimiter=", "/>
46
- <label form="short" prefix=" (" text-case="capitalize-first" suffix=")"/>
47
- <substitute>
48
- <names variable="translator"/>
49
- </substitute>
50
+ <label form="short" prefix=" (" text-case="title" suffix=")"/>
50
51
  </names>
51
52
  </if>
52
53
  </choose>
@@ -54,12 +55,9 @@
54
55
  <macro name="secondary-contributors">
55
56
  <choose>
56
57
  <if type="chapter paper-conference" match="none">
57
- <names variable="translator" delimiter=", " prefix=" (" suffix=")">
58
+ <names variable="translator editor" delimiter=", " prefix=" (" suffix=")">
58
59
  <name and="symbol" initialize-with=". " delimiter=", "/>
59
- <label form="short" prefix=", " text-case="capitalize-first" suffix=""/>
60
- <substitute>
61
- <names variable="editor"/>
62
- </substitute>
60
+ <label form="short" prefix=", " text-case="title" suffix=""/>
63
61
  </names>
64
62
  </if>
65
63
  </choose>
@@ -67,7 +65,7 @@
67
65
  <macro name="author">
68
66
  <names variable="author">
69
67
  <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
70
- <label form="short" prefix=" (" suffix=".)" text-case="capitalize-first" strip-periods="true"/>
68
+ <label form="short" prefix=" (" suffix=")" text-case="capitalize-first"/>
71
69
  <substitute>
72
70
  <names variable="editor"/>
73
71
  <names variable="translator"/>
@@ -136,11 +134,7 @@
136
134
  <group delimiter=" ">
137
135
  <text term="retrieved" text-case="capitalize-first" suffix=" "/>
138
136
  <group>
139
- <date variable="accessed" suffix=", ">
140
- <date-part name="month" suffix=" "/>
141
- <date-part name="day" suffix=", "/>
142
- <date-part name="year"/>
143
- </date>
137
+ <date variable="accessed" form="text" suffix=", "/>
144
138
  </group>
145
139
  <text term="from"/>
146
140
  <text variable="URL"/>
@@ -293,7 +287,7 @@
293
287
  <if is-numeric="edition">
294
288
  <group delimiter=" ">
295
289
  <number variable="edition" form="ordinal"/>
296
- <text term="edition" form="short" suffix="." strip-periods="true"/>
290
+ <text term="edition" form="short"/>
297
291
  </group>
298
292
  </if>
299
293
  <else>
@@ -322,11 +316,11 @@
322
316
  <group prefix=" (" suffix=")" delimiter=", ">
323
317
  <text macro="edition"/>
324
318
  <group>
325
- <text term="volume" form="short" plural="true" text-case="capitalize-first" suffix=". " strip-periods="true"/>
319
+ <text term="volume" form="short" plural="true" text-case="capitalize-first" suffix=" "/>
326
320
  <number variable="number-of-volumes" form="numeric" prefix="1-"/>
327
321
  </group>
328
322
  <group>
329
- <text term="volume" form="short" text-case="capitalize-first" suffix=". " strip-periods="true"/>
323
+ <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>
330
324
  <number variable="volume" form="numeric"/>
331
325
  </group>
332
326
  <group>
@@ -338,11 +332,7 @@
338
332
  <else-if type="legal_case">
339
333
  <group prefix=" (" suffix=")" delimiter=" ">
340
334
  <text variable="authority"/>
341
- <date variable="issued" delimiter=" ">
342
- <date-part name="month" form="short"/>
343
- <date-part name="day" suffix=","/>
344
- <date-part name="year"/>
345
- </date>
335
+ <date variable="issued" form="text"/>
346
336
  </group>
347
337
  </else-if>
348
338
  <else-if type="bill legislation">
@@ -354,16 +344,23 @@
354
344
  </macro>
355
345
  <macro name="citation-locator">
356
346
  <group>
357
- <label variable="locator" form="short"/>
347
+ <choose>
348
+ <if locator="chapter">
349
+ <label variable="locator" form="long" text-case="capitalize-first"/>
350
+ </if>
351
+ <else>
352
+ <label variable="locator" form="short"/>
353
+ </else>
354
+ </choose>
358
355
  <text variable="locator" prefix=" "/>
359
356
  </group>
360
357
  </macro>
361
358
  <macro name="container">
362
359
  <group>
363
360
  <choose>
364
- <if type="chapter paper-conference entry-encyclopedia" match="any">
365
- <text term="in" text-case="capitalize-first" suffix=" "/>
366
- </if>
361
+ <if type="chapter paper-conference entry-encyclopedia" match="any">
362
+ <text term="in" text-case="capitalize-first" suffix=" "/>
363
+ </if>
367
364
  </choose>
368
365
  <text macro="container-contributors"/>
369
366
  <text macro="secondary-contributors"/>
@@ -382,7 +379,7 @@
382
379
  <text variable="volume"/>
383
380
  <text variable="container-title"/>
384
381
  <group delimiter=" ">
385
- <!--change to label variable="section" as that becomes available -->
382
+ <!--change to label variable="section" as that becomes available -->
386
383
  <text term="section" form="symbol"/>
387
384
  <text variable="section"/>
388
385
  </group>
@@ -396,7 +393,7 @@
396
393
  <else>
397
394
  <text variable="number" prefix="Pub. L. No. "/>
398
395
  <group delimiter=" ">
399
- <!--change to label variable="section" as that becomes available -->
396
+ <!--change to label variable="section" as that becomes available -->
400
397
  <text term="section" form="symbol"/>
401
398
  <text variable="section"/>
402
399
  </group>
@@ -432,7 +429,7 @@
432
429
  <text macro="author"/>
433
430
  <text macro="issued"/>
434
431
  <text macro="title" prefix=" "/>
435
- <text macro="container"/>
432
+ <text macro="container"/>
436
433
  </group>
437
434
  <text macro="locators"/>
438
435
  <group delimiter=", " prefix=". ">
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre12
4
+ version: 1.0.0.pre13
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -115,7 +115,6 @@ files:
115
115
  - lib/csl/loader.rb
116
116
  - lib/csl/locale.rb
117
117
  - lib/csl/locale/date.rb
118
- - lib/csl/locale/ordinalize.rb
119
118
  - lib/csl/locale/style_options.rb
120
119
  - lib/csl/locale/term.rb
121
120
  - lib/csl/node.rb
@@ -183,7 +182,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
182
  version: '0'
184
183
  segments:
185
184
  - 0
186
- hash: 1070711312713509519
185
+ hash: -2590038154395651463
187
186
  required_rubygems_version: !ruby/object:Gem::Requirement
188
187
  none: false
189
188
  requirements:
@@ -1,137 +0,0 @@
1
- module CSL
2
- class Locale
3
-
4
- # Ordinalizes the passed-in number using either the ordinal or
5
- # long-ordinal forms defined by the locale. If a long-ordinal form is
6
- # requested but not available, the regular ordinal will be returned
7
- # instead.
8
- #
9
- # @example
10
- # Locale.load('en').ordinalize(13)
11
- # #-> "13th"
12
- #
13
- # de = Locale.load('de')
14
- # de.ordinalize(13)
15
- # #-> "13."
16
- #
17
- # de.ordinalize(3, :form => :long, :gender => :feminine)
18
- # #-> "dritte"
19
- #
20
- # @note
21
- # For CSL 1.0 (and older) locales that do not define an "ordinal-00"
22
- # term the algorithm specified by CSL 1.0 is used; otherwise uses the
23
- # CSL 1.0.1 algorithm with improved support for languages other than
24
- # English.
25
- #
26
- # @param number [#to_i] the number to ordinalize
27
- # @param options [Hash] formatting options
28
- #
29
- # @option options [:short,:long] :form (:short) which ordinals form to use
30
- # @option options [:feminine,:masculine,:neutral] :gender (:neutral)
31
- # which ordinals gender-form to use
32
- #
33
- # @raise [ArgumentError] if number cannot be converted to an integer
34
- #
35
- # @return [String] the ordinal for the passed-in number
36
- def ordinalize(number, options = {})
37
- raise ArgumentError, "unable to ordinalize #{number}; integer expected" unless
38
- number.respond_to?(:to_i)
39
-
40
- number = number.to_i
41
-
42
-
43
-
44
- key = query[:name]
45
-
46
- # Try to match long-ordinals first
47
- if key.start_with?('l')
48
- query[:name] = key % number.abs
49
- ordinal = terms[query]
50
-
51
- if ordinal.nil?
52
- key = 'ordinal-%02d'
53
- else
54
- return ordinal.to_s(options)
55
- end
56
- end
57
-
58
- # CSL 1.0 (legacy algorithm)
59
- return legacy_ordinalize(number) if legacy?
60
-
61
- #
62
- # CSL 1.0.1
63
- #
64
-
65
- # Calculate initial modulus
66
- mod = 10 ** Math.log10([number.abs, 1].max).to_i
67
-
68
- # Try to find direct match first
69
- query.merge! :name => key % number.abs
70
- ordinal = terms[query]
71
-
72
- # Try to match modulus of number, dividing mod by 10 at each
73
- # iteration until a match is found
74
- while ordinal.nil? && mod > 1
75
- query.merge! :name => key % (number.abs % mod)
76
- ordinal = terms.lookup_modulo(query, mod)
77
-
78
- mod = mod / 10
79
- end
80
-
81
- # If we have not found a match at this point, we try to match
82
- # the default ordinal instead
83
- if ordinal.nil?
84
- query[:name] = 'ordinal'
85
- ordinal = terms[query]
86
-
87
- if ordinal.nil? && query.key?(:'gender-form')
88
- query.delete(:'gender-form')
89
- ordinal = terms[query]
90
- end
91
- end
92
-
93
- if ordinal.nil?
94
- number.to_s
95
- else
96
- [number, ordinal.to_s(options)].join
97
- end
98
- end
99
-
100
- private
101
-
102
- def normalize_gender_options(options)
103
- gender = (options[:'gender-form'] || options[:gender]).to_s
104
- unless gender.empty? || gender =~ /^n/i
105
- q[:'gender-form'] = (gender =~ /^m/i) ? 'masculine' : 'feminine'
106
- end
107
- end
108
-
109
- def normalize_plural_options(options)
110
- end
111
-
112
- def ordinalize_options_for(options)
113
- q = { :name => 'ordinal-%02d' }
114
-
115
- unless options.nil?
116
- if options.key?(:form) && options[:form].to_s =~ /^long(-ordinal)?$/i
117
- q[:name] = 'long-ordinal-%02d'
118
- end
119
-
120
- end
121
-
122
- q
123
- end
124
-
125
- def legacy_ordinalize(number)
126
- case
127
- when (11..13).include?(number.abs % 100)
128
- [number, terms['ordinal-04']].join
129
- when (1..3).include?(number.abs % 10)
130
- [number, terms['ordinal-%02d' % (number.abs % 10)]].join
131
- else
132
- [number, terms['ordinal-04']].join
133
- end
134
- end
135
-
136
- end
137
- end