1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
=begin
textdomain.rb - GetText::Textdomain
Copyright (C) 2001-2006 Masao Mutoh
Copyright (C) 2001-2003 Masahiro Sakai
Masahiro Sakai <s01397ms@sfc.keio.ac.jp>
Masao Mutoh <mutoh@highway.ne.jp>
You may redistribute it and/or modify it under the same
license terms as Ruby.
$Id: textdomain.rb,v 1.18 2006/06/11 15:36:20 mutoh Exp $
=end
require 'gettext/string'
require 'rbconfig'
module GetText
# GetText::TextDomain class manages mo-files of a textdomain.
#
# Usually, you don't need to use this class directly.
#
# Notice: This class is unstable. APIs will be changed.
class TextDomain
GEM_PATH_RE = /(.*)\/lib$/ # :nodoc:
attr_reader :current_locale
attr_reader :locale_paths
attr_reader :current_mo
attr_reader :name
@@check_mo = false
# Check mo-file is modified or not, and if mo-file is modified,
# reload mo-file again. This is effective in debug mode.
# Default is false. If $DEBUG is true, mo-file is checked even if
# this value is false.
# * Returns: true if "check mo" mode.
def self.check_mo?
@@check_mo
end
# Sets to check mo-file or not. See GetText::TextDoman.check_mo? for more details.
# * val: true if "check mo" mode.
# * Returns: val
def self.check_mo=(val)
@@check_mo = val
end
# The default locale paths.
CONFIG_PREFIX = Config::CONFIG['prefix'].gsub(/\/local/, "")
DEFAULT_LOCALE_PATHS = [
"#{Config::CONFIG['datadir']}/locale/%{locale}/LC_MESSAGES/%{name}.mo",
"#{Config::CONFIG['datadir'].gsub(/\/local/, "")}/locale/%{locale}/LC_MESSAGES/%{name}.mo",
"#{CONFIG_PREFIX}/share/locale/%{locale}/LC_MESSAGES/%{name}.mo",
"#{CONFIG_PREFIX}/local/share/locale/%{locale}/LC_MESSAGES/%{name}.mo"
].uniq
# Add default locale path. Usually you should use GetText.add_default_locale_path instead.
# * path: a new locale path. (e.g.) "/usr/share/locale/%{locale}/LC_MESSAGES/%{name}.mo"
# ('locale' => "ja_JP", 'name' => "textdomain")
# * Returns: the new DEFAULT_LOCALE_PATHS
def self.add_default_locale_path(path)
DEFAULT_LOCALE_PATHS << path
end
# Creates a new GetText::TextDomain.
# * name: the textdomain name.
# * topdir: the top directory of mo files or nil.
# * locale: the Locale::Object or nil.
# * Returns: a newly created GetText::TextDomain object.
def initialize(name, topdir = nil, locale = nil)
@name, @topdir = name, topdir
@search_files = Array.new
@locale_paths = []
if ENV["GETTEXT_PATH"]
ENV["GETTEXT_PATH"].split(/,/).each {|i|
@locale_paths += ["#{i}/%{locale}/LC_MESSAGES/%{name}.mo", "#{i}/%{locale}/%{name}.mo"]
}
elsif @topdir
@locale_paths += ["#{@topdir}/%{locale}/LC_MESSAGES/%{name}.mo", "#{@topdir}/%{locale}/%{name}.mo"]
end
unless @topdir
@locale_paths += DEFAULT_LOCALE_PATHS
if defined? Gem
$:.each do |path|
if GEM_PATH_RE =~ path
@locale_paths += [
"#{$1}/data/locale/%{locale}/LC_MESSAGES/%{name}.mo",
"#{$1}/data/locale/%{locale}/%{name}.mo",
"#{$1}/locale/%{locale}/%{name}.mo"]
end
end
end
end
@mofiles = Hash.new
set_locale(locale)
end
# Sets a new Locale::Object.
# * locale: a Locale::Object
# * reload: true if the mo-file is reloaded forcely
# * Returns: self
def set_locale(locale, reload = false)
@current_locale = locale
load_mo(reload)
self
end
# Gets the translated string.
# * msgid: the original message.
# * Returns: the translated string or nil if not found.
def gettext(msgid)
return "" if msgid == "" or msgid.nil?
if @current_mo and @current_mo[msgid] and (@current_mo[msgid].size > 0)
@current_mo[msgid]
else
nil
end
end
# Gets the translated string.
# * msgid: the original message(single).
# * msgid: the original message(plural).
# * n: the number
# * Returns: the translated string or nil if not found.
def ngettext(msgid, msgid_plural, n)
key = msgid + "\000" + msgid_plural
msg = gettext(key)
if ! msg
nil
elsif msg == key
msg = n == 1 ? msgid : msgid_plural
elsif msg.include?("\000")
ary = msg.split("\000")
if @current_mo
plural = eval(@current_mo.plural)
if plural.kind_of?(Numeric)
msg = ary[plural]
else
msg = plural ? ary[1] : ary[0]
end
else
msg = n == 1 ? ary[0] : ary[1]
end
end
msg
end
# Compare this object has the same name, topdir and locale.
# * name: the textdomain name
# * topdir: the top directory of mo files or nil.
# * locale: the Locale::Object or nil.
# * Returns: true if this object has all of the same name, topdir and locale.
def same_property?(name, topdir, locale)
@name == name and @topdir == topdir and @current_locale == locale
end
private
def load_mo(reload = false)
@current_mo = nil
return @current_mo unless @current_locale
unless reload
@current_mo = @mofiles[@current_locale]
if @current_mo
if @current_mo == :empty
@current_mo = nil
return nil unless (@@check_mo or $DEBUG)
elsif (@@check_mo or $DEBUG)
@current_mo.update!
return @current_mo
else
return @current_mo
end
end
end
locales = [@current_locale.orig_str, @current_locale.to_posix, @current_locale.language].uniq
matched = false
@locale_paths.each do |dir|
locales.each{|locale|
fname = dir % {:locale => locale, :name => @name}
@search_files << fname
if File.exist?(fname)
$stderr.puts "GetText::TextDomain#load_mo: mo file is #{fname}" if $DEBUG
@current_mo = MOFile.open(fname, @current_locale.charset)
@mofiles[@current_locale] = @current_mo
matched = true
break
end
}
break if matched
end
unless @current_mo
@mofiles[@current_locale] = :empty
if $DEBUG
$stderr.puts "MO file is not found in"
@search_files.each do |v|
$stderr.puts " #{v}"
end
end
end
@current_mo
end
end
end
|