ofm_gettext 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +56 -0
- data/ChangeLog-1 +2016 -0
- data/NEWS-1 +414 -0
- data/gettext.gemspec +7 -8
- data/lib/gettext/runtime/class_info.rb +69 -0
- data/lib/gettext/runtime/locale_path.rb +123 -0
- data/lib/gettext/runtime/mofile.rb +332 -0
- data/lib/gettext/runtime/textdomain.rb +179 -0
- data/lib/gettext/runtime/textdomain_group.rb +26 -0
- data/lib/gettext/runtime/textdomain_manager.rb +214 -0
- data/lib/gettext/tools/parser/erb.rb +54 -0
- data/lib/gettext/tools/parser/glade.rb +100 -0
- data/lib/gettext/tools/parser/ruby.rb +226 -0
- data/lib/gettext/tools/pomessage.rb +199 -0
- data/lib/gettext/tools/poparser.rb +358 -0
- data/po/uk/rgettext.po +143 -0
- data/samples/cgi/po/uk/helloerb1.po +62 -0
- data/samples/cgi/po/uk/helloerb2.po +54 -0
- data/samples/cgi/po/uk/hellolib.po +26 -0
- data/samples/cgi/po/uk/main.po +84 -0
- data/samples/po/uk/hello.po +22 -0
- data/samples/po/uk/hello2.po +30 -0
- data/samples/po/uk/hello_glade2.po +34 -0
- data/samples/po/uk/hello_gtk.po +22 -0
- data/samples/po/uk/hello_noop.po +26 -0
- data/samples/po/uk/hello_plural.po +29 -0
- data/samples/po/uk/hello_tk.po +26 -0
- data/test/po/ja/test3.po +19 -0
- data/test/po/li/plural_error.po +27 -0
- data/test/test_locale_path.rb +76 -0
- data/test/test_po_generation.rb +22 -0
- data/test/test_pomessage.rb +101 -0
- data/test/test_textdomain_bind.rb +39 -0
- data/test/test_thread.rb +43 -0
- data/test/tools/files/app.pot +0 -0
- data/test/tools/files/de/app.po +0 -0
- data/test/tools/files/en/app.po +0 -0
- data/test/tools/files/en/test.po +21 -0
- data/test/tools/files/simple_1.po +2 -0
- data/test/tools/files/simple_2.po +2 -0
- data/test/tools/files/simple_translation.rb +3 -0
- data/test/tools/files/version.po +7 -0
- data/test/tools/test.pot +21 -0
- data/test/tools/test_tools.rb +63 -0
- metadata +380 -335
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
parser/glade.rb - parser for Glade-2
|
5
|
+
|
6
|
+
Copyright (C) 2004,2005 Masao Mutoh
|
7
|
+
|
8
|
+
You may redistribute it and/or modify it under the same
|
9
|
+
license terms as Ruby or LGPL.
|
10
|
+
=end
|
11
|
+
|
12
|
+
require 'cgi'
|
13
|
+
require 'gettext'
|
14
|
+
|
15
|
+
module GetText
|
16
|
+
module GladeParser
|
17
|
+
extend GetText
|
18
|
+
extend self
|
19
|
+
|
20
|
+
bindtextdomain("rgettext")
|
21
|
+
|
22
|
+
TARGET1 = /<property.*translatable="yes">(.*)/
|
23
|
+
TARGET2 = /(.*)<\/property>/
|
24
|
+
|
25
|
+
def parse(file, targets = []) # :nodoc:
|
26
|
+
lines = IO.readlines(file)
|
27
|
+
parse_lines(file, lines, targets)
|
28
|
+
end
|
29
|
+
|
30
|
+
#from ary of lines.
|
31
|
+
def parse_lines(file, lines, targets) # :nodoc:
|
32
|
+
cnt = 0
|
33
|
+
target = false
|
34
|
+
line_no = 0
|
35
|
+
val = nil
|
36
|
+
|
37
|
+
loop do
|
38
|
+
line = lines.shift
|
39
|
+
break unless line
|
40
|
+
|
41
|
+
cnt += 1
|
42
|
+
if TARGET1 =~ line
|
43
|
+
line_no = cnt
|
44
|
+
val = $1 + "\n"
|
45
|
+
target = true
|
46
|
+
if TARGET2 =~ $1
|
47
|
+
val = $1
|
48
|
+
add_target(val, file, line_no, targets)
|
49
|
+
val = nil
|
50
|
+
target = false
|
51
|
+
end
|
52
|
+
elsif target
|
53
|
+
if TARGET2 =~ line
|
54
|
+
val << $1
|
55
|
+
add_target(val, file, line_no, targets)
|
56
|
+
val = nil
|
57
|
+
target = false
|
58
|
+
else
|
59
|
+
val << line
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
targets
|
64
|
+
end
|
65
|
+
|
66
|
+
XML_RE = /<\?xml/
|
67
|
+
GLADE_RE = /glade-2.0.dtd/
|
68
|
+
|
69
|
+
def target?(file) # :nodoc:
|
70
|
+
data = IO.readlines(file)
|
71
|
+
if XML_RE =~ data[0] and GLADE_RE =~ data[1]
|
72
|
+
true
|
73
|
+
else
|
74
|
+
if File.extname(file) == '.glade'
|
75
|
+
raise _("`%{file}' is not glade-2.0 format.") % {:file => file}
|
76
|
+
end
|
77
|
+
false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_target(val, file, line_no, targets) # :nodoc:
|
82
|
+
return unless val.size > 0
|
83
|
+
assoc_data = targets.assoc(val)
|
84
|
+
val = CGI.unescapeHTML(val)
|
85
|
+
if assoc_data
|
86
|
+
targets[targets.index(assoc_data)] = assoc_data << "#{file}:#{line_no}"
|
87
|
+
else
|
88
|
+
targets << [val.gsub(/\n/, '\n'), "#{file}:#{line_no}"]
|
89
|
+
end
|
90
|
+
targets
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if __FILE__ == $0
|
96
|
+
# ex) ruby glade.rb foo.glade bar.glade
|
97
|
+
ARGV.each do |file|
|
98
|
+
p GetText::GladeParser.parse(file)
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
=begin
|
3
|
+
parser/ruby.rb - parser for ruby script
|
4
|
+
|
5
|
+
Copyright (C) 2003-2009 Masao Mutoh
|
6
|
+
Copyright (C) 2005 speakillof
|
7
|
+
Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh
|
8
|
+
|
9
|
+
You may redistribute it and/or modify it under the same
|
10
|
+
license terms as Ruby or LGPL.
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
require 'irb/ruby-lex.rb'
|
15
|
+
require 'stringio'
|
16
|
+
require 'gettext/tools/pomessage'
|
17
|
+
|
18
|
+
module GetText
|
19
|
+
class RubyLexX < RubyLex # :nodoc: all
|
20
|
+
# Parser#parse resemlbes RubyLex#lex
|
21
|
+
def parse
|
22
|
+
until ( (tk = token).kind_of?(RubyToken::TkEND_OF_SCRIPT) && !@continue or tk.nil? )
|
23
|
+
s = get_readed
|
24
|
+
if RubyToken::TkSTRING === tk
|
25
|
+
def tk.value
|
26
|
+
@value
|
27
|
+
end
|
28
|
+
|
29
|
+
def tk.value=(s)
|
30
|
+
@value = s
|
31
|
+
end
|
32
|
+
|
33
|
+
if @here_header
|
34
|
+
s = s.sub(/\A.*?\n/, '').sub(/^.*\n\Z/, '')
|
35
|
+
else
|
36
|
+
begin
|
37
|
+
s = eval(s)
|
38
|
+
rescue Exception
|
39
|
+
# Do nothing.
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
tk.value = s
|
44
|
+
end
|
45
|
+
|
46
|
+
if $DEBUG
|
47
|
+
if tk.is_a? TkSTRING
|
48
|
+
$stderr.puts("#{tk}: #{tk.value}")
|
49
|
+
elsif tk.is_a? TkIDENTIFIER
|
50
|
+
$stderr.puts("#{tk}: #{tk.name}")
|
51
|
+
else
|
52
|
+
$stderr.puts(tk)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
yield tk
|
57
|
+
end
|
58
|
+
return nil
|
59
|
+
end
|
60
|
+
|
61
|
+
# Original parser does not keep the content of the comments,
|
62
|
+
# so monkey patching this with new token type and extended
|
63
|
+
# identify_comment implementation
|
64
|
+
RubyToken.def_token :TkCOMMENT_WITH_CONTENT, TkVal
|
65
|
+
|
66
|
+
def identify_comment
|
67
|
+
@ltype = "#"
|
68
|
+
get_readed # skip the hash sign itself
|
69
|
+
|
70
|
+
while ch = getc
|
71
|
+
if ch == "\n"
|
72
|
+
@ltype = nil
|
73
|
+
ungetc
|
74
|
+
break
|
75
|
+
end
|
76
|
+
end
|
77
|
+
return Token(TkCOMMENT_WITH_CONTENT, get_readed)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
# Extends PoMessage for RubyParser.
|
83
|
+
# Implements a sort of state machine to assist the parser.
|
84
|
+
module PoMessageForRubyParser
|
85
|
+
# Supports parsing by setting attributes by and by.
|
86
|
+
def set_current_attribute(str)
|
87
|
+
param = @param_type[@param_number]
|
88
|
+
raise ParseError, 'no more string parameters expected' unless param
|
89
|
+
set_value(param, str)
|
90
|
+
end
|
91
|
+
|
92
|
+
def init_param
|
93
|
+
@param_number = 0
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
def advance_to_next_attribute
|
98
|
+
@param_number += 1
|
99
|
+
end
|
100
|
+
end
|
101
|
+
class PoMessage
|
102
|
+
include PoMessageForRubyParser
|
103
|
+
alias :initialize_old :initialize
|
104
|
+
def initialize(type)
|
105
|
+
initialize_old(type)
|
106
|
+
init_param
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module RubyParser
|
111
|
+
extend self
|
112
|
+
|
113
|
+
ID = ['gettext', '_', 'N_', 'sgettext', 's_']
|
114
|
+
PLURAL_ID = ['ngettext', 'n_', 'Nn_', 'ns_', 'nsgettext']
|
115
|
+
MSGCTXT_ID = ['pgettext', 'p_']
|
116
|
+
MSGCTXT_PLURAL_ID = ['npgettext', 'np_']
|
117
|
+
|
118
|
+
# (Since 2.1.0) the 2nd parameter is deprecated
|
119
|
+
# (and ignored here).
|
120
|
+
# And You don't need to keep the pomessages as unique.
|
121
|
+
|
122
|
+
def parse(path, deprecated = []) # :nodoc:
|
123
|
+
lines = IO.readlines(path)
|
124
|
+
parse_lines(path, lines, deprecated)
|
125
|
+
end
|
126
|
+
|
127
|
+
def parse_lines(path, lines, deprecated = []) # :nodoc:
|
128
|
+
pomessages = deprecated
|
129
|
+
file = StringIO.new(lines.join + "\n")
|
130
|
+
rl = RubyLexX.new
|
131
|
+
rl.set_input(file)
|
132
|
+
rl.skip_space = true
|
133
|
+
#rl.readed_auto_clean_up = true
|
134
|
+
|
135
|
+
pomessage = nil
|
136
|
+
line_no = nil
|
137
|
+
last_comment = ''
|
138
|
+
reset_comment = false
|
139
|
+
rl.parse do |tk|
|
140
|
+
begin
|
141
|
+
case tk
|
142
|
+
when RubyToken::TkIDENTIFIER, RubyToken::TkCONSTANT
|
143
|
+
store_pomessage(pomessages, pomessage, path, line_no, last_comment)
|
144
|
+
if ID.include?(tk.name)
|
145
|
+
pomessage = PoMessage.new(:normal)
|
146
|
+
elsif PLURAL_ID.include?(tk.name)
|
147
|
+
pomessage = PoMessage.new(:plural)
|
148
|
+
elsif MSGCTXT_ID.include?(tk.name)
|
149
|
+
pomessage = PoMessage.new(:msgctxt)
|
150
|
+
elsif MSGCTXT_PLURAL_ID.include?(tk.name)
|
151
|
+
pomessage = PoMessage.new(:msgctxt_plural)
|
152
|
+
else
|
153
|
+
pomessage = nil
|
154
|
+
end
|
155
|
+
line_no = tk.line_no.to_s
|
156
|
+
when RubyToken::TkSTRING
|
157
|
+
pomessage.set_current_attribute tk.value if pomessage
|
158
|
+
when RubyToken::TkPLUS, RubyToken::TkNL
|
159
|
+
#do nothing
|
160
|
+
when RubyToken::TkCOMMA
|
161
|
+
pomessage.advance_to_next_attribute if pomessage
|
162
|
+
else
|
163
|
+
if store_pomessage(pomessages, pomessage, path, line_no, last_comment)
|
164
|
+
pomessage = nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
rescue
|
168
|
+
$stderr.print "\n\nError"
|
169
|
+
$stderr.print " parsing #{path}:#{tk.line_no}\n\t #{lines[tk.line_no - 1]}" if tk
|
170
|
+
$stderr.print "\n #{$!.inspect} in\n"
|
171
|
+
$stderr.print $!.backtrace.join("\n")
|
172
|
+
$stderr.print "\n"
|
173
|
+
exit 1
|
174
|
+
end
|
175
|
+
|
176
|
+
case tk
|
177
|
+
when RubyToken::TkCOMMENT_WITH_CONTENT
|
178
|
+
last_comment = "" if reset_comment
|
179
|
+
if last_comment.empty?
|
180
|
+
# new comment from programmer to translator?
|
181
|
+
comment1 = tk.value.lstrip
|
182
|
+
if comment1 =~ /^TRANSLATORS\:/
|
183
|
+
last_comment = $'
|
184
|
+
end
|
185
|
+
else
|
186
|
+
last_comment += "\n"
|
187
|
+
last_comment += tk.value
|
188
|
+
end
|
189
|
+
reset_comment = false
|
190
|
+
when RubyToken::TkNL
|
191
|
+
else
|
192
|
+
reset_comment = true
|
193
|
+
end
|
194
|
+
end
|
195
|
+
pomessages
|
196
|
+
end
|
197
|
+
|
198
|
+
def target?(file) # :nodoc:
|
199
|
+
true # always true, as the default parser.
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
def store_pomessage(pomessages, pomessage, file_name, line_no, last_comment) #:nodoc:
|
204
|
+
if pomessage && pomessage.msgid
|
205
|
+
pomessage.sources << file_name + ":" + line_no
|
206
|
+
pomessage.add_comment(last_comment) unless last_comment.empty?
|
207
|
+
pomessages << pomessage
|
208
|
+
true
|
209
|
+
else
|
210
|
+
false
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
if __FILE__ == $0
|
217
|
+
require 'pp'
|
218
|
+
ARGV.each do |path|
|
219
|
+
pp GetText::RubyParser.parse(path)
|
220
|
+
end
|
221
|
+
|
222
|
+
#rl = GetText::RubyLexX.new; rl.set_input(ARGF)
|
223
|
+
#rl.parse do |tk|
|
224
|
+
#p tk
|
225
|
+
#end
|
226
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module GetText
|
4
|
+
class ParseError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
# Contains data related to the expression or sentence that
|
8
|
+
# is to be translated.
|
9
|
+
class PoMessage
|
10
|
+
PARAMS = {
|
11
|
+
:normal => [:msgid],
|
12
|
+
:plural => [:msgid, :msgid_plural],
|
13
|
+
:msgctxt => [:msgctxt, :msgid],
|
14
|
+
:msgctxt_plural => [:msgctxt, :msgid, :msgid_plural]
|
15
|
+
}
|
16
|
+
|
17
|
+
@@max_line_length = 70
|
18
|
+
|
19
|
+
# Sets the max line length.
|
20
|
+
def self.max_line_length=(len)
|
21
|
+
@@max_line_length = len
|
22
|
+
end
|
23
|
+
|
24
|
+
# Gets the max line length.
|
25
|
+
def self.max_line_length
|
26
|
+
@@max_line_length
|
27
|
+
end
|
28
|
+
|
29
|
+
# Required
|
30
|
+
attr_accessor :type # :normal, :plural, :msgctxt, :msgctxt_plural
|
31
|
+
attr_accessor :msgid
|
32
|
+
# Options
|
33
|
+
attr_accessor :msgid_plural
|
34
|
+
attr_accessor :msgctxt
|
35
|
+
attr_accessor :sources # ["file1:line1", "file2:line2", ...]
|
36
|
+
attr_accessor :comment
|
37
|
+
|
38
|
+
# Create the object. +type+ should be :normal, :plural, :msgctxt or :msgctxt_plural.
|
39
|
+
def initialize(type)
|
40
|
+
@type = type
|
41
|
+
@sources = []
|
42
|
+
@param_type = PARAMS[@type]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Support for extracted comments. Explanation s.
|
46
|
+
# http://www.gnu.org/software/gettext/manual/gettext.html#Names
|
47
|
+
def add_comment(new_comment)
|
48
|
+
if (new_comment and ! new_comment.empty?)
|
49
|
+
@comment ||= ""
|
50
|
+
@comment += new_comment
|
51
|
+
end
|
52
|
+
to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns a parameter representation suitable for po-files
|
56
|
+
# and other purposes.
|
57
|
+
def escaped(param_name)
|
58
|
+
orig = self.send param_name
|
59
|
+
orig.gsub(/"/, '\"').gsub(/\r/, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
# Checks if the other translation target is mergeable with
|
63
|
+
# the current one. Relevant are msgid and translation context (msgctxt).
|
64
|
+
def ==(other)
|
65
|
+
other && other.msgid == self.msgid && other.msgctxt == self.msgctxt
|
66
|
+
end
|
67
|
+
|
68
|
+
# Merges two translation targets with the same msgid and returns the merged
|
69
|
+
# result. If one is declared as plural and the other not, then the one
|
70
|
+
# with the plural wins.
|
71
|
+
def merge(other)
|
72
|
+
return self unless other
|
73
|
+
raise ParseError, "Translation targets do not match: \n" \
|
74
|
+
" self: #{self.inspect}\n other: '#{other.inspect}'" unless self == other
|
75
|
+
if other.msgid_plural && !self.msgid_plural
|
76
|
+
res = other
|
77
|
+
unless (res.sources.include? self.sources[0])
|
78
|
+
res.sources += self.sources
|
79
|
+
res.add_comment(self.comment)
|
80
|
+
end
|
81
|
+
else
|
82
|
+
res = self
|
83
|
+
unless (res.sources.include? other.sources[0])
|
84
|
+
res.sources += other.sources
|
85
|
+
res.add_comment(other.comment)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
res
|
89
|
+
end
|
90
|
+
|
91
|
+
# Output the po message for the po-file.
|
92
|
+
def to_po_str
|
93
|
+
raise "msgid is nil." unless @msgid
|
94
|
+
raise "sources is nil." unless @sources
|
95
|
+
|
96
|
+
str = ""
|
97
|
+
# extracted comments
|
98
|
+
if comment
|
99
|
+
comment.split("\n").each do |comment_line|
|
100
|
+
str << "\n#. #{comment_line.strip}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# references
|
105
|
+
curr_pos = @@max_line_length
|
106
|
+
sources.each do |e|
|
107
|
+
if curr_pos + e.size > @@max_line_length
|
108
|
+
str << "\n#:"
|
109
|
+
curr_pos = 3
|
110
|
+
else
|
111
|
+
curr_pos += (e.size + 1)
|
112
|
+
end
|
113
|
+
str << " " << e
|
114
|
+
end
|
115
|
+
|
116
|
+
# msgctxt, msgid, msgstr
|
117
|
+
str << "\nmsgctxt \"" << msgctxt << "\"" if msgctxt?
|
118
|
+
str << "\nmsgid \"" << escaped(:msgid) << "\"\n"
|
119
|
+
if plural?
|
120
|
+
str << "msgid_plural \"" << escaped(:msgid_plural) << "\"\n"
|
121
|
+
str << "msgstr[0] \"\"\n"
|
122
|
+
str << "msgstr[1] \"\"\n"
|
123
|
+
else
|
124
|
+
str << "msgstr \"\"\n"
|
125
|
+
end
|
126
|
+
str
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns true if the type is kind of msgctxt.
|
130
|
+
# And if this is a kind of msgctxt and msgctxt property
|
131
|
+
# is nil, then raise an RuntimeException.
|
132
|
+
def msgctxt?
|
133
|
+
if [:msgctxt, :msgctxt_plural].include? @type
|
134
|
+
raise "This PoMessage is a kind of msgctxt but the msgctxt property is nil. msgid: #{msgid}" unless @msgctxt
|
135
|
+
true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns true if the type is kind of plural.
|
140
|
+
# And if this is a kind of plural and msgid_plural property
|
141
|
+
# is nil, then raise an RuntimeException.
|
142
|
+
def plural?
|
143
|
+
if [:plural, :msgctxt_plural].include? @type
|
144
|
+
raise "This PoMessage is a kind of plural but the msgid_plural property is nil. msgid: #{msgid}" unless @msgid_plural
|
145
|
+
true
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
# sets or extends the value of a translation target params like msgid,
|
152
|
+
# msgctxt etc.
|
153
|
+
# param is symbol with the name of param
|
154
|
+
# value - new value
|
155
|
+
def set_value(param, value)
|
156
|
+
send "#{param}=", (send(param) || '') + value.gsub(/\n/, '\n')
|
157
|
+
end
|
158
|
+
|
159
|
+
public
|
160
|
+
# For backward comatibility. This doesn't support "comment".
|
161
|
+
# ary = [msgid1, "file1:line1", "file2:line"]
|
162
|
+
def self.new_from_ary(ary)
|
163
|
+
ary = ary.dup
|
164
|
+
msgid = ary.shift
|
165
|
+
sources = ary
|
166
|
+
type = :normal
|
167
|
+
msgctxt = nil
|
168
|
+
msgid_plural = nil
|
169
|
+
|
170
|
+
if msgid.include? "\004"
|
171
|
+
msgctxt, msgid = msgid.split(/\004/)
|
172
|
+
type = :msgctxt
|
173
|
+
end
|
174
|
+
if msgid.include? "\000"
|
175
|
+
ids = msgid.split(/\000/)
|
176
|
+
msgid = ids[0]
|
177
|
+
msgid_plural = ids[1]
|
178
|
+
if type == :msgctxt
|
179
|
+
type = :msgctxt_plural
|
180
|
+
else
|
181
|
+
type = :plural
|
182
|
+
end
|
183
|
+
end
|
184
|
+
ret = self.new(type)
|
185
|
+
ret.msgid = msgid
|
186
|
+
ret.sources = sources
|
187
|
+
ret.msgctxt = msgctxt
|
188
|
+
ret.msgid_plural = msgid_plural
|
189
|
+
ret
|
190
|
+
end
|
191
|
+
|
192
|
+
def [](number)
|
193
|
+
param = @param_type[number]
|
194
|
+
raise ParseError, 'no more string parameters expected' unless param
|
195
|
+
send param
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|