phrase 0.1.4 → 0.2.0.beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -6,6 +6,6 @@ gem "activesupport", :require => "active_support"
6
6
  group :test do
7
7
  gem 'rspec'
8
8
  gem 'i18n'
9
- gem 'webmock', '~>1.7.0'
10
- gem 'vcr', '~>1.11'
9
+ gem 'webmock'
10
+ gem 'vcr'
11
11
  end
data/Gemfile.lock CHANGED
@@ -2,7 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  activesupport (3.0.0)
5
- addressable (2.2.7)
5
+ addressable (2.2.8)
6
6
  crack (0.3.1)
7
7
  diff-lcs (1.1.3)
8
8
  i18n (0.6.0)
@@ -15,9 +15,9 @@ GEM
15
15
  rspec-expectations (2.8.0)
16
16
  diff-lcs (~> 1.1.2)
17
17
  rspec-mocks (2.8.0)
18
- vcr (1.11.3)
19
- webmock (1.7.10)
20
- addressable (~> 2.2, > 2.2.5)
18
+ vcr (2.2.1)
19
+ webmock (1.8.7)
20
+ addressable (>= 2.2.7)
21
21
  crack (>= 0.1.7)
22
22
 
23
23
  PLATFORMS
@@ -28,5 +28,5 @@ DEPENDENCIES
28
28
  i18n
29
29
  json
30
30
  rspec
