Class: ZLocalize::SourceProcessor
- Inherits:
-
Object
- Object
- ZLocalize::SourceProcessor
- Defined in:
- lib/zlocalize/source_processor.rb
Constant Summary collapse
- BARE_TRANSLATE_METHODS =
Methods recognized as translation calls when called without an explicit receiver (bare calls), mapped to whether they yield plural entries.
{ '_' => false, 'n_' => true }.freeze
- QUALIFIED_TRANSLATE_METHODS =
Methods recognized as translation calls when called on the ZLocalize constant, mapped to whether they yield plural entries.
{ 'translate' => false, 'pluralize' => true }.freeze
Instance Method Summary collapse
- #format_parse_errors(parse_result) ⇒ Object
- #get_string_array_node_value(node) ⇒ Object
- #get_string_node_value(node) ⇒ Object
-
#initialize(filename, root, is_erb = false) ⇒ SourceProcessor
constructor
A new instance of SourceProcessor.
- #make_translation_entry(h) ⇒ Object
- #process(content) ⇒ Object
- #record_call(node, plural) ⇒ Object
- #string_node?(node) ⇒ Boolean
-
#translation_entries ⇒ Object
return a Hash of all translation entries we collected.
- #walk(node) ⇒ Object
- #zlocalize_const?(node) ⇒ Boolean
Constructor Details
#initialize(filename, root, is_erb = false) ⇒ SourceProcessor
Returns a new instance of SourceProcessor.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/zlocalize/source_processor.rb', line 23 def initialize(filename, root, is_erb = false) @in_hash = 0 @translate_calls = [] @root = File.join(File.(root).downcase,'/') # add a trailing / @filename = File.(filename).downcase @relative_filename = @filename.gsub(@root,'') @line_offset = 0 content = File.open(filename, "r") { |f| f.read } if is_erb content = ActionView::Template::Handlers::ERB::Erubi.new(content, escape: true, trim: true).src # Erubi compiles ERB to bare Ruby with top-level `yield`, which Prism # rejects (yield is only valid inside a method). Wrap in a method and # track the offset so reported line numbers still match the template. content = "def __zlocalize_erb__\n#{content}\nend" @line_offset = 1 end begin process(content) rescue ArgumentError => ae raise ArgumentError.new("In #{filename} #{ae.message}") end end |
Instance Method Details
#format_parse_errors(parse_result) ⇒ Object
106 107 108 109 110 |
# File 'lib/zlocalize/source_processor.rb', line 106 def format_parse_errors(parse_result) parse_result.errors.map do |error| "line #{error.location.start_line}: #{error.message}" end.join("\n") end |
#get_string_array_node_value(node) ⇒ Object
95 96 97 98 99 100 |
# File 'lib/zlocalize/source_processor.rb', line 95 def get_string_array_node_value(node) unless node.is_a?(Prism::ArrayNode) raise ArgumentError.new("On line #{node.location.start_line} at column #{node.location.start_column+1} : Array expected but got: #{node.inspect}") end node.elements.map { |element| get_string_node_value(element) } end |
#get_string_node_value(node) ⇒ Object
88 89 90 91 92 93 |
# File 'lib/zlocalize/source_processor.rb', line 88 def get_string_node_value(node) unless string_node?(node) raise ArgumentError.new("On line #{node.location.start_line} at column #{node.location.start_column+1} : String Expected but got: #{node.inspect}") end return node.unescaped end |
#make_translation_entry(h) ⇒ Object
126 127 128 129 130 |
# File 'lib/zlocalize/source_processor.rb', line 126 def make_translation_entry(h) TranslationEntry.new('plural' => h[:name] == 'n_' || h[:name] == 'pluralize', 'source' => h[:parameter], 'references' => [ "#{@relative_filename}:#{h[:line_no]}" ]) end |
#process(content) ⇒ Object
46 47 48 49 50 |
# File 'lib/zlocalize/source_processor.rb', line 46 def process(content) parse_result = Prism.parse(content) raise ArgumentError.new("Syntax error: #{format_parse_errors(parse_result)}") unless parse_result.success? walk(parse_result.value) end |
#record_call(node, plural) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/zlocalize/source_processor.rb', line 72 def record_call(node, plural) argument_nodes = node.arguments.arguments source = plural ? get_string_array_node_value(argument_nodes[0]) : get_string_node_value(argument_nodes[0]) @translate_calls << { name: node.name.to_s, line_no: node..start_line - @line_offset, char_no: node..start_column + 1, parameter: source } # keep harvesting inside any nested arguments (e.g. options hashes containing # further translation calls) argument_nodes[1..].each { |child| walk(child) } if argument_nodes.size > 1 end |
#string_node?(node) ⇒ Boolean
102 103 104 |
# File 'lib/zlocalize/source_processor.rb', line 102 def string_node?(node) node.is_a?(Prism::StringNode) end |
#translation_entries ⇒ Object
return a Hash of all translation entries we collected
113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/zlocalize/source_processor.rb', line 113 def translation_entries entries = {} @translate_calls.each do |c| e = make_translation_entry(c) if entries[e.source] entries[e.source].references += e.references else entries[e.source] = e end end entries end |
#walk(node) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/zlocalize/source_processor.rb', line 52 def walk(node) return unless node.is_a?(Prism::Node) if node.is_a?(Prism::CallNode) if node.receiver.nil? plural = BARE_TRANSLATE_METHODS[node.name.to_s] if !plural.nil? && node.arguments && node.arguments.arguments.size >= 1 record_call(node, plural) and return end elsif zlocalize_const?(node.receiver) plural = QUALIFIED_TRANSLATE_METHODS[node.name.to_s] if !plural.nil? && node.arguments && node.arguments.arguments.size >= 1 record_call(node, plural) and return end end end node.compact_child_nodes.each { |child| walk(child) } end |
#zlocalize_const?(node) ⇒ Boolean
84 85 86 |
# File 'lib/zlocalize/source_processor.rb', line 84 def zlocalize_const?(node) node.is_a?(Prism::ConstantReadNode) && node.name.to_s == 'ZLocalize' end |