Class: GetText::RubyParser

Inherits:
Object
  • Object
show all
Defined in:
lib/gettext/tools/parser/ruby.rb

Constant Summary collapse

ID =
["gettext", "_", "N_", "sgettext", "s_"]
PLURAL_ID =
["ngettext", "n_", "Nn_", "ns_", "nsgettext"]
MSGCTXT_ID =
["pgettext", "p_"]
MSGCTXT_PLURAL_ID =
["npgettext", "np_"]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, options = {}) ⇒ RubyParser

Returns a new instance of RubyParser.

Examples:

:comment_tag option: String tag

path = "hello.rb"
# content:
#   # TRANSLATORS: This is a comment to translators.
#   _("Hello")
#
#   # This is a comment for programmers.
#   # TRANSLATORS: This is a comment to translators.
#   # This is also a comment to translators.
#   _("World")
#
#   # This is a comment for programmers.
#   # This is also a comment for programmers
#   # because all lines don't start with "TRANSRATORS:".
#   _("Bye")
options = {:comment_tag => "TRANSLATORS:"}
parser = GetText::RubyParser.new(path, options)
parser.parse
# => [
#   POEntry<
#     :msgid => "Hello",
#     :extracted_comment =>
#       "TRANSLATORS: This is a comment to translators.",
#   >,
#   POEntry<
#     :msgid => "World",
#     :extracted_comment =>
#       "TRANSLATORS: This is a comment to translators.\n" +
#       "This is also a comment to translators.",
#   >,
#   POEntry<
#     :msgid => "Bye",
#     :extracted_comment => nil,
#   >,
# ]

:comment_tag option: nil tag

path = "hello.rb"
# content:
#   # This is a comment to translators.
#   # This is also a comment for translators.
#   _("Hello")
options = {:comment_tag => nil}
parser = GetText::RubyParser.new(path, options)
parser.parse
# => [
#   POEntry<
#     :msgid => "Hello",
#     :extracted_comment =>
#       "This is a comment to translators.\n" +
#       " This is also a comment for translators.",
#   >,
# ]

Parameters:

  • path (String)

    Ruby script path to be parsed

  • options (Hash) (defaults to: {})

    Options

Options Hash (options):

  • :comment_tag (String, nil)

    The tag to detect comments to be extracted. The extracted comments are used to deliver messages to translators from programmers.

    If the tag is String and a line in a comment start with the tag, the line and the following lines are extracted.

    If the tag is nil, all comments are extracted.



203
204
205
206
# File 'lib/gettext/tools/parser/ruby.rb', line 203

def initialize(path, options={})
  @path = path
  @options = options
end

Class Method Details

.parse(path, options = {}) ⇒ Array<POEntry>

Parses Ruby script located at path.

This is a short cut method. It equals to new(path, options).parse.

Parameters:

  • path (String)

    Ruby script path to be parsed

  • options (Hash) (defaults to: {})

    Options

Options Hash (options):

  • :comment_tag (String, nil)

    The tag to detect comments to be extracted. The extracted comments are used to deliver messages to translators from programmers.

    If the tag is String and a line in a comment start with the tag, the line and the following lines are extracted.

    If the tag is nil, all comments are extracted.

Returns:

  • (Array<POEntry>)

    Extracted messages

See Also:



132
133
134
135
# File 'lib/gettext/tools/parser/ruby.rb', line 132

def parse(path, options={})
  parser = new(path, options)
  parser.parse
end

.target?(file) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


118
119
120
# File 'lib/gettext/tools/parser/ruby.rb', line 118

def target?(file)  # :nodoc:
  true # always true, as the default parser.
end

Instance Method Details

#detect_encoding(source) ⇒ Object



220
221
222
223
224
225
226
227
# File 'lib/gettext/tools/parser/ruby.rb', line 220

def detect_encoding(source)
  binary_source = source.dup.force_encoding("ASCII-8BIT")
  if /\A.*coding\s*[=:]\s*([[:alnum:]\-_]+)/ =~ binary_source
    $1.gsub(/-(?:unix|mac|dos)\z/, "")
  else
    nil
  end
end

#parseArray<POEntry>

Extracts messages from @path.

Returns:

  • (Array<POEntry>)

    Extracted messages



211
212
213
214
215
216
217
218
# File 'lib/gettext/tools/parser/ruby.rb', line 211

def parse
  source = IO.read(@path)

  encoding = detect_encoding(source) || source.encoding
  source.force_encoding(encoding)

  parse_source(source)
end

#parse_source(source) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/gettext/tools/parser/ruby.rb', line 229

def parse_source(source)
  po = []
  file = StringIO.new(source)
  rl = RubyLexX.new
  rl.set_input(file)
  rl.skip_space = true
  #rl.readed_auto_clean_up = true

  po_entry = nil
  line_no = nil
  last_comment = ""
  reset_comment = false
  ignore_next_comma = false
  rl.parse do |tk|
    begin
      ignore_current_comma = ignore_next_comma
      ignore_next_comma = false
      case tk
      when RubyToken::TkIDENTIFIER, RubyToken::TkCONSTANT
        if store_po_entry(po, po_entry, line_no, last_comment)
          last_comment = ""
        end
        if ID.include?(tk.name)
          po_entry = POEntry.new(:normal)
        elsif PLURAL_ID.include?(tk.name)
          po_entry = POEntry.new(:plural)
        elsif MSGCTXT_ID.include?(tk.name)
          po_entry = POEntry.new(:msgctxt)
        elsif MSGCTXT_PLURAL_ID.include?(tk.name)
          po_entry = POEntry.new(:msgctxt_plural)
        else
          po_entry = nil
        end
        line_no = tk.line_no.to_s
      when RubyToken::TkSTRING, RubyToken::TkDSTRING
        po_entry.set_current_attribute tk.value if po_entry
      when RubyToken::TkPLUS, RubyToken::TkNL
        #do nothing
      when RubyToken::TkINTEGER
        ignore_next_comma = true
      when RubyToken::TkCOMMA
        unless ignore_current_comma
          po_entry.advance_to_next_attribute if po_entry
        end
      else
        if store_po_entry(po, po_entry, line_no, last_comment)
          po_entry = nil
          last_comment = ""
        end
      end
    rescue
      $stderr.print "\n\nError"
      $stderr.print " parsing #{@path}:#{tk.line_no}\n\t #{source.lines.to_a[tk.line_no - 1]}" if tk
      $stderr.print "\n #{$!.inspect} in\n"
      $stderr.print $!.backtrace.join("\n")
      $stderr.print "\n"
      exit 1
    end

    case tk
    when RubyToken::TkCOMMENT_WITH_CONTENT
      last_comment = "" if reset_comment
      if last_comment.empty?
        comment1 = tk.value.lstrip
        if comment_to_be_extracted?(comment1)
          last_comment << comment1
        end
      else
        last_comment += "\n"
        last_comment += tk.value
      end
      reset_comment = false
    when RubyToken::TkNL
    else
      reset_comment = true
    end
  end
  po
end