File: textdomain.rb

package info (click to toggle)
libgettext-ruby 1.7.0-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 3,892 kB
  • ctags: 1,198
  • sloc: ruby: 6,738; ansic: 67; makefile: 38; sql: 14; sh: 6
file content (209 lines) | stat: -rw-r--r-- 6,278 bytes parent folder | download
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