light_tr 1.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fefec0155db0e698e81b29f9260d2b4fb844b3ec2a148fa1d7f419bbdf6d9b71
4
- data.tar.gz: 266422371befd490f89cc0b918eab19be2b103c414710a40e9931300e6a99291
3
+ metadata.gz: 3b2f82e905041870f9f842318362e0c01cf4be7ca0e754703cc24d5d479eaaf3
4
+ data.tar.gz: 300eb6fb7519db67951e4432627e855d80c0335d3f22a2cd4b9417d80c4aa47e
5
5
  SHA512:
6
- metadata.gz: b48c7b2ff2f42bb22c2487026ae5856af6a73671baa898b4eac0bef35ac788de87d33c42aeac9be50de5a23037be2b124135f0ff6aea46f1a93a3e1751d7c29a
7
- data.tar.gz: ccb46e927dbaa8aea893017f5ec63d4b25f2e8e30cf8d94c23613986a56d384e03b760aa1ecb4024e057835f3628bbbf6393c0af976cffdf79054084ac175038
6
+ metadata.gz: f4c558e2eb2fc941538e8d542ab38f52b6f354929821f66877606485b74aa0172c216d7febe5857c7ed94956a3579b5798ece72dfc4705a62fa06fe30f237137
7
+ data.tar.gz: 9c2b18fcfc3754f7ff51840eee3d7c45b3792867cd65944bc5cd05500af869e67cf880b44079e78dbcd11cedc65416c38ed27c1a89f6fa319def60b77190fcf8
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: [pniemczyk]
data/Gemfile.lock CHANGED
@@ -1,9 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- light_tr (1.0.0)
4
+ light_tr (2.0.1)
5
5
  awesome_print (~> 1.2)
6
6
  executable (~> 1.2)
7
+ faraday (~> 2.0)
8
+ faraday-mashify (~> 0.1)
7
9
  hashie (~> 2.1)
8
10
  lockbox (~> 0.6)
9
11
 
@@ -15,6 +17,15 @@ GEM
15
17
  coderay (1.1.3)
16
18
  diff-lcs (1.4.4)
17
19
  executable (1.2.1)
20
+ faraday (2.12.0)
21
+ faraday-net_http (>= 2.0, < 3.4)
22
+ json
23
+ logger
24
+ faraday-mashify (0.1.1)
25
+ faraday (~> 2.0)
26
+ hashie
27
+ faraday-net_http (3.3.0)
28
+ net-http
18
29
  ffi (1.15.4)
19
30
  formatador (0.3.0)
20
31
  guard (2.18.0)
@@ -29,13 +40,17 @@ GEM
29
40
  guard-rspec (0.7.3)
30
41
  guard (>= 0.10.0)
31
42
  hashie (2.1.2)
43
+ json (2.7.2)
32
44
  listen (3.7.0)
33
45
  rb-fsevent (~> 0.10, >= 0.10.3)
34
46
  rb-inotify (~> 0.9, >= 0.9.10)
35
- lockbox (0.6.6)
47
+ lockbox (0.6.8)
48
+ logger (1.6.1)
36
49
  lumberjack (1.2.8)
37
50
  method_source (1.0.0)
38
51
  nenv (0.3.0)
52
+ net-http (0.4.1)
53
+ uri
39
54
  notiffany (0.1.3)
40
55
  nenv (~> 0.1)
41
56
  shellany (~> 0.0)
@@ -80,9 +95,11 @@ GEM
80
95
  shellany (0.0.1)
81
96
  thor (1.1.0)
82
97
  unicode-display_width (2.1.0)
98
+ uri (0.13.1)
83
99
 
84
100
  PLATFORMS
85
101
  arm64-darwin-20
102
+ arm64-darwin-21
86
103
 
87
104
  DEPENDENCIES
88
105
  guard-rspec (~> 0)
