#!/usr/bin/ruby require 'set' require 'optparse' def generate_keys_file(opts) tables = [] strings = {} lang_count = 0 all_langs = [] Dir.glob("**/*.lproj/*.strings").each do |filename| if filename.start_with?("Pods") next end if opts[:verbose] puts "Processing: #{ filename }" end table_basename = File.basename(filename, ".strings") if not tables.include? table_basename tables << table_basename end lang = filename[/[^\.]*/].split("/").last File.open(filename, "r:UTF-8") do |f| contents = f.read contents.scan(/^\"([^\"]*)\"\s=\s\"(.*)\";/) do |key, value| key = key.split().join("_") strings[key] ||= {} strings[key][lang] = value end end end strings.each do |key, value| if (value.count > lang_count) then lang_count = value.count all_langs = value.keys end end f = File.open("#{ opts[:output] }/MKLocalizationKeys.h", "w") f.write("// Header automatically generated by MiawKit. Do not edit.\n") if opts[:includes_date] f.write("// Generated on #{ Time.now.asctime }\n") end f.write("\n") f.write("#import <Foundation/Foundation.h>\n"); f.write("\n") f.write("#ifndef MK_LOCALIZATION_KEYS\n") f.write("#define MK_LOCALIZATION_KEYS\n") f.write("\n") tables.each do |table| f.write("/*!\n") f.write(" * #{ table } strings file \n") f.write(" */\n") f.write("static NSString * const #{ table } = @\"#{ table }\";\n\n") end strings.each do |key, value| if (value.count != lang_count) and opts[:warnings] then missing_langs = all_langs.inject([]) { |a, v| if not value.keys.include? v then a << v else a end } f.write("#warning Missing languages #{ missing_langs.join(', ') } for key '#{key}'\n"); end f.write("/*!\n") value.each do |lang, desc| if (lang == opts[:default_language]) then f.write(" * \"#{ desc }\"\n\n") end end f.write(" * All translations:\n\n") value.each do |lang, desc| f.write(" * @b #{ lang }@: \"#{ desc }\"\n\n") end f.write(" */\n") f.write("static NSString * const #{key.gsub("%", "").gsub("@", "X").gsub(".", "_").gsub(/^[\d]/, 'n\0')} = @\"#{ key }\";\n\n") end f.write(" \n") f.write("#endif \n") f.close() end options = { :output => ".", :default_language => "en", :verbose => false, :includes_date => true, :warnings => true } gopts = nil OptionParser.new do |opts| opts.banner = "Usage: #{ $PROGRAM_NAME } -g [options]" opts.on("-oPATH", "--output=PATH", String, "Specify output path.") do |o| if !File.directory?(o) puts "Specified output directory does not exist: #{ o }" exit end options[:output] = o end opts.on("-g", "--generate", "Generates a header with all localization keys.") do |g| options[:generate] = true end opts.on("-w", "--nowarn", "Skips warnings for missing strings.") do |g| options[:warnings] = false end opts.on("-l", "--language", "Code of your development language. Default is en.") do |l| options[:default_language] = l end opts.on("-d", "--no-date", "Removes the date from the header.") do |d| options[:includes_date] = d end opts.on("-v", "--verbose", "Set verbosity.") do |v| options[:verbose] = v end opts.on("-h", "--help", "Displays this information.") do puts opts exit end gopts = opts end.parse! if options.has_key?(:generate) then generate_keys_file(options) else puts gopts end