]> git.openstreetmap.org Git - rails.git/blob - vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb
Localisation updates from http://translatewiki.net
[rails.git] / vendor / plugins / globalize2 / lib / globalize / locale / language_tag.rb
1 # for specifications see http://en.wikipedia.org/wiki/IETF_language_tag
2 #
3 # SimpleParser does not implement advanced usages such as grandfathered tags
4
5 module Globalize
6   module Locale
7     module Rfc4646
8       SUBTAGS = [:language, :script, :region, :variant, :extension, :privateuse, :grandfathered]
9       FORMATS = {:language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase}
10     end
11     
12     class LanguageTag < Struct.new(*Rfc4646::SUBTAGS)
13       class << self
14         def parser
15           @@parser ||= SimpleParser
16         end
17     
18         def parser=(parser)
19           @@parser = parser
20         end
21     
22         def tag(tag)
23           matches = parser.match(tag)
24           new *matches if matches
25         end
26       end
27   
28       Rfc4646::FORMATS.each do |name, format|
29         define_method(name) { self[name].send(format) unless self[name].nil? }
30       end
31       
32       def to_sym
33         to_s.to_sym
34       end
35       
36       def to_s
37         @tag ||= to_a.compact.join("-")
38       end
39   
40       def to_a
41         members.collect {|attr| self.send(attr) }
42       end
43   
44       def parent
45         segs = to_a.compact
46         segs.length < 2 ? nil : LanguageTag.tag(segs[0..(segs.length-2)].join('-'))
47       end
48       
49       def parents(include_self = true)
50         result, parent = [], self.dup
51         result << parent if include_self
52         while parent = parent.parent
53           result << parent
54         end
55         result
56       end
57   
58       module SimpleParser
59         PATTERN = %r{\A(?:
60           ([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language
61           (?:-([a-z]{4}))?                                        # script
62           (?:-([a-z]{2}|\d{3}))?                                  # region
63           (?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))*                     # variant
64           (?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))*                   # extension
65           (?:-(x(?:-[0-9a-z]{1,8})+))?|                           # privateuse subtag
66           (x(?:-[0-9a-z]{1,8})+)|                                 # privateuse tag
67           /* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */               # grandfathered
68           )\z}xi 
69
70         class << self
71           def match(tag)
72             c = PATTERN.match(tag.to_s).captures
73             c[0..4] << (c[5].nil? ? c[6] : c[5])  << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here?
74           rescue
75             false
76           end
77         end
78       end
79     end
80   end
81 end