31
- vcr (~> 1.11)
32
- webmock (~> 1.7.0)
31
+ vcr
32
+ webmock
data/bin/phrase CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'phrase/tool'
4
- PhraseGem::Tool.new(ARGV).run
4
+ Phrase::Tool.new(ARGV).run
@@ -0,0 +1,168 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'phrase'
6
+ require 'phrase/api'
7
+
8
+ class Phrase::Api::Client
9
+
10
+ METHOD_GET = :get
11
+ METHOD_POST = :post
12
+ METHOD_PUT = :put
13
+
14
+ attr_reader :auth_token
15
+
16
+ def initialize(auth_token)
17
+ raise "No auth token specified!" if (auth_token.nil? or auth_token.blank?)
18
+ @auth_token = auth_token
19
+ end
20
+
21
+ def fetch_locales
22
+ result = perform_api_request("/locales", :get)
23
+ locales = []
24
+ JSON.parse(result).map do |locale|
25
+ locales << locale['name']
26
+ end
27
+ locales
28
+ end
29
+
30
+ def translate(key)
31
+ raise "You must specify a key" if key.nil? or key.blank?
32
+ keys = {}
33
+ result = JSON.parse(perform_api_request("/translation_keys/translate", :get, {:key => key}))
34
+ if result["translate"]
35
+ keys = result["translate"]
36
+ end
37
+ keys
38
+ end
39
+
40
+ def create_locale(name)
41
+ raise "You must specify a name" if name.nil? or name.blank?
42
+
43
+ begin
44
+ perform_api_request("/locales", :post, {
45
+ "locale[name]" => name
46
+ })
47
+ rescue Phrase::Api::Exceptions::ServerError => e
48
+ raise "Locale #{name} could not be created (Maybe it already exists)"
49
+ end
50
+ true
51
+ end
52
+
53
+ def make_locale_default(name)
54
+ raise "You must specify a name" if name.nil? or name.blank?
55
+
56
+ begin
57
+ perform_api_request("/locales/#{name}/make_default", :put)
58
+ rescue Phrase::Api::Exceptions::ServerError => e
59
+ raise "Locale #{name} could not be made the default locale"
60
+ end
61
+ true
62
+ end
63
+
64
+ def download_translations_for_locale(name)
65
+ raise "You must specify a name" if name.nil? or name.blank?
66
+
67
+ begin
68
+ content = perform_api_request("/translations/download", :get, {'locale' => name})
69
+ return content
70
+ rescue Phrase::Api::Exceptions::ServerError => e
71
+ raise "Translations #{name} could not be downloaded"
72
+ end
73
+ end
74
+
75
+ def upload(filename, file_content)
76
+ begin
77
+ perform_api_request("/translation_keys/upload", :post, {
78
+ "filename" => filename,
79
+ "file_content" => file_content,
80
+ })
81
+ rescue Phrase::Api::Exceptions::ServerError => e
82
+ raise "File #{filename} could not be uploaded"
83
+ end
84
+ true
85
+ end
86
+
87
+ private
88
+ def display_api_error(response)
89
+ error_message = api_error_message(response)
90
+ $stderr.puts error_message
91
+ end
92
+
93
+ def api_error_message(response)
94
+ message = ""
95
+ begin
96
+ error = JSON.parse(response.body)["error"]
97
+ if error.class == String
98
+ message = error
99
+ else
100
+ message = JSON.parse(response.body)["message"]
101
+ end
102
+ rescue JSON::ParserError
103
+ end
104
+ message = "Unknown Error" if message.blank?
105
+ "Error: #{message} (#{response.code})"
106
+ end
107
+
108
+ def perform_api_request(endpoint, method=METHOD_GET, params={})
109
+ request = case method
110
+ when METHOD_GET
111
+ get_request(endpoint, params)
112
+ when METHOD_POST
113
+ post_request(endpoint, params)
114
+ when METHOD_PUT
115
+ put_request(endpoint, params)
116
+ else
117
+ raise "Invalid Request Method: #{method}"
118
+ end
119
+ response = http_client.request(request)
120
+ code = response.code.to_i
121
+ if (code == 200)
122
+ return response.body
123
+ else
124
+ error_message = api_error_message(response)
125
+ raise Phrase::Api::Exceptions::Unauthorized.new(error_message) if (code == 401)
126
+ raise Phrase::Api::Exceptions::ServerError.new(error_message)
127
+ end
128
+ end
129
+
130
+ def get_request(endpoint, params={})
131
+ query_string = "?auth_token=#{@auth_token}"
132
+ params.each do |key, value|
133
+ query_string << "&#{key}=#{value}"
134
+ end unless params.empty?
135
+ request = Net::HTTP::Get.new("#{api_path_for(endpoint)}#{query_string}")
136
+ request
137
+ end
138
+
139
+ def post_request(endpoint, params={})
140
+ request = Net::HTTP::Post.new("#{api_path_for(endpoint)}")
141
+ params.merge!({
142
+ 'auth_token' => @auth_token
143
+ })
144
+ request.set_form_data(params)
145
+ request
146
+ end
147
+
148
+ def put_request(endpoint, params={})
149
+ request = Net::HTTP::Put.new("#{api_path_for(endpoint)}")
150
+ params.merge!({
151
+ 'auth_token' => @auth_token
152
+ })
153
+ request.set_form_data(params)
154
+ request
155
+ end
156
+
157
+ def api_path_for(endpoint)
158
+ "#{Phrase::Api::Config.api_path_prefix}#{endpoint}"
159
+ end
160
+
161
+ def http_client
162
+ client = Net::HTTP.new(Phrase::Api::Config.api_host, Phrase::Api::Config.api_port)
163
+ client.use_ssl = true if Phrase::Api::Config.api_use_ssl?
164
+ client.verify_mode = OpenSSL::SSL::VERIFY_NONE
165
+ client.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem")
166
+ client
167
+ end
168
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'phrase'
4
+ require 'phrase/api'
5
+
6
+ class Phrase::Api::Config
7
+ def self.api_port
8
+ ENV.fetch("PHRASE_API_PORT", "443")
9
+ end
10
+
11
+ def self.api_host
12
+ ENV.fetch("PHRASE_API_HOST", "phraseapp.com")
13
+ end
14
+
15
+ def self.api_path_prefix
16
+ "/api/#{Phrase::API_VERSION}"
17
+ end
18
+
19
+ def self.api_use_ssl?
20
+ (ENV.fetch("PHRASE_API_USE_SSL", "1") == "1")
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'phrase'
4
+ require 'phrase/api'
5
+
6
+ module Phrase::Api::Exceptions
7
+ class Unauthorized < StandardError; end
8
+ class ServerError < StandardError; end
9
+ end
data/lib/phrase/api.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Phrase::Api
2
+ end
3
+
4
+ require 'phrase/api/client'
5
+ require 'phrase/api/config'
6
+ require 'phrase/api/exceptions'
@@ -1,20 +1,22 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
+ require 'phrase/delegate'
4
+
3
5
  module Phrase::Backend::Base
4
6
 
5
7
  def translate(*args)
6
8
  if Phrase.enabled?
7
9
  key = lookup_normalized_key(*args)
