File: textdomain.rb

package info (click to toggle)
libgettext-ruby 2.1.0-2.1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 3,628 kB
  • ctags: 511
  • sloc: ruby: 4,391; makefile: 12
file content (177 lines) | stat: -rw-r--r-- 5,143 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
=begin
  textdomain.rb - GetText::Textdomain

  Copyright (C) 2001-2009  Masao Mutoh
  Copyright (C) 2001-2003  Masahiro Sakai

      Masahiro Sakai    <s01397ms@sfc.keio.ac.jp>
      Masao Mutoh       <mutomasa at gmail.com>

  You may redistribute it and/or modify it under the same
  license terms as Ruby or LGPL.
=end

require 'gettext/core_ext/string'
require 'gettext/runtime/mofile'
require 'gettext/runtime/locale_path'

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

    attr_reader :output_charset
    attr_reader :mofiles
    attr_reader :name

    @@cached = ! $DEBUG
    # Cache the mo-file or not.
    # Default is true. If $DEBUG is set then false.
    def self.cached?
      @@cached
    end

    # Set to cache the mo-file or not.
    # * val: true if cached, otherwise false.
    def self.cached=(val)
      @@cached = val
    end

    # Add default locale path. Usually you should use GetText.add_default_locale_path instead.
    # * path: a new locale path. (e.g.) "/usr/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
    #   ('locale' => "ja_JP", 'name' => "textdomain")
    # * Returns: the new DEFAULT_LOCALE_PATHS
    def self.add_default_locale_path(path)
      warn "Deprecated. Use GetText::LocalePath.add_default_rule instead."
      LocalePath.add_default_rule(path)
    end

    # Creates a new GetText::TextDomain.
    # * name: the textdomain name.
    # * topdir: the locale path ("%{topdir}/%{lang}/LC_MESSAGES/%{name}.mo") or nil.
    # * output_charset: output charset.
    # * Returns: a newly created GetText::TextDomain object.
    def initialize(name, topdir = nil, output_charset = nil)
      @name, @output_charset = name, output_charset

      @locale_path = LocalePath.new(@name, topdir)
      @mofiles = {}
    end
    
    # Translates the translated string.
    # * lang: Locale::Tag::Simple's subclass.
    # * msgid: the original message.
    # * Returns: the translated string or nil.
    def translate_singluar_message(lang, msgid)
      return "" if msgid == "" or msgid.nil?

      lang_key = lang.to_s

      mofile = nil
      if self.class.cached?
        mofile = @mofiles[lang_key]
      end
      unless mofile
        mofile = load_mo(lang)
      end
     
      if (! mofile) or (mofile ==:empty)
        return nil
      end

      msgstr = mofile[msgid]
      if msgstr and (msgstr.size > 0)
        msgstr
      elsif msgid.include?("\000")
        # Check "aaa\000bbb" and show warning but return the singluar part.
        ret = nil
        msgid_single = msgid.split("\000")[0]
        mofile.each{|key, val| 
          if key =~ /^#{Regexp.quote(msgid_single)}\000/
            # Usually, this is not caused to make po-files from rgettext.
            warn %Q[Warning: n_("#{msgid_single}", "#{msgid.split("\000")[1]}") and n_("#{key.gsub(/\000/, '", "')}") are duplicated.]
            ret = val
            break
          end
        }
        ret
      else
        ret = nil
        mofile.each{|key, val| 
          if key =~ /^#{Regexp.quote(msgid)}\000/
            ret = val.split("\000")[0]
            break
          end
        }
        ret
      end
    end

    DEFAULT_PLURAL_CALC = Proc.new{|n| n != 1}
    DEFAULT_SINGLE_CALC = Proc.new{|n| 0}

    # Translates the translated string.
    # * lang: Locale::Tag::Simple's subclass.
    # * msgid: the original message.
    # * msgid_plural: the original message(plural).
    # * Returns: the translated string as an Array ([[msgstr1, msgstr2, ...], cond]) or nil.
    def translate_plural_message(lang, msgid, msgid_plural)   #:nodoc:
      key = msgid + "\000" + msgid_plural
      msg = translate_singluar_message(lang, key)
      ret = nil
      if ! msg
        ret = nil
      elsif msg.include?("\000")
        # [[msgstr[0], msgstr[1], msgstr[2],...], cond]
        mofile = @mofiles[lang.to_posix.to_s]
        cond = (mofile and mofile != :empty) ? mofile.plural_as_proc : DEFAULT_PLURAL_CALC
        ret = [msg.split("\000"), cond]
      else
        ret = [[msg], DEFAULT_SINGLE_CALC]
      end
      ret
    end

    # Clear cached mofiles.
    def clear
      @mofiles = {}
    end

    # Set output_charset.
    # * charset: output charset.
    def output_charset=(charset)
      @output_charset = charset
      clear
    end

    private
    # Load a mo-file from the file.
    # lang is the subclass of Locale::Tag::Simple.
    def load_mo(lang)
      lang = lang.to_posix unless lang.kind_of? Locale::Tag::Posix
      lang_key = lang.to_s

      mofile = @mofiles[lang_key]
      if mofile
        if mofile == :empty
          return :empty
        elsif ! self.class.cached?
          mofile.update!
        end
        return mofile
      end

      path = @locale_path.current_path(lang)

      if path
        charset = @output_charset || lang.charset || Locale.charset || "UTF-8"
        @mofiles[lang_key] = MOFile.open(path, charset)
      else
        @mofiles[lang_key] = :empty
      end
    end
  end
end