1
# $Id: msgcat.rb,v 1.44 2004/01/15 17:58:53 sdalu Exp $
4
# CONTACT : zonecheck@nic.fr
5
# AUTHOR : Stephane D'Alu <sdalu@nic.fr>
7
# CREATED : 2002/08/02 13:58:17
8
# REVISION : $Revision: 1.44 $
9
# DATE : $Date: 2004/01/15 17:58:53 $
11
# CONTRIBUTORS: (see also CREDITS file)
14
# LICENSE : GPL v2 (or MIT/X11-like after agreement)
15
# COPYRIGHT : AFNIC (c) 2003
17
# This file is part of ZoneCheck.
19
# ZoneCheck is free software; you can redistribute it and/or modify it
20
# under the terms of the GNU General Public License as published by
21
# the Free Software Foundation; either version 2 of the License, or
22
# (at your option) any later version.
24
# ZoneCheck is distributed in the hope that it will be useful, but
25
# WITHOUT ANY WARRANTY; without even the implied warranty of
26
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27
# General Public License for more details.
29
# You should have received a copy of the GNU General Public License
30
# along with ZoneCheck; if not, write to the Free Software Foundation,
31
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39
## Message catalog for I18N/L10N
42
## WARN: this file is not localized
45
## - method readfile: inode is always 0 on Windows
46
## we replace the inode number by the filename if the inode is 0
49
# BUG: @lang / @language / @country?
58
EXPLANATION = 'explanation'
63
## Exception: the corresponding message catalog is not installed
65
class NoCatalogFound < StandardError
70
## Exception: Syntax error, while parsing the file
72
class SyntaxError < StandardError
77
## Exception: no message for the 'tag'
79
class EntryNotFound < StandardError
86
def initialize(directory, dfltlang)
87
$dbg.msg(DBG::LOCALE) { 'creating message catalogue' }
88
$dbg.msg(DBG::LOCALE) {"fallback for language is set to '#{dfltlang}'"}
90
@directory = directory
98
attr_writer :language, :country
105
@shortcut = { EXPLANATION => {}, DETAILS => {} }
109
# Test if a file catalog is available
111
def available?(where)
112
filepath(where).each { |fp| return true if File::readable?(fp) }
119
# Read catalog (from the template filename)
120
# (the occurence of %s is replaced by the language name)
123
filepath(where).each { |fp|
124
if File::readable?(fp)
126
@catfiles << where unless res.nil?
130
raise NoCatalogFound, "No valid catalog found for #{@lang}"
135
# Get message associated with the 'tag'
137
def get(tag, type=TAG, subtype=nil)
138
$dbg.msg(DBG::LOCALE) {
139
category = type != TAG ? " (#{type}/#{subtype})" : ''
140
"requesting locale for: #{tag}#{category}"
148
res = @check.fetch(tag)[subtype]
149
if res && (sameas = res['sameas'])
151
when /^shortcut:(.*)$/
152
@shortcut.fetch(subtype).fetch($1)
154
@check.fetch(sameas).fetch(subtype)
159
@test.fetch(tag)[subtype]
162
category = type != TAG ? " (#{type}/#{subtype})" : ''
164
"Entity '#{tag}'#{category} has not been defined/localized"
166
"Entity '#{tag}'#{category} doesn't have a link to '#{sameas}'"
168
raise EntryNotFound, xcp
175
# Reload the message catalogs
176
# (allowing to take into account a new locale)
179
$dbg.msg(DBG::LOCALE, 'reloading message catalogue')
182
@catfiles.each { |where|
184
filepath(where).each { |fp|
185
if File::readable?(fp)
186
readfile(fp) ; throw :loaded
189
raise NoCatalogFound, "No valid catalog found for #{@lang}"
198
# Establish the possible filepaths from the template file
199
# - %s is replace by lang
200
# - if not fullpath the default directory is prepend
202
# WARN: An array is returned has for exemple we could need to
203
# test for fr_CA and next fr
206
where = "#{@directory}/#{where}" unless where[0] == ?/
210
fp << "#{@language}_#{@country}" if @country
214
fp.collect { |x| where % x }
220
# (return false if the file was already loaded, true otherwise)
222
def readfile(msgfile)
223
# Check for already loaded catalog
224
file_stat = File::stat(msgfile)
225
file_id = [ file_stat.dev, file_stat.ino != 0 ? file_stat.ino \
227
if @loaded.has_key?(file_id)
228
$dbg.msg(DBG::LOCALE) { "file already loaded: #{msgfile}" }
233
# Read message catalogue
234
$dbg.msg(DBG::LOCALE, "reading file: #{msgfile}")
239
File::open(msgfile) { |io|
240
doc = MyXML::Document::new(io)
244
root.each('//tag') { |element|
245
# create prefix from parent sections
247
xmlsection = element.parent
248
while xmlsection.name == 'section'
249
prefix = xmlsection['name'] + ':' + prefix
250
xmlsection = xmlsection.parent
253
name = prefix + element['name']
254
$dbg.msg(DBG::LOCALE) { "locale tag: #{name}" }
255
@tag[name] = element.text
259
root.each('shortcut') { |shortcut|
260
shortcut.each { |element|
261
name = element['name']
262
@shortcut[element.name][name] = element
267
root.each("check") { |element|
268
checkname = element['name']
269
name = element.child(NAME)
270
success = element.child(SUCCESS)
271
failure = element.child(FAILURE)
272
explanation = element.child(EXPLANATION)
273
details = element.child(DETAILS)
275
if explanation['sameas'].nil?
276
explanation = nil unless explanation.empty?
279
if details['sameas'].nil?
280
details = nil unless details.empty?
283
@check[checkname] = {
285
SUCCESS => success, FAILURE => failure,
286
EXPLANATION => explanation, DETAILS => details }
290
root.each('test') { |element|
291
testname = element['name']
292
name = element.child(NAME)
298
# Consider the file loaded
299
@loaded[file_id] = true
307
# Include the 'with_msgcat' facility in every objects
309
def with_msgcat(*msgcat_list)
310
return unless $mc && $mc.kind_of?(MsgCat)
311
msgcat_list.each { |msgcat| $mc.read(msgcat) }