8
- decorate_translation(key[:key])
10
+ phrase_delegate_for(key[:key])
9
11
  else
10
12
  I18n.translate_without_phrase(*args)
11
13
  end
12
14
  end
13
15
 
14
16
  protected
15
- def decorate_translation(key=nil)
17
+ def phrase_delegate_for(key=nil)
16
18
  return nil unless key.presence
17
- "#{Phrase.prefix}phrase_#{key}#{Phrase.suffix}"
19
+ Phrase::Delegate.new(key)
18
20
  end
19
21
 
20
22
  def lookup_normalized_key(*args)
data/lib/phrase/config.rb CHANGED
@@ -1,68 +1,70 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- module Phrase
4
- class Config
5
- def client_version
6
- Phrase::CLIENT_VERSION
7
- end
3
+ class Phrase::Config
4
+ def client_version
5
+ Phrase::CLIENT_VERSION
6
+ end
8
7
 
9
- def auth_token
10
- @@auth_token = "" if !defined? @@auth_token or @@auth_token.nil?
11
- @@auth_token
12
- end
13
-
14
- def auth_token=(auth_token)
15
- @@auth_token = auth_token
16
- end
17
-
18
- def enabled
19
- @@enabled = true if !defined? @@enabled or @@enabled.nil?
20
- @@enabled
21
- end
22
-
23
- def enabled=(enabled)
24
- @@enabled = enabled
25
- end
26
-
27
- def backend
28
- @@backend ||= Backend::PhraseService.new
29
- end
30
-
31
- def backend=(backend)
32
- @@backend = backend
33
- end
34
-
35
- def prefix
36
- @@prefix ||= "{{__"
37
- end
38
-
39
- def prefix=(prefix)
40
- @@prefix = prefix
41
- end
42
-
43
- def suffix
44
- @@suffix ||= "__}}"
45
- end
46
-
47
- def suffix=(suffix)
48
- @@suffix = suffix
49
- end
50
-
51
- def js_host
52
- @@js_host ||= 'phraseapp.com'
53
- end
54
-
55
- def js_host=(js_host)
56
- @@js_host = js_host
57
- end
58
-
59
- def js_use_ssl
60
- @@js_use_ssl = true if !defined? @@js_use_ssl or @@js_use_ssl.nil?
61
- @@js_use_ssl
62
- end
8
+ def api_version
9
+ Phrase::API_VERSION
10
+ end
11
+
12
+ def auth_token
13
+ @@auth_token = "" if !defined? @@auth_token or @@auth_token.nil?
14
+ @@auth_token
15
+ end
16
+
17
+ def auth_token=(auth_token)
18
+ @@auth_token = auth_token
19
+ end
20
+
21
+ def enabled
22
+ @@enabled = true if !defined? @@enabled or @@enabled.nil?
23
+ @@enabled
24
+ end
25
+
26
+ def enabled=(enabled)
27
+ @@enabled = enabled
28
+ end
63
29
 
64
- def js_use_ssl=(js_use_ssl)
65
- @@js_use_ssl = js_use_ssl
66
- end
30
+ def backend
31
+ @@backend ||= Phrase::Backend::PhraseService.new
32
+ end
33
+
34
+ def backend=(backend)
35
+ @@backend = backend
36
+ end
37
+
38
+ def prefix
39
+ @@prefix ||= "{{__"
40
+ end
41
+
42
+ def prefix=(prefix)
43
+ @@prefix = prefix
44
+ end
45
+
46
+ def suffix
47
+ @@suffix ||= "__}}"
48
+ end
49
+
50
+ def suffix=(suffix)
51
+ @@suffix = suffix
52
+ end
53
+
54
+ def js_host
55
+ @@js_host ||= 'phraseapp.com'
56
+ end
57
+
58
+ def js_host=(js_host)
59
+ @@js_host = js_host
60
+ end
61
+
62
+ def js_use_ssl
63
+ @@js_use_ssl = true if !defined? @@js_use_ssl or @@js_use_ssl.nil?
64
+ @@js_use_ssl
65
+ end
66
+
67
+ def js_use_ssl=(js_use_ssl)
68
+ @@js_use_ssl = js_use_ssl
67
69
  end
68
70
  end
