fastlane-plugin-translate_gpt 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +105 -0
- data/lib/fastlane/plugin/translate_gpt/actions/translate_gpt_action.rb +167 -0
- data/lib/fastlane/plugin/translate_gpt/helper/translate_gpt_helper.rb +67 -0
- data/lib/fastlane/plugin/translate_gpt/version.rb +5 -0
- data/lib/fastlane/plugin/translate_gpt.rb +16 -0
- metadata +203 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d61950fe5af16ec1511687b4cab646b8397be0d4870a5e7c2a8d7f22adc06687
|
4
|
+
data.tar.gz: a04a4b37ba73505bdfea8d6ca7a1b6b0b63cd95f8e2856c9d237a21f513d0a91
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15b62929364a8be8f709c950d728a22ee72179a65aeffcb7a1156a23d3883404daf36219101b9aab8c2f0c8b12e22316d93a60407c9addaa72fdac5a1a68ca42
|
7
|
+
data.tar.gz: 6ac27ed65e2acca6a533ada325f1fe3e0756befd2fb803429b79864092a66eadaefff681a1eefd5fcd74e3f2b65bb87b301ded820a6541e628183df816a2a8ee
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Aleksei Cherepanov <ftp27host@gmail.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+

|
2
|
+
|
3
|
+
# translate-gpt plugin
|
4
|
+
|
5
|
+
[](https://rubygems.org/gems/fastlane-plugin-translate_gpt)
|
6
|
+
[](https://badge.fury.io/rb/fastlane-plugin-translate_gpt)
|
7
|
+
|
8
|
+
## Getting Started
|
9
|
+
|
10
|
+
This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-translate_gpt`, add it to your project by running:
|
11
|
+
|
12
|
+
```bash
|
13
|
+
fastlane add_plugin translate_gpt
|
14
|
+
```
|
15
|
+
|
16
|
+
## About translate-gpt
|
17
|
+
|
18
|
+
`translate-gpt` is a fastlane plugin that allows you to easily translate your iOS app's strings using the OpenAI GPT API.
|
19
|
+
|
20
|
+
|
21
|
+
## Features
|
22
|
+
|
23
|
+
- Automatically detects the source language and translates to the desired target language.
|
24
|
+
- Can take contextual information, such as comments in your code, into account to improve translation accuracy.
|
25
|
+
- Can automatically skip strings that are already translated, improving performance and reducing costs.
|
26
|
+
|
27
|
+
## Example
|
28
|
+
|
29
|
+
The following example demonstrates how to use `translate-gpt` in a `Fastfile` to translate an app's strings from English to French:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
lane :translate_strings do
|
33
|
+
translate_gpt(
|
34
|
+
api_key: 'YOUR_API_KEY',
|
35
|
+
target_language: 'fr'
|
36
|
+
)
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Options
|
41
|
+
|
42
|
+
The following options are available for `translate-gpt`:
|
43
|
+
|
44
|
+
| Key | Description | Environment Variable |
|
45
|
+
| --- | --- | --- |
|
46
|
+
| `api_key` | The API key for your OpenAI GPT account. | `GPT_API_KEY` |
|
47
|
+
| `model_name` | Name of the ChatGPT model to use | `GPT_MODEL_NAME` |
|
48
|
+
| `temperature` | What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. Defaults to 0.5 | `GPT_TEMPERATURE` |
|
49
|
+
| `request_timeout` | Timeout for the request in seconds. Defaults to 30 seconds | `GPT_REQUEST_TIMEOUT` |
|
50
|
+
| `skip_translated` | Whether to skip strings that have already been translated. Defaults to `true`. | `GPT_SKIP_TRANSLATED` |
|
51
|
+
| `source_language` | The source language of the strings to be translated. Defaults to auto-detection. | `GPT_SOURCE_LANGUAGE` |
|
52
|
+
| `target_language` | The target language of the translated strings. Required. | `GPT_TARGET_LANGUAGE` |
|
53
|
+
| `source_file` | The path to the `Localizable.strings` file to be translated. Defaults to `./Resources/Localizable.strings`. | `GPT_SOURCE_FILE` |
|
54
|
+
| `target_file` | The path to the output file for the translated strings. Defaults to `./Resources/Localizable.strings.<target_language>`. | `GPT_TARGET_FILE` |
|
55
|
+
|
56
|
+
## Authentication
|
57
|
+
|
58
|
+
`translate-gpt` supports multiple authentication methods for the OpenAI GPT API:
|
59
|
+
|
60
|
+
### API Key
|
61
|
+
|
62
|
+
You can provide your API key directly as an option to `translate-gpt`:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
translate-gpt(
|
66
|
+
api_key: 'YOUR_API_KEY',
|
67
|
+
target_language: 'fr'
|
68
|
+
)
|
69
|
+
```
|
70
|
+
|
71
|
+
### Environment Variable
|
72
|
+
|
73
|
+
Alternatively, you can set the `GPT_API_KEY` environment variable with your API key:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
export GPT_API_KEY='YOUR_API_KEY'
|
77
|
+
```
|
78
|
+
|
79
|
+
And then call `translate-gpt` without specifying an API key:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
translate-gpt(
|
83
|
+
target_language: 'fr'
|
84
|
+
)
|
85
|
+
```
|
86
|
+
|
87
|
+
## Issues and Feedback
|
88
|
+
|
89
|
+
If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide. For any other issues and feedback about this plugin, please submit it to this repository or contact the maintainers on [Twitter](https://twitter.com/ftp27host).
|
90
|
+
|
91
|
+
## Using _fastlane_ Plugins
|
92
|
+
|
93
|
+
For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
|
94
|
+
|
95
|
+
## About _fastlane_
|
96
|
+
|
97
|
+
_fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
|
98
|
+
|
99
|
+
## Contributing
|
100
|
+
|
101
|
+
If you'd like to contribute to this plugin, please fork the repository and make your changes. When you're ready, submit a pull request explaining your changes.
|
102
|
+
|
103
|
+
## License
|
104
|
+
|
105
|
+
This action is released under the [MIT License](LICENSE).
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require 'openai'
|
3
|
+
require_relative '../helper/translate_gpt_helper'
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
module Actions
|
7
|
+
class TranslateGptAction < Action
|
8
|
+
def self.run(params)
|
9
|
+
client = OpenAI::Client.new(
|
10
|
+
access_token: params[:api_token],
|
11
|
+
request_timeout: params[:request_timeout]
|
12
|
+
)
|
13
|
+
|
14
|
+
input_hash = Helper::TranslateGptHelper.get_strings(params[:source_file])
|
15
|
+
output_hash = Helper::TranslateGptHelper.get_strings(params[:target_file])
|
16
|
+
|
17
|
+
if params[:skip_translated]
|
18
|
+
to_translate = input_hash.reject { |k, v| output_hash[k] }
|
19
|
+
else
|
20
|
+
to_translate = input_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
UI.message "Translating #{input_hash.size} strings..."
|
24
|
+
|
25
|
+
to_translate.each do |key, value|
|
26
|
+
prompt = "Translate the following string from #{params[:source_language]} to #{params[:target_language]}:\n#{value}"
|
27
|
+
context = Helper::TranslateGptHelper.get_context(params[:source_file], key)
|
28
|
+
if context && !context.empty?
|
29
|
+
prompt += "\n\nAdditional context:\n#{context}"
|
30
|
+
end
|
31
|
+
# translate the source string to the target language
|
32
|
+
response = client.chat(
|
33
|
+
parameters: {
|
34
|
+
model: params[:model_name],
|
35
|
+
messages: [{ role: "user", content: prompt}],
|
36
|
+
temperature: params[:temperature],
|
37
|
+
}
|
38
|
+
)
|
39
|
+
#puts response
|
40
|
+
# extract the translated string from the response
|
41
|
+
error = response.dig("error", "message")
|
42
|
+
if error
|
43
|
+
UI.error "Error translating #{key}: #{error}"
|
44
|
+
else
|
45
|
+
target_string = response.dig("choices", 0, "message", "content")
|
46
|
+
if target_string && !target_string.empty?
|
47
|
+
UI.message "Translating #{key} - #{value} -> #{target_string}"
|
48
|
+
output_hash[key] = target_string
|
49
|
+
else
|
50
|
+
UI.warning "Unable to translate #{key} - #{value}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
Helper::TranslateGptHelper.timeout params[:request_timeout]
|
54
|
+
end
|
55
|
+
|
56
|
+
UI.message "Writing #{output_hash.size} strings to #{params[:target_file]}..."
|
57
|
+
|
58
|
+
# write the output hash to the output file
|
59
|
+
File.open(params[:target_file], "w") do |file|
|
60
|
+
output_hash.each do |key, value|
|
61
|
+
file.puts "\"#{key}\" = \"#{value}\";"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#####################################################
|
67
|
+
# @!group Documentation
|
68
|
+
#####################################################
|
69
|
+
|
70
|
+
def self.description
|
71
|
+
"Translate a strings file using OpenAI's GPT API"
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.available_options
|
75
|
+
[
|
76
|
+
FastlaneCore::ConfigItem.new(
|
77
|
+
key: :api_token,
|
78
|
+
env_name: "GPT_API_KEY",
|
79
|
+
description: "API token for ChatGPT",
|
80
|
+
sensitive: true,
|
81
|
+
code_gen_sensitive: true,
|
82
|
+
default_value: ""
|
83
|
+
),
|
84
|
+
FastlaneCore::ConfigItem.new(
|
85
|
+
key: :model_name,
|
86
|
+
env_name: "GPT_MODEL_NAME",
|
87
|
+
description: "Name of the ChatGPT model to use",
|
88
|
+
default_value: "gpt-3.5-turbo"
|
89
|
+
),
|
90
|
+
FastlaneCore::ConfigItem.new(
|
91
|
+
key: :request_timeout,
|
92
|
+
env_name: "GPT_REQUEST_TIMEOUT",
|
93
|
+
description: "Timeout for the request in seconds",
|
94
|
+
default_value: 30
|
95
|
+
),
|
96
|
+
FastlaneCore::ConfigItem.new(
|
97
|
+
key: :temperature,
|
98
|
+
env_name: "GPT_TEMPERATURE",
|
99
|
+
description: "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic",
|
100
|
+
type: Float,
|
101
|
+
optional: true,
|
102
|
+
default_value: 0.5
|
103
|
+
),
|
104
|
+
FastlaneCore::ConfigItem.new(
|
105
|
+
key: :skip_translated,
|
106
|
+
env_name: "GPT_SKIP_TRANSLATED",
|
107
|
+
description: "Whether to skip strings that have already been translated",
|
108
|
+
type: Boolean,
|
109
|
+
optional: true,
|
110
|
+
default_value: true
|
111
|
+
),
|
112
|
+
FastlaneCore::ConfigItem.new(
|
113
|
+
key: :source_language,
|
114
|
+
env_name: "GPT_SOURCE_LANGUAGE",
|
115
|
+
description: "Source language to translate from",
|
116
|
+
default_value: "auto"
|
117
|
+
),
|
118
|
+
FastlaneCore::ConfigItem.new(
|
119
|
+
key: :target_language,
|
120
|
+
env_name: "GPT_TARGET_LANGUAGE",
|
121
|
+
description: "Target language to translate to",
|
122
|
+
default_value: "en"
|
123
|
+
),
|
124
|
+
FastlaneCore::ConfigItem.new(
|
125
|
+
key: :source_file,
|
126
|
+
env_name: "GPT_SOURCE_FILE",
|
127
|
+
description: "The path to the Localizable.strings file to be translated",
|
128
|
+
verify_block: proc do |value|
|
129
|
+
UI.user_error!("Invalid file path: #{value}") unless File.exist?(value)
|
130
|
+
UI.user_error!("Translation file must have .strings extension") unless File.extname(value) == ".strings"
|
131
|
+
end
|
132
|
+
),
|
133
|
+
FastlaneCore::ConfigItem.new(
|
134
|
+
key: :target_file,
|
135
|
+
env_name: "GPT_TARGET_FILE",
|
136
|
+
description: "Path to the translation file to update",
|
137
|
+
verify_block: proc do |value|
|
138
|
+
UI.user_error!("Invalid file path: #{value}") unless File.exist?(value)
|
139
|
+
UI.user_error!("Translation file must have .strings extension") unless File.extname(value) == ".strings"
|
140
|
+
end
|
141
|
+
),
|
142
|
+
]
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.output
|
146
|
+
[
|
147
|
+
['TRANSLATED_STRING', 'The translated string'],
|
148
|
+
['SOURCE_LANGUAGE', 'The source language of the string'],
|
149
|
+
['TARGET_LANGUAGE', 'The target language of the translation']
|
150
|
+
]
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.return_value
|
154
|
+
# This action doesn't return any specific value, so we return nil
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.authors
|
159
|
+
["ftp27"]
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.is_supported?(platform)
|
163
|
+
[:ios, :mac].include?(platform)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'fastlane_core/ui/ui'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
5
|
+
|
6
|
+
module Helper
|
7
|
+
class TranslateGptHelper
|
8
|
+
# Read the strings file into a hash
|
9
|
+
# @param localization_file [String] The path to the strings file
|
10
|
+
# @return [Hash] The strings file as a hash
|
11
|
+
def self.get_strings(localization_file)
|
12
|
+
# Read the strings file into a hash
|
13
|
+
strings_file = File.read(localization_file)
|
14
|
+
strings_hash = strings_file.split(/\n/).reduce({}) do |hash, line|
|
15
|
+
match = line.match(/^"(.+)" = "(.+)";$/)
|
16
|
+
if match
|
17
|
+
hash[match[1]] = match[2]
|
18
|
+
end
|
19
|
+
hash
|
20
|
+
end
|
21
|
+
return strings_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get the context associated with a localization key
|
25
|
+
# @param localization_file [String] The path to the strings file
|
26
|
+
# @param localization_key [String] The localization key
|
27
|
+
# @return [String] The context associated with the localization key
|
28
|
+
def self.get_context(localization_file, localization_key)
|
29
|
+
# read the localization file
|
30
|
+
content = File.read(localization_file)
|
31
|
+
|
32
|
+
# search for the comments associated with the localization key
|
33
|
+
regex = /\/\*\*\n\s*\* @key\s+#{localization_key}\n((\s*\*.*\n)+)\s*\*\/\n\s*"#{localization_key}"/
|
34
|
+
match = content.match(regex)
|
35
|
+
|
36
|
+
# return the comments, if found
|
37
|
+
if match && match.captures.size > 0
|
38
|
+
comments = match.captures[0].strip
|
39
|
+
return comments.gsub(/\n\s*\*\s?/, "\n").strip
|
40
|
+
else
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Sleep for a specified number of seconds, displaying a progress bar
|
46
|
+
# @param seconds [Integer] The number of seconds to sleep
|
47
|
+
def self.timeout(total)
|
48
|
+
sleep_time = 0
|
49
|
+
while sleep_time < total
|
50
|
+
percent_complete = (sleep_time.to_f / total.to_f) * 100.0
|
51
|
+
progress_bar_width = 20
|
52
|
+
completed_width = (progress_bar_width * percent_complete / 100.0).round
|
53
|
+
remaining_width = progress_bar_width - completed_width
|
54
|
+
print "\rTimeout ["
|
55
|
+
print "=" * completed_width
|
56
|
+
print " " * remaining_width
|
57
|
+
print "] %.2f%%" % percent_complete
|
58
|
+
$stdout.flush
|
59
|
+
sleep(1)
|
60
|
+
sleep_time += 1
|
61
|
+
end
|
62
|
+
print "\r"
|
63
|
+
$stdout.flush
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'fastlane/plugin/translate_gpt/version'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module TranslateGpt
|
5
|
+
# Return all .rb files inside the "actions" and "helper" directory
|
6
|
+
def self.all_classes
|
7
|
+
Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# By default we want to import all available actions and helpers
|
13
|
+
# A plugin can contain any number of actions and plugins
|
14
|
+
Fastlane::TranslateGpt.all_classes.each do |current|
|
15
|
+
require current
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fastlane-plugin-translate_gpt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aleksei Cherepanov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby-openai
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fastlane
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.212.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.212.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec_junit_formatter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.12.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.12.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-performance
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop-require_tools
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description:
|
168
|
+
email: ftp27host@gmail.com
|
169
|
+
executables: []
|
170
|
+
extensions: []
|
171
|
+
extra_rdoc_files: []
|
172
|
+
files:
|
173
|
+
- LICENSE
|
174
|
+
- README.md
|
175
|
+
- lib/fastlane/plugin/translate_gpt.rb
|
176
|
+
- lib/fastlane/plugin/translate_gpt/actions/translate_gpt_action.rb
|
177
|
+
- lib/fastlane/plugin/translate_gpt/helper/translate_gpt_helper.rb
|
178
|
+
- lib/fastlane/plugin/translate_gpt/version.rb
|
179
|
+
homepage: https://github.com/ftp27/fastlane-plugin-translate_gpt
|
180
|
+
licenses:
|
181
|
+
- MIT
|
182
|
+
metadata: {}
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '2.6'
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
requirements: []
|
198
|
+
rubygems_version: 3.4.10
|
199
|
+
signing_key:
|
200
|
+
specification_version: 4
|
201
|
+
summary: This fastlane plugin provides an easy way to use the OpenAI GPT language
|
202
|
+
model to translate strings in your iOS application.
|
203
|
+
test_files: []
|