require 'set' module Xcmultilingual class Parser attr_accessor :verbose def initialize(destination) @destination = destination end def parse puts "+ START PARSING" if @verbose puts "" if @verbose destination_path = File.expand_path(@destination) destination_dir = File.dirname(destination_path) bundles = {} Dir.glob("#{destination_dir}/**/*.lproj/**/*.strings") do |file_path| file_path = File.expand_path(file_path) # bundle if match = file_path.match(/(?(?[^\/]*).bundle)/) bundle_name = match["name"] relative_path = file_path[0, match.end("dir")] relative_path = create_relative_path(destination_path, relative_path) else bundle_name = nil relative_path = nil end bundles[bundle_name] = {:relative_path => relative_path, :name => bundle_name, :tables => {}} unless bundles[bundle_name] # name name = File.basename(file_path, ".strings") bundles[bundle_name][:tables][name] = Set.new unless bundles[bundle_name][:tables].keys.include?(name) # keys File.readlines(file_path, encoding: 'UTF-8').each do |line| safe_line = line.scrub('?') if key = find_key(safe_line) bundles[bundle_name][:tables][name] << key puts " PARSE: #{File.basename(file_path)} > #{line}" if @verbose end end end bundle_data = [] bundles.each do |k, v| bundle = Bundle.new(v[:relative_path], v[:name], []) v[:tables].each do |o, p| table = Table.new(o, p.to_a) bundle.tables << table end puts "" if @verbose puts "#{bundle.description}" if @verbose bundle_data << bundle end puts "" if @verbose puts "+ PARSE SUCCEEDED" if @verbose puts "" if @verbose bundle_data end private def create_relative_path(dest_path, src_path) dest_split = dest_path.split("/") src_split = src_path.split("/") src_extras = [] src_split.each_with_index do |val, idx| next if val == dest_split[idx] src_extras << val end dest_extras = [] dest_split.each_with_index do |val, idx| next if val == src_split[idx] dest_extras << val end prefix = "" (dest_extras.size - 1).times do |idx| prefix += "../" end prefix + src_extras.join("/") end def find_key(line) if match = line.match(/^\"(.*)\"\s*=\s*\"(.*)\"\;$/) return match[1] end nil end end end