lib/yaml-validator.rb in yaml-validator-0.0.1 vs lib/yaml-validator.rb in yaml-validator-0.1.0

- old
+ new

@@ -1,23 +1,40 @@ require 'yaml' require 'yaml-validator/version' +require_relative './helpers' class YamlValidator - def initialize(root_path) + def initialize(root_path, options = {}) + @options = options + @options[:show_missing] ||= true @root_path = root_path end + def en + return @en unless @en.nil? + + fullpath = File.join(@root_path, 'en.yml') + return nil unless File.exists?(fullpath) + + @en = YAML.load_file(fullpath)['en'] + @en = Helpers.normalize_yaml(@en) + end + def en_with_vars - @en ||= YAML.load_file(File.join(@root_path, 'en.yml'))['en'] - @en_with_vars ||= get_all_variables(@en) + return nil if en.nil? + @en_with_vars ||= get_all_variables(en) end def validate() + if en_with_vars.nil? + return ["no en.yml file in the directory (an en.yml file is required as reference)"] + end yml_files = File.join(@root_path, '*.yml') errors = [] Dir[yml_files].each do |filename| + next if File.basename(filename) == 'en.yml' errors.concat validate_yaml(filename) end errors end @@ -27,18 +44,25 @@ begin yaml_object = YAML.load_file(filepath) rescue Psych::SyntaxError => e return [e.message.sub(/^\([^)]+\)/, filename)] end + yaml_object = yaml_object[yaml_object.keys[0]] + yaml_object = Helpers.normalize_yaml(yaml_object) errors = validate_yaml_object('', yaml_object) + if @options[:show_missing] + errors.concat find_missing_translations(yaml_object) + end errors.map { |err| "#{filename}: #{err}" } end def validate_yaml_object(full_key, yaml_object) + return [] if yaml_object.nil? errors = [] + yaml_object.each do |key, value| full_subkey = (full_key.empty?) ? key : "#{full_key}.#{key}" if value.is_a? String errors.concat validate_item(full_subkey, value) else @@ -46,10 +70,45 @@ end end errors end + def find_missing_translations(yaml_object) + find_missing_translations_in_en_object('', en, yaml_object) + end + + def find_missing_translations_in_en_object(full_key, en_yaml_object, yaml_object) + return [] if en_yaml_object.nil? + errors = [] + + en_yaml_object.each do |key, value| + full_subkey = (full_key.empty?) ? key : "#{full_key}.#{key}" + if value.is_a? String or value.is_a? Symbol + if self.class.find_key_in_yaml_object(full_subkey, yaml_object).nil? + errors << "missing translation for #{full_subkey} ('#{value}')" + end + else + errors.concat find_missing_translations_in_en_object(full_subkey, value, yaml_object) + end + end + errors + end + + def self.find_key_in_yaml_object(full_key, yaml_object) + position = yaml_object + full_key.split('.').each do |key| + return nil unless position.is_a? Hash + position = position[key] + end + + if position.is_a? String or position.is_a? Symbol + position + else + nil + end + end + def validate_item(full_key, value) real_vars = get_key_en_vars(full_key) if real_vars.nil? return ["#{full_key} doesn't exist in en.yml"] end @@ -78,21 +137,26 @@ nil end end def get_all_variables(yaml_object) + return {} if yaml_object.nil? with_vars = {} + yaml_object.each do |key, value| if value.is_a? String with_vars[key] = identify_variables(value) + elsif value.is_a? Symbol + with_vars[key] = {} else with_vars[key] = get_all_variables(value) end end with_vars end def identify_variables(string) string.scan(/%{([^}]+)}/).map { |v| v[0] } end + end