@@ -0,0 +1,55 @@
1
+ require 'phrase/api'
2
+
3
+ class Phrase::Delegate
4
+ attr_accessor :key, :api_client
5
+
6
+ def initialize(key)
7
+ @key = key
8
+ end
9
+
10
+ def to_s
11
+ "#{decorated_key_name}"
12
+ end
13
+
14
+ def method_missing(*args, &block)
15
+ if @key.respond_to?(args.first)
16
+ to_s.send(*args)
17
+ else
18
+ data = translation_or_subkeys
19
+ if data.is_a?(String)
20
+ to_s
21
+ elsif data.respond_to?(args.first)
22
+ data.send(*args, &block)
23
+ else
24
+ log "You are trying to execute the method ##{args.first} on a translation key which is not supported. Please make sure you treat your translations as strings only."
25
+ nil
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+ def decorated_key_name
32
+ "#{Phrase.prefix}phrase_#{@key}#{Phrase.suffix}"
33
+ end
34
+
35
+ def translation_or_subkeys
36
+ begin
37
+ api_client.translate(@key)
38
+ rescue Exception => e
39
+ log "Server Error: #{e.message}"
40
+ end
41
+ end
42
+
43
+ def api_client
44
+ @api_client ||= Phrase::Api::Client.new(Phrase.auth_token)
45
+ end
46
+
47
+ def log(message)
48
+ message = "phrase: #{message}"
49
+ if defined?(Rails)
50
+ Rails.logger.warn(message)
51
+ else
52
+ $stderr.puts message
53
+ end
54
+ end
55
+ end
data/lib/phrase/engine.rb CHANGED
@@ -4,11 +4,9 @@ require 'phrase'
4
4
  require 'i18n'
5
5
 
6
6
  if defined? Rails
7
- module Phrase
8
- class Engine < Rails::Engine
9
- initializer 'phrase' do |app|
10
- ActionView::Base.send :include, Phrase::ViewHelpers
11
- end
7
+ class Phrase::Engine < Rails::Engine
8
+ initializer 'phrase' do |app|
9
+ ActionView::Base.send :include, Phrase::ViewHelpers
12
10
  end
13
11
  end
14
12
  end
data/lib/phrase/tool.rb CHANGED
@@ -1,277 +1,240 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- require 'phrase/tool_config'
4
-
5
3
  require 'optparse'
6
4
  require 'net/http'
7
5
  require 'net/https'
8
6
  require 'fileutils'
7
+ require 'phrase/tool_config'
9
8
 
10
- module PhraseGem
11
- class Tool
9
+ class Phrase::Tool
10
+
11
+ attr_accessor :config
12
+
13
+ def initialize(argv)
14
+ @args = argv
15
+ end
12
16
 
13
- def initialize(argv)
14
- @args = argv
17
+ def run
18
+ @config = Phrase::ToolConfig.new
19
+ command = args.first
20
+
21
+ case command
22
+ when /init/
23
+ init
24
+ when /push/
25
+ push
26
+ when /pull/
27
+ pull
28
+ else
29
+ print_usage
15
30
  end
31
+ end
16
32
 
17
- def run
18
- config = ToolConfig.new
19
- command = args.first
20
-
21
- case command
22
- when /init/
23
- init(config)
24
- when /push/
25
- push(config)
26
- when /pull/
27
- pull(config)
28
- else
29
- print_usage
30
- end
33
+ protected
34
+ def init
35
+ secret_param = args.find{ |arg| arg =~ /secret=/ }
36
+ unless secret_param.to_s.match(/secret=.+/)
37
+ $stderr.puts "Need a secret to init, but found none."
38
+ $stderr.puts "Please provide the --secret=YOUR_SECRET parameter."
39
+ exit(41)
31
40
  end
32
41
 
33
- private
42
+ secret = secret_param.split("=", 2).last
43
+ @config.secret = secret
44
+ puts "Wrote secret to config file .phrase"
34
45
 
35
- def init(config)
36
- secret_param = args.find{ |arg| arg =~ /secret=/ }
37
- unless secret_param.to_s.match(/secret=.+/)
38
- $stderr.puts "Need a secret to init, but found none."
39
- $stderr.puts "Please provide the --secret=YOUR_SECRET parameter."
40
- exit(41)
41
- end
46
+ default_locale_param = args.find{ |arg| arg =~ /default-locale=/ }
47
+ if default_locale_param.to_s.match(/default-locale=.+/)
48
+ locale_name = default_locale_param.split("=", 2).last
49
+ else
50
+ locale_name = "en"
51
+ end
52
+ create_locale(locale_name)
53
+ make_locale_default(locale_name)
54
+ end
42
55
 
