lib/missing_t.rb in missing_t-0.4.0 vs lib/missing_t.rb in missing_t-0.4.1

- old
+ new

@@ -1,32 +1,37 @@ require "yaml" #TODO: Should I feel about these 'global' helper functions? -def hashify(strings) - strings.map { |s| s.split('.') }.each_with_object({}) do |segmented_string, h| - segmented_string.each do |segment| - h[segment] ||= {} - h = h[segment] - end +def hashify(segments, value) + return {} if segments.empty? + s, *rest = segments + if rest.empty? + { s => value } + else + { s => hashify(rest, value) } end end def print_hash(h, level) h.each_pair do |k,v| - puts %(#{" " * (level*2)}#{k}:) - print_hash(v, level+1) + if v.respond_to?(:each_pair) + puts %(#{" " * (level*2)}#{k}:) + print_hash(v, level+1) + else + puts %(#{" " * (level*2)}#{k}: #{v}) + end end end class Hash # idea snatched from deep_merge in Rails source code def deep_safe_merge(other_hash) self.merge(other_hash) do |key, oldval, newval| oldval = oldval.to_hash if oldval.respond_to?(:to_hash) newval = newval.to_hash if newval.respond_to?(:to_hash) - if oldval === Hash - if newval === Hash + if oldval.is_a? Hash + if newval.is_a? Hash oldval.deep_safe_merge(newval) else oldval end else @@ -43,52 +48,52 @@ class MissingT class FileReader def read(file) - open(File.expand_path(file), "r") do |f| - yield f.read + IO.readlines(file).each do |line| + yield line end end end - VERSION = "0.4.0" + VERSION = "0.4.1" def initialize(options={}) @reader = options.fetch(:reader, FileReader.new) @languages = options[:languages] @path = options[:path] end def run - missing_translations = collect - missing_message_strings = missing_translations.values.map { |ms| hashify(ms) } - - missing = missing_message_strings.each_with_object({}) do |h, all_message_strings| - all_message_strings.deep_safe_merge!(h) + missing = {} + collect_missing.each do |file, message_strings| + message_strings.each do |message_string, value| + missing.deep_safe_merge! hashify(message_string.split('.'), value) + end end missing.each do |language, missing_for_language| puts puts "#{language}:" print_hash(missing_for_language, 1) end end - def collect + def collect_missing ts = translation_keys #TODO: If no translation keys were found and the languages were not given explicitly # issue a warning and bail out languages = @languages ? @languages : ts.keys get_missing_translations(translation_keys, translation_queries, languages) end def get_missing_translations(keys, queries, languages) languages.each_with_object({}) do |lang, missing| - get_missing_translations_for_lang(keys, queries, lang).each do |file, queries| - missing[file] ||= [] - missing[file].concat(queries).uniq! + get_missing_translations_for_language(keys, queries, lang).each do |file, queries_for_language| + missing[file] ||= {} + missing[file].merge!(queries_for_language) end end end def translation_keys @@ -142,32 +147,61 @@ ] end.flatten end def extract_i18n_queries(file) - i18n_query_pattern = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s*\((.*?)[,\)]/ - i18n_query_no_parens_pattern = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s+(['"])(.*?)\1/ - - @reader.read(File.expand_path(file)) do |content| - ([]).tap do |i18n_message_strings| - i18n_message_strings.concat content.scan(i18n_query_pattern).map { |match| match[0].gsub(/['"\s]/, '') } - i18n_message_strings.concat content.scan(i18n_query_no_parens_pattern).map { |match| match[1].gsub(/['"\s]/, '') } + ({}).tap do |queries| + @reader.read(File.expand_path(file)) do |line| + qs = scan_line(line) + queries.merge!(qs) end end end private - def get_missing_translations_for_lang(keys, queries, lang) - queries.map do |file, queries_in_file| - queries_with_no_translation = queries_in_file.reject { |q| has_translation?(keys, lang, q) } + def get_missing_translations_for_language(keys, queries, l) + queries.each_with_object({}) do |(file, queries_in_file), missing_translations| + queries_with_no_translation = queries_in_file.reject { |q, _| has_translation?(keys, l, q) } if queries_with_no_translation.any? - [file, queries_with_no_translation.map { |q| i18n_label(lang, q) }] + missing_translations[file] = add_langauge_prefix(queries_with_no_translation, l) end - end.compact + end end + def add_langauge_prefix(qs, l) + qs.each_with_object({}) do |(q, v), with_prefix| + with_prefix["#{l}.#{q}"] = v + end + end + def i18n_label(lang, query) "#{lang}.#{query}" end + + def scan_line(line) + with_parens = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s*\((['"](.*?)['"].*?)\)/ + no_parens = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s+(['"](.*?)['"].*?)/ + [with_parens, no_parens].each_with_object({}) do |pattern, extracted_queries| + line.scan(pattern).each do |m| + if m.any? + message_string = m[1] + _, *options = m[0].split(',') + extracted_queries[message_string] = extract_default_value(options) + end + end + end + end + + def extract_default_value(message_string_options) + [/:default\s*=>\s*['"](.*)['"]/, /default:\s*['"](.*)['"]/].each do |default_extractor| + message_string_options.each do |option| + if default_key_match=default_extractor.match(option) + return default_key_match[1] + end + end + end + '' + end + end