to_lang 0.1.0 → 0.1.1

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/.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