43
- secret = secret_param.split("=", 2).last
44
- config.secret = secret
45
- puts "Wrote secret to config file .phrase"
46
-
47
- default_locale_param = args.find{ |arg| arg =~ /default-locale=/ }
48
- if default_locale_param.to_s.match(/default-locale=.+/)
49
- locale_name = default_locale_param.split("=", 2).last
50
- else
51
- locale_name = "en"
52
- end
53
- create_locale(locale_name, config)
54
- make_locale_default(locale_name, config)
56
+ def push
57
+ check_config_available
58
+
59
+ files = choose_files_to_upload
60
+ if files.empty?
61
+ puts "Could not find any files to upload :("
62
+ exit(43)
55
63
  end
64
+ upload_files(files)
65
+ end
56
66
 
57
- def push(config)
58
- files = choose_files_to_upload
59
- if files.empty?
60
- puts "Could not find any files to upload :("
61
- exit(43)
62
- end
63
-
64
- if !config.secret || config.secret.empty?
65
- puts "No config present. Please initialize phrase before pushing or pulling."
66
- exit(43)
67
- end
68
-
69
- upload_files(files, config)
67
+ def pull
68
+ check_config_available
69
+
70
+ create_locales_folder!
71
+
72
+ locale = args[1]
73
+ locales = []
74
+ if locale && locale.strip != ''
75
+ locales = [locale]
76
+ else
77
+ locales = fetch_locales
70
78
  end
79
+
80
+ locales.each do |locale_name|
81
+ print "Downloading phrase.#{locale_name}.yml..."
82
+ fetch_translations_for_locale(locale_name)
83
+ end
84
+ end
85
+
86
+ def print_usage
87
+ $stderr.puts <<USAGE
88
+ Welcome to phrase!
71
89
 
72
- def choose_files_to_upload
73
- file_name = args[1]
74
-
75
- unless file_name
76
- if self.class.rails_default_locale_folder_is_available
77
- file_name = self.class.rails_default_locale_folder
78
- puts "No file or directory specified, using #{self.class.rails_default_locale_folder}"
79
- else
80
- $stderr.puts "Need either a file or directory:"
81
- $stderr.puts "phrase push FILE"
82
- $stderr.puts "phrase push DIRECTORY"
83
- exit(46)
84
- end
85
- end
90
+ phrase Prints usage
86
91
 
87
- unless File.exist?(file_name)
88
- $stderr.puts "The file #{file_name} could not be found."
89
- exit(42)
90
- end
92
+ phrase init --secret=<YOUR SECRET> --default-locale=<YOUR DEFAULT LOCALE>
91
93
 
92
- if File.directory?(file_name)
93
- files = Dir.glob("#{File.expand_path(file_name)}/**")
94
- else
95
- files = [file_name]
94
+ phrase push FILE
95
+ phrase push DIRECTORY
96
+ USAGE
97
+ end
98
+
99
+ private
100
+ def choose_files_to_upload
101
+ file_name = args[1]
102
+
103
+ unless file_name
104
+ if self.class.rails_default_locale_folder_is_available
105
+ file_name = self.class.rails_default_locale_folder
106
+ puts "No file or directory specified, using #{self.class.rails_default_locale_folder}"
107
+ else
108
+ $stderr.puts "Need either a file or directory:"
109
+ $stderr.puts "phrase push FILE"
110
+ $stderr.puts "phrase push DIRECTORY"
111
+ exit(46)
96
112
  end
97
113
  end
98
114
 
99
- def upload_files(files, config)
100
- files.each do |file|
101
- proceed_with_upload = true
102
-
103
- if File.directory?(file)
104
- proceed_with_upload = false
105
- end
106
-
107
- if is_yaml_file(file)
108
- proceed_with_upload = false
109
- $stderr.puts "Notice: Could not upload #{file} (extension not supported - see http://phraseapp.com/help for more information)"
110
- end
111
-
112
- if proceed_with_upload
113
- puts "Uploading #{file}..."
114
- params = {
115
- 'auth_token' => config.secret,
116
- 'filename' => file,
117
- 'file_content' => File.read(file)
118
- }
119
-
120
- http = http_client(config)
121
-
122
- request = Net::HTTP::Post.new("#{config.api_path_prefix}/translation_keys/upload")
123
- request.set_form_data(params)
124
- res = http.request(request)
125
-
126
- unless res.code.to_s =~ /^[23]/
127
- print_server_error(res, file)
128
- end
129
- end
130
- end
115
+ unless File.exist?(file_name)
116
+ $stderr.puts "The file #{file_name} could not be found."
117
+ exit(42)
131
118
  end
