fastlane-plugin-translate_gpt 0.1.6 → 0.1.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be8140845fda90144346f59a44239c4baa066fc8b75f1afc26655783be3e3686
4
- data.tar.gz: 0a39de422d2b3760c4678df1053a61799cd444434399d8f3f0f22a9dfcf261b0
3
+ metadata.gz: 5e16882ee4e890369a5c14b579f362303a3196e4238d4d3b3f685a9e6b4fb21a
4
+ data.tar.gz: 59719d66698e72c02ae4c625a68a9b5fe8d7dfc34023a5c329d0625bed27b2e9
5
5
  SHA512:
6
- metadata.gz: a60eb486cf4a385386e429d85d6d53e833ff3afb80c8f60dae482a6596f55fce3218e6268669a4ad4f60e7868244ffaf62a772e2e481fd91e168e18d746f1dd2
7
- data.tar.gz: e4a68b0fa334c61c03dc8fdb26fcab4a1310fa9ca877f57522e21d138ea754c937d9ce11263e9dde2d184a23f05d76fc91566c4994167847dd32f2c220bd69a2
6
+ metadata.gz: 23f15a4ca667b24e958ca6775cd6894dc43b85ecf3e705f4270526af2428a1e7a947824b0bbf74132dbc0fa55059edd9020f1dad10946f5e345ae2d69d7997ac
7
+ data.tar.gz: d94703743059519b4e3c17ea988a7591c8f67b981d3d38a075ed8fc801ce952509c146e3fb3f92207102680b490cefbc103f325da85c0f7c7e1c2e0281255e0b
@@ -84,7 +84,9 @@ module Fastlane
84
84
  description: "The path to the Localizable.strings file to be translated",
85
85
  verify_block: proc do |value|
86
86
  UI.user_error!("Invalid file path: #{value}") unless File.exist?(value)
87
- UI.user_error!("Translation file must have .strings extension") unless File.extname(value) == ".strings"
87
+ extension = File.extname(value)
88
+ available_extensions = [".strings", ".xcstrings"]
89
+ UI.user_error!("Translation file must have any of these extensions: #{available_extensions}") unless available_extensions.include? extension
88
90
  end
89
91
  ),
90
92
  FastlaneCore::ConfigItem.new(
@@ -93,7 +95,9 @@ module Fastlane
93
95
  description: "Path to the translation file to update",
94
96
  verify_block: proc do |value|
95
97
  UI.user_error!("Invalid file path: #{value}") unless File.exist?(value)
96
- UI.user_error!("Translation file must have .strings extension") unless File.extname(value) == ".strings"
98
+ extension = File.extname(value)
99
+ available_extensions = [".strings", ".xcstrings"]
100
+ UI.user_error!("Translation file must have any of these extensions: #{available_extensions}") unless available_extensions.include? extension
97
101
  end
98
102
  ),
