class GettextI18nRailsJs::JsAndCoffeeParser

Attributes

js_gettext_function[RW]

The gettext function name can be configured at the module level as ::js_gettext_function This is to provide a way to avoid conflicts with other javascript libraries. You only need to define the base function name to replace '_' and all the other variants (s_, n_, N_) will be deduced automatically.

Public Class Methods

parse(file, msgids = []) click to toggle source

We're lazy and klumsy, so this is a regex based parser that looks for invocations of the various gettext functions. Once captured, we scan them once again to fetch all the function arguments. Invoke regex captures like this: source: "#{ __('hello') } #{ __("wor)ld") }" matches: [0]: __('hello') [1]: __ [2]: 'hello'

source: __('item', 'items', 33) matches: [0]: __('item', 'items', 33) [1]: __ [2]: 'item', 'items', 33

# File lib/gettext_i18n_rails_js/js_and_coffee_parser.rb, line 34
def self.parse(file, msgids = [])
  _ = self.js_gettext_function

  arg_regex = %r
    \s*                     # Some whitespace
    ('(?:[^'\\]|\\.)*?'|    # A token inside the argument list, like a single quoted string
     "(?:[^"\\]|\\.)*?"|    # ...Double quote string, both support escapes
     [a-zA-Z0-9_\.()]*?)    # ...a number, variable name, or called function lik: 33, foo, Foo.bar()
    \s*                     # More whitespace
  /

  # We first parse full invocations
  invoke_regex = %r
    (\b[snN]?#{_})          # Matches the function call grouping the method used (__, n__, N__, etc)
      \(                    # and a parenthesis to start the arguments to the function.
        ((#{arg_regex},)*   # There may be many arguments to the same function call
          #{arg_regex})?    # then the last, or only argument to the function call.
      \)                    # function call closing parenthesis
  /

  File.new(file).each_line.each_with_index.collect do |line, idx|
    line.scan(invoke_regex).collect do |function, arguments|
      separator = function == "n#{_}" ? "\0000" : "\0004"
      key = arguments.scan(%r('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*")/).
        collect{|match| match.first[1..-2]}.
        join(separator)
      next if key == ''
      key.gsub!("\n", '\n')
      key.gsub!("\t", '\t')
      key.gsub!("\00"", '\0')

      [key, "#{file}:#{idx+1}"]
    end
  end.inject(:+).compact
end
target?(file) click to toggle source
# File lib/gettext_i18n_rails_js/js_and_coffee_parser.rb, line 15
def self.target?(file)
  ['.js', '.coffee'].include?(File.extname(file))
end