132
119
 
133
- def pull(config)
134
- locale = args[1]
135
-
136
- locales = []
137
- if locale && locale.strip != ''
138
- locales = [locale]
139
- else
140
- locales = fetch_locales(config)
141
- end
142
-
143
- locales.each do |locale|
144
- fetch_translation_for_locale(config, locale)
145
- end
120
+ if File.directory?(file_name)
121
+ files = Dir.glob("#{File.expand_path(file_name)}/**")
122
+ else
123
+ files = [file_name]
146
124
  end
125
+ end
126
+
127
+ def upload_files(files)
128
+ files.each do |file|
129
+ proceed_with_upload = true
147
130
 
148
- def fetch_translation_for_locale(config, locale)
149
- print "Downloading phrase.#{locale}.yml..."
150
- ::FileUtils.mkdir_p("phrase/locales")
151
-
152
- http = http_client(config)
153
-
154
- request = Net::HTTP::Get.new("#{config.api_path_prefix}/translations/download?auth_token=#{config.secret}&locale=#{locale}")
155
- res = http.request(request)
156
-
157
- if res.code.to_s =~ /200/
158
- puts "OK"
159
- File.open("phrase/locales/phrase.#{locale}.yml", "w") do |file|
160
- file.write(res.body)
161
- end
162
- else
163
- puts "Failed"
164
- print_server_error(res)
131
+ if File.directory?(file)
132
+ proceed_with_upload = false
165
133
  end
166
- end
167
134
 
168
- def fetch_locales(config)
169
- http = http_client(config)
170
-
171
- request = Net::HTTP::Get.new("#{config.api_path_prefix}/locales?auth_token=#{config.secret}")
172
- res = http.request(request)
173
-
174
- if res.code.to_s =~ /200/
175
- puts "Fetched all locales"
176
- return JSON.parse(res.body).map { |locale| locale['name'] }
177
- else
178
- puts "Failed"
179
- print_server_error(res)
180
- exit(47)
135
+ if is_yaml_file(file)
136
+ proceed_with_upload = false
137
+ $stderr.puts "Notice: Could not upload #{file} (extension not supported - see http://phraseapp.com/help for more information)"
181
138
  end
182
- end
183
139
 
184
- def create_locale(locale_name, config)
185
- params = {
186
- 'auth_token' => config.secret,
187
- 'locale[name]' => locale_name
188
- }
189
-
190
- http = http_client(config)
191
-
192
- request = Net::HTTP::Post.new("#{config.api_path_prefix}/locales")
193
- request.set_form_data(params)
194
- res = http.request(request)
195
-
196
- if res.code.to_s =~ /200/
197
- puts "Created locale \"#{locale_name}\""
198
- else
199
- puts "Notice: Locale \"#{locale_name}\" could not be created (maybe it already exists)"
140
+ if proceed_with_upload
141
+ begin
142
+ puts "Uploading #{file}..."
143
+ api_client.upload(file, File.read(file))
144
+ puts "OK"
145
+ rescue Exception => e
146
+ puts "Failed"
147
+ print_server_error(e.message, file)
148
+ end
200
149
  end
201
150
  end
202
-
203
- def make_locale_default(locale_name, config)
204
- params = {
205
- 'auth_token' => config.secret,
206
- }
151
+ end
207
152
 
208
- http = http_client(config)
209
-
210
- request = Net::HTTP::Put.new("#{config.api_path_prefix}/locales/#{locale_name}/make_default")
211
- request.set_form_data(params)
212
- res = http.request(request)
213
-
214
- if res.code.to_s =~ /200/
215
- puts "Locale \"#{locale_name}\" is now the default locale"
216
- else
217
- puts "Notice: Locale \"#{locale_name}\" could not be made the default locale"
218
- print_server_error(res)
219
- end
153
+ def fetch_translations_for_locale(name)
154
+ begin
155
+ content = api_client.download_translations_for_locale(name)
156
+ puts "OK"
157
+ store_translations_file(name, content)
158
+ rescue Exception => e
159
+ puts "Failed"
160
+ print_server_error(e.message)
220
161
  end
