# -*- encoding : utf-8 -*- require 'phrase/tool_config' require 'optparse' require 'net/http' require 'net/https' require 'fileutils' module PhraseGem class Tool def initialize(argv) @args = argv end def run config = ToolConfig.new command = args.first case command when /init/ init(config) when /push/ push(config) when /pull/ pull(config) else print_usage end end private def init(config) secret_param = args.find{ |arg| arg =~ /secret=/ } unless secret_param.to_s.match(/secret=.+/) $stderr.puts "Need a secret to init, but found none." $stderr.puts "Please provide the --secret=YOUR_SECRET parameter." exit(41) end secret = secret_param.split("=", 2).last config.secret = secret puts "Wrote secret to config file .phrase" default_locale_param = args.find{ |arg| arg =~ /default-locale=/ } if default_locale_param.to_s.match(/default-locale=.+/) locale_name = default_locale_param.split("=", 2).last else locale_name = "en" end create_locale(locale_name, config) make_locale_default(locale_name, config) end def push(config) files = choose_files_to_upload if files.empty? puts "Could not find any files to upload :(" exit(43) end if !config.secret || config.secret.empty? puts "No config present. Please initialize phrase before pushing or pulling." exit(43) end upload_files(files, config) end def choose_files_to_upload file_name = args[1] unless file_name if self.class.rails_default_locale_folder_is_available file_name = self.class.rails_default_locale_folder puts "No file or directory specified, using #{self.class.rails_default_locale_folder}" else $stderr.puts "Need either a file or directory:" $stderr.puts "phrase push FILE" $stderr.puts "phrase push DIRECTORY" exit(46) end end unless File.exist?(file_name) $stderr.puts "The file #{file_name} could not be found." exit(42) end if File.directory?(file_name) files = Dir.glob("#{File.expand_path(file_name)}/**") else files = [file_name] end end def upload_files(files, config) files.each do |file| proceed_with_upload = true if File.directory?(file) proceed_with_upload = false end if is_yaml_file(file) proceed_with_upload = false $stderr.puts "Notice: Could not upload #{file} (extension not supported - see http://phraseapp.com/help for more information)" end if proceed_with_upload puts "Uploading #{file}..." params = { 'auth_token' => config.secret, 'filename' => file, 'file_content' => File.read(file) } http = http_client(config) request = Net::HTTP::Post.new("#{config.api_path_prefix}/translation_keys/upload") request.set_form_data(params) res = http.request(request) unless res.code.to_s =~ /^[23]/ print_server_error(res, file) end end end end def pull(config) locale = args[1] locales = [] if locale && locale.strip != '' locales = [locale] else locales = fetch_locales(config) end locales.each do |locale| fetch_translation_for_locale(config, locale) end end def fetch_translation_for_locale(config, locale) print "Downloading phrase.#{locale}.yml..." ::FileUtils.mkdir_p("phrase/locales") http = http_client(config) request = Net::HTTP::Get.new("#{config.api_path_prefix}/translations/download?auth_token=#{config.secret}&locale=#{locale}") res = http.request(request) if res.code.to_s =~ /200/ puts "OK" File.open("phrase/locales/phrase.#{locale}.yml", "w") do |file| file.write(res.body) end else puts "Failed" print_server_error(res) end end def fetch_locales(config) http = http_client(config) request = Net::HTTP::Get.new("#{config.api_path_prefix}/locales?auth_token=#{config.secret}") res = http.request(request) if res.code.to_s =~ /200/ puts "Fetched all locales" return JSON.parse(res.body).map { |locale| locale['name'] } else puts "Failed" print_server_error(res) exit(47) end end def create_locale(locale_name, config) params = { 'auth_token' => config.secret, 'locale[name]' => locale_name } http = http_client(config) request = Net::HTTP::Post.new("#{config.api_path_prefix}/locales") request.set_form_data(params) res = http.request(request) if res.code.to_s =~ /200/ puts "Created locale \"#{locale_name}\"" else puts "Notice: Locale \"#{locale_name}\" could not be created (maybe it already exists)" end end def make_locale_default(locale_name, config) params = { 'auth_token' => config.secret, } http = http_client(config) request = Net::HTTP::Put.new("#{config.api_path_prefix}/locales/#{locale_name}/make_default") request.set_form_data(params) res = http.request(request) if res.code.to_s =~ /200/ puts "Locale \"#{locale_name}\" is now the default locale" else puts "Notice: Locale \"#{locale_name}\" could not be made the default locale" print_server_error(res) end end def print_server_error(res, filename=nil) error_message = server_error_message(res.body) $stderr.puts "Server error: #{res.code} - #{error_message} (#{filename})" end def server_error_message(body) begin JSON.parse(body)["error"] rescue JSON::ParserError "Unknown error" end end def print_usage $stderr.puts < --default-locale= phrase push FILE phrase push DIRECTORY USAGE end def args @args end def puts_debug_info puts "ARGS: #{args.join(",")}" puts "Dir.pwd: #{Dir.pwd}" end def http_client(config) http = Net::HTTP.new(config.api_host, config.api_port) http.use_ssl = true if config.api_use_ssl == "1" http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem") http end def is_yaml_file(filepath) !File.directory?(filepath) && filepath.split('.').last != 'yml' end def self.rails_default_locale_folder "./config/locales/" end def self.rails_default_locale_folder_is_available File.exist?(rails_default_locale_folder) && File.directory?(rails_default_locale_folder) end end end