locale 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,13 @@
1
+ = locale-2.0.1 (2009-04-18)
2
+ * Locale::Tag::Common#extensions are shown order by the keys.[reported by
3
+ Dan Coutu]
4
+ * Enhance to support ruby-1.9.x [by OZAWA Sakuro]
5
+ * Reimplement memoize to be able to freeze or dup the object.
6
+ * Improve Locale.candidates.
7
+
8
+ Thanks to:
9
+ Dan Coutu, OZAWA Sakuro
10
+
1
11
  = locale-2.0.0 (2009-03-21)
2
12
  * Support Rack.
3
13
  * move to github from svn.
data/Rakefile CHANGED
@@ -29,7 +29,7 @@ Rake::RDocTask.new { |rdoc|
29
29
  rdoc.rdoc_dir = 'doc'
30
30
  rdoc.title = "Ruby-Locale library"
31
31
  rdoc.options << '--line-numbers' << '--inline-source'
32
- rdoc.rdoc_files.include('README', 'ChangeLog')
32
+ rdoc.rdoc_files.include('README.rdoc', 'ChangeLog')
33
33
  rdoc.rdoc_files.include('lib/**/*.rb')
34
34
  rdoc.template = allison if allison.size > 0
35
35
  }
@@ -184,18 +184,25 @@ module Locale
184
184
  opts = {:supported_language_tags => nil, :type => :common,
185
185
  :default_language_tags => ["en"]}.merge(options)
186
186
 
187
- cache_key = opts.hash
188
187
  if Thread.current[:candidates_caches]
189
- cache = Thread.current[:candidates_caches][cache_key]
188
+ cache = Thread.current[:candidates_caches][opts.hash]
190
189
  return cache if cache
191
190
  else
192
191
  Thread.current[:candidates_caches] = {}
193
192
  end
193
+ Thread.current[:candidates_caches][opts.hash] =
194
+ collect_candidates(opts[:type], current,
195
+ opts[:default_language_tags],
196
+ opts[:supported_language_tags])
197
+ end
194
198
 
195
- default_language_tags = opts[:default_language_tags].collect{|v|
196
- Locale::Tag.parse(v).send("to_#{opts[:type]}")}.flatten.uniq
199
+ # collect tag candidates and memoize it.
200
+ # The result is shared from all threads.
201
+ def collect_candidates(type, tags, default_tags, supported_tags) # :nodoc:
202
+ default_language_tags = default_tags.collect{|v|
203
+ Locale::Tag.parse(v).send("to_#{type}")}.flatten.uniq
197
204
 
198
- candidate_tags = current.collect{|v| v.send("to_#{opts[:type]}").candidates}
205
+ candidate_tags = tags.collect{|v| v.send("to_#{type}").candidates}
199
206
 
200
207
  tags = []