221
-
222
- def print_server_error(res, filename=nil)
223
- error_message = server_error_message(res.body)
224
- $stderr.puts "Server error: #{res.code} - #{error_message} (#{filename})"
162
+ end
163
+
164
+ def store_translations_file(name, content)
165
+ File.open("phrase/locales/phrase.#{name}.yml", "w") do |file|
166
+ file.write(content)
225
167
  end
226
-
227
- def server_error_message(body)
228
- begin
229
- JSON.parse(body)["error"]
230
- rescue JSON::ParserError
231
- "Unknown error"
232
- end
168
+ end
169
+
170
+ def fetch_locales
171
+ begin
172
+ locales = api_client.fetch_locales
173
+ puts "Fetched all locales"
174
+ return locales
175
+ rescue Exception => e
176
+ puts "Failed"
177
+ print_server_error(e.message)
178
+ exit(47)
233
179
  end
234
-
235
- def print_usage
236
- $stderr.puts <<USAGE
237
- Welcome to phrase!
238
-
239
- phrase Prints usage
240
-
241
- phrase init --secret=<YOUR SECRET> --default-locale=<YOUR DEFAULT LOCALE>
242
-
243
- phrase push FILE
244
- phrase push DIRECTORY
245
- USAGE
180
+ end
181
+
182
+ def create_locale(name)
183
+ begin
184
+ api_client.create_locale(name)
185
+ puts "Created locale \"#{name}\""
186
+ rescue Exception => e
187
+ puts "Notice: Locale \"#{name}\" could not be created (maybe it already exists)"
246
188
  end
247
-
248
- def args
249
- @args
189
+ end
190
+
191
+ def make_locale_default(name)
192
+ begin
193
+ api_client.make_locale_default(name)
194
+ puts "Locale \"#{name}\" is now the default locale"
195
+ rescue Exception => e
196
+ puts "Notice: Locale \"#{name}\" could not be made the default locale"
197
+ print_server_error(e.message)
250
198
  end
199
+ end
200
+
201
+ def api_client
202
+ Phrase::Api::Client.new(@config.secret)
203
+ end
251
204
 
252
- def puts_debug_info
253
- puts "ARGS: #{args.join(",")}"
254
- puts "Dir.pwd: #{Dir.pwd}"
255
- end
256
-
257
- def http_client(config)
258
- http = Net::HTTP.new(config.api_host, config.api_port)
259
- http.use_ssl = true if config.api_use_ssl == "1"
260
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
261
- http.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem")
262
- http
263
- end
264
-
265
- def is_yaml_file(filepath)
266
- !File.directory?(filepath) && filepath.split('.').last != 'yml'
267
- end
268
-
269
- def self.rails_default_locale_folder
270
- "./config/locales/"
271
- end
272
-
273
- def self.rails_default_locale_folder_is_available
274
- File.exist?(rails_default_locale_folder) && File.directory?(rails_default_locale_folder)
205
+ def print_server_error(message, filename=nil)
206
+ $stderr.puts "#{message} (#{filename})"
207
+ end
208
+
209
+ def args
210
+ @args
211
+ end
212
+
213
+ def puts_debug_info
214
+ puts "ARGS: #{args.join(",")}"
215
+ puts "Dir.pwd: #{Dir.pwd}"
216
+ end
217
+
218
+ def is_yaml_file(filepath)
219
+ !File.directory?(filepath) && filepath.split('.').last != 'yml'
220
+ end
221
+
222
+ def create_locales_folder!
223
+ ::FileUtils.mkdir_p("phrase/locales")
224
+ end
225
+
226
+ def check_config_available
227
+ if !@config.secret || @config.secret.empty?
228
+ $stderr.puts "No config present. You need to initialize phrase first."
229
+ exit(43)
275
230
  end
276
231
  end
277
- end
232
+
233
+ def self.rails_default_locale_folder
234
+ "./config/locales/"
235
+ end
236
+
237
+ def self.rails_default_locale_folder_is_available
238
+ File.exist?(rails_default_locale_folder) && File.directory?(rails_default_locale_folder)
239
+ end
240
+ end
@@ -1,56 +1,37 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
+ require 'phrase'
3
4
  require 'json'
