class Twine::Runner
Public Class Methods
new(options = {}, twine_file = TwineFile.new)
click to toggle source
# File lib/twine/runner.rb, line 43 def initialize(options = {}, twine_file = TwineFile.new) @options = options @twine_file = twine_file if @options[:quite] Twine::stdout = NullOutput.new end end
run(args)
click to toggle source
# File lib/twine/runner.rb, line 16 def self.run(args) options = CLI.parse(args) return unless options twine_file = TwineFile.new twine_file.read options[:twine_file] runner = new(options, twine_file) case options[:command] when 'generate-localization-file' runner.generate_localization_file when 'generate-all-localization-files' runner.generate_all_localization_files when 'consume-localization-file' runner.consume_localization_file when 'consume-all-localization-files' runner.consume_all_localization_files when 'generate-localization-archive' runner.generate_localization_archive when 'consume-localization-archive' runner.consume_localization_archive when 'validate-twine-file' runner.validate_twine_file end end
Public Instance Methods
consume_all_localization_files()
click to toggle source
# File lib/twine/runner.rb, line 185 def consume_all_localization_files if !File.directory?(@options[:input_path]) raise Twine::Error.new("Directory does not exist: #{@options[:input_path]}") end Dir.glob(File.join(@options[:input_path], "**/*")) do |item| if File.file?(item) begin read_localization_file(item) rescue Twine::Error => e Twine::stderr.puts "#{e.message}" end end end output_path = @options[:output_path] || @options[:twine_file] write_twine_data(output_path) end
consume_localization_archive()
click to toggle source
# File lib/twine/runner.rb, line 204 def consume_localization_archive require_rubyzip if !File.file?(@options[:input_path]) raise Twine::Error.new("File does not exist: #{@options[:input_path]}") end error_encountered = false Dir.mktmpdir do |temp_dir| Zip::File.open(@options[:input_path]) do |zipfile| zipfile.each do |entry| next if entry.name.end_with? '/' or File.basename(entry.name).start_with? '.' real_path = File.join(temp_dir, entry.name) FileUtils.mkdir_p(File.dirname(real_path)) zipfile.extract(entry.name, real_path) begin read_localization_file(real_path) rescue Twine::Error => e Twine::stderr.puts "#{e.message}" error_encountered = true end end end end output_path = @options[:output_path] || @options[:twine_file] write_twine_data(output_path) if error_encountered raise Twine::Error.new("At least one file could not be consumed") end end
consume_localization_file()
click to toggle source
# File lib/twine/runner.rb, line 174 def consume_localization_file lang = nil if @options[:languages] lang = @options[:languages][0] end read_localization_file(@options[:input_path], lang) output_path = @options[:output_path] || @options[:twine_file] write_twine_data(output_path) end
generate_all_localization_files()
click to toggle source
# File lib/twine/runner.rb, line 72 def generate_all_localization_files validate_twine_file if @options[:validate] if !File.directory?(@options[:output_path]) if @options[:create_folders] FileUtils.mkdir_p(@options[:output_path]) else raise Twine::Error.new("Directory does not exist: #{@options[:output_path]}") end end if @options[:format] formatter = formatter_for_format(@options[:format]) else formatter = find_formatter { |f| f.can_handle_directory?(@options[:output_path]) } end unless formatter raise Twine::Error.new "Could not determine format given the contents of #{@options[:output_path]}. Try using `--format`." end file_name = @options[:file_name] || formatter.default_file_name if @options[:create_folders] @twine_file.language_codes.each do |lang| output_path = File.join(@options[:output_path], formatter.output_path_for_language(lang)) FileUtils.mkdir_p(output_path) file_path = File.join(output_path, file_name) output = formatter.format_file(lang) unless output Twine::stdout.puts "Skipping file at path #{file_path} since it would not contain any translations." next end IO.write(file_path, output, encoding: output_encoding) end else language_found = false Dir.foreach(@options[:output_path]) do |item| next if item == "." or item == ".." output_path = File.join(@options[:output_path], item) next unless File.directory?(output_path) lang = formatter.determine_language_given_path(output_path) next unless lang language_found = true file_path = File.join(output_path, file_name) output = formatter.format_file(lang) unless output Twine::stdout.puts "Skipping file at path #{file_path} since it would not contain any translations." next end IO.write(file_path, output, encoding: output_encoding) end unless language_found raise Twine::Error.new("Failed to generate any files: No languages found at #{@options[:output_path]}") end end end
generate_localization_archive()
click to toggle source
# File lib/twine/runner.rb, line 140 def generate_localization_archive validate_twine_file if @options[:validate] require_rubyzip if File.file?(@options[:output_path]) File.delete(@options[:output_path]) end Dir.mktmpdir do |temp_dir| Zip::File.open(@options[:output_path], Zip::File::CREATE) do |zipfile| zipfile.mkdir('Locales') formatter = formatter_for_format(@options[:format]) @twine_file.language_codes.each do |lang| if @options[:languages] == nil || @options[:languages].length == 0 || @options[:languages].include?(lang) file_name = lang + formatter.extension temp_path = File.join(temp_dir, file_name) zip_path = File.join('Locales', file_name) output = formatter.format_file(lang) unless output Twine::stdout.puts "Skipping file #{file_name} since it would not contain any translations." next end IO.write(temp_path, output, encoding: output_encoding) zipfile.add(zip_path, temp_path) end end end end end
generate_localization_file()
click to toggle source
# File lib/twine/runner.rb, line 58 def generate_localization_file validate_twine_file if @options[:validate] lang = nil lang = @options[:languages][0] if @options[:languages] formatter, lang = prepare_read_write(@options[:output_path], lang) output = formatter.format_file(lang) raise Twine::Error.new "Nothing to generate! The resulting file would not contain any translations." unless output IO.write(@options[:output_path], output, encoding: output_encoding) end
validate_twine_file()
click to toggle source
# File lib/twine/runner.rb, line 238 def validate_twine_file total_definitions = 0 all_keys = Set.new duplicate_keys = Set.new keys_without_tags = Set.new invalid_keys = Set.new keys_with_python_only_placeholders = Set.new valid_key_regex = /^[A-Za-z0-9_]+$/ @twine_file.sections.each do |section| section.definitions.each do |definition| total_definitions += 1 duplicate_keys.add(definition.key) if all_keys.include? definition.key all_keys.add(definition.key) keys_without_tags.add(definition.key) if definition.tags == nil or definition.tags.length == 0 invalid_keys << definition.key unless definition.key =~ valid_key_regex keys_with_python_only_placeholders << definition.key if definition.translations.values.any? { |v| Placeholders.contains_python_specific_placeholder(v) } end end errors = [] join_keys = lambda { |set| set.map { |k| " " + k }.join("\n") } unless duplicate_keys.empty? errors << "Found duplicate key(s):\n#{join_keys.call(duplicate_keys)}" end if @options[:pedantic] if keys_without_tags.length == total_definitions errors << "None of your definitions have tags." elsif keys_without_tags.length > 0 errors << "Found definitions without tags:\n#{join_keys.call(keys_without_tags)}" end end unless invalid_keys.empty? errors << "Found key(s) with invalid characters:\n#{join_keys.call(invalid_keys)}" end unless keys_with_python_only_placeholders.empty? errors << "Found key(s) with placeholders that are only supported by Python:\n#{join_keys.call(keys_with_python_only_placeholders)}" end raise Twine::Error.new errors.join("\n\n") unless errors.empty? Twine::stdout.puts "#{@options[:twine_file]} is valid." end
write_twine_data(path)
click to toggle source
# File lib/twine/runner.rb, line 51 def write_twine_data(path) if @options[:developer_language] @twine_file.set_developer_language_code(@options[:developer_language]) end @twine_file.write(path) end
Private Instance Methods
find_formatter(&block)
click to toggle source
# File lib/twine/runner.rb, line 308 def find_formatter(&block) formatters = Formatters.formatters.select(&block) if formatters.empty? return nil elsif formatters.size > 1 raise Twine::Error.new("Unable to determine format. Candidates are: #{formatters.map(&:format_name).join(', ')}. Please specify the format you want using `--format`") end formatter = formatters.first formatter.twine_file = @twine_file formatter.options = @options formatter end
formatter_for_format(format)
click to toggle source
# File lib/twine/runner.rb, line 304 def formatter_for_format(format) find_formatter { |f| f.format_name == format } end
output_encoding()
click to toggle source
# File lib/twine/runner.rb, line 292 def output_encoding @options[:encoding] || 'UTF-8' end
prepare_read_write(path, lang)
click to toggle source
# File lib/twine/runner.rb, line 336 def prepare_read_write(path, lang) if @options[:format] formatter = formatter_for_format(@options[:format]) else formatter = find_formatter { |f| f.extension == File.extname(path) } end unless formatter raise Twine::Error.new "Unable to determine format of #{path}. Try using `--format`." end lang = lang || formatter.determine_language_given_path(path) unless lang raise Twine::Error.new "Unable to determine language for #{path}. Try using `--lang`." end @twine_file.language_codes << lang unless @twine_file.language_codes.include? lang return formatter, lang end
read_localization_file(path, lang = nil)
click to toggle source
# File lib/twine/runner.rb, line 321 def read_localization_file(path, lang = nil) unless File.file?(path) raise Twine::Error.new("File does not exist: #{path}") end formatter, lang = prepare_read_write(path, lang) external_encoding = @options[:encoding] || Twine::Encoding.encoding_for_path(path) IO.open(IO.sysopen(path, 'rb'), 'rb', external_encoding: external_encoding, internal_encoding: 'UTF-8') do |io| io.read(2) if Twine::Encoding.has_bom?(path) formatter.read(io, lang) end end
require_rubyzip()
click to toggle source
# File lib/twine/runner.rb, line 296 def require_rubyzip begin require 'zip' rescue LoadError raise Twine::Error.new "You must run 'gem install rubyzip' in order to create or consume localization archives." end end