locale 2.0.0 → 2.0.1

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/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
-