]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/language.rb
plugin(points): +/- must come after, closes #34
[user/henk/code/ruby/rbot.git] / lib / rbot / language.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: Language module for rbot
5 #
6 # This module takes care of language handling for rbot:
7 # setting the core.language value, loading the appropriate
8 # .lang file etc.
9
10 module Irc
11 class Bot
12   class Language
13
14     # Access needed for tests:
15     attr_reader :strings
16
17     # This constant hash holds the mapping
18     # from long language names to the usual POSIX
19     # locale specifications
20     Lang2Locale = {
21       :english  => 'en',
22       :british_english  => 'en_GB',
23       :american_english  => 'en_US',
24       :italian  => 'it',
25       :french   => 'fr',
26       :german   => 'de',
27       :dutch    => 'nl',
28       :japanese => 'ja',
29       :russian  => 'ru',
30       :finnish  => 'fi',
31       :traditional_chinese => 'zh_TW',
32       :simplified_chinese => 'zh_CN'
33     }
34     # On WIN32 it appears necessary to have ".UTF-8" explicitly for gettext to use UTF-8
35     Lang2Locale.each_value {|v| v.replace(v + '.UTF-8')}
36
37     # Return the shortest language for the current
38     # GetText locale
39     def Language.from_locale
40       return 'english' unless defined?(GetText)
41       lang = locale.language
42       if locale.country
43         str = lang + "_#{locale.country}"
44         if Lang2Locale.value?(str)
45           # Get the shortest key in Lang2Locale which maps to the given lang_country
46           lang_str = Lang2Locale.select { |k, v| v == str }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
47           if File.exist?(File.join(Config::datadir, "languages/#{lang_str}.lang"))
48             return lang_str
49           end
50         end
51       end
52       # lang_country didn't work, let's try lan
53       if Lang2Locale.value?(lang)
54         # Get the shortest key in Lang2Locale which maps to the given lang
55         lang_str = Lang2Locale.select { |k, v| v == lang }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
56         if File.exist?(File.join(Config::datadir, "/languages/#{lang_str}.lang"))
57           return lang_str
58         end
59       end
60       # all else fail, return 'english'
61       return 'english'
62     end
63
64     Config.register Config::EnumValue.new('core.language',
65       :default => Irc::Bot::Language.from_locale, :wizard => true,
66       :values => Proc.new{|bot|
67             Dir.new(Config::datadir + "/languages").collect {|f|
68               f =~ /\.lang$/ ? f.gsub(/\.lang$/, "") : nil
69             }.compact
70           },
71       :on_change => Proc.new {|bot, v| bot.lang.set_language v},
72       :desc => "Which language file the bot should use")
73
74     def initialize(bot, language)
75       @bot = bot
76       set_language language
77     end
78     attr_reader :language
79
80     def set_language(language)
81       lang_str = language.to_s.downcase.gsub(/\s+/,'_')
82       lang_sym = lang_str.intern
83       if defined?(GetText) and Lang2Locale.key?(lang_sym)
84         GetText.set_locale(Lang2Locale[lang_sym])
85         debug "locale set to #{locale}"
86         rbot_gettext_debug
87       else
88         warning "Unable to set locale, unknown language #{language} (#{lang_str})"
89       end
90
91       file = Config::datadir + "/languages/#{lang_str}.lang"
92       unless(FileTest.exist?(file))
93         raise "no such language: #{lang_str} (no such file #{file})"
94       end
95       @language = lang_str
96       @file = file
97       scan
98       return if @bot.plugins.nil?
99       @bot.plugins.core_modules.each { |p|
100         if p.respond_to?('set_language')
101           p.set_language(@language)
102         end
103       }
104       @bot.plugins.plugins.each { |p|
105         if p.respond_to?('set_language')
106           p.set_language(@language)
107         end
108       }
109     end
110
111     def scan
112       @strings = Hash.new
113       current_key = nil
114       IO.foreach(@file) {|l|
115         next if l =~ /^$/
116         next if l =~ /^\s*#/
117         if(l =~ /^(\S+):$/)
118           @strings[$1] = Array.new
119           current_key = $1
120         elsif(l =~ /^\s*(.*)$/)
121           @strings[current_key] << $1
122         end
123       }
124     end
125
126     def rescan
127       scan
128     end
129
130     def get(key)
131       if(@strings.has_key?(key))
132         return @strings[key][rand(@strings[key].length)]
133       else
134         raise "undefined language key"
135       end
136     end
137
138     def save
139       File.open(@file, "w") {|file|
140         @strings.each {|key,val|
141           file.puts "#{key}:"
142           val.each_value {|v|
143             file.puts "   #{v}"
144           }
145         }
146       }
147     end
148   end
149
150 end
151 end