to_lang 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,5 @@ pkg/*
3
3
  .bundle
4
4
  Gemfile.lock
5
5
  coverage/*
6
+ doc/*
7
+ .yardoc
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --no-private
2
+ --protected
3
+ --markup textile
4
+ -
5
+ README.textile
data/README.textile CHANGED
@@ -8,7 +8,11 @@ Simply run @gem install to_lang@.
8
8
 
9
9
  h2. Usage
10
10
 
11
- To use *to_lang*, require the library, then call @ToLang.start@ with your Google Translate API key. At this point you will have access to all the new translation methods, which take the form @to_language@, where "language" is the language you wish to translate to. Google Translate attempts to detect the source language, but you can specify it explicitly by calling methods in the form @to_language_from_source_language@, where "source_language" is the source language. These methods are generated dynamically and will not appear in a call to @String.new.methods@ until they have been called once. Strings will, however, @respond_to?@ these methods prior to their dynamic definition.
11
+ To use *to_lang*, require the library, then call @ToLang.start@ with your Google Translate API key. At this point you will have access to all the new translation methods, which take the form @to_language@, where "language" is the language you wish to translate to.
12
+
13
+ Google Translate attempts to detect the source language, but you can specify it explicitly by calling methods in the form @to_language_from_source_language@, where "source_language" is the source language. These methods are generated dynamically and will not appear in a call to @String.new.methods@ until they have been called once. Strings will, however, @respond_to?@ these methods prior to their dynamic definition.
14
+
15
+ The dynamic methods are simply syntactic sugar for @String#translate@, which you can use directly as well.
12
16
 
13
17
  h2. Examples
14
18
 
@@ -29,6 +33,13 @@ bq. "a pie".to_spanish
29
33
  "a pie".to_spanish_from_english
30
34
  => "un pastel"
31
35
 
36
+ Using @String#translate@ directly:
37
+
38
+ bq. "hello world".translate('es')
39
+ => "hola mundo"
40
+ "a pie".translate('es', :from => 'en')
41
+ => "un pastel"
42
+
32
43
  h2. Supported Languages
33
44
 
34
45
  *to_lang* adds the following methods to strings. Each of these methods can be called with an explicit source language by appending @_to_source_language@ to the method name.
@@ -87,10 +98,13 @@ h2. Supported Languages
87
98
  * to_welsh
88
99
  * to_yiddish
89
100
 
101
+ h2. Documentation
102
+
103
+ API documentation can be found at "rubydoc.info":http://rubydoc.info/github/jimmycuadra/to_lang/master/frames.
104
+
90
105
  h2. Roadmap
91
106
 
92
- - Add complete documentation for the library.
93
- - Add Unicode support for Ruby 1.8. *to_lang* currently works safely only under 1.9.
107
+ * Add Unicode support for Ruby 1.8. *to_lang* currently works safely only under 1.9.
94
108
 
95
109
  h2. Feedback and Contributions
96
110
 
data/Rakefile CHANGED
@@ -5,3 +5,12 @@ require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
7
  task :default => :spec
8
+
9
+ require 'yard'
10
+ YARD::Rake::YardocTask.new do |t|
11
+ t.options = [
12
+ '--no-private',
13
+ '--protected',
14
+ '--markup', 'textile',
15
+ ]
16
+ end
@@ -1,4 +1,6 @@
1
1
  module ToLang
2
+ # A list of all the languages {ToLang} supports and the language code each maps to. Strings will gain @to_language@ and @to_language_from_language@ methods for any @language@ in this list.
3
+ #
2
4
  CODEMAP = {
3
5
  'afrikaans' => 'af',
4
6
  'albanian' => 'sq',
@@ -1,28 +1,57 @@
1
- require 'rubygems'
2
1
  require 'httparty'
3
- require 'uri'
2
+ require 'cgi'
4
3
 
5
4
  module ToLang
5
+ # Responsible for making the actual HTTP request to the Google Translate API.
6
+ #
6
7
  class Connector
8
+ # The base URL for all requests to the Google Translate API.
9
+ #
7
10
  API_URL = "https://www.googleapis.com/language/translate/v2"
8
11
 
12
+ # The Google Translate API key to use when making API calls.
13
+ #
14
+ # @return [String] The Google Translate API key.
15
+ #
9
16
  attr_reader :key
10
17
 
18
+ # Initializes a new {ToLang::Connector} and stores a Google Translate API key.
19
+ #
20
+ # @return [ToLang::Connector] The new {ToLang::Connector} instance.
11
21
  def initialize(key)
12
22
  @key = key
13
23
  end
14
24
 
25
+ # Makes a request to the Google Translate API.
26
+ #
27
+ # @param [String] q The string to translate.
28
+ # @param [String] target The language code for the language to translate to.
29
+ # @param [Hash] options A hash of options.
30
+ # @option options [String] :from The language code for the language of @q@.
31
+ #
32
+ # @raise [RuntimeError] Raises an error for any errors returned by Google Translate.
33
+ # @return [String] The translated string.
34
+ #
15
35
  def request(q, target, options = {})
16
36
  response = HTTParty.get request_url(q, target, options)
17
37
  raise response.parsed_response["error"]["message"] if response.parsed_response["error"] && response.parsed_response["error"]["message"]
18
- response.parsed_response["data"]["translations"][0]["translatedText"]
38
+ CGI.unescapeHTML(response.parsed_response["data"]["translations"][0]["translatedText"])
19
39
  end
20
40
 
21
41
  private
22
42
 
43
+ # Constructs the URL that will be used by {#request}.
44
+ #
45
+ # @param [String] q The string to translate.
46
+ # @param [String] target The language code for the language to translate to.
47
+ # @param [Hash] options A hash of options.
48
+ # @option options [String] :from The language code for the language of @q@.
49
+ #
50
+ # @return [String] The URL to request for the API call.
51
+ #
23
52
  def request_url(q, target, options)
24
53
  source = options[:from]
25
- url = "#{API_URL}?key=#{@key}&q=#{URI.escape(q)}&target=#{target}"
54
+ url = "#{API_URL}?key=#{@key}&q=#{CGI.escape(q)}&target=#{target}"
26
55
  url += "&source=#{source}" if source
27
56
  url
28
57
  end
@@ -0,0 +1,76 @@
1
+ require "to_lang/codemap"
2
+
3
+ module ToLang
4
+ # The methods {ToLang} will mix into the String class when initialized.
5
+ #
6
+ module StringMethods
7
+ # Translates a string to another language. All the magic methods use this internally. It, in turn, forwards
8
+ # everything on to {ToLang::Connector#request}
9
+ #
10
+ # @param [String] target The language code for the language to translate to.
11
+ # @param args Any additional arguments, such as the source language.
12
+ #
13
+ # @return [String] The translated string.
14
+ #
15
+ def translate(target, *args)
16
+ ToLang.connector.request(self, target, *args)
17
+ end
18
+
19
+ # Chain @method_missing@ in case another library has used it.
20
+ #
21
+ alias_method :original_method_missing, :method_missing
22
+
23
+ # Overrides @method_missing@ to catch and define dynamic translation methods.
24
+ #
25
+ # @private
26
+ #
27
+ def method_missing(method, *args, &block)
28
+ case method.to_s
29
+ when /^to_(.*)_from_(.*)$/
30
+ if CODEMAP[$1] && CODEMAP[$2]
31
+ new_method_name = "to_#{$1}_from_#{$2}".to_sym
32
+
33
+ self.class.send(:define_method, new_method_name) do
34
+ translate(CODEMAP[$1], :from => CODEMAP[$2])
35
+ end
36
+
37
+ return send(new_method_name)
38
+ else
39
+ original_method_missing(method, *args, &block)
40
+ end
41
+ when /^to_(.*)$/
42
+ if CODEMAP[$1]
43
+ new_method_name = "to_#{$1}".to_sym
44
+
45
+ self.class.send(:define_method, new_method_name) do
46
+ translate(CODEMAP[$1])
47
+ end
48
+
49
+ return send(new_method_name)
50
+ else
51
+ original_method_missing(method, *args, &block)
52
+ end
53
+ else
54
+ original_method_missing(method, *args, &block)
55
+ end
56
+ end
57
+
58
+ # Chain @respond_to?@ in case another library has used it.
59
+ alias_method :original_respond_to?, :respond_to?
60
+
61
+ # Overrides @respond_to?@ to make strings aware of the dynamic translation methods.
62
+ #
63
+ # @private
64
+ #
65
+ def respond_to?(method, include_private = false)
66
+ case method.to_s
67
+ when /^to_(.*)_from_(.*)$/
68
+ return true if CODEMAP[$1] && CODEMAP[$2]
69
+ when /^to_(.*)$/
70
+ return true if CODEMAP[$1]
71
+ end
72
+
73
+ original_respond_to?(method, include_private)
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,5 @@
1
1
  module ToLang
2
- VERSION = "0.1.0"
2
+ # The current version of the Ruby gem.
3
+ #
4
+ VERSION = "0.1.1"
3
5
  end
data/lib/to_lang.rb CHANGED
@@ -1,60 +1,29 @@
1
- require File.expand_path("../to_lang/codemap", __FILE__)
2
- require File.expand_path("../to_lang/connector", __FILE__)
3
-
1
+ require "to_lang/connector"
2
+ require "to_lang/string_methods"
3
+
4
+ # {ToLang} is a Ruby library that adds language translation methods to strings, backed by the Google Translate API.
5
+ #
6
+ # @author Jimmy Cuadra
7
+ # @see https://github.com/jimmycuadra/to_lang Source on GitHub
8
+ #
4
9
  module ToLang
5
10
  class << self
11
+ # A {ToLang::Connector} object to use for translation requests.
12
+ #
13
+ # @return [ToLang::Constructor, NilClass] An initialized {ToLang::Connector connector} or nil.
14
+ #
6
15
  attr_reader :connector
7
16
 
17
+ # Initializes {ToLang}, after which the translation methods will be available from strings.
18
+ #
19
+ # @param [String] key A Google Translate API key.
20
+ #
21
+ # @return [Class, Boolean] @String@ if initialization succeeded, @false@ if this method has already been called successfully.
22
+ #
8
23
  def start(key)
9
24
  return false if defined?(@connector) && !@connector.nil?
10
25
  @connector = ToLang::Connector.new(key)
11
26
  String.send(:include, StringMethods)
12
- add_magic_methods
13
- true
14
- end
15
-
16
- private
17
-
18
- def add_magic_methods
19
- String.class_eval do
20
- def method_missing(method, *args, &block)
21
- if method.to_s =~ /^to_(.*)_from_(.*)$/ && CODEMAP[$1] && CODEMAP[$2]
22
- new_method_name = "to_#{$1}_from_#{$2}".to_sym
23
-
24
- self.class.send(:define_method, new_method_name, Proc.new {
25
- translate(CODEMAP[$1], :from => CODEMAP[$2])
26
- })
27
-
28
- send new_method_name
29
- elsif method.to_s =~ /^to_(.*)$/ && CODEMAP[$1]
30
- new_method_name = "to_#{$1}".to_sym
31
-
32
- self.class.send(:define_method, new_method_name, Proc.new {
33
- translate(CODEMAP[$1])
34
- })
35
-
36
- send new_method_name
37
- else
38
- super
39
- end
40
- end
41
-
42
- def respond_to?(method, include_private = false)
43
- if method.to_s =~ /^to_(.*)_from_(.*)$/ && CODEMAP[$1] && CODEMAP[$2]
44
- true
45
- elsif method.to_s =~ /^to_(.*)$/ && CODEMAP[$1]
46
- true
47
- else
48
- super
49
- end
50
- end
51
- end
52
- end
53
- end
54
-
55
- module StringMethods
56
- def translate(target, *args)
57
- ToLang.connector.request(self, target, *args)
58
27
  end
59
28
  end
60
29
  end
data/spec/spec_helper.rb CHANGED
@@ -3,4 +3,4 @@ SimpleCov.start do
3
3
  add_filter "/spec/"
4
4
  end
5
5
 
6
- require File.expand_path('../../lib/to_lang', __FILE__)
6
+ require "to_lang"
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../spec_helper', __FILE__)
1
+ require "spec_helper"
2
2
 
3
3
  describe ToLang::Connector do
4
4
  before :all do
@@ -0,0 +1,68 @@
1
+ require "spec_helper"
2
+
3
+ describe "A ToLang-enabled string" do
4
+ before :all do
5
+ ToLang.start('apikey')
6
+ end
7
+
8
+ it "responds to :translate" do
9
+ String.new.should respond_to :translate
10
+ end
11
+
12
+ context "when sent :translate" do
13
+ it "calls ToLang::Connector#request" do
14
+ ToLang.connector.stub(:request)
15
+ ToLang.connector.should_receive(:request).with("hello world", "es")
16
+ "hello world".translate("es")
17
+ end
18
+ end
19
+
20
+ ToLang::CODEMAP.each do |language, code|
21
+ it "will respond_to :to_#{language}" do
22
+ "hello_world".should respond_to "to_#{language}"
23
+ end
24
+
25
+ it "will respond to :to_#{language}_from_english" do
26
+ "hello_world".should respond_to "to_#{language}_from_english"
27
+ end
28
+
29
+ it "translates to #{language} when sent :to_#{language}" do
30
+ ToLang.connector.stub(:request)
31
+ ToLang.connector.should_receive(:request).with("hello world", code)
32
+ "hello world".send("to_#{language}")
33
+ end
34
+
35
+ it "translates to #{language} from english when sent :to_#{language}_from_english" do
36
+ ToLang.connector.stub(:request)
37
+ ToLang.connector.should_receive(:request).with("hello world", code, :from => 'en')
38
+ "hello world".send("to_#{language}_from_english")
39
+ end
40
+ end
41
+
42
+ context "when a magic method has been called once" do
43
+ before :each do
44
+ ToLang.connector.stub(:request)
45
+ "hello world".to_spanish
46
+ "hello world".to_spanish_from_english
47
+ end
48
+
49
+ it "defines the method and does not call :method_missing the next time" do
50
+ string = "hello world"
51
+ string.should_not_receive(:method_missing)
52
+ string.to_spanish
53
+ string.to_spanish_from_english
54
+ end
55
+ end
56
+
57
+ it "calls the original :method_missing if there is no language match in the first form" do
58
+ expect { "hello world".to_foo }.to raise_error(NoMethodError)
59
+ end
60
+
61
+ it "calls the original :method_missing if there is a bad language match in the second form" do
62
+ expect { "hello world".to_foo_from_bar }.to raise_error(NoMethodError)
63
+ end
64
+
65
+ it "calls the original :method_missing if the method does not match either form" do
66
+ expect { "hello world".foo }.to raise_error(NoMethodError)
67
+ end
68
+ end
data/spec/to_lang_spec.rb CHANGED
@@ -19,60 +19,3 @@ describe ToLang do
19
19
  end
20
20
  end
21
21
  end
22
-
23
- describe "A string" do
24
- context "after ToLang has received :start" do
25
- before :all do
26
- ToLang.start('apikey')
27
- end
28
-
29
- it "responds to :translate" do
30
- String.new.should respond_to :translate
31
- end
32
-
33
- context "when sent :translate" do
34
- it "calls ToLang::Connector#request" do
35
- ToLang.connector.stub(:request)
36
- ToLang.connector.should_receive(:request).with("hello world", "es")
37
- "hello world".translate("es")
38
- end
39
- end
40
-
41
- ToLang::CODEMAP.each do |language, code|
42
- it "will respond_to :to_#{language}" do
43
- "hello_world".should respond_to "to_#{language}"
44
- end
45
-
46
- it "will respond to :to_#{language}_from_english" do
47
- "hello_world".should respond_to "to_#{language}_from_english"
48
- end
49
-
50
- it "translates to #{language} when sent :to_#{language}" do
51
- ToLang.connector.stub(:request)
52
- ToLang.connector.should_receive(:request).with("hello world", code)
53
- "hello world".send("to_#{language}")
54
- end
55
-
56
- it "translates to #{language} from english when sent :to_#{language}_from_english" do
57
- ToLang.connector.stub(:request)
58
- ToLang.connector.should_receive(:request).with("hello world", code, :from => 'en')
59
- "hello world".send("to_#{language}_from_english")
60
- end
61
- end
62
-
63
- context "when a magic method has been called once" do
64
- before :each do
65
- ToLang.connector.stub(:request)
66
- "hello world".to_spanish
67
- "hello world".to_spanish_from_english
68
- end
69
-
70
- it "defines the method and does not call :method_missing the next time" do
71
- string = "hello world"
72
- string.should_not_receive(:method_missing)
73
- string.to_spanish
74
- string.to_spanish_from_english
75
- end
76
- end
77
- end
78
- end
data/to_lang.gemspec CHANGED
@@ -17,6 +17,10 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
 
19
19
  s.add_dependency "httparty", "~> 0.6"
20
+ s.add_development_dependency "bundler", "~> 1.0"
21
+ s.add_development_dependency "rake", "~> 0.8"
20
22
  s.add_development_dependency "rspec", "~> 2.3"
21
23
  s.add_development_dependency "simplecov", "~> 0.3"
24
+ s.add_development_dependency "yard", "~> 0.6"
25
+ s.add_development_dependency "RedCloth", "~> 4.2"
22
26
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jimmy Cuadra
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-26 00:00:00 -08:00
17
+ date: 2010-12-29 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -32,9 +32,37 @@ dependencies:
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
35
- name: rspec
35
+ name: bundler
36
36
  prerelease: false
37
37
  requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 0
45
+ version: "1.0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 8
59
+ version: "0.8"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
38
66
  none: false
39
67
  requirements:
40
68
  - - ~>
@@ -44,11 +72,11 @@ dependencies:
44
72
  - 3
45
73
  version: "2.3"
46
74
  type: :development
47
- version_requirements: *id002
75
+ version_requirements: *id004
48
76
  - !ruby/object:Gem::Dependency
49
77
  name: simplecov
50
78
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
79
+ requirement: &id005 !ruby/object:Gem::Requirement
52
80
  none: false
53
81
  requirements:
54
82
  - - ~>
@@ -58,7 +86,35 @@ dependencies:
58
86
  - 3
59
87
  version: "0.3"
60
88
  type: :development
61
- version_requirements: *id003
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: yard
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
100
+ - 6
101
+ version: "0.6"
102
+ type: :development
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: RedCloth
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ~>
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 4
114
+ - 2
115
+ version: "4.2"
116
+ type: :development
117
+ version_requirements: *id007
62
118
  description: Adds language translation methods to strings, backed by the Google Translate API
63
119
  email:
64
120
  - jimmy@jimmycuadra.com
@@ -70,15 +126,18 @@ extra_rdoc_files: []
70
126
 
71
127
  files:
72
128
  - .gitignore
129
+ - .yardopts
73
130
  - Gemfile
74
131
  - README.textile
75
132
  - Rakefile
76
133
  - lib/to_lang.rb
77
134
  - lib/to_lang/codemap.rb
78
135
  - lib/to_lang/connector.rb
136
+ - lib/to_lang/string_methods.rb
79
137
  - lib/to_lang/version.rb
80
138
  - spec/spec_helper.rb
81
139
  - spec/to_lang/connector_spec.rb
140
+ - spec/to_lang/string_methods_spec.rb
82
141
  - spec/to_lang_spec.rb
83
142
  - to_lang.gemspec
84
143
  has_rdoc: true
@@ -116,4 +175,5 @@ summary: Adds language translation methods to strings, backed by the Google Tran
116
175
  test_files:
117
176
  - spec/spec_helper.rb
118
177
  - spec/to_lang/connector_spec.rb
178
+ - spec/to_lang/string_methods_spec.rb
119
179
  - spec/to_lang_spec.rb