csl 1.0.0.pre12 → 1.0.0.pre13

Sign up to get free protection for your applications and to get access to all the features.
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