201
208
  (0...candidate_tags[0].size).each {|i|
@@ -204,16 +211,14 @@ module Locale
204
211
  tags += default_language_tags
205
212
  tags.uniq!
206
213
 
207
- if opts[:supported_language_tags]
208
- tags &= opts[:supported_language_tags].collect{|v|
209
- Locale::Tag.parse(v).send("to_#{opts[:type]}")}.flatten
210
- tags += default_language_tags if tags.size == 0
214
+ if supported_tags
215
+ tags &= supported_tags.collect{|v|
216
+ Locale::Tag.parse(v).send("to_#{type}")}.flatten
217
+ tags = default_language_tags if tags.size == 0
211
218
  end
212
- tags = Locale::TagList.new(tags)
213
- Thread.current[:candidates_caches][cache_key] = tags
214
- tags
219
+ Locale::TagList.new(tags)
215
220
  end
216
-
221
+ memoize :collect_candidates
217
222
 
218
223
  # Gets the current charset.
219
224
  #
@@ -226,7 +231,7 @@ module Locale
226
231
  end
227
232
  memoize :charset
228
233
 
229
- # Clear current locale and current charset.
234
+ # Clear current locale.
230
235
  # * Returns: self
231
236
  def clear
232
237
  Thread.current[:current_languages] = nil
@@ -88,6 +88,7 @@ module Locale
88
88
 
89
89
  Zlib::GzipReader.open(File.dirname(__FILE__) + "/../data/languages.tab.gz") do |gz|
90
90
  gz.readlines.each do |l|
91
+ l.force_encoding('UTF-8') if l.respond_to?(:force_encoding)
91
92
  unless l =~ /^\s*$/
92
93
  parts = l.split(/\t/)
93
94
  lang = Language.new(parts[2], parts[0], parts[3], parts[4], parts[5].strip)
@@ -39,6 +39,7 @@ module Locale
39
39
  @@regions = Hash.new
40
40
  Zlib::GzipReader.open(File.dirname(__FILE__) + "/../data/regions.tab.gz") do |gz|
41
41
  gz.readlines.each do |l|
42
+ l.force_encoding('UTF-8') if l.respond_to?(:force_encoding)
42
43
  unless l =~ /^\s*$/
43
44
  parts = l.split(/\t/)
44
45
  region = Region.new(parts[0], parts[1].strip)
@@ -1,10 +1,10 @@
1
1
  =begin
2
+ tag.rb - Locale::Tag module
2
3
 
3
- tag.rb - Locale::Tag module
4
-
5
- Copyright (C) 2008 Masao Mutoh
4
+ Copyright (C) 2008,2009 Masao Mutoh
6
5
 
7
- $Id: tag.rb 27 2008-12-03 15:06:50Z mutoh $
6
+ You may redistribute it and/or modify it under the same
7
+ license terms as Ruby.
8
8
  =end
9
9
 
10
10
  require 'locale/tag/simple'
@@ -13,11 +13,13 @@ require 'locale/tag/common'
13
13
  require 'locale/tag/rfc'
14
14
  require 'locale/tag/cldr'
15
15
  require 'locale/tag/posix'
16
+ require 'locale/util/memoizable'
16
17
 
17
18
  module Locale
18
19
 
19
20
  # Language tag / locale identifiers.
20
21
  module Tag
22
+ include Util::Memoizable
21
23
  module_function
22
24
  # Parse a language tag/locale name and return Locale::Tag
23
25
  # object.
@@ -31,6 +33,7 @@ module Locale
31
33
  end
32
34
  Locale::Tag::Illegular.new(tag)
33
35
  end
36
+ memoize :parse
34
37
  end
35
38
  end
36
39
 
@@ -1,14 +1,14 @@
1
1
  =begin
2
2
  locale/tag/cldr.rb - Locale::Tag::CLDR
3
3
 
4
- Copyright (C) 2008 Masao Mutoh
4
+ Copyright (C) 2008,2009 Masao Mutoh
5
5
 
6
6
  You may redistribute it and/or modify it under the same
7
7
  license terms as Ruby.
8
-
9
- $Id: cldr.rb 27 2008-12-03 15:06:50Z mutoh $
10
8
  =end
11
9
 
10
+ require 'locale/tag/common'
11
+
12
12
  module Locale #:nodoc:
13
13
  module Tag #:nodoc:
14
14
 
@@ -24,7 +24,34 @@ module Locale #:nodoc:
24
24
  (?:@(#{EXTENSION};?)+)*)\Z/ix
25
25
 
26
26
  attr_reader :extensions
27
-
27
+
28
+ class << self
29
+ include Util::Memoizable
30
+ # Parse the language tag and return the new Locale::Tag::CLDR.
31
+ def parse(tag)
32
+ if tag =~ /\APOSIX\Z/ # This is the special case of POSIX locale but match this regexp.
33
+ nil
34
+ elsif tag =~ TAG_RE
35
+ lang, script, region, subtag = $1, $2, $3, $4
36
+
37
+ extensions = {}
38
+ subtag.scan(/#{EXTENSION}/i).each{|v|
39
+ subtag.sub!(v, "")
40
+ key, type = v.split("=")
41
+ extensions[key] = type
42
+ }
43
+ variants = subtag.scan(/#{VARIANT}/i).collect{|v| v[0].upcase}
44
+
45
+ ret = self.new(lang, script, region, variants, extensions)
46
+ ret.tag = tag
47
+ ret
48
+ else
49
+ nil
50
+ end
51
+ end
52
+ memoize_dup :parse
53
+ end
54
+
28
55
  # Create Locale::Tag::Cldr.
29
56
  #
30
57
  # variants should be upcase.
@@ -34,39 +61,6 @@ module Locale #:nodoc:
34
61
  super(language, script, region, variants.map{|v| v.upcase})
35
62
  end
36
63
 
37
- # Parse the language tag and return the new Locale::Tag::CLDR.
38
- def self.parse(tag)
39
- if tag =~ /\APOSIX\Z/ # This is the special case of POSIX locale but match this regexp.
40
- nil
41
- elsif tag =~ TAG_RE
42
- lang, script, region, subtag = $1, $2, $3, $4
43
-
44
- extensions = {}
45
- subtag.scan(/#{EXTENSION}/i).each{|v|
46
- subtag.sub!(v, "")
47
- key, type = v.split("=")
48
- extensions[key] = type
49
- }
50
- variants = subtag.scan(/#{VARIANT}/i).collect{|v| v[0].upcase}
51
-
52
- ret = self.new(lang, script, region, variants, extensions)
53
- ret.tag = tag
54
- ret
55
- else
56
- nil
57
- end
58
- end
59
-
60
- # Returns the language tag.
61
- # (e.g.) "ja_Hira_JP_VARIANT1_VARIANT2@foo1=var1;foo2=var2"
62
- def to_s
63
- s = super
64
- if @extensions.size > 0
65
- s << "@" << @extensions.to_a.sort.map{|k, v| "#{k}=#{v}"}.join(";")
66
- end
67
- s
68
- end
69
-
70
64
  # Sets the extensions.
71
65
  def extensions=(val)
72
66
  clear
@@ -74,12 +68,12 @@ module Locale #:nodoc:
74
68
  end
75
69
 
76
70
  private
77
- def convert_to(klass)
71
+ def convert_to(klass) # :nodoc:
78
72
  if klass == Cldr
79
73
  klass.new(language, script, region, variants, extensions)
80
74
  elsif klass == Rfc
81
75
  exts = []
82
- @extensions.each do |k, v|
76
+ @extensions.to_a.sort.each do |k, v|
83
77
  exts << "k-#{k[0,8]}-#{v[0,8]}"
84
78
  end
85
79
 
@@ -88,6 +82,18 @@ module Locale #:nodoc:
88
82
  super
89
83
  end
90
84
  end
85
+
86
+ # Returns the language tag.
87
+ # (e.g.) "ja_Hira_JP_VARIANT1_VARIANT2@foo1=var1;foo2=var2"
88
+ #
89
+ # This is used in internal only. Use to_s instead.
90
+ def to_string
91
+ s = super
92
+ if @extensions.size > 0
93
+ s << "@" << @extensions.to_a.sort.map{|k, v| "#{k}=#{v}"}.join(";")
94
+ end
95
+ s
96
+ end
91
97
  end
92
98
  end
93
99
  end
@@ -1,14 +1,14 @@
1
1
  =begin
2
2
  locale/tag/common.rb - Locale::Tag::Common
3
3
 
4
- Copyright (C) 2008 Masao Mutoh
4
+ Copyright (C) 2008,2009 Masao Mutoh
5
5
 
6
6
  You may redistribute it and/or modify it under the same
7
7
  license terms as Ruby.
8
-
9
- $Id: common.rb 27 2008-12-03 15:06:50Z mutoh $
10
8
  =end
11
9
 
10
+ require 'locale/tag/simple'
11
+
12
12
  module Locale
13
13
  module Tag
14
14
  # Common Language tag class for Ruby.
@@ -32,34 +32,38 @@ module Locale
32
32
 
33
33
  attr_reader :script, :variants
34
34
 
35
+ class << self
36
+ include Util::Memoizable
37
+ # Parse the language tag and return the new Locale::Tag::Common.
38
+ def parse(tag)
39
+ if tag =~ /\APOSIX\Z/ # This is the special case of POSIX locale but match this regexp.
40
+ nil
41
+ elsif tag =~ TAG_RE
42
+ lang, script, region, subtag = $1, $2, $3, $4
43
+ variants = subtag.scan(/(^|[-_])#{VARIANT}(?=([-_]|$))/i).collect{|v| v[1]}
44
+
45
+ ret = self.new(lang, script, region, variants)
46
+ ret.tag = tag
47
+ ret
48
+ else
49
+ nil
50
+ end
51
+ end
52
+ memoize_dup :parse
53
+ end
54
+
35
55
  # Create a Locale::Tag::Common.
36
56
  def initialize(language, script = nil, region = nil, variants = [])
37
57
  @script, @variants = script, variants
38
- @script.capitalize! if @script
58
+ @script = @script.capitalize if @script
39
59
  super(language, region)
40
60
  end
41
-
42
- # Parse the language tag and return the new Locale::Tag::Common.
43
- def self.parse(tag)
44
- if tag =~ /\APOSIX\Z/ # This is the special case of POSIX locale but match this regexp.
45
- nil
46
- elsif tag =~ TAG_RE
47
- lang, script, region, subtag = $1, $2, $3, $4
48
- variants = subtag.scan(/(^|[-_])#{VARIANT}(?=([-_]|$))/i).collect{|v| v[1]}
49
-
50
- ret = self.new(lang, script, region, variants)
51
- ret.tag = tag
52
- ret
53
- else
54
- nil
55
- end
56
- end
57
-
61
+
58
62
  # Set the script (with capitalize)
59
63
  def script=(val)
60
64
  clear
61
65
  @script = val
62
- @script.capitalize! if @script
66
+ @script = @script.capitalize if @script
63
67
  @script
64
68
  end
65
69
 
@@ -69,21 +73,6 @@ module Locale
69
73
  @variants = val
70
74
  end
71
75
 
72
- # Returns the common language tag with "_".
73
- # <language>_<Script>_<REGION>_VARIANTS1_VARIANTS2
74
- # (e.g.) "ja_Hira_JP_VARIANTS1_VARIANTS2"
75
- def to_s
76
- s = @language.dup
77
-
78
- s << "_" << @script if @script
79
- s << "_" << @region if @region
80
-
81
- @variants.each do |v|
82
- s << "_#{v}"
83
- end
84
- s
85
- end
86
-
87
76
  # Returns an Array of tag-candidates order by priority.
88
77
  # Use Locale.candidates instead of this method.
89
78
  #
@@ -99,9 +88,10 @@ module Locale
99
88
  self.class.new(language, nil, nil, variants), #ja-FOO
100
89
  self.class.new(language)] #ja
101
90
  end
91
+ memoize_dup :candidates
102
92
 
103
93
  private
104
- def convert_to(klass)
94
+ def convert_to(klass) #:nodoc:
105
95
  if klass == Simple
106
96
  super
107
97
  elsif klass == Posix
@@ -117,6 +107,23 @@ module Locale
117
107
  klass.new(language, script, region, variants)
118
108
  end
119
109
  end
110
+
111
+ # Returns the common language tag with "_".
112
+ # <language>_<Script>_<REGION>_VARIANTS1_VARIANTS2
113
+ # (e.g.) "ja_Hira_JP_VARIANTS1_VARIANTS2"
114
+ #
115
+ # This is used in internal only. Use to_s instead.
116
+ def to_string
117
+ s = @language.dup
118
+
119
+ s << "_" << @script if @script
120
+ s << "_" << @region if @region
121
+
122
+ @variants.each do |v|
123
+ s << "_#{v}"
124
+ end
125
+ s
126
+ end
120
127
  end
121
128
  end
122
129
  end
@@ -27,12 +27,14 @@ module Locale
27
27
  def candidates
28
28
  [Illegular.new(tag)]
29
29
  end
30
+ memoize :candidates
30
31
 
31
32
  # Conver to the klass(the class of Language::Tag)
32
33
  private
33
34
  def convert_to(klass)
34
35
  klass.new(tag)
35
36
  end
37
+ memoize :convert_to
36
38
  end
37
39
  end
38
40
  end
@@ -1,14 +1,14 @@
1
1
  =begin
2
2
  locale/tag/rfc.rb - Locale::Tag::Rfc
3
3
 
4
- Copyright (C) 2008 Masao Mutoh
4
+ Copyright (C) 2008,2009 Masao Mutoh
5
5
 
6
6
  You may redistribute it and/or modify it under the same
7
7
  license terms as Ruby.
8
-
9
- $Id: rfc.rb 27 2008-12-03 15:06:50Z mutoh $
10
8
  =end
11
9
 
10
+ require 'locale/tag/common'
11
+
12
12
  module Locale #:nodoc:
13
13
  module Tag #:nodoc:
14
14
 
@@ -26,50 +26,42 @@ module Locale #:nodoc:
26
26
 
27
27
  attr_reader :extensions, :privateuse
28
28
 
29
- def initialize(language, script = nil, region = nil, variants = [],
30
- extensions = [], privateuse = nil)
31
- @extensions, @privateuse = extensions, privateuse
32
- super(language, script, region, variants)
33
- end
34
-
35
- # Parse the language tag and return the new Locale::Tag::Common.
36
- def self.parse(tag)
37
- if tag =~ /\APOSIX\Z/ # This is the special case of POSIX locale but match this regexp.
38
- nil
39
- elsif tag =~ TAG_RE
40
- lang, script, region, subtag = $1, $2, $3, $4
41
- extensions = []
42
- variants = []
43
- if subtag =~ /#{PRIVATEUSE}/
44
- subtag, privateuse = $`, $1
45
- # Private use for CLDR.
46
- if /x-ldml(.*)/ =~ privateuse
47
- p_subtag = $1
48
- extensions = p_subtag.scan(/(^|-)#{EXTENSION}/i).collect{|v| p_subtag.sub!(v[1], ""); v[1]}
49
- variants = p_subtag.scan(/(^|-)#{VARIANT}(?=(-|$))/i).collect{|v| v[1]}
29
+ class << self
30
+ include Util::Memoizable
31
+ # Parse the language tag and return the new Locale::Tag::Rfc.
32
+ def parse(tag)
33
+ if tag =~ /\APOSIX\Z/ # This is the special case of POSIX locale but match this regexp.
34
+ nil
35
+ elsif tag =~ TAG_RE
36
+ lang, script, region, subtag = $1, $2, $3, $4
37
+ extensions = []
38
+ variants = []
39
+ if subtag =~ /#{PRIVATEUSE}/
40
+ subtag, privateuse = $`, $1
41
+ # Private use for CLDR.
42
+ if /x-ldml(.*)/ =~ privateuse
43
+ p_subtag = $1
44
+ extensions = p_subtag.scan(/(^|-)#{EXTENSION}/i).collect{|v| p_subtag.sub!(v[1], ""); v[1]}
45
+ variants = p_subtag.scan(/(^|-)#{VARIANT}(?=(-|$))/i).collect{|v| v[1]}
46
+ end
50
47
  end
48
+ extensions += subtag.scan(/(^|-)#{EXTENSION}/i).collect{|v| subtag.sub!(v[1], ""); v[1]}
49
+ variants += subtag.scan(/(^|-)#{VARIANT}(?=(-|$))/i).collect{|v| v[1]}
50
+
51
+ ret = self.new(lang, script, region, variants, extensions, privateuse)
52
+ ret.tag = tag
53
+ ret
54
+ else
55
+ nil
51
56
  end
52
- extensions += subtag.scan(/(^|-)#{EXTENSION}/i).collect{|v| subtag.sub!(v[1], ""); v[1]}
53
- variants += subtag.scan(/(^|-)#{VARIANT}(?=(-|$))/i).collect{|v| v[1]}
54
-
55
- ret = self.new(lang, script, region, variants, extensions, privateuse)
56
- ret.tag = tag
57
- ret
58
- else
59
- nil
60
57
  end
58
+ memoize_dup :parse
61
59
  end
62
60
 
63
- # Returns the language tag
64
- # <language>-<Script>-<REGION>-<variants>-<extensions>-<PRIVATEUSE>
65
- # (e.g.) "ja-Hira-JP-variant"
66
- def to_s
67
- s = super.to_s.gsub(/_/, "-")
68
- @extensions.each do |v|
69
- s << "-#{v}"
70
- end
71
- s << "-#{@privateuse}" if @privateuse
72
- s
61
+ def initialize(language, script = nil, region = nil, variants = [],
62
+ extensions = [], privateuse = nil)
63
+ @extensions, @privateuse = extensions, privateuse
64
+ super(language, script, region, variants)
73
65
  end
74
66
 
75
67
  # Sets the extensions.
@@ -90,7 +82,7 @@ module Locale #:nodoc:
90
82
  klass.new(language, script, region, variants, extensions, privateuse)
91
83
  elsif klass == Cldr
92
84
  exts = {}
93
- extensions.each do |v|
85
+ extensions.sort.each do |v|
94
86
  if v =~ /^k-(#{ALPHANUM}{2,})-(.*)$/i
95
87
  exts[$1] = $2
96
88
  end
@@ -100,7 +92,21 @@ module Locale #:nodoc:
100
92
  super
101
93
  end
102
94
  end
103
-
95
+
96
+ # Returns the language tag
97
+ # <language>-<Script>-<REGION>-<variants>-<extensions>-<PRIVATEUSE>
98
+ # (e.g.) "ja-Hira-JP-variant"
99
+ #
100
+ # This is used in internal only. Use to_s instead.
101
+ def to_string
102
+ s = super.gsub(/_/, "-")
103
+ @extensions.sort.each do |v|
104
+ s << "-#{v}"
105
+ end
106
+ s << "-#{@privateuse}" if @privateuse
107
+ s
108
+ end
109
+
104
110
  end
105
111
  end
106
112
  end
@@ -1,12 +1,10 @@
1
1
  =begin
2
2
  locale/tag/simple.rb - Locale::Tag::Simple
3
3
 
4
- Copyright (C) 2008 Masao Mutoh
4
+ Copyright (C) 2008,2009 Masao Mutoh
5
5
 
6
6
  You may redistribute it and/or modify it under the same
7
7
  license terms as Ruby.
8
-
9
- $Id: simple.rb 27 2008-12-03 15:06:50Z mutoh $
10
8
  =end
11
9
 
12
10
  require 'locale/util/memoizable'
@@ -22,6 +20,8 @@ module Locale
22
20
  # * ja-JP
23
21
  # * ja-392
24
22
  class Simple
23
+ include Util::Memoizable
24
+
25
25
  ALPHA = '[a-z]'
26
26
  DIGIT = '[0-9]'
27
27
  ALPHANUM = "[a-zA-Z0-9]"
@@ -40,17 +40,6 @@ module Locale
40
40
  # String.
41
41
  attr_accessor :tag
42
42
 
43
- # Parse the language tag and return the new Locale::Tag::Simple.
44
- def self.parse(tag)
45
- if tag =~ TAG_RE
46
- ret = self.new($1, $2)
47
- ret.tag = tag
48
- ret
49
- else
50
- nil
51
- end
52
- end
53
-
54
43
  # call-seq:
55
44
  # to_common
56
45
  # to_posix
@@ -63,26 +52,40 @@ module Locale
63
52
  def to_#{name}
64
53
  convert_to(#{name.to_s.capitalize})
65
54
  end
66
- memoize :to_#{name}
55
+ memoize_dup :to_#{name}
67
56
  EOS
68
57
  end
69
58
 
59
+ class << self
60
+ include Util::Memoizable
61
+ # Parse the language tag and return the new Locale::Tag::Simple.
62
+ def parse(tag)
63
+ if tag =~ TAG_RE
64
+ ret = self.new($1, $2)
65
+ ret.tag = tag
66
+ ret
67
+ else
68
+ nil
69
+ end
70
+ end
71
+ memoize_dup :parse
72
+ end
73
+
70
74
  # Create a Locale::Tag::Simple
71
75
  def initialize(language, region = nil)
72
76
  raise "language can't be nil." unless language
73
77
  @language, @region = language, region
74
- @language.downcase! if @language
75
- @region.upcase! if @region
78
+ @language = @language.downcase if @language
79
+ @region = @region.upcase if @region
76
80
  end
77
81
 
78
82
  # Returns the language tag as the String.
79
83
  # <language>_<REGION>
80
84
  # (e.g.) "ja_JP"
81
85
  def to_s
82
- s = @language.dup
83
- s << "_" << @region if @region
84
- s
86
+ to_string
85
87
  end
88
+ memoize :to_s
86
89
 
87
90
  def to_str #:nodoc:
88
91
  to_s
@@ -95,14 +98,17 @@ module Locale
95
98
  def eql?(other) #:nodoc:
96
99
  self.==(other)
97
100
  end
101
+ memoize :eql?
98
102
 
99
103
  def hash #:nodoc:
100
104
  "#{self.class}:#{to_s}".hash
101
105
  end
106
+ memoize :hash
102
107
 
103
108
  def inspect #:nodoc:
104
109
  %Q[#<#{self.class}: #{to_s}>]
105
110
  end
111
+ memoize :inspect
106
112
 
107
113
  # For backward compatibility.
108
114
  def country; region end
@@ -111,7 +117,7 @@ module Locale
111
117
  def language=(val)
112
118
  clear
113
119
  @language = val
114
- @language.downcase! if @language
120
+ @language = @language.downcase if @language
115
121
  @language
116
122
  end
117
123
 
@@ -119,7 +125,7 @@ module Locale
119
125
  def region=(val)
120
126
  clear
121
127
  @region = val
122
- @region.upcase! if @region
128
+ @region = @region.upcase if @region
123
129
  @region
124
130
  end
125
131
 
@@ -128,18 +134,25 @@ module Locale
128
134
  def candidates
129
135
  [self.class.new(language, region), self.class.new(language)]
130
136
  end
137
+ memoize_dup :candidates
131
138
 
132
- memoize :to_s, :to_str, :hash, :inspect, :candidates
133
-
134
- # Conver to the klass(the class of Language::Tag)
139
+ # Convert to the klass(the class of Language::Tag)
135
140
  private
136
- def convert_to(klass)
141
+ def convert_to(klass) #:nodoc:
137
142
  if klass == Simple || klass == Posix
138
143
  klass.new(language, region)
139
144
  else
140
145
  klass.new(language, nil, region)
141
146
  end
142
147
  end
148
+
149
+ # Return simple language tag which format is"<lanuguage>_<REGION>".
150
+ # This is to use internal only. Use to_s instead.
151
+ def to_string
152
+ s = @language.dup
153
+ s << "_" << @region if @region
154
+ s
155
+ end
143
156
  end
144
157
  end
145
158
  end
@@ -9,6 +9,8 @@
9
9
  $Id: taglist.rb 27 2008-12-03 15:06:50Z mutoh $
10
10
  =end
11
11
 
12
+ require 'locale/util/memoizable'
13
+
12
14
  module Locale
13
15
  # This provides the subclass of Array which behaves like
14
16
  # the first(top priority) Locale::Tag object.
@@ -24,6 +26,8 @@ module Locale
24
26
  # of this function.
25
27
  #
26
28
  class TagList < Array
29
+ include Util::Memoizable
30
+
27
31
  # Returns the top priority language. (simple)
28
32
  def language
29
33
  self[0].language
@@ -48,18 +52,31 @@ module Locale
48
52
  ::Locale.driver_module.charset
49
53
  end
50
54
  end
55
+ memoize :charset
56
+
51
57
  # Returns the top priority modifier. (posix)
52
58
  def modifier
53
59
  (self[0].respond_to? :modifier) ? self[0].modifier : nil
54
60
  end
61
+ memoize :modifier
62
+
63
+ # Returns the top priority variants.(common, rfc, cldr)
64
+ def variants
65
+ (self[0].respond_to? :variants) ? self[0].variants : nil
66
+ end
67
+ memoize :variants
68
+
55
69
  # Returns the top priority extensions.(common, rfc, cldr)
56
70
  def extensions
57
71
  (self[0].respond_to? :extensions) ? self[0].extensions : nil
58
72
  end
73
+ memoize :extensions
74
+
59
75
  # Returns the top priority privateuse(rfc)
60
76
  def privateuse
61
77
  (self[0].respond_to? :privateuse) ? self[0].privateuse : nil
62
78
  end
79
+ memoize :privateuse
63
80
 
64
81
  def to_str
65
82
  self[0].to_str
@@ -88,6 +105,5 @@ module Locale
88
105
  def to_posix
89
106
  self[0].to_posix
90
107
  end
91
-
92
108
  end
93
109
  end
@@ -1,4 +1,5 @@
1
1
  # Refer from activesupport-2.2.0.
2
+ #
2
3
  # * Remove the dependecies to activesupport.
3
4
  # * change the key to hash value of args.
4
5
  # * Not Thread safe
@@ -43,33 +44,59 @@ module Locale
43
44
  #
44
45
  # To clear cache, #clear_foo, #clear_bar is also defined.
45
46
  #
46
- # (NOTE) Consider to use this with huge objects to avoid memory leaks.
47
+ # (NOTE)
48
+ # * Consider to use this with huge objects to avoid memory leaks.
49
+ # * Can't use this with super.<method> because of infinity loop.
47
50
  def memoize(*symbols)
51
+ memoize_impl(false, *symbols)
52
+ end
53
+
54
+ # memoize with dup. A copy object is returned.
55
+ def memoize_dup(*symbols)
56
+ memoize_impl(true, *symbols)
57
+ end
58
+
59
+ def memoize_impl(is_dup, *symbols) #:nodoc:
48
60
  symbols.each do |symbol|
49
61
  original_method = "_unmemoized_#{symbol}"
50
62
  memoized_ivar = MEMOIZED_IVAR.call(symbol)
51
- class_eval <<-EOS, __FILE__, __LINE__
52
- raise "Already memoized #{symbol}" if method_defined?(:#{original_method})
53
- alias #{original_method} #{symbol}
63
+ dup_meth = is_dup ? "_dup" : ""
54
64
 
55
- def #{symbol}(*args)
56
- @_memoized_ivars ||= {}
57
- @_memoized_ivars[:#{memoized_ivar}] ||= {}
65
+ class_eval <<-EOS, __FILE__, __LINE__
66
+ alias #{original_method} #{symbol}
67
+ def #{symbol}(*args)
68
+ _memoize#{dup_meth}(:#{memoized_ivar}, args.hash) do
69
+ #{original_method}(*args)
70
+ end
71
+ end
72
+ EOS
73
+ end
74
+ end
58
75
 
59
- key = args.hash
76
+ def _memoize(ivar, key) #:nodoc:
77
+ @_memoized_ivars ||= {}
78
+ @_memoized_ivars[ivar] ||= {}
60
79
 
61
- ret = @_memoized_ivars[:#{memoized_ivar}][key]
80
+ ret = @_memoized_ivars[ivar][key]
81
+ unless ret
82
+ ret = yield
83
+ ret.freeze
84
+ @_memoized_ivars[ivar][key] = ret
85
+ end
86
+ ret
87
+ end
62
88
 
63
- if ret
64
- ret
65
- else
66
- @_memoized_ivars[:#{memoized_ivar}][key] = #{original_method}(*args).freeze
67
- end
89
+ def _memoize_dup(ivar, key) #:nodoc:
90
+ ret = _memoize(ivar, key) do; yield; end
91
+ if ret
92
+ if ret.kind_of? Array
93
+ ret.map{|v| v.dup}.dup
94
+ else
95
+ ret.dup
68
96
  end
69
-
70
- EOS
97
+ else
98
+ nil
71
99
  end
72
-
73
100
  end
74
101
  end
75
102
  end
@@ -7,6 +7,6 @@
7
7
  license terms as Ruby.
8
8
  =end
9
9
  module Locale
10
- VERSION = "2.0.0"
10
+ VERSION = "2.0.1"
11
11
  end
12
12
 
@@ -0,0 +1,133 @@
1
+ require 'locale/util/memoizable'
2
+ require 'test/unit'
3
+
4
+ class A
5
+ include Locale::Util::Memoizable
6
+ def initialize
7
+ @count = 0
8
+ @a = ""
9
+ end
10
+ def test1(a)
11
+ @a += String(a)
12
+ @count += 1
13
+ end
14
+ memoize :test1
15
+ attr_reader :a
16
+ end
17
+
18
+ class B < A
19
+ end
20
+
21
+ class C < A
22
+ def test1(a)
23
+ @a = String(a) + @a
24
+ @count += 1
25
+ end
26
+ memoize :test1
27
+ end
28
+
29
+ class D
30
+ class << self
31
+ include Locale::Util::Memoizable
32
+ def init
33
+ @@count = 0
34
+ @@a = "a"
35
+ end
36
+ def test1(a)
37
+ @@a = @@a + "b" * a
38
+ @@count += 1
39
+ end
40
+ memoize :test1
41
+ def a
42
+ @@a
43
+ end
44
+ end
45
+ end
46
+
47
+ class E
48
+ include Locale::Util::Memoizable
49
+ def test2
50
+ "aa"
51
+ end
52
+ memoize :test2
53
+
54
+ def test2_dup
55
+ "bb"
56
+ end
57
+ memoize_dup :test2_dup
58
+ end
59
+
60
+ class TestMemoizable < Test::Unit::TestCase
61
+ def test_simple
62
+ t = A.new
63
+ assert_equal 1, t.test1(1)
64
+ assert_equal "1", t.a
65
+ assert_equal 1, t.test1(1)
66
+ assert_equal "1", t.a
67
+ assert_equal 2, t.test1(2)
68
+ assert_equal "12", t.a
69
+ assert_equal 2, t.test1(2)
70
+ assert_equal "12", t.a
71
+ assert_equal 1, t.test1(1)
72
+ assert_equal "12", t.a
73
+ end
74
+
75
+ def test_simple_inherited
76
+ t = B.new
77
+ assert_equal 1, t.test1(1)
78
+ assert_equal "1", t.a
79
+ assert_equal 1, t.test1(1)
80
+ assert_equal "1", t.a
81
+ assert_equal 2, t.test1(2)
82
+ assert_equal "12", t.a
83
+ assert_equal 2, t.test1(2)
84
+ assert_equal "12", t.a
85
+ assert_equal 1, t.test1(1)
86
+ assert_equal "12", t.a
87
+ end
88
+
89
+ def test_override
90
+ t = C.new
91
+ assert_equal 1, t.test1(1)
92
+ assert_equal "1", t.a
93
+ assert_equal 1, t.test1(1)
94
+ assert_equal "1", t.a
95
+ assert_equal 2, t.test1(2)
96
+ assert_equal "21", t.a
97
+ assert_equal 2, t.test1(2)
98
+ assert_equal "21", t.a
99
+ assert_equal 1, t.test1(1)
100
+ assert_equal "21", t.a
101
+ end
102
+
103
+ def test_class_method
104
+ D.init
105
+ assert_equal 1, D.test1(1)
106
+ assert_equal "ab", D.a
107
+ assert_equal 1, D.test1(1)
108
+ assert_equal "ab", D.a
109
+ assert_equal 2, D.test1(2)
110
+ assert_equal "abbb", D.a
111
+ assert_equal 2, D.test1(2)
112
+ assert_equal "abbb", D.a
113
+ assert_equal 1, D.test1(1)
114
+ assert_equal "abbb", D.a
115
+ end
116
+
117
+ def test_freeze_or_dup
118
+ t = E.new
119
+ assert_equal "aa", t.test2
120
+ # When modification attempted on frozen objects,
121
+ # ruby 1.9 raises RuntimeError instead of TypeError.
122
+ # http://redmine.ruby-lang.org/issues/show/409
123
+ # http://redmine.ruby-lang.org/repositories/diff/ruby-19/error.c?rev=7294
124
+ if RUBY_VERSION < '1.9.0'
125
+ assert_raise(TypeError){ t.test2 << "a" }
126
+ else
127
+ assert_raise(RuntimeError){ t.test2 << "a" }
128
+ end
129
+ assert_equal "bb", t.test2_dup
130
+ assert_equal "bbb", t.test2_dup << "b"
131
+ assert_equal "bb", t.test2_dup
132
+ end
133
+ end
@@ -815,11 +815,7 @@ class TagTest < Test::Unit::TestCase
815
815
 
816
816
  assert_equal Locale::Tag::Simple.parse("de_DE"), lang.to_simple
817
817
  assert_equal Locale::Tag::Common.parse("de_DE"), lang.to_common
818
- if RUBY_VERSION < "1.9.0" and RUBY_PLATFORM != "java"
819
- assert_equal Locale::Tag::Rfc.parse("de-DE-k-currency-DDM-k-collatio-phoneboo"), lang.to_rfc
820
- else
821
- assert_equal Locale::Tag::Rfc.parse("de-DE-k-collatio-phoneboo-k-currency-DDM"), lang.to_rfc
822
- end
818
+ assert_equal Locale::Tag::Rfc.parse("de-DE-k-collatio-phoneboo-k-currency-DDM"), lang.to_rfc
823
819
  assert_equal Locale::Tag::Cldr.parse("de_DE@collation=phonebook;currency=DDM"), lang.to_cldr
824
820
  assert_equal Locale::Tag::Posix.parse("de_DE"), lang.to_posix
825
821
 
@@ -844,11 +840,7 @@ class TagTest < Test::Unit::TestCase
844
840
 
845
841
  assert_equal Locale::Tag::Simple.parse("en_US"), lang.to_simple
846
842
  assert_equal Locale::Tag::Common.parse("en_US_POSIX"), lang.to_common
847
- if RUBY_VERSION < "1.9.0" and RUBY_PLATFORM != "java"
848
- assert_equal Locale::Tag::Rfc.parse("en-US-POSIX-k-colStren-secondar-k-collatio-traditio-k-calendar-islamic"), lang.to_rfc
849
- else
850
- assert_equal Locale::Tag::Rfc.parse("en-US-POSIX-k-calendar-islamic-k-collatio-traditio-k-colStren-secondar"), lang.to_rfc
851
- end
843
+ assert_equal Locale::Tag::Rfc.parse("en-US-POSIX-k-calendar-islamic-k-collatio-traditio-k-colStren-secondar"), lang.to_rfc
852
844
  assert_equal Locale::Tag::Cldr.parse("en_US_POSIX@calendar=islamic;collation=traditional;colStrength=secondary"), lang.to_cldr
853
845
  assert_equal Locale::Tag::Posix.parse("en_US@POSIX"), lang.to_posix
854
846
 
@@ -873,11 +865,7 @@ class TagTest < Test::Unit::TestCase
873
865
 
874
866
  assert_equal Locale::Tag::Simple.parse("en_US"), lang.to_simple
875
867
  assert_equal Locale::Tag::Common.parse("en_US"), lang.to_common
876
- if RUBY_VERSION < "1.9.0" and RUBY_PLATFORM != "java"
877
- assert_equal Locale::Tag::Rfc.parse("en-US-k-colStren-secondar-k-collatio-traditio-k-calendar-islamic"), lang.to_rfc
878
- else
879
- assert_equal Locale::Tag::Rfc.parse("en-US-k-calendar-islamic-k-collatio-traditio-k-colStren-secondar"), lang.to_rfc
880
- end
868
+ assert_equal Locale::Tag::Rfc.parse("en-US-k-calendar-islamic-k-collatio-traditio-k-colStren-secondar"), lang.to_rfc
881
869
  assert_equal Locale::Tag::Cldr.parse("en_US@calendar=islamic;collation=traditional;colStrength=secondary"), lang.to_cldr
882
870
  assert_equal Locale::Tag::Posix.parse("en_US"), lang.to_posix
883
871
 
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'locale/tag'
4
+ require 'locale/taglist'
5
+ require 'test/unit'
6
+
7
+ class TestTagList < Test::Unit::TestCase
8
+ def test_taglist_posix
9
+ list = Locale::TagList.new([Locale::Tag.parse("ja_JP.eucJP@mobile"),
10
+ Locale::Tag.parse("en_US.iso8859-1")])
11
+
12
+ assert_equal "ja", list.language
13
+ assert_equal "JP", list.region
14
+ assert_equal "eucJP", list.charset
15
+ assert_equal "mobile", list.modifier
16
+ assert_equal "ja_JP.eucJP@mobile", list.to_s
17
+ assert_equal Locale::Tag::Common.parse("ja_JP_mobile"), list.to_common
18
+ assert_equal Locale::Tag::Rfc.parse("ja-JP-mobile"), list.to_rfc
19
+ assert_equal Locale::Tag::Cldr.parse("ja_JP_mobile"), list.to_cldr
20
+ assert_equal Locale::Tag::Posix.parse("ja_JP.eucJP@mobile"), list.to_posix
21
+ assert_equal Locale::Tag::Posix.parse("en_US.iso8859-1"), list[1]
22
+ end
23
+
24
+ def test_taglist_rfc
25
+ list = Locale::TagList.new([Locale::Tag.parse("ja-Hira-JP-MOBILE-y-aaa-x-bbb"),
26
+ Locale::Tag.parse("en-US-mobile")])
27
+ assert_equal "ja", list.language
28
+ assert_equal "Hira", list.script
29
+ assert_equal "JP", list.region
30
+ assert_equal ["MOBILE"], list.variants
31
+ assert_equal ["y-aaa"], list.extensions
32
+ assert_equal "x-bbb", list.privateuse
33
+ end
34
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locale
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masao Mutoh
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-21 00:00:00 +09:00
12
+ date: 2009-04-19 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -22,7 +22,6 @@ extensions: []
22
22
  extra_rdoc_files: []
23
23
 
24
24
  files:
25
- - replace.rb
26
25
  - ChangeLog
27
26
  - samples
28
27
  - samples/sample_info.rb
@@ -68,7 +67,9 @@ files:
68
67
  - test
69
68
  - test/test_detect_general.rb
70
69
  - test/test_info.rb
70
+ - test/test_memoizable.rb
71
71
  - test/test_thread.rb
72
+ - test/test_taglist.rb
72
73
  - test/test_tag.rb
73
74
  - test/test_detect_cgi.rb
74
75
  - Rakefile
data/replace.rb DELETED
@@ -1,21 +0,0 @@
1
- Dir.glob("**/*") do |v|
2
- lines = []
3
- changed = false
4
- next if File.directory? v
5
- IO.foreach(v) {|line|
6
- if line =~ /mutoh(at|@)highway.ne.jp/
7
- lines << line.gsub(/mutoh( at |@)highway.ne.jp/, "mutomasa at gmail.com")
8
- changed = true
9
- else
10
- lines << line
11
- end
12
- }
13
- if changed
14
- out = open(v, "w")
15
- lines.each {|l|
16
- out.write l
17
- }
18
- out.close
19
- end
20
- end
21
-