gettext 3.2.9 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +276 -198
  3. data/Rakefile +2 -1
  4. data/doc/text/news.md +43 -0
  5. data/gettext.gemspec +3 -2
  6. data/lib/gettext/locale_path.rb +5 -1
  7. data/lib/gettext/po.rb +4 -4
  8. data/lib/gettext/po_entry.rb +17 -7
  9. data/lib/gettext/text_domain.rb +1 -1
  10. data/lib/gettext/tools/parser/ruby.rb +238 -224
  11. data/lib/gettext/version.rb +2 -2
  12. data/po/bg/gettext.edit.po +10 -4
  13. data/po/bg/gettext.po +5 -0
  14. data/po/bs/gettext.edit.po +10 -4
  15. data/po/bs/gettext.po +5 -0
  16. data/po/ca/gettext.edit.po +10 -4
  17. data/po/ca/gettext.po +5 -0
  18. data/po/cs/gettext.edit.po +10 -4
  19. data/po/cs/gettext.po +5 -0
  20. data/po/de/gettext.edit.po +10 -4
  21. data/po/de/gettext.po +5 -0
  22. data/po/el/gettext.edit.po +10 -4
  23. data/po/el/gettext.po +5 -0
  24. data/po/eo/gettext.edit.po +10 -4
  25. data/po/eo/gettext.po +5 -0
  26. data/po/es/gettext.edit.po +10 -4
  27. data/po/es/gettext.po +5 -0
  28. data/po/et/gettext.edit.po +10 -4
  29. data/po/et/gettext.po +5 -0
  30. data/po/fr/gettext.edit.po +10 -4
  31. data/po/fr/gettext.po +5 -0
  32. data/po/gettext.pot +32 -25
  33. data/po/hr/gettext.edit.po +10 -4
  34. data/po/hr/gettext.po +5 -0
  35. data/po/hu/gettext.edit.po +10 -4
  36. data/po/hu/gettext.po +5 -0
  37. data/po/it/gettext.edit.po +10 -4
  38. data/po/it/gettext.po +5 -0
  39. data/po/ja/gettext.edit.po +10 -4
  40. data/po/ja/gettext.po +5 -0
  41. data/po/ko/gettext.edit.po +10 -4
  42. data/po/ko/gettext.po +5 -0
  43. data/po/lv/gettext.edit.po +10 -4
  44. data/po/lv/gettext.po +5 -0
  45. data/po/nb/gettext.edit.po +10 -4
  46. data/po/nb/gettext.po +5 -0
  47. data/po/nl/gettext.edit.po +10 -4
  48. data/po/nl/gettext.po +5 -0
  49. data/po/pt_BR/gettext.edit.po +10 -4
  50. data/po/pt_BR/gettext.po +5 -0
  51. data/po/ru/gettext.edit.po +10 -4
  52. data/po/ru/gettext.po +5 -0
  53. data/po/sr/gettext.edit.po +10 -4
  54. data/po/sr/gettext.po +5 -0
  55. data/po/sv/gettext.edit.po +10 -4
  56. data/po/sv/gettext.po +5 -0
  57. data/po/uk/gettext.edit.po +10 -4
  58. data/po/uk/gettext.po +5 -0
  59. data/po/vi/gettext.edit.po +10 -4
  60. data/po/vi/gettext.po +5 -0
  61. data/po/zh/gettext.edit.po +10 -4
  62. data/po/zh/gettext.po +5 -0
  63. data/po/zh_TW/gettext.edit.po +10 -4
  64. data/po/zh_TW/gettext.po +5 -0
  65. data/samples/cgi/po/helloerb1.pot +3 -3
  66. data/samples/cgi/po/helloerb2.pot +3 -3
  67. data/samples/cgi/po/hellolib.pot +3 -3
  68. data/samples/cgi/po/main.pot +3 -3
  69. data/samples/po/hello.pot +3 -3
  70. data/samples/po/hello2.pot +4 -4
  71. data/samples/po/hello_glade2.pot +4 -4
  72. data/samples/po/hello_gtk2.pot +4 -4
  73. data/samples/po/hello_gtk_builder.pot +4 -5
  74. data/samples/po/hello_noop.pot +4 -4
  75. data/samples/po/hello_plural.pot +4 -4
  76. data/samples/po/hello_tk.pot +4 -4
  77. data/test/fixtures/_.rb +9 -0
  78. data/test/fixtures/erb/non_ascii.rhtml +1 -0
  79. data/test/gettext-test-utils.rb +10 -3
  80. data/test/locale/fr/LC_MESSAGES/plural_error.mo +0 -0
  81. data/test/locale/ja/LC_MESSAGES/_.mo +0 -0
  82. data/test/po/_.pot +8 -4
  83. data/test/po/backslash.pot +6 -4
  84. data/test/po/fr/plural_error.po +7 -0
  85. data/test/po/hello.pot +3 -3
  86. data/test/po/ja/_.edit.po +6 -2
  87. data/test/po/ja/_.po +5 -2
  88. data/test/po/ja/hello.edit.po +0 -1
  89. data/test/po/non_ascii.pot +4 -4
  90. data/test/po/np_.pot +8 -5
  91. data/test/po/ns_.pot +6 -4
  92. data/test/po/p_.pot +3 -3
  93. data/test/po/s_.pot +6 -4
  94. data/test/po/untranslated.pot +4 -4
  95. data/test/test_class_info.rb +8 -9
  96. data/test/test_gettext.rb +7 -1
  97. data/test/test_parser.rb +1 -1
  98. data/test/test_po_entry.rb +1 -13
  99. data/test/test_po_parser.rb +6 -4
  100. data/test/test_string.rb +9 -5
  101. data/test/tools/test_msgmerge.rb +5 -2
  102. data/test/tools/test_xgettext.rb +5 -1
  103. metadata +17 -18
  104. data/lib/gettext/tools/parser/haml.rb +0 -61
data/Rakefile CHANGED
@@ -49,7 +49,8 @@ end
49
49
 
50
50
  po_parser_ry_path = "src/po_parser.ry"
51
51
  file po_parser_rb_path => po_parser_ry_path do
52
- racc = File.join(Gem.bindir, "racc")
52
+ racc_spec = Gem::Specification.find_by_name("racc")
53
+ racc = File.join(racc_spec.bin_dir, racc_spec.executable)
53
54
  tempfile = Tempfile.new("gettext-po-parser")
54
55
  ruby(racc, "-g", po_parser_ry_path, "-o", tempfile.path)
55
56
 
@@ -1,5 +1,48 @@
1
1
  # News
2
2
 
3
+ ## 3.3.0: 2020-01-08 {#version-3-3-0}
4
+
5
+ ### Improvements
6
+
7
+ * Fixed README markup.
8
+ [GitHub#57][Patch by Alexander Paukste]
9
+
10
+ * Suppressed warnings.
11
+ [GitHub#58][Patch by 284km]
12
+
13
+ * Improved README.
14
+ [GitHub#62][Patch by Robert Graff]
15
+
16
+ * Added support for finding `racc` of Ruby 2.7.
17
+ [GitHub#65][Patch by KITAITI Makoto]
18
+
19
+ * Added support for Ruby 2.7.
20
+ [GitHub#64][Reported by Anatol Pomozov]
21
+
22
+ * Dropped support for Ruby 2.4.
23
+
24
+ ### Fixes
25
+
26
+ * Fixed a bug that `n_` may return nil.
27
+ [GitHub#60][Patch by Michaël Hoste]
28
+
29
+ * Fixed a sort by msgid bug.
30
+ [GitHub#61][Patch by Robert Graff]
31
+
32
+ ### Thanks
33
+
34
+ * Alexander Paukste
35
+
36
+ * 284km
37
+
38
+ * Michaël Hoste
39
+
40
+ * Robert Graff
41
+
42
+ * KITAITI Makoto
43
+
44
+ * Anatol Pomozov
45
+
3
46
  ## 3.2.9: 2018-03-05 {#version-3-2-9}
4
47
 
5
48
  ### Fixes
@@ -15,8 +15,7 @@ So you can use GNU gettext tools for maintaining.
15
15
  EOD
16
16
  s.authors = ["Kouhei Sutou", "Masao Mutoh"]
17
17
  s.email = ["kou@clear-code.com", "mutomasa at gmail.com"]
18
- s.homepage = "http://ruby-gettext.github.com/"
19
- s.rubyforge_project = "gettext"
18
+ s.homepage = "https://ruby-gettext.github.io/"
20
19
  s.require_paths = ["lib"]
21
20
  Dir.chdir(base_dir) do
22
21
  s.files = Dir.glob("{locale,bin,data,doc/text,lib,po,samples,src,test}/**/*")
@@ -28,6 +27,8 @@ So you can use GNU gettext tools for maintaining.
28
27
  s.test_files = Dir.glob("test/test_*.rb")
29
28
  end
30
29
 
30
+ s.required_ruby_version = ">= 2.5.0"
31
+
31
32
  s.add_runtime_dependency("locale", ">= 2.0.5")
32
33
  s.add_runtime_dependency("text", ">= 1.3.0")
33
34
  s.add_development_dependency("rake")
@@ -85,7 +85,11 @@ module GetText
85
85
  this_path_rules = rule % {:lang => "([^\/]+)", :name => name}
86
86
  Dir.glob(rule % {:lang => "*", :name => name}).each do |path|
87
87
  if /#{this_path_rules}/ =~ path
88
- @locale_paths[$1] = path.untaint unless @locale_paths[$1]
88
+ locale_path = $1
89
+ unless @locale_paths[locale_path]
90
+ path.untaint if RUBY_VERSION < "2.7"
91
+ @locale_paths[locale_path] = path
92
+ end
89
93
  end
90
94
  end
91
95
  end
@@ -222,11 +222,11 @@ module GetText
222
222
  def sort(entries)
223
223
  case @order
224
224
  when :reference, :references # :references is deprecated.
225
- sorted_entries = sort_by_reference(entries)
225
+ sort_by_reference(entries)
226
226
  when :msgid
227
- sorted_entries = sort_by_msgid(entries)
227
+ sort_by_msgid(entries)
228
228
  else
229
- sorted_entries = entries.to_a
229
+ entries.to_a
230
230
  end
231
231
  end
232
232
 
@@ -268,7 +268,7 @@ module GetText
268
268
  def sort_by_msgid(entries)
269
269
  entries.sort_by do |msgid_entry|
270
270
  # msgid_entry = [[msgctxt, msgid], POEntry]
271
- msgid_entry[0]
271
+ msgid_entry[0][1]
272
272
  end
273
273
  end
274
274
  end
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2012-2017 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2012-2019 Sutou Kouhei <kou@clear-code.com>
4
2
  # Copyright (C) 2010 masone (Christian Felder) <ema@rh-productions.ch>
5
3
  # Copyright (C) 2009 Masao Mutoh
6
4
  #
@@ -210,13 +208,25 @@ module GetText
210
208
  true
211
209
  end
212
210
 
213
- def [](number)
214
- param = @param_type[number]
215
- raise ParseError, 'no more string parameters expected' unless param
216
- send param
211
+ def [](number_or_param)
212
+ __send__(resolve_param(number_or_param))
213
+ end
214
+
215
+ def []=(number_or_param, value)
216
+ __send__("#{resolve_param(number_or_param)}=", value)
217
217
  end
218
218
 
219
219
  private
220
+ def resolve_param(number_or_param)
221
+ case number_or_param
222
+ when Integer
223
+ param = @param_type[number_or_param]
224
+ raise ParseError, 'no more string parameters expected' unless param
225
+ param
226
+ else
227
+ number_or_param
228
+ end
229
+ end
220
230
 
221
231
  # sets or extends the value of a translation target params like msgid,
222
232
  # msgctxt etc.
@@ -124,7 +124,7 @@ module GetText
124
124
  # [[msgstr[0], msgstr[1], msgstr[2],...], cond]
125
125
  mo = @mofiles[lang.to_s]
126
126
  cond = (mo and mo != :empty) ? mo.plural_as_proc : DEFAULT_PLURAL_CALC
127
- ret = [msg.split("\000"), cond]
127
+ ret = [msg.split("\000", -1), cond]
128
128
  else
129
129
  ret = [[msg], DEFAULT_SINGLE_CALC]
130
130
  end
@@ -1,8 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
1
  =begin
3
2
  parser/ruby.rb - parser for ruby script
4
3
 
5
- Copyright (C) 2013-2017 Kouhei Sutou <kou@clear-code.com>
4
+ Copyright (C) 2013-2019 Sutou Kouhei <kou@clear-code.com>
6
5
  Copyright (C) 2003-2009 Masao Mutoh
7
6
  Copyright (C) 2005 speakillof
8
7
  Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh
@@ -12,162 +11,271 @@
12
11
 
13
12
  =end
14
13
 
15
- require "irb/ruby-lex"
14
+ require "ripper"
16
15
  require "stringio"
17
- require "gettext/po_entry"
18
16
 
19
- require "ripper"
17
+ require "gettext/po_entry"
20
18
 
21
19
  module GetText
22
- class RubyLexX < RubyLex # :nodoc: all
23
- class StringExtractor < Ripper::Filter
20
+ class RubyParser
21
+ class POExtractor < Ripper::Filter
22
+ ID = ["gettext", "_", "N_", "sgettext", "s_"]
23
+ PLURAL_ID = ["ngettext", "n_", "Nn_", "ns_", "nsgettext"]
24
+ MSGCTXT_ID = ["pgettext", "p_"]
25
+ MSGCTXT_PLURAL_ID = ["npgettext", "np_"]
26
+
27
+ attr_accessor :use_comment
28
+ attr_accessor :comment_tag
24
29
  def initialize(*args)
25
- super
30
+ super(*args)
31
+ @in_block_arguments = false
32
+ @ignore_next_comma = false
33
+ @context_stack = []
34
+ @need_definition_name = false
35
+ @current_po_entry = nil
36
+ @current_po_entry_nth_attribute = 0
37
+ @use_comment = false
38
+ @comment_tag = nil
39
+ @last_comment = ""
40
+ @reset_comment = false
41
+ @embed_expression_level = 0
26
42
  @string_mark_stack = []
43
+ @string_stack = []
27
44
  end
28
45
 
29
- def on_default(event, token, output)
30
- case event
31
- when :on_tstring_content
32
- if @string_mark_stack.last == "\""
33
- output << token.gsub(/\\./) do |data|
34
- case data
35
- when "\\n"
36
- "\n"
37
- when "\\t"
38
- "\t"
39
- when "\\\\"
40
- "\\"
41
- when "\\\""
42
- "\""
43
- when "\\\#"
44
- "#"
45
- else
46
- data
47
- end
48
- end
49
- else
50
- output << token.gsub(/\\./) do |data|
51
- case data
52
- when "\\\\"
53
- "\\"
54
- when "\\'"
55
- "'"
56
- else
57
- data
58
- end
59
- end
60
- end
61
- when :on_tstring_beg
62
- unless @string_mark_stack.empty?
63
- output << token
64
- end
65
- @string_mark_stack << token
66
- when :on_tstring_end
67
- @string_mark_stack.pop
68
- unless @string_mark_stack.empty?
69
- output << token
46
+ def process_on_op(token, po)
47
+ @in_block_arguments = !@in_block_arguments if token == "|"
48
+ po
49
+ end
50
+
51
+ def process_on_kw(token, po)
52
+ store_po_entry(po)
53
+ case token
54
+ when "begin", "case", "do", "for"
55
+ @context_stack.push(token)
56
+ when "class", "def", "module"
57
+ @context_stack.push(token)
58
+ when "if", "unless", "until", "while"
59
+ # postfix case
60
+ unless state.allbits?(Ripper::EXPR_LABEL)
61
+ @context_stack.push(token)
70
62
  end
63
+ when "end"
64
+ @context_stack.pop
65
+ end
66
+ po
67
+ end
68
+
69
+ def process_on_ident(token, po)
70
+ if @embed_expression_level > 0
71
+ @string_stack.last << token
72
+ return po
73
+ end
74
+
75
+ store_po_entry(po)
76
+
77
+ return po if @in_block_arguments
78
+ return po if state.allbits?(Ripper::EXPR_ENDFN)
79
+
80
+ case token
81
+ when *ID
82
+ @current_po_entry = POEntry.new(:normal)
83
+ when *PLURAL_ID
84
+ @current_po_entry = POEntry.new(:plural)
85
+ when *MSGCTXT_ID
86
+ @current_po_entry = POEntry.new(:msgctxt)
87
+ when *MSGCTXT_PLURAL_ID
88
+ @current_po_entry = POEntry.new(:msgctxt_plural)
89
+ end
90
+ if @current_po_entry
91
+ @current_po_entry.add_comment(@last_comment) unless @last_comment.empty?
92
+ @last_comment = ""
93
+ @current_po_entry.references << "#{filename}:#{lineno}"
94
+ @current_po_entry_nth_attribute = 0
95
+ end
96
+ po
97
+ end
98
+
99
+ def process_on_const(token, po)
100
+ case token
101
+ when "N_"," Nn_"
102
+ # TODO: Check the next token is :on_lparen
103
+ process_on_ident(token, po)
71
104
  else
72
- unless @string_mark_stack.empty?
73
- output << token.to_s
74
- end
105
+ po
75
106
  end
76
- output
77
107
  end
78
- end
79
108
 
80
- # Parser#parse resemlbes RubyLex#lex
81
- def parse
82
- until ( (tk = token).kind_of?(RubyToken::TkEND_OF_SCRIPT) && !@continue or tk.nil? )
83
- s = get_readed
84
- if RubyToken::TkSTRING === tk or RubyToken::TkDSTRING === tk
85
- def tk.value
86
- @value
109
+ def process_on_comment(token, po)
110
+ @last_comment = "" if @reset_comment
111
+ @reset_comment = false
112
+ if @last_comment.empty?
113
+ content = token.gsub(/\A#\s*/, "").chomp
114
+ if comment_to_be_extracted?(content)
115
+ @last_comment << content
87
116
  end
117
+ else
118
+ content = token.gsub(/\A#/, "").chomp
119
+ @last_comment << "\n"
120
+ @last_comment << content
121
+ end
122
+ po
123
+ end
88
124
 
89
- def tk.value=(s)
90
- @value = s
91
- end
125
+ def process_on_sp(token, po)
126
+ po
127
+ end
92
128
 
93
- if @here_header
94
- s = s.sub(/\A.*?\n/, "").sub(/^.*\n\Z/, "")
95
- else
96
- s = StringExtractor.new(s).parse("")
129
+ def process_on_tstring_beg(token, po)
130
+ @string_mark_stack << token
131
+ @string_stack << ""
132
+ po
133
+ end
134
+
135
+ def process_on_tstring_content(token, po)
136
+ if @string_mark_stack.last == "\""
137
+ @string_stack.last << token.gsub(/\\./) do |data|
138
+ case data
139
+ when "\\n"
140
+ "\n"
141
+ when "\\t"
142
+ "\t"
143
+ when "\\\\"
144
+ "\\"
145
+ when "\\\""
146
+ "\""
147
+ when "\\\#"
148
+ "#"
149
+ else
150
+ data
151
+ end
152
+ end
153
+ else
154
+ @string_stack.last << token.gsub(/\\./) do |data|
155
+ case data
156
+ when "\\\\"
157
+ "\\"
158
+ when "\\'"
159
+ "'"
160
+ else
161
+ data
162
+ end
97
163
  end
164
+ end
165
+ po
166
+ end
98
167
 
99
- tk.value = s
168
+ def process_on_tstring_end(token, po)
169
+ @ignore_next_comma = false
170
+ @string_mark_stack.pop
171
+ last_string = @string_stack.pop
172
+ if @current_po_entry and last_string
173
+ @current_po_entry[@current_po_entry_nth_attribute] =
174
+ (@current_po_entry[@current_po_entry_nth_attribute] || "") +
175
+ last_string
100
176
  end
177
+ po
178
+ end
101
179
 
102
- if $DEBUG
103
- if tk.is_a? TkSTRING or tk.is_a? TkDSTRING
104
- $stderr.puts("#{tk}: #{tk.value}")
105
- elsif tk.is_a? TkIDENTIFIER
106
- $stderr.puts("#{tk}: #{tk.name}")
107
- else
108
- $stderr.puts(tk)
109
- end
180
+ def process_on_heredoc_beg(token, po)
181
+ if token.end_with?("'")
182
+ @string_mark_stack << "'"
183
+ else
184
+ @string_mark_stack << "\""
110
185
  end
186
+ @string_stack << ""
187
+ po
188
+ end
111
189
 
112
- yield tk
190
+ def process_on_heredoc_end(token, po)
191
+ process_on_tstring_end(token, po)
192
+ end
193
+
194
+ def process_on_regexp_beg(token, po)
195
+ @string_mark_stack << "\""
196
+ @string_stack << ""
197
+ po
113
198
  end
114
- return nil
115
- end
116
199
 
117
- # Original parser does not keep the content of the comments,
118
- # so monkey patching this with new token type and extended
119
- # identify_comment implementation
120
- RubyToken.def_token :TkCOMMENT_WITH_CONTENT, TkVal
200
+ def process_on_embexpr_beg(token, po)
201
+ @embed_expression_level += 1
202
+ @string_stack.last << token
203
+ po
204
+ end
121
205
 
122
- def identify_comment
123
- @ltype = "#"
124
- get_readed # skip the hash sign itself
206
+ def process_on_embexpr_end(token, po)
207
+ @embed_expression_level -= 1
208
+ @string_stack.last << token
209
+ po
210
+ end
125
211
 
126
- while ch = getc
127
- if ch == "\n"
128
- @ltype = nil
129
- ungetc
130
- break
212
+ def process_on_regexp_end(token, po)
213
+ @string_mark_stack.pop
214
+ @string_stack.pop
215
+ po
216
+ end
217
+
218
+ def process_on_int(token, po)
219
+ @ignore_next_comma = true
220
+ po
221
+ end
222
+
223
+ def process_on_comma(token, po)
224
+ unless @ignore_next_comma
225
+ if @current_po_entry
226
+ @current_po_entry_nth_attribute += 1
227
+ end
131
228
  end
229
+ po
132
230
  end
133
- return Token(TkCOMMENT_WITH_CONTENT, get_readed)
134
- end
135
231
 
136
- end
232
+ def process_on_rparen(token, po)
233
+ store_po_entry(po)
234
+ po
235
+ end
137
236
 
138
- # Extends POEntry for RubyParser.
139
- # Implements a sort of state machine to assist the parser.
140
- module POEntryForRubyParser
141
- # Supports parsing by setting attributes by and by.
142
- def set_current_attribute(str)
143
- param = @param_type[@param_number]
144
- raise ParseError, "no more string parameters expected" unless param
145
- set_value(param, str)
146
- end
237
+ def process_on_nl(token, po)
238
+ @reset_comment = true
239
+ po
240
+ end
147
241
 
148
- def init_param
149
- @param_number = 0
150
- self
151
- end
242
+ def on_default(event, token, po)
243
+ trace(event, token) do
244
+ process_method = "process_#{event}"
245
+ if respond_to?(process_method)
246
+ __send__(process_method, token, po)
247
+ else
248
+ po
249
+ end
250
+ end
251
+ end
152
252
 
153
- def advance_to_next_attribute
154
- @param_number += 1
155
- end
156
- end
157
- class POEntry
158
- include POEntryForRubyParser
159
- alias :initialize_old :initialize
160
- def initialize(type)
161
- initialize_old(type)
162
- init_param
163
- end
164
- end
253
+ private
254
+ @@debug = ENV["GETTEXT_RUBY_PARSER_DEBUG"]
255
+ def debug?
256
+ @@debug
257
+ end
165
258
 
166
- class RubyParser
167
- ID = ["gettext", "_", "N_", "sgettext", "s_"]
168
- PLURAL_ID = ["ngettext", "n_", "Nn_", "ns_", "nsgettext"]
169
- MSGCTXT_ID = ["pgettext", "p_"]
170
- MSGCTXT_PLURAL_ID = ["npgettext", "np_"]
259
+ def trace(event_name, token)
260
+ pp [event_name, token, state, @context_stack.last] if debug?
261
+ yield
262
+ end
263
+
264
+ def store_po_entry(po)
265
+ return if @current_po_entry.nil?
266
+ po << @current_po_entry if @current_po_entry.msgid
267
+ @current_po_entry = nil
268
+ @current_po_entry_nth_attribute = 0
269
+ end
270
+
271
+ def comment_to_be_extracted?(comment)
272
+ return false unless @use_comment
273
+
274
+ return true if @comment_tag.nil?
275
+
276
+ comment.start_with?(@comment_tag)
277
+ end
278
+ end
171
279
 
172
280
  class << self
173
281
  def target?(file) # :nodoc:
@@ -282,106 +390,12 @@ module GetText
282
390
  end
283
391
 
284
392
  def parse_source(source)
285
- po = []
286
- file = StringIO.new(source)
287
- rl = RubyLexX.new
288
- rl.set_input(file)
289
- rl.skip_space = true
290
- #rl.readed_auto_clean_up = true
291
-
292
- po_entry = nil
293
- line_no = nil
294
- last_comment = ""
295
- reset_comment = false
296
- ignore_next_comma = false
297
- rl.parse do |tk|
298
- begin
299
- ignore_current_comma = ignore_next_comma
300
- ignore_next_comma = false
301
- case tk
302
- when RubyToken::TkIDENTIFIER, RubyToken::TkCONSTANT
303
- if store_po_entry(po, po_entry, line_no, last_comment)
304
- last_comment = ""
305
- end
306
- if ID.include?(tk.name)
307
- po_entry = POEntry.new(:normal)
308
- elsif PLURAL_ID.include?(tk.name)
309
- po_entry = POEntry.new(:plural)
310
- elsif MSGCTXT_ID.include?(tk.name)
311
- po_entry = POEntry.new(:msgctxt)
312
- elsif MSGCTXT_PLURAL_ID.include?(tk.name)
313
- po_entry = POEntry.new(:msgctxt_plural)
314
- else
315
- po_entry = nil
316
- end
317
- line_no = tk.line_no.to_s
318
- when RubyToken::TkBITOR
319
- po_entry = nil
320
- when RubyToken::TkSTRING, RubyToken::TkDSTRING
321
- po_entry.set_current_attribute tk.value if po_entry
322
- when RubyToken::TkPLUS, RubyToken::TkNL
323
- #do nothing
324
- when RubyToken::TkINTEGER
325
- ignore_next_comma = true
326
- when RubyToken::TkCOMMA
327
- unless ignore_current_comma
328
- po_entry.advance_to_next_attribute if po_entry
329
- end
330
- else
331
- if store_po_entry(po, po_entry, line_no, last_comment)
332
- po_entry = nil
333
- last_comment = ""
334
- end
335
- end
336
- rescue
337
- $stderr.print "\n\nError"
338
- $stderr.print " parsing #{@path}:#{tk.line_no}\n\t #{source.lines.to_a[tk.line_no - 1]}" if tk
339
- $stderr.print "\n #{$!.inspect} in\n"
340
- $stderr.print $!.backtrace.join("\n")
341
- $stderr.print "\n"
342
- exit 1
343
- end
344
-
345
- case tk
346
- when RubyToken::TkCOMMENT_WITH_CONTENT
347
- last_comment = "" if reset_comment
348
- if last_comment.empty?
349
- comment1 = tk.value.lstrip
350
- if comment_to_be_extracted?(comment1)
351
- last_comment += comment1
352
- end
353
- else
354
- last_comment += "\n"
355
- last_comment += tk.value
356
- end
357
- reset_comment = false
358
- when RubyToken::TkNL
359
- else
360
- reset_comment = true
361
- end
362
- end
363
- po
364
- end
365
-
366
- private
367
- def store_po_entry(po, po_entry, line_no, last_comment) #:nodoc:
368
- if po_entry && po_entry.msgid
369
- po_entry.references << @path + ":" + line_no
370
- po_entry.add_comment(last_comment) unless last_comment.empty?
371
- po << po_entry
372
- true
373
- else
374
- false
393
+ extractor = POExtractor.new(source, @path)
394
+ if @options.key?(:comment_tag)
395
+ extractor.use_comment = true
396
+ extractor.comment_tag = @options[:comment_tag]
375
397
  end
376
- end
377
-
378
- def comment_to_be_extracted?(comment)
379
- return false unless @options.has_key?(:comment_tag)
380
-
381
- tag = @options[:comment_tag]
382
- return true if tag.nil?
383
-
384
- /\A#{Regexp.escape(tag)}/ === comment
398
+ extractor.parse([])
385
399
  end
386
400
  end
387
401
  end