fastlane-plugin-translate_gpt_release_notes 0.1.0 → 0.2.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/README.md +352 -40
- data/lib/fastlane/plugin/translate_gpt_release_notes/actions/translate_gpt_release_notes_action.rb +80 -5
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/credential_resolver.rb +118 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/anthropic_provider.rb +119 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/base_provider.rb +161 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/deepl_provider.rb +145 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/gemini_provider.rb +153 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/openai_provider.rb +136 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/provider_factory.rb +148 -0
- data/lib/fastlane/plugin/translate_gpt_release_notes/helper/translate_gpt_release_notes_helper.rb +19 -40
- data/lib/fastlane/plugin/translate_gpt_release_notes/version.rb +1 -1
- metadata +52 -4
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
require 'openai'
|
|
2
|
+
require_relative 'base_provider'
|
|
3
|
+
|
|
4
|
+
module Fastlane
|
|
5
|
+
module Helper
|
|
6
|
+
module Providers
|
|
7
|
+
# Provider implementation for OpenAI GPT translation API.
|
|
8
|
+
# Supports various GPT models including gpt-5.2 for translation tasks.
|
|
9
|
+
class OpenAIProvider < BaseProvider
|
|
10
|
+
# Default model for OpenAI translations
|
|
11
|
+
DEFAULT_MODEL = 'gpt-5.2'.freeze
|
|
12
|
+
|
|
13
|
+
# Default temperature for translation generation (0.5 = balanced creativity)
|
|
14
|
+
DEFAULT_TEMPERATURE = 0.5
|
|
15
|
+
|
|
16
|
+
# Default request timeout in seconds
|
|
17
|
+
DEFAULT_TIMEOUT = 30
|
|
18
|
+
|
|
19
|
+
# Returns the provider identifier string.
|
|
20
|
+
#
|
|
21
|
+
# @return [String] Provider identifier
|
|
22
|
+
def self.provider_name
|
|
23
|
+
'openai'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the human-readable display name for the provider.
|
|
27
|
+
#
|
|
28
|
+
# @return [String] Human-readable name
|
|
29
|
+
def self.display_name
|
|
30
|
+
'OpenAI GPT'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns the list of required credential symbols for this provider.
|
|
34
|
+
#
|
|
35
|
+
# @return [Array<Symbol>] Array of required credential keys
|
|
36
|
+
def self.required_credentials
|
|
37
|
+
[:api_token]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns a hash of optional parameter definitions for this provider.
|
|
41
|
+
#
|
|
42
|
+
# @return [Hash] Optional parameter definitions
|
|
43
|
+
def self.optional_params
|
|
44
|
+
{
|
|
45
|
+
model_name: { default: DEFAULT_MODEL, description: 'OpenAI model to use' },
|
|
46
|
+
temperature: { default: DEFAULT_TEMPERATURE, description: 'Sampling temperature (0-2)' },
|
|
47
|
+
service_tier: { default: nil, description: 'Service tier (e.g., "flex")' },
|
|
48
|
+
request_timeout: { default: DEFAULT_TIMEOUT, description: 'Request timeout in seconds' }
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Initializes the OpenAI provider with configuration parameters.
|
|
53
|
+
# Sets up the OpenAI::Client with appropriate credentials and timeout.
|
|
54
|
+
#
|
|
55
|
+
# @param params [Hash] Configuration parameters for the provider
|
|
56
|
+
def initialize(params)
|
|
57
|
+
super
|
|
58
|
+
|
|
59
|
+
timeout = normalized_timeout
|
|
60
|
+
@client = OpenAI::Client.new(
|
|
61
|
+
access_token: credential(:api_token),
|
|
62
|
+
request_timeout: timeout
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Validates the provider configuration.
|
|
67
|
+
# Ensures that the required api_token credential is present.
|
|
68
|
+
#
|
|
69
|
+
# @return [void]
|
|
70
|
+
def validate_config!
|
|
71
|
+
require_credential(:api_token)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Translates text from source locale to target locale using OpenAI's API.
|
|
75
|
+
#
|
|
76
|
+
# @param text [String] The text to translate
|
|
77
|
+
# @param source_locale [String] Source language code (e.g., 'en', 'de')
|
|
78
|
+
# @param target_locale [String] Target language code (e.g., 'es', 'fr')
|
|
79
|
+
# @return [String, nil] Translated text or nil on error
|
|
80
|
+
def translate(text, source_locale, target_locale)
|
|
81
|
+
# Build prompt using inherited build_prompt method
|
|
82
|
+
prompt = build_prompt(text, source_locale, target_locale)
|
|
83
|
+
|
|
84
|
+
# Add Android limitations if needed
|
|
85
|
+
prompt = apply_android_limitations(prompt) if @params[:platform] == 'android'
|
|
86
|
+
|
|
87
|
+
# Build parameters hash
|
|
88
|
+
parameters = {
|
|
89
|
+
model: @params[:model_name] || DEFAULT_MODEL,
|
|
90
|
+
messages: [{ role: 'user', content: prompt }],
|
|
91
|
+
temperature: (@params[:temperature] || DEFAULT_TEMPERATURE).to_f
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Add service_tier if present
|
|
95
|
+
service_tier = @params[:service_tier].to_s.strip
|
|
96
|
+
parameters[:service_tier] = service_tier unless service_tier.empty?
|
|
97
|
+
|
|
98
|
+
# Make API call
|
|
99
|
+
response = @client.chat(parameters: parameters)
|
|
100
|
+
|
|
101
|
+
# Handle errors and extract text
|
|
102
|
+
if (error = response.dig('error', 'message'))
|
|
103
|
+
UI.error "OpenAI translation error: #{error}"
|
|
104
|
+
nil
|
|
105
|
+
else
|
|
106
|
+
response.dig('choices', 0, 'message', 'content')&.strip
|
|
107
|
+
end
|
|
108
|
+
rescue StandardError => e
|
|
109
|
+
UI.error "OpenAI provider error: #{e.message}"
|
|
110
|
+
nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
# Normalizes the request timeout value based on service tier.
|
|
116
|
+
# Flex service tier requires a minimum timeout of 900 seconds.
|
|
117
|
+
#
|
|
118
|
+
# @return [Integer, nil] Normalized timeout value or nil
|
|
119
|
+
def normalized_timeout
|
|
120
|
+
service_tier = @params[:service_tier].to_s.strip
|
|
121
|
+
raw_timeout = @params[:request_timeout]
|
|
122
|
+
|
|
123
|
+
# Use default timeout if not specified
|
|
124
|
+
timeout = raw_timeout.nil? ? DEFAULT_TIMEOUT : raw_timeout.to_i
|
|
125
|
+
|
|
126
|
+
if service_tier == 'flex' && timeout > 0 && timeout < 900
|
|
127
|
+
UI.message('Flex processing detected; increasing request_timeout to 900s.')
|
|
128
|
+
return 900
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
timeout
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
require_relative '../credential_resolver'
|
|
2
|
+
require_relative 'base_provider'
|
|
3
|
+
require_relative 'openai_provider'
|
|
4
|
+
require_relative 'anthropic_provider'
|
|
5
|
+
require_relative 'gemini_provider'
|
|
6
|
+
require_relative 'deepl_provider'
|
|
7
|
+
|
|
8
|
+
module Fastlane
|
|
9
|
+
module Helper
|
|
10
|
+
module Providers
|
|
11
|
+
# ProviderFactory is the central component for creating provider instances.
|
|
12
|
+
# It uses CredentialResolver to resolve API keys and instantiates the
|
|
13
|
+
# appropriate provider based on the provider_name parameter.
|
|
14
|
+
#
|
|
15
|
+
# This class provides a unified interface for creating any supported provider
|
|
16
|
+
# with automatic credential resolution and validation.
|
|
17
|
+
#
|
|
18
|
+
# @example Creating a provider with automatic credential resolution
|
|
19
|
+
# provider = ProviderFactory.create('openai', { model_name: 'gpt-5.2' })
|
|
20
|
+
#
|
|
21
|
+
# @example Creating a provider with explicit API key
|
|
22
|
+
# provider = ProviderFactory.create_with_key('openai', 'sk-...', { model_name: 'gpt-5.2' })
|
|
23
|
+
#
|
|
24
|
+
class ProviderFactory
|
|
25
|
+
# Mapping of provider names to their respective provider classes.
|
|
26
|
+
# Used to look up and instantiate the correct provider implementation.
|
|
27
|
+
PROVIDERS = {
|
|
28
|
+
OpenAIProvider.provider_name => OpenAIProvider,
|
|
29
|
+
AnthropicProvider.provider_name => AnthropicProvider,
|
|
30
|
+
GeminiProvider.provider_name => GeminiProvider,
|
|
31
|
+
DeepLProvider.provider_name => DeepLProvider
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
34
|
+
# Default provider to use when none is specified.
|
|
35
|
+
DEFAULT_PROVIDER = 'openai'.freeze
|
|
36
|
+
|
|
37
|
+
# Creates a provider instance with automatic credential resolution.
|
|
38
|
+
#
|
|
39
|
+
# This method resolves the API key using CredentialResolver, merges it into
|
|
40
|
+
# the params, and instantiates the appropriate provider class.
|
|
41
|
+
#
|
|
42
|
+
# @param provider_name [String, nil] The provider identifier (e.g., 'openai', 'anthropic').
|
|
43
|
+
# Defaults to DEFAULT_PROVIDER if nil or not provided.
|
|
44
|
+
# @param params [Hash] Configuration parameters for the provider.
|
|
45
|
+
# May include provider-specific options and credential overrides.
|
|
46
|
+
# @return [BaseProvider] An instance of the requested provider class.
|
|
47
|
+
# @raise [FastlaneCore::Interface::FastlaneError] If the provider name is unknown
|
|
48
|
+
# or if no API key can be resolved.
|
|
49
|
+
def self.create(provider_name, params)
|
|
50
|
+
provider_name = provider_name.to_s.empty? ? DEFAULT_PROVIDER : provider_name.to_s.downcase
|
|
51
|
+
provider_class = PROVIDERS[provider_name]
|
|
52
|
+
|
|
53
|
+
unless provider_class
|
|
54
|
+
UI.user_error!("Unknown provider '#{provider_name}'. Available: #{available_provider_names.join(', ')}")
|
|
55
|
+
return nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Resolve API key
|
|
59
|
+
api_key = CredentialResolver.resolve(provider_name, params)
|
|
60
|
+
|
|
61
|
+
unless api_key
|
|
62
|
+
UI.user_error!("No API key found for provider '#{provider_name}'. #{CredentialResolver.credential_help(provider_name)}")
|
|
63
|
+
return nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Merge API key into params
|
|
67
|
+
provider_params = params.merge(api_token: api_key)
|
|
68
|
+
|
|
69
|
+
provider_class.new(provider_params)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Creates a provider instance with an explicit API key.
|
|
73
|
+
#
|
|
74
|
+
# This method bypasses credential resolution and uses the provided API key
|
|
75
|
+
# directly. Useful when the key is obtained from an external source or
|
|
76
|
+
# when credential resolution is not desired.
|
|
77
|
+
#
|
|
78
|
+
# @param provider_name [String] The provider identifier (e.g., 'openai', 'anthropic').
|
|
79
|
+
# @param api_key [String] The API key to use for authentication.
|
|
80
|
+
# @param params [Hash] Optional configuration parameters for the provider.
|
|
81
|
+
# @return [BaseProvider] An instance of the requested provider class.
|
|
82
|
+
# @raise [FastlaneCore::Interface::FastlaneError] If the provider name is unknown.
|
|
83
|
+
def self.create_with_key(provider_name, api_key, params = {})
|
|
84
|
+
provider_name = provider_name.to_s.downcase
|
|
85
|
+
provider_class = PROVIDERS[provider_name]
|
|
86
|
+
|
|
87
|
+
unless provider_class
|
|
88
|
+
UI.user_error!("Unknown provider '#{provider_name}'")
|
|
89
|
+
return nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
provider_params = params.merge(api_token: api_key)
|
|
93
|
+
provider_class.new(provider_params)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Returns an array of all available provider names.
|
|
97
|
+
#
|
|
98
|
+
# @return [Array<String>] Array of provider identifiers.
|
|
99
|
+
def self.available_provider_names
|
|
100
|
+
PROVIDERS.keys.freeze
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Returns a hash mapping provider names to their display names.
|
|
104
|
+
#
|
|
105
|
+
# @return [Hash<String, String>] Hash with provider names as keys and
|
|
106
|
+
# human-readable display names as values.
|
|
107
|
+
def self.provider_display_names
|
|
108
|
+
PROVIDERS.transform_values(&:display_name)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Checks if a provider name is valid.
|
|
112
|
+
#
|
|
113
|
+
# @param provider_name [String] The provider identifier to check.
|
|
114
|
+
# @return [Boolean] true if the provider is supported, false otherwise.
|
|
115
|
+
def self.valid_provider?(provider_name)
|
|
116
|
+
PROVIDERS.key?(provider_name.to_s.downcase)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Gets the full configuration for a provider.
|
|
120
|
+
#
|
|
121
|
+
# Returns a comprehensive hash containing all configuration details
|
|
122
|
+
# for the specified provider, including name, display name, required
|
|
123
|
+
# credentials, optional parameters, and credential help text.
|
|
124
|
+
#
|
|
125
|
+
# @param provider_name [String] The provider identifier.
|
|
126
|
+
# @return [Hash] Provider configuration hash with keys:
|
|
127
|
+
# - :name [String] Provider identifier
|
|
128
|
+
# - :display_name [String] Human-readable name
|
|
129
|
+
# - :required_credentials [Array<Symbol>] Required credential symbols
|
|
130
|
+
# - :optional_params [Hash] Optional parameter definitions
|
|
131
|
+
# - :credential_help [String] Help text for configuring credentials
|
|
132
|
+
# @return [Hash] Empty hash if provider is not found.
|
|
133
|
+
def self.provider_config(provider_name)
|
|
134
|
+
provider_class = PROVIDERS[provider_name.to_s.downcase]
|
|
135
|
+
return {} unless provider_class
|
|
136
|
+
|
|
137
|
+
{
|
|
138
|
+
name: provider_class.provider_name,
|
|
139
|
+
display_name: provider_class.display_name,
|
|
140
|
+
required_credentials: provider_class.required_credentials,
|
|
141
|
+
optional_params: provider_class.optional_params,
|
|
142
|
+
credential_help: CredentialResolver.credential_help(provider_name)
|
|
143
|
+
}
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
data/lib/fastlane/plugin/translate_gpt_release_notes/helper/translate_gpt_release_notes_helper.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require 'fastlane_core/ui/ui'
|
|
2
|
-
|
|
3
|
-
require 'json'
|
|
2
|
+
require_relative 'providers/provider_factory'
|
|
4
3
|
|
|
5
4
|
module Fastlane
|
|
6
5
|
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
|
@@ -9,49 +8,29 @@ module Fastlane
|
|
|
9
8
|
class TranslateGptReleaseNotesHelper
|
|
10
9
|
def initialize(params)
|
|
11
10
|
@params = params
|
|
12
|
-
|
|
13
|
-
access_token: params[:api_token],
|
|
14
|
-
request_timeout: params[:request_timeout]
|
|
15
|
-
)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Request a translation from the GPT API
|
|
19
|
-
def translate_text(text, target_locale, platform)
|
|
20
|
-
source_locale = @params[:master_locale]
|
|
21
|
-
prompt = "Translate this text from #{source_locale} to #{target_locale}:\n#{text}"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Add condition for Android platform
|
|
25
|
-
if platform == 'android'
|
|
26
|
-
prompt += "\n\nNote: The length of the translated text should be 500 symbols maximum. Rephrase a little if needed."
|
|
27
|
-
end
|
|
11
|
+
provider_name = params[:provider] || 'openai'
|
|
28
12
|
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
# Validate provider selection
|
|
14
|
+
unless Providers::ProviderFactory.valid_provider?(provider_name)
|
|
15
|
+
UI.warning "Unknown provider '#{provider_name}', falling back to OpenAI"
|
|
16
|
+
provider_name = 'openai'
|
|
32
17
|
end
|
|
33
18
|
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
parameters: {
|
|
37
|
-
model: @params[:model_name] || 'gpt-4-1106-preview',
|
|
38
|
-
messages: [{ role: "user", content: prompt }],
|
|
39
|
-
temperature: @params[:temperature] || 0.5
|
|
40
|
-
}
|
|
41
|
-
)
|
|
19
|
+
# Create provider via factory (handles credential resolution)
|
|
20
|
+
@provider = Providers::ProviderFactory.create(provider_name, params)
|
|
42
21
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
UI.error "Error translating text: #{error}"
|
|
47
|
-
return nil
|
|
48
|
-
else
|
|
49
|
-
translated_text = response.dig("choices", 0, "message", "content").strip
|
|
50
|
-
UI.message "Translated text: #{translated_text}"
|
|
51
|
-
return translated_text
|
|
22
|
+
# Validate provider configuration
|
|
23
|
+
unless @provider.valid?
|
|
24
|
+
UI.user_error!("Provider configuration errors: #{@provider.config_errors.join(', ')}")
|
|
52
25
|
end
|
|
53
26
|
end
|
|
54
|
-
|
|
27
|
+
|
|
28
|
+
# Request a translation from the configured provider
|
|
29
|
+
def translate_text(text, target_locale, _platform)
|
|
30
|
+
source_locale = @params[:master_locale]
|
|
31
|
+
@provider.translate(text, source_locale, target_locale)
|
|
32
|
+
end
|
|
33
|
+
|
|
55
34
|
# Sleep for a specified number of seconds, displaying a progress bar
|
|
56
35
|
def wait(seconds = @params[:request_timeout])
|
|
57
36
|
sleep_time = 0
|
|
@@ -89,7 +68,7 @@ module Fastlane
|
|
|
89
68
|
white: 37,
|
|
90
69
|
reset: 0,
|
|
91
70
|
}
|
|
92
|
-
|
|
71
|
+
|
|
93
72
|
def self.colorize(text, color)
|
|
94
73
|
color_code = COLORS[color.to_sym]
|
|
95
74
|
"\e[#{color_code}m#{text}\e[0m"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fastlane-plugin-translate_gpt_release_notes
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anton Karliner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ruby-openai
|
|
@@ -52,6 +52,48 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: 1.18.9
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: anthropic
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.16'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.16'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: deepl-rb
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '3.6'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '3.6'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: openssl
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 3.2.0
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 3.2.0
|
|
55
97
|
- !ruby/object:Gem::Dependency
|
|
56
98
|
name: bundler
|
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -202,6 +244,13 @@ files:
|
|
|
202
244
|
- README.md
|
|
203
245
|
- lib/fastlane/plugin/translate_gpt_release_notes.rb
|
|
204
246
|
- lib/fastlane/plugin/translate_gpt_release_notes/actions/translate_gpt_release_notes_action.rb
|
|
247
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/credential_resolver.rb
|
|
248
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/anthropic_provider.rb
|
|
249
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/base_provider.rb
|
|
250
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/deepl_provider.rb
|
|
251
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/gemini_provider.rb
|
|
252
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/openai_provider.rb
|
|
253
|
+
- lib/fastlane/plugin/translate_gpt_release_notes/helper/providers/provider_factory.rb
|
|
205
254
|
- lib/fastlane/plugin/translate_gpt_release_notes/helper/translate_gpt_release_notes_helper.rb
|
|
206
255
|
- lib/fastlane/plugin/translate_gpt_release_notes/version.rb
|
|
207
256
|
homepage: https://github.com/antonkarliner/fastlane-plugin-translate_gpt_release_notes
|
|
@@ -229,6 +278,5 @@ requirements: []
|
|
|
229
278
|
rubygems_version: 3.4.10
|
|
230
279
|
signing_key:
|
|
231
280
|
specification_version: 4
|
|
232
|
-
summary: Translate release notes
|
|
233
|
-
GPT API
|
|
281
|
+
summary: 'Translate release notes using AI providers: OpenAI, Claude, Gemini, or DeepL'
|
|
234
282
|
test_files: []
|