4
5
 
5
- module PhraseGem
6
- class ToolConfig
7
-
8
- def initialize
9
- if File.exist?(".phrase")
10
- begin
11
- contents = File.read(".phrase")
12
- @config = JSON.parse(contents)
13
- rescue JSON::ParserError => err
14
- $stderr.puts "Could not parse config file: #{err}"
15
- end
6
+ class Phrase::ToolConfig
7
+ def initialize
8
+ if File.exist?(".phrase")
9
+ begin
10
+ contents = File.read(".phrase")
11
+ @config = JSON.parse(contents)
12
+ rescue JSON::ParserError => err
13
+ $stderr.puts "Could not parse config file: #{err}"
16
14
  end
17
15
  end
16
+ end
17
+
18
+ def secret
19
+ config["secret"]
20
+ end
18
21
 
19
- def secret
20
- config["secret"]
21
- end
22
-
23
- def secret=(new_secret)
24
- config["secret"] = new_secret
25
- save_config!
26
- end
27
-
28
- def api_port
29
- ENV.fetch("PHRASE_API_PORT", "443")
30
- end
31
-
32
- def api_host
33
- ENV.fetch("PHRASE_API_HOST", "phraseapp.com")
34
- end
35
-
36
- def api_path_prefix
37
- "/api/v1"
38
- end
39
-
40
- def api_use_ssl
41
- ENV.fetch("PHRASE_API_USE_SSL", "1")
42
- end
43
-
44
- private
45
-
46
- def config
47
- @config ||= {}
48
- end
22
+ def secret=(new_secret)
23
+ config["secret"] = new_secret
24
+ save_config!
25
+ end
26
+
27
+ private
28
+ def config
29
+ @config ||= {}
30
+ end
49
31
 
50
- def save_config!
51
- File.open(".phrase", "w+") do |file|
52
- file.write(JSON.pretty_generate(config))
53
- end
32
+ def save_config!
33
+ File.open(".phrase", "w+") do |file|
34
+ file.write(JSON.pretty_generate(config))
54
35
  end
55
36
  end
56
37
  end
data/lib/phrase.rb CHANGED
@@ -6,6 +6,7 @@ module Phrase
6
6
  autoload :Config, 'phrase/config'
7
7
 
8
8
  CLIENT_VERSION = "0.1"
9
+ API_VERSION = "v1"
9
10
 
10
11
  class << self
11
12
 
data/phrase.gemspec CHANGED
@@ -4,7 +4,7 @@ $:.unshift lib unless $:.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "phrase"
7
- s.version = "0.1.4"
7
+ s.version = "0.2.0.beta.2"
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Dynport GmbH"]
10
10
  s.email = ["info@phraseapp.com"]
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phrase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
5
- prerelease:
4
+ version: 0.2.0.beta.2
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Dynport GmbH
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-14 00:00:00.000000000 Z
12
+ date: 2012-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70112071528200 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70112071528200
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
25
30
  description: phrase allows you to edit translations inline, on the page itself. More
26
31
  information at phraseapp.com
27
32
  email:
@@ -38,10 +43,15 @@ files:
38
43
  - bin/phrase
39
44
  - cacert.pem
40
45
  - lib/phrase.rb
46
+ - lib/phrase/api.rb
47
+ - lib/phrase/api/client.rb
48
+ - lib/phrase/api/config.rb
49
+ - lib/phrase/api/exceptions.rb
41
50
  - lib/phrase/backend.rb
42
51
  - lib/phrase/backend/base.rb
43
52
  - lib/phrase/backend/phrase_service.rb
44
53
  - lib/phrase/config.rb
54
+ - lib/phrase/delegate.rb
45
55
  - lib/phrase/engine.rb
46
56
  - lib/phrase/tool.rb
47
57
  - lib/phrase/tool_config.rb
@@ -67,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
77
  version: 1.3.6
68
78
  requirements: []
69
79
  rubyforge_project: phrase
70
- rubygems_version: 1.8.10
80
+ rubygems_version: 1.8.24
71
81
  signing_key:
72
82
  specification_version: 3
73
83
  summary: The best way to manage i18n.