Class: GetText::RubyParser

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

Constant Summary

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.



258
259
260
261
# File 'lib/gettext/tools/parser/ruby.rb', line 258

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:



187
188
189
190
# File 'lib/gettext/tools/parser/ruby.rb', line 187

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

.target?(file) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


173
174
175
# File 'lib/gettext/tools/parser/ruby.rb', line 173

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

Instance Method Details

#detect_encoding(source) ⇒ Object



275
276
277
278
279
280
281
282
# File 'lib/gettext/tools/parser/ruby.rb', line 275

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



266
267
268
269
270
271
272
273
# File 'lib/gettext/tools/parser/ruby.rb', line 266

def parse
  source = IO.read(@path)

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

  parse_source(source)
end

#parse_source(source) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/gettext/tools/parser/ruby.rb', line 284

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::TkBITOR
        po_entry = nil
      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