data/exe/trans CHANGED
@@ -12,26 +12,34 @@ languages = (override_language ? ARGV[0].strip[1..2] : LightTr::Config.l
12
12
  full_text = (override_language ? ARGV[1..] : ARGV).join(' ')
13
13
  store = LightTr::Store.new(name: 'translations', file_path: LightTr::Config.config_path)
14
14
  translator = LightTr::Translator.new(LightTr::Config.api_key)
15
+ gpt = LightTr::ChatGpt.new(LightTr::Config.open_ai_key, LightTr::Config.model)
15
16
  text = full_text.gsub(/[[:space:]]+/, ' ').strip
16
17
  interactive = command == '-i'
17
18
 
18
19
  unless text.empty?
19
- runner = LightTr::Runner.new(store, translator)
20
- return puts runner.translate(languages[0], text) if languages.count == 1
21
- languages.each { |target| puts "#{target.upcase}: #{runner.translate(target, text)}" }
20
+ if LightTr::Config.provider == 'google'
21
+ runner = LightTr::Runner.new(store, translator)
22
+ return puts runner.translate(languages[0], text) if languages.count == 1
23
+ languages.each { |target| puts "#{target.upcase}: #{runner.translate(target, text)}" }
24
+ else
25
+ puts gpt.translate(text, languages)
26
+ end
22
27
  end
23
28
 
24
29
  if interactive
25
30
  puts 'Interactive mode! (quit by /q or empty line)'
26
- puts 'Type any sentence now:'
31
+ puts "Type any sentence now:\n"
27
32
 
28
33
  loop do
29
34
  text = STDIN.gets.chomp.to_s.gsub(/[[:space:]]+/, ' ').strip
30
35
  break if text == '/q' || text.empty?
31
-
32
- runner = LightTr::Runner.new(store, translator)
33
- return puts " " + runner.translate(languages[0], text) if languages.count == 1
34
- languages.each { |target| puts " #{target.upcase}: #{runner.translate(target, text)}" }
36
+ if LightTr::Config.provider == 'google'
37
+ runner = LightTr::Runner.new(store, translator)
38
+ return puts " " + runner.translate(languages[0], text) if languages.count == 1
39
+ languages.each { |target| puts " #{target.upcase}: #{runner.translate(target, text)}" }
40
+ else
41
+ puts gpt.translate(text, languages)
42
+ end
35
43
  puts "\n"
36
44
  end
37
45
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday/mashify'
5
+
6
+ module LightTr
7
+ class ChatGpt
8
+ SUPPORTED_LANGUAGES_MAP = { 'af' => 'Afrikaans', 'ga' => 'Irish', 'sq' => 'Albanian', 'it' => 'Italian', 'ar' => 'Arabic', 'ja' => 'Japanese', 'az' => 'Azerbaijani', 'kn' => 'Kannada', 'eu' => 'Basque', 'ko' => 'Korean', 'bn' => 'Bengali', 'la' => 'Latin', 'be' => 'Belarusian', 'lv' => 'Latvian', 'bg' => 'Bulgarian', 'lt' => 'Lithuanian', 'ca' => 'Catalan', 'mk' => 'Macedonian', 'ms' => 'Malay', 'mt' => 'Maltese', 'hr' => 'Croatian', 'no' => 'Norwegian', 'cs' => 'Czech', 'fa' => 'Persian', 'da' => 'Danish', 'pl' => 'Polish', 'nl' => 'Dutch', 'pt' => 'Portuguese', 'en' => 'English', 'ro' => 'Romanian', 'eo' => 'Esperanto', 'ru' => 'Russian', 'et' => 'Estonian', 'sr' => 'Serbian', 'tl' => 'Filipino', 'sk' => 'Slovak', 'fi' => 'Finnish', 'sl' => 'Slovenian', 'fr' => 'French', 'es' => 'Spanish', 'gl' => 'Galician', 'sw' => 'Swahili', 'ka' => 'Georgian', 'sv' => 'Swedish', 'de' => 'German', 'ta' => 'Tamil', 'el' => 'Greek', 'te' => 'Telugu', 'gu' => 'Gujarati', 'th' => 'Thai', 'ht' => 'Haitian Creole', 'tr' => 'Turkish', 'iw' => 'Hebrew', 'uk' => 'Ukrainian', 'hi' => 'Hindi', 'ur' => 'Urdu', 'hu' => 'Hungarian', 'vi' => 'Vietnamese', 'is' => 'Icelandic', 'cy' => 'Welsh', 'id' => 'Indonesian', 'yi' => 'Yiddish', 'zh-CN' => 'Chinese (Simplified)', 'zh-TW' => 'Chinese (Traditional)' }.freeze # rubocop:disable Layout/LineLength
9
+
10
+ def initialize(api_key, model = 'gpt-3.5-turbo')
11
+ @api_key = api_key
12
+ @model = model
13
+ end
14
+
15
+ def translate(query, languages)
16
+ completion(query, languages)
17
+ end
18
+
19
+ def models
20
+ @models ||= client.get('models').body.data.map(&:id).select { |id| id.include?('gpt') }
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :api_key, :model
26
+
27
+ def system(languages)
28
+ langs = languages.map { |lang| SUPPORTED_LANGUAGES_MAP[lang] }
29
+ intro = if langs.count == 1
30
+ "You are a translator, everything you receive next should be translated into #{langs[0]}."
31
+ else
32
+ "You are a translator, everything you receive next should be translated into #{langs[0]} or #{langs[1]}.\nIf the given text is in #{langs[1]}, translate it into #{langs[0]}.\nIf the text is in #{langs[0]}, translate it into #{langs[1]}." # rubocop:disable Layout/LineLength
33
+ end
34
+ intro + "\nTry to translate in a way that sounds natural to a native speaker of that language.\nOnly return the translation of the text; you don’t need to translate the code." # rubocop:disable Layout/LineLength
35
+ end
36
+
37
+ def completion(query, languages)
38
+ client.post(
39
+ 'chat/completions', {
40
+ model: model,
41
+ temperature: 0.7,
42
+ messages: [
43
+ { role: 'system', content: system(languages) },
44
+ { role: 'user', content: query }
45
+ ] }
46
+ ).body.choices[0].message.content
47
+ end
48
+
49
+ def client
50
+ @client ||= Faraday.new(url: 'https://api.openai.com/v1') do |faraday|
51
+ faraday.request :authorization, 'Bearer', api_key
52
+ faraday.request :json
53
+ faraday.response :mashify
54
+ faraday.response :json
55
+ faraday.adapter Faraday.default_adapter
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'fileutils'
3
3
  require 'lockbox'
4
+ require 'light_tr/chat_gpt'
4
5
 
5
6
  module LightTr
6
7
  class Commands
@@ -36,8 +37,8 @@ module LightTr
36
37
  puts "\noptions:"
37
38
  puts ' -config : init configuration'
38
39
  puts ' -show_config : show configuration'
39
- puts ' -clear_cache : clear translation cache'
40
- puts ' -pl : translate only one language (pl can be changed on any supported language)'
40
+ puts ' -clear_cache : clear translation cache [only for google provider]'
41
+ puts ' -pl : translate only one language (pl can be changed on any supported language) [only for google provider]'
41
42
  puts ' -i : run translator in interactive mode'
42
43
  end
43
44
 
@@ -48,11 +49,14 @@ module LightTr
48
49
  end
49
50
 
50
51
  def self.show_config
51
- api_key = ::LightTr::Config.api_key
52
+ api_key = ::LightTr::Config.api_key
52
53
  show_key = api_key[..10] + ('*' * (api_key.size - 10))
53
54
  puts 'Current configuration:'
54
55
  puts "\nlanguages : #{::LightTr::Config.languages}"
55
56
  puts "Goggle Translate API key : #{show_key}\n"
57
+ puts "OpenAI API key : #{::LightTr::Config.open_ai_key}"
58
+ puts "Provider : #{::LightTr::Config.provider}"
59
+ puts "Model : #{::LightTr::Config.model}"
56
60
  end
57
61
 
58
62
  def self.supported_languages
@@ -80,21 +84,63 @@ module LightTr
80
84
  value.to_s.split(',').map(&:strip).compact
81
85
  end
82
86
 
87
+ def self.default_model
88
+ 'gpt-3.5-turbo'
89
+ end
90
+
83
91
  def self.update_config
84
92
  FileUtils.mkdir_p(::LightTr::Config.config_path) unless File.directory?(::LightTr::Config.config_path)
85
93
  puts 'Hello my friend lets setup Light Translator now!'
86
94
  puts 'We will need only two things, Google Translate API key and your favorite languages'
87
95
  puts "When you complete setup in your home directory will be created .light_tr/.config file with encrypted configuration"
96
+ puts "\n"
97
+ puts "\nYou can use two providers and set which one will be default: 'google' or 'openai'"
88
98
  puts "\nLet's add Google Translate API key first. Instructions on: https://cloud.google.com/translate/docs/quickstarts"
89
- print 'Give me the Google Translate API key: '
99
+ print 'Give me the Google Translate API key: (empty to skip) '
90
100
  api_key = STDIN.gets.chomp
91
101
 
92
- puts "\nlanguages example: pl, en, ru"
102
+ puts "\n"
103
+ puts "\nYou can choice multiple languages example: pl, en, ru"
104
+ puts "\nBut openia provider support only two languages because it's working a little bit differently."
105
+ puts "\nIt is detecting source language and translate to target language automatically. For example: pl, en"
106
+ puts "\n`Jak się dziś masz?` -> `How are you today?`"
93
107
  print 'Give me languages: '
94
108
  languages = prepare_languages(STDIN.gets.chomp).join(', ')
95
109
 
110
+ puts "\n"
111
+ puts "\nLet's add OpenAI API key now. Instructions on: https://platform.openai.com/api-keys"
112
+ print 'Give me the OpenAI API key key: (empty to skip) '
113
+ open_ai_api_key = STDIN.gets.chomp
114
+ models = open_ai_api_key.empty? ? [default_model] : ::LightTr::ChatGpt.new(open_ai_api_key).models
115
+ model = unless open_ai_api_key.empty?
116
+ puts "\n"
117
+ puts "\nLet's choice model for OpenAI. Default is (gpt-4o-mini)"
118
+ puts "\nAll available models:"
119
+ models.each { |m| puts m }
120
+
121
+ print 'Give me the model: (default is gpt-3.5-turbo) '
122
+ STDIN.gets.chomp
123
+ end
124
+
125
+ model = models.include?(model) ? model : default_model
126
+
127
+ puts "\n"
128
+ puts "\n Now let's set default provider. You can choice between 'google' and 'openai' (default is google if present)"
129
+ print 'Give me the provider: (you can use just letters g, o)'
130
+ provider = STDIN.gets.chomp
131
+ if %w[g google].include?(provider.downcase) && !api_key.empty?
132
+ provider = 'google'
133
+ elsif %w[o openai].include?(provider.downcase) && !open_ai_api_key.empty?
134
+ provider = 'openai'
135
+ else
136
+ provider = 'google'
137
+ end
138
+
96
139
  puts "\nYour configuration is:"
97
- puts "API key: #{api_key}"
140
+ puts "Google API key: #{api_key}"
141
+ puts "OpenAI API key: #{open_ai_api_key}"
142
+ puts "OpenAI model: #{model.empty? ? default_model : model}"
143
+ puts "Provider: #{provider}"
98
144
  puts "languages: #{languages}\n\n"
99
145
 
100
146
  return languages_errors_and_update_config(languages) unless languages_valid?(languages)
@@ -109,6 +155,9 @@ module LightTr
109
155
  ::LightTr::Config.set({ 'master_key' => master_key })
110
156
  ::LightTr::Config.set({ 'api_key' => Lockbox.new(key: master_key).encrypt(api_key.strip) })
111
157
  ::LightTr::Config.set({ 'languages' => languages.strip })
158
+ ::LightTr::Config.set({ 'open_ai_key' => Lockbox.new(key: master_key).encrypt(open_ai_api_key.strip) })
159
+ ::LightTr::Config.set({ 'provider' => provider.strip })
160
+ ::LightTr::Config.set({ 'model' => (model.empty? ? default_model : model).strip })
112
161
 
113
162
  puts "\nHappy translating!"
114
163
  end
@@ -11,18 +11,32 @@ module LightTr
11
11
  get['languages']
12
12
  end
13
13
 
14
+ def self.open_ai_key
15
+ get['open_ai_key'] || raise('OpenAI API key missing. Try to update configuration via `trans -config`')
16
+ master_key = get['master_key'] || raise('Config file corrupted. Try to update configuration via `trans -config`')
17
+ Lockbox.new(key: master_key).decrypt(get['open_ai_key'])
18
+ end
19
+
14
20
  def self.api_key
15
21
  get['api_key'] || raise('Google Translation API key missing. Try to update configuration via `trans -config`')
16
22
  master_key = get['master_key'] || raise('Config file corrupted. Try to update configuration via `trans -config`')
17
23
  Lockbox.new(key: master_key).decrypt(get['api_key'])
18
24
  end
19
25
 
26
+ def self.provider
27
+ get['provider'] || 'google'
28
+ end
29
+
30
+ def self.model
31
+ get['model'] || 'gpt-3.5-turbo'
32
+ end
33
+
20
34
  def self.config_path
21
35
  File.join(Dir.home, '.light_tr')
22
36
  end
23
37
 
24
38
  def self.config_exists?
25
- File.exists?(config_file)
39
+ File.exist?(config_file)
26
40
  end
27
41
 
28
42
  def self.config_missing?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LightTr
4
- VERSION = "1.0.0"
4
+ VERSION = "2.0.1"
5
5
  end
data/lib/light_tr.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "light_tr/version"
4
4
  require_relative "light_tr/config"
5
5
  require_relative "light_tr/store"
6
6
  require_relative "light_tr/translator"
7
+ require_relative "light_tr/chat_gpt"
7
8
  require_relative "light_tr/runner"
8
9
  require_relative "light_tr/commands"
9
10
 
data/light_tr.gemspec CHANGED
@@ -27,6 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'rspec', '~> 2.12'
28
28
  spec.add_development_dependency 'guard-rspec', '~> 0'
29
29
  spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_dependency 'faraday-mashify', '~> 0.1'
31
+ spec.add_dependency 'faraday', '~> 2.0'
30
32
  spec.add_dependency 'hashie', '~> 2.1'
31
33
  spec.add_dependency 'executable', '~> 1.2'
32
34
  spec.add_dependency 'awesome_print', '~> 1.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: light_tr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paweł Niemczyk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-13 00:00:00.000000000 Z
11
+ date: 2024-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faraday-mashify
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: hashie
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +144,7 @@ executables:
116
144
  extensions: []
117
145
  extra_rdoc_files: []
118
146
  files:
147
+ - ".github/FUNDING.yml"
119
148
  - ".gitignore"
120
149
  - ".rspec"
121
150
  - ".rubocop.yml"
@@ -128,6 +157,7 @@ files:
128
157
  - bin/setup
129
158
  - exe/trans
130
159
  - lib/light_tr.rb
160
+ - lib/light_tr/chat_gpt.rb
131
161
  - lib/light_tr/commands.rb
132
162
  - lib/light_tr/config.rb
133
163
  - lib/light_tr/runner.rb