jekyll-chatgpt-translate 0.2.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +25 -25
- data/jekyll-chatgpt-translate.gemspec +3 -2
- data/lib/jekyll-chatgpt-translate/chatgpt.rb +30 -30
- data/lib/jekyll-chatgpt-translate/generator.rb +85 -85
- data/lib/jekyll-chatgpt-translate/ping.rb +1 -1
- data/lib/jekyll-chatgpt-translate/version.rb +1 -1
- metadata +25 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a33656cc2e5c82d51feb6cb2900c339cce6f210bbe9615dd19756f457ace47c7
|
|
4
|
+
data.tar.gz: 2867d144dfa9e867a6bbecce340a1d77eb908a54c9790fbef9f7985223861250
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 370cf4f063e237ab00af98e0212b738211d33f868e24c89547a4b378f867389ff46c6dfce39ac90553e25e448751490b8c465382d5a6ffdefb6aa8bca59b6826
|
|
7
|
+
data.tar.gz: beafec1d47ac6b1f731d9557de276c7ce4d9b9223a6a19e3791e7b9555cf2d3950501e99d77bc92c54501a0c8b8d4ba21710cb35102ad4a932430330c32b6795
|
data/Gemfile
CHANGED
|
@@ -11,6 +11,7 @@ gem 'kramdown-parser-gfm', '~>1.1', require: false
|
|
|
11
11
|
gem 'minitest', '~>6.0', require: false
|
|
12
12
|
gem 'minitest-reporters', '~>1.7', require: false
|
|
13
13
|
gem 'rake', '~>13.2', require: false
|
|
14
|
+
gem 'rdoc', '~>7.0', require: false
|
|
14
15
|
gem 'rubocop', '~>1.64', require: false
|
|
15
16
|
gem 'rubocop-minitest', '~>0.38', require: false
|
|
16
17
|
gem 'rubocop-performance', '>1.26', require: false
|
data/README.md
CHANGED
|
@@ -6,17 +6,18 @@
|
|
|
6
6
|
[](https://badge.fury.io/rb/jekyll-chatgpt-translate)
|
|
7
7
|
|
|
8
8
|
If you have a [Jekyll](https://jekyllrb.com/) static site,
|
|
9
|
-
this plugin may help you automatically
|
|
10
|
-
translate its pages to another language, through
|
|
11
|
-
[ChatGPT](https://chat.openai.com/).
|
|
12
|
-
works for [my blog](https://github.com/yegor256/ru.yegor256.com),
|
|
13
|
-
for example [this page](https://ru.yegor256.com/2023-08-13-dictators.html)
|
|
14
|
-
is translated to
|
|
15
|
-
[English](https://www.yegor256.com/en/2023/08/13/dictators.html).
|
|
16
|
-
|
|
17
|
-
Install it first
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
this plugin may help you automatically
|
|
10
|
+
translate its pages to another language, through
|
|
11
|
+
[ChatGPT](https://chat.openai.com/).
|
|
12
|
+
See how it works for [my blog](https://github.com/yegor256/ru.yegor256.com),
|
|
13
|
+
for example [this page](https://ru.yegor256.com/2023-08-13-dictators.html)
|
|
14
|
+
is translated to
|
|
15
|
+
[English](https://www.yegor256.com/en/2023/08/13/dictators.html).
|
|
16
|
+
|
|
17
|
+
Install it first
|
|
18
|
+
(you need
|
|
19
|
+
[Ruby 3+](https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/)
|
|
20
|
+
and [Jekyll 3+](https://jekyllrb.com/)):
|
|
20
21
|
|
|
21
22
|
```bash
|
|
22
23
|
gem install jekyll-chatgpt-translate
|
|
@@ -49,29 +50,28 @@ where the layout for Chinese is `_layout/chinese-translated.html` and for
|
|
|
49
50
|
French is `_layout/translated.html` (you must have these files).
|
|
50
51
|
|
|
51
52
|
OpenAI API KEY must be set in the `OPENAI_API_KEY` environment variable,
|
|
52
|
-
otherwise
|
|
53
|
-
|
|
54
|
-
You can get your key
|
|
55
|
-
[here][open-ai].
|
|
53
|
+
otherwise the plugin will not do any translation
|
|
54
|
+
and won't generate translated pages.
|
|
55
|
+
You can get your key go to [OpenAI][open-ai].
|
|
56
56
|
|
|
57
57
|
OpenAI API base URL can be customized by the `OPENAI_API_BASE`
|
|
58
|
-
environment variable.
|
|
58
|
+
environment variable.
|
|
59
59
|
If this variable is not set, the default value is `https://api.openai.com/`.
|
|
60
60
|
|
|
61
61
|
Inside the original page you can use `{{ page.chatgpt-translate.urls[XX] }}`
|
|
62
|
-
in order to render the URL
|
|
63
|
-
of the translated page, where `XX` is the [ISO-639-1][iso-639]
|
|
64
|
-
code of the target language.
|
|
62
|
+
in order to render the URL
|
|
63
|
+
of the translated page, where `XX` is the [ISO-639-1][iso-639]
|
|
64
|
+
code of the target language.
|
|
65
65
|
Inside the translated page you can use
|
|
66
|
-
`{{ page.chatgpt-translate.original-url }}` in order
|
|
67
|
-
to get the URL of the page that was translated.
|
|
66
|
+
`{{ page.chatgpt-translate.original-url }}` in order
|
|
67
|
+
to get the URL of the page that was translated.
|
|
68
68
|
|
|
69
69
|
You can also use `{{ page.chatgpt-translate.model }}`
|
|
70
|
-
inside both the original page and the translated one,
|
|
71
|
-
to refer to the model of ChatGPT.
|
|
70
|
+
inside both the original page and the translated one,
|
|
71
|
+
to refer to the model of ChatGPT.
|
|
72
72
|
The presence of `{{ page.chatgpt-translate }}` means that the
|
|
73
|
-
page was translated or the translated HTML was downloaded
|
|
74
|
-
and placed into the `_site` directory.
|
|
73
|
+
page was translated or the translated HTML was downloaded
|
|
74
|
+
and placed into the `_site` directory.
|
|
75
75
|
|
|
76
76
|
## Options
|
|
77
77
|
|
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
|
9
9
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
|
10
10
|
s.required_ruby_version = '>= 3.0'
|
|
11
11
|
s.name = 'jekyll-chatgpt-translate'
|
|
12
|
-
s.version = '0.
|
|
12
|
+
s.version = '0.3.0'
|
|
13
13
|
s.license = 'MIT'
|
|
14
14
|
s.summary = 'Translate Jekyll Pages Through ChatGPT'
|
|
15
15
|
s.description = [
|
|
@@ -24,10 +24,11 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
s.rdoc_options = ['--charset=UTF-8']
|
|
25
25
|
s.extra_rdoc_files = %w[README.md LICENSE.txt]
|
|
26
26
|
s.add_dependency 'base64', '~>0.3'
|
|
27
|
+
s.add_dependency 'elapsed', '~>0.2'
|
|
27
28
|
s.add_dependency 'humanize', '~>3.1'
|
|
28
29
|
s.add_dependency 'iri', '~>0.11'
|
|
29
30
|
s.add_dependency 'iso-639', '~>0.3'
|
|
30
|
-
s.add_dependency 'jekyll', '
|
|
31
|
+
s.add_dependency 'jekyll', '>= 3.0', '< 5.0'
|
|
31
32
|
s.add_dependency 'json', '~>2.18'
|
|
32
33
|
s.add_dependency 'redcarpet', '~>3.6'
|
|
33
34
|
s.add_dependency 'ruby-openai', '~>8.3'
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2023-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
+
require 'elapsed'
|
|
7
|
+
require 'iso-639'
|
|
6
8
|
require 'jekyll'
|
|
7
9
|
require 'json'
|
|
8
10
|
require 'openai'
|
|
9
|
-
require 'iso-639'
|
|
10
11
|
require 'tiktoken_ruby'
|
|
11
12
|
require_relative 'pars'
|
|
12
13
|
require_relative 'prompt'
|
|
@@ -115,40 +116,39 @@ class GptTranslate::ChatGPT
|
|
|
115
116
|
@@models_printed = true
|
|
116
117
|
end
|
|
117
118
|
prompt = GptTranslate::Prompt.new(par, @source, @target).to_s
|
|
118
|
-
start = Time.now
|
|
119
119
|
answer = nil
|
|
120
120
|
attempt = 0
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
json = response.is_a?(Hash) ? response : JSON.parse(response)
|
|
130
|
-
answer = json.dig('choices', 0, 'message', 'content')
|
|
131
|
-
if answer.nil?
|
|
132
|
-
Jekyll.logger.error("No content returned by ChatGPT: #{response}")
|
|
133
|
-
raise 'No content returned by ChatGPT'
|
|
134
|
-
end
|
|
135
|
-
Jekyll.logger.debug("ChatGPT prompt: #{prompt.inspect}, ChatGPT answer: #{answer.inspect}")
|
|
136
|
-
rescue StandardError => e
|
|
137
|
-
attempt += 1
|
|
138
|
-
if attempt < 4
|
|
139
|
-
Jekyll.logger.error(
|
|
140
|
-
"ChatGPT failed to answer to #{prompt.inspect}" \
|
|
141
|
-
"(attempt no.#{attempt}): #{e.message.inspect}"
|
|
121
|
+
elapsed(Jekyll.logger) do
|
|
122
|
+
begin
|
|
123
|
+
response = @client.chat(
|
|
124
|
+
parameters: {
|
|
125
|
+
model: @model,
|
|
126
|
+
messages: [{ role: 'user', content: prompt }],
|
|
127
|
+
temperature: 0.7
|
|
128
|
+
}
|
|
142
129
|
)
|
|
143
|
-
|
|
130
|
+
json = response.is_a?(Hash) ? response : JSON.parse(response)
|
|
131
|
+
answer = json.dig('choices', 0, 'message', 'content')
|
|
132
|
+
if answer.nil?
|
|
133
|
+
Jekyll.logger.error("No content returned by ChatGPT: #{response}")
|
|
134
|
+
raise 'No content returned by ChatGPT'
|
|
135
|
+
end
|
|
136
|
+
Jekyll.logger.debug("ChatGPT prompt: #{prompt.inspect}, ChatGPT answer: #{answer.inspect}")
|
|
137
|
+
rescue StandardError => e
|
|
138
|
+
attempt += 1
|
|
139
|
+
if attempt < 4
|
|
140
|
+
Jekyll.logger.error(
|
|
141
|
+
"ChatGPT failed to answer to #{prompt.inspect}" \
|
|
142
|
+
"(attempt no.#{attempt}): #{e.message.inspect}"
|
|
143
|
+
)
|
|
144
|
+
retry
|
|
145
|
+
end
|
|
146
|
+
raise e
|
|
144
147
|
end
|
|
145
|
-
|
|
148
|
+
throw :"Translated #{par.split.count} #{@source.upcase} words \
|
|
149
|
+
to #{answer.split.count} #{@target.upcase} words \
|
|
150
|
+
through #{@model}: #{"#{par[0..24]}...".inspect}"
|
|
146
151
|
end
|
|
147
|
-
Jekyll.logger.info(
|
|
148
|
-
"Translated #{par.split.count} #{@source.upcase} words " \
|
|
149
|
-
"to #{answer.split.count} #{@target.upcase} words " \
|
|
150
|
-
"through #{@model} in #{(Time.now - start).round(2)}s: #{"#{par[0..24]}...".inspect}"
|
|
151
|
-
)
|
|
152
152
|
answer
|
|
153
153
|
end
|
|
154
154
|
end
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2023-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
-
require '
|
|
6
|
+
require 'elapsed'
|
|
7
7
|
require 'fileutils'
|
|
8
|
+
require 'jekyll'
|
|
8
9
|
require 'json'
|
|
9
10
|
require_relative 'chatgpt'
|
|
10
11
|
require_relative 'permalink'
|
|
@@ -29,7 +30,7 @@ class GptTranslate::Generator < Jekyll::Generator
|
|
|
29
30
|
Jekyll.logger.info("jekyll-chatgpt-translate #{GptTranslate::VERSION} skipped, due to the --offline option")
|
|
30
31
|
return
|
|
31
32
|
end
|
|
32
|
-
Jekyll.logger.info("jekyll-chatgpt-translate #{GptTranslate::VERSION}
|
|
33
|
+
Jekyll.logger.info("jekyll-chatgpt-translate #{GptTranslate::VERSION} starts (no --offline option)...")
|
|
33
34
|
config ||= site.config['chatgpt-translate'] || {}
|
|
34
35
|
home = config['tmpdir'] || '_chatgpt-translate'
|
|
35
36
|
key = api_key(config)
|
|
@@ -41,101 +42,100 @@ class GptTranslate::Generator < Jekyll::Generator
|
|
|
41
42
|
version = config['version'] || GptTranslate::VERSION
|
|
42
43
|
threshold = config['threshold'] || 1024
|
|
43
44
|
min_chars = config['min_chars'] || 128
|
|
44
|
-
start = Time.now
|
|
45
45
|
translated = 0
|
|
46
46
|
copied = 0
|
|
47
47
|
model = config['model'] || 'gpt-3.5-turbo'
|
|
48
48
|
marker = "Translated by ChatGPT #{model}#{"/#{version}" unless version.empty?}"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
path = File.join(home, lang, doc.basename.gsub(/\.md$/, "-#{lang}.md"))
|
|
63
|
-
FileUtils.mkdir_p(File.dirname(path))
|
|
64
|
-
File.write(
|
|
65
|
-
path,
|
|
66
|
-
[
|
|
67
|
-
'---',
|
|
68
|
-
"layout: #{target['layout'] || layout}",
|
|
69
|
-
"title: #{doc['title'].to_json}",
|
|
70
|
-
"description: #{doc['description'].to_json}",
|
|
71
|
-
"permalink: #{link.to_json}",
|
|
72
|
-
'chatgpt-translate:',
|
|
73
|
-
" original-url: #{doc.url.to_json}",
|
|
74
|
-
" language: #{lang.to_json}",
|
|
75
|
-
" model: #{model.to_json}",
|
|
76
|
-
'---'
|
|
77
|
-
].join("\n")
|
|
78
|
-
)
|
|
79
|
-
html = config['no_download'].nil? ? GptTranslate::Ping.new(site, link).download : nil
|
|
80
|
-
needed = false
|
|
81
|
-
added = false
|
|
82
|
-
if html.nil?
|
|
83
|
-
Jekyll.logger.info("The page is absent, need to translate #{link.inspect}")
|
|
84
|
-
needed = true
|
|
85
|
-
else
|
|
86
|
-
copied += 1
|
|
87
|
-
site.static_files << DownloadedFile.new(site, link, html)
|
|
88
|
-
added = true
|
|
89
|
-
if version.empty?
|
|
90
|
-
Jekyll.logger.info("Re-translation not required, since version is empty: #{link.inspect}")
|
|
91
|
-
elsif html.include?(marker)
|
|
92
|
-
Jekyll.logger.info("No need to translate, the page exists at \
|
|
93
|
-
#{link.inspect} (#{html.split.count} words)")
|
|
94
|
-
else
|
|
95
|
-
Jekyll.logger.info("Re-translation required for #{link.inspect}")
|
|
96
|
-
needed = true
|
|
49
|
+
elapsed(Jekyll.logger) do
|
|
50
|
+
site.posts.docs.shuffle.each_with_index do |doc, pos|
|
|
51
|
+
plain = GptTranslate::Plain.new(doc.content).to_s
|
|
52
|
+
layout = doc['layout']
|
|
53
|
+
config['targets'].each do |target|
|
|
54
|
+
link = GptTranslate::Permalink.new(doc, target['permalink']).to_path
|
|
55
|
+
lang = target['language']
|
|
56
|
+
raise 'Language must be defined for each target' if target.nil?
|
|
57
|
+
only = target['only']
|
|
58
|
+
if !only.nil? && layout != only
|
|
59
|
+
Jekyll.logger.debug("Not translating #{link.inspect}, b/c 'only' set to '#{only}'")
|
|
60
|
+
next
|
|
97
61
|
end
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Jekyll.logger.info("Page ##{pos} is ignored, we are over the threshold of #{threshold}: #{link}")
|
|
101
|
-
elsif needed
|
|
102
|
-
gpt = GptTranslate::ChatGPT.new(
|
|
103
|
-
key,
|
|
104
|
-
model,
|
|
105
|
-
target['source'] || config['source'] || 'en',
|
|
106
|
-
lang
|
|
107
|
-
)
|
|
108
|
-
foreign = gpt.translate(
|
|
109
|
-
plain,
|
|
110
|
-
min: min_chars,
|
|
111
|
-
window_length: (config['window_length'] || '2048').to_i
|
|
112
|
-
)
|
|
62
|
+
path = File.join(home, lang, doc.basename.gsub(/\.md$/, "-#{lang}.md"))
|
|
63
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
113
64
|
File.write(
|
|
114
65
|
path,
|
|
115
66
|
[
|
|
116
|
-
'',
|
|
117
|
-
|
|
118
|
-
'',
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
67
|
+
'---',
|
|
68
|
+
"layout: #{target['layout'] || layout}",
|
|
69
|
+
"title: #{doc['title'].to_json}",
|
|
70
|
+
"description: #{doc['description'].to_json}",
|
|
71
|
+
"permalink: #{link.to_json}",
|
|
72
|
+
'chatgpt-translate:',
|
|
73
|
+
" original-url: #{doc.url.to_json}",
|
|
74
|
+
" language: #{lang.to_json}",
|
|
75
|
+
" model: #{model.to_json}",
|
|
76
|
+
'---'
|
|
77
|
+
].join("\n")
|
|
122
78
|
)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
added =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
79
|
+
html = config['no_download'].nil? ? GptTranslate::Ping.new(site, link).download : nil
|
|
80
|
+
needed = false
|
|
81
|
+
added = false
|
|
82
|
+
if html.nil?
|
|
83
|
+
Jekyll.logger.info("The page is absent, need to translate #{link.inspect}")
|
|
84
|
+
needed = true
|
|
85
|
+
else
|
|
86
|
+
copied += 1
|
|
87
|
+
site.static_files << DownloadedFile.new(site, link, html)
|
|
88
|
+
added = true
|
|
89
|
+
if version.empty?
|
|
90
|
+
Jekyll.logger.info("Re-translation not required, since version is empty: #{link.inspect}")
|
|
91
|
+
elsif html.include?(marker)
|
|
92
|
+
Jekyll.logger.info("The page exists at #{link.inspect} (#{html.split.count} words)")
|
|
93
|
+
else
|
|
94
|
+
Jekyll.logger.info("Re-translation required for #{link.inspect}")
|
|
95
|
+
needed = true
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
if translated >= threshold
|
|
99
|
+
Jekyll.logger.info("Page ##{pos} is ignored, we are over the threshold of #{threshold}: #{link}")
|
|
100
|
+
elsif needed
|
|
101
|
+
elapsed(Jekyll.logger) do
|
|
102
|
+
gpt = GptTranslate::ChatGPT.new(
|
|
103
|
+
key,
|
|
104
|
+
model,
|
|
105
|
+
target['source'] || config['source'] || 'en',
|
|
106
|
+
lang
|
|
107
|
+
)
|
|
108
|
+
foreign = gpt.translate(
|
|
109
|
+
plain,
|
|
110
|
+
min: min_chars,
|
|
111
|
+
window_length: (config['window_length'] || '2048').to_i
|
|
112
|
+
)
|
|
113
|
+
File.write(
|
|
114
|
+
path,
|
|
115
|
+
[
|
|
116
|
+
'',
|
|
117
|
+
foreign,
|
|
118
|
+
'',
|
|
119
|
+
"#{marker} on #{Time.now.strftime('%Y-%m-%d at %H:%M')}\n{: .jekyll-chatgpt-translate}"
|
|
120
|
+
].join("\n"),
|
|
121
|
+
mode: 'a+'
|
|
122
|
+
)
|
|
123
|
+
site.pages << Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path))
|
|
124
|
+
site.static_files.delete_if { |f| f.is_a?(DownloadedFile) && f.link == link }
|
|
125
|
+
added = true
|
|
126
|
+
translated += 1
|
|
127
|
+
throw :"Translated via ChatGPT #{path} (#{File.size(path)} bytes)"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
next unless added
|
|
131
|
+
doc.data['chatgpt-translate'] ||= {}
|
|
132
|
+
doc.data['chatgpt-translate']['model'] ||= model
|
|
133
|
+
doc.data['chatgpt-translate']['urls'] ||= {}
|
|
134
|
+
doc.data['chatgpt-translate']['urls'][lang] = link
|
|
129
135
|
end
|
|
130
|
-
next unless added
|
|
131
|
-
doc.data['chatgpt-translate'] ||= {}
|
|
132
|
-
doc.data['chatgpt-translate']['model'] ||= model
|
|
133
|
-
doc.data['chatgpt-translate']['urls'] ||= {}
|
|
134
|
-
doc.data['chatgpt-translate']['urls'][lang] = link
|
|
135
136
|
end
|
|
137
|
+
throw :"#{translated} page(s) translated and #{copied} page(s) copied"
|
|
136
138
|
end
|
|
137
|
-
Jekyll.logger.info("jekyll-chatgpt-translate #{GptTranslate::VERSION}: \
|
|
138
|
-
#{translated} pages translated and #{copied} pages copied in #{(Time.now - start).round(2)}s")
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
# The file we just downloaded.
|
|
@@ -10,7 +10,7 @@ require_relative 'version'
|
|
|
10
10
|
|
|
11
11
|
# see https://stackoverflow.com/a/6048451/187141
|
|
12
12
|
require 'openssl'
|
|
13
|
-
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
|
13
|
+
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
|
14
14
|
|
|
15
15
|
# The module we are in.
|
|
16
16
|
module GptTranslate; end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-chatgpt-translate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yegor Bugayenko
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0.3'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: elapsed
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.2'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.2'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
42
|
name: humanize
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -70,16 +84,22 @@ dependencies:
|
|
|
70
84
|
name: jekyll
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
72
86
|
requirements:
|
|
73
|
-
- - "
|
|
87
|
+
- - ">="
|
|
74
88
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '3.
|
|
89
|
+
version: '3.0'
|
|
90
|
+
- - "<"
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '5.0'
|
|
76
93
|
type: :runtime
|
|
77
94
|
prerelease: false
|
|
78
95
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
96
|
requirements:
|
|
80
|
-
- - "
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '3.0'
|
|
100
|
+
- - "<"
|
|
81
101
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
102
|
+
version: '5.0'
|
|
83
103
|
- !ruby/object:Gem::Dependency
|
|
84
104
|
name: json
|
|
85
105
|
requirement: !ruby/object:Gem::Requirement
|