99
103
  FastlaneCore::ConfigItem.new(
@@ -1,6 +1,7 @@
1
1
  require 'fastlane_core/ui/ui'
2
- require 'loco_strings'
2
+ require 'loco_strings/parsers/xcstrings_file'
3
3
  require 'json'
4
+ # rubocop:disable all
4
5
 
5
6
  module Fastlane
6
7
  UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
@@ -16,13 +17,50 @@ module Fastlane
16
17
  @timeout = params[:request_timeout]
17
18
  end
18
19
 
19
- # Get the strings from a file
20
- def prepare_hashes()
20
+ def prepare_xcstrings()
21
+ @xcfile = LocoStrings::XCStringsFile.new @params[:source_file]
22
+ @output_hash = {}
23
+ @to_translate = @xcfile.read
24
+
25
+ if @params[:skip_translated] == true
26
+ @to_translate = @to_translate.reject { |k, original|
27
+ !check_value_for_translate(
28
+ @xcfile.unit(k, @params[:target_language]),
29
+ original
30
+ )
31
+ }
32
+ end
33
+ end
34
+
35
+ def check_value_for_translate(string, orignal_string)
36
+ return true unless string
37
+ if string.is_a? LocoStrings::LocoString
38
+ return false if orignal_string.value.nil? || orignal_string.value.empty?
39
+ return string.value.empty?
40
+ elsif string.is_a? LocoStrings::LocoVariantions
41
+ orignal_string.strings.each do |key, _|
42
+ return true unless string.strings.has_key?(key)
43
+ return true if string.strings[key].value.empty?
44
+ end
45
+ end
46
+ return false
47
+ end
48
+
49
+ def prepare_strings()
21
50
  @input_hash = get_strings(@params[:source_file])
22
51
  @output_hash = get_strings(@params[:target_file])
23
52
  @to_translate = filter_translated(@params[:skip_translated], @input_hash, @output_hash)
24
53
  end
25
54
 
55
+ # Get the strings from a file
56
+ def prepare_hashes()
57
+ if File.extname(@params[:source_file]) == ".xcstrings"
58
+ prepare_xcstrings()
59
+ else
60
+ prepare_strings()
61
+ end
62
+ end
63
+
26
64
  # Log information about the input strings
27
65
  def log_input(bunch_size)
28
66
  @translation_count = @to_translate.size
@@ -66,8 +104,13 @@ module Fastlane
66
104
  def translate_bunch_of_strings(bunch_size)
67
105
  bunch_index = 0
68
106
  number_of_bunches = (@translation_count / bunch_size.to_f).ceil
107
+ @keys_associations = {}
69
108
  @to_translate.each_slice(bunch_size) do |bunch|
70
109
  prompt = prepare_bunch_prompt bunch
110
+ if prompt.empty?
111
+ UI.important "Empty prompt, skipping bunch"
112
+ next
113
+ end
71
114
  max_retries = 10
72
115
  times_retried = 0
73
116
 
@@ -109,7 +152,7 @@ module Fastlane
109
152
  def prepare_bunch_prompt(strings)
110
153
  prompt = "I want you to act as a translator for a mobile application strings. " + \
111
154
  "Try to keep length of the translated text. " + \
112
- "You need to response with a JSON only with the translation and nothing else until I say to stop it."
155
+ "You need to response with a JSON only with the translation and nothing else until I say to stop it. "
113
156
  if @params[:context] && !@params[:context].empty?
114
157
  prompt += "This app is #{@params[:context]}. "
115
158
  end
@@ -117,21 +160,46 @@ module Fastlane
117
160
 
118
161
  json_hash = []
119
162
  strings.each do |key, string|
163
+ UI.message "Translating #{key} - #{string}"
164
+ next if string.nil?
165
+
120
166
  string_hash = {}
121
167
  context = string.comment
122
- if context && !context.empty?
123
- string_hash["context"] = context
168
+ string_hash["context"] = context if context && !context.empty?
169
+
170
+ key = transform_string(string.key)
171
+ @keys_associations[key] = string.key
172
+ string_hash["key"] = key
173
+
174
+ if string.is_a? LocoStrings::LocoString
175
+ next if string.value.nil? || string.value.empty?
176
+ string_hash["string_to_translate"] = string.value
177
+ elsif string.is_a? LocoStrings::LocoVariantions
178
+ variants = {}
179
+ string.strings.each do |key, variant|
180
+ next if variant.nil? || variant.value.nil? || variant.value.empty?
181
+ variants[key] = variant.value
182
+ end
183
+ string_hash["strings_to_translate"] = variants
184
+ else
185
+ UI.warning "Unknown type of string: #{string.key}"
124
186
  end
125
- string_hash["key"] = string.key
126
- string_hash["string_to_translate"] = string.value
127
187
  json_hash << string_hash
128
188
  end
189
+ return '' if json_hash.empty?
129
190
  prompt += "'''\n"
130
191
  prompt += json_hash.to_json
131
192
  prompt += "\n'''"
193
+ UI.message "Prompt: #{prompt}"
132
194
  return prompt
133
195
  end
134
196
 
197
+ def transform_string(input_string)
198
+ uppercased_string = input_string.upcase
199
+ escaped_string = uppercased_string.gsub(/[^0-9a-zA-Z]+/, '_')
200
+ return escaped_string
201
+ end
202
+
135
203
  # Request a translation from the GPT API
136
204
  def request_translate(key, string, prompt, index)
137
205
  response = @client.chat(
@@ -195,12 +263,21 @@ module Fastlane
195
263
  string_hash.delete("key")
196
264
  string_hash.delete("context")
197
265
  translated_string = string_hash.values.first
198
- if key && !key.empty? && translated_string && !translated_string.empty?
199
- UI.message "#{index_log} Translating #{key} - #{translated_string}"
200
- string = LocoStrings::LocoString.new(key, translated_string, context)
201
- @output_hash[key] = string
202
- keys_to_translate.delete(key)
266
+ return unless key && !key.empty?
267
+ real_key = @keys_associations[key]
268
+ if translated_string.is_a? Hash
269
+ strings = {}
270
+ translated_string.each do |pl_key, value|
271
+ UI.message "#{index_log} Translating #{real_key} > #{pl_key} - #{value}"
272
+ strings[pl_key] = LocoStrings::LocoString.new(pl_key, value, context)
273
+ end
274
+ string = LocoStrings::LocoVariantions.new(real_key, strings, context)
275
+ elsif translated_string && !translated_string.empty?
276
+ UI.message "#{index_log} Translating #{real_key} - #{translated_string}"
277
+ string = LocoStrings::LocoString.new(real_key, translated_string, context)
203
278
  end
279
+ @output_hash[real_key] = string
280
+ keys_to_translate.delete(key)
204
281
  end
205
282
 
206
283
  if keys_to_translate.length > 0
@@ -215,12 +292,26 @@ module Fastlane
215
292
  target_string = Colorizer::colorize(@params[:target_file], :white)
216
293
  UI.message "Writing #{number_of_strings} strings to #{target_string}..."
217
294
 
218
- file = LocoStrings.load(@params[:target_file])
219
- file.read
220
- @output_hash.each do |key, value|
221
- file.update(key, value.value, value.comment)
295
+ if @xcfile.nil?
296
+ file = LocoStrings.load(@params[:target_file])
297
+ file.read
298
+ @output_hash.each do |key, value|
299
+ file.update(key, value.value, value.comment)
300
+ end
301
+ file.write
302
+ else
303
+ @xcfile.update_file_path(@params[:target_file])
304
+ @output_hash.each do |key, value|
305
+ if value.is_a? LocoStrings::LocoString
306
+ @xcfile.update(key, value.value, value.comment, "translated", @params[:target_language])
307
+ elsif value.is_a? LocoStrings::LocoVariantions
308
+ value.strings.each do |pl_key, variant|
309
+ @xcfile.update_variation(key, pl_key, variant.value, variant.comment, "translated", @params[:target_language])
310
+ end
311
+ end
312
+ end
313
+ @xcfile.write
222
314
  end
223
- file.write
224
315
  end
225
316
 
226
317
  # Read the strings file into a hash
@@ -298,3 +389,5 @@ module Fastlane
298
389
  end
299
390
  end
300
391
  end
392
+
393
+ # rubocop:enable all
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module TranslateGpt
3
- VERSION = "0.1.6"
3
+ VERSION = "0.1.8"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-translate_gpt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksei Cherepanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-24 00:00:00.000000000 Z
11
+ date: 2024-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-openai
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.1.1
33
+ version: 0.1.4.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.1.1
40
+ version: 0.1.4.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -212,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
212
  - !ruby/object:Gem::Version
213
213
  version: '0'
214
214
  requirements: []
215
- rubygems_version: 3.4.13
215
+ rubygems_version: 3.4.19
216
216
  signing_key:
217
217
  specification_version: 4
218
218
  summary: This fastlane plugin provides an easy way to use the OpenAI GPT language