gettext 3.2.9 → 3.3.0

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.
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