ETLane 0.1.42 → 0.1.46
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/Lanes/CommonFastfile +4 -8
- data/Lanes/actions/README.md +47 -0
- data/Lanes/actions/add_keys_to_lokalise.rb +106 -0
- data/Lanes/actions/android/README.md +53 -0
- data/Lanes/actions/android/lokalise_download.rb +144 -0
- data/Lanes/actions/android/lokalise_upload.rb +98 -0
- data/Lanes/actions/lokalise.rb +180 -0
- data/Lanes/actions/lokalise_metadata.rb +624 -0
- data/Lanes/actions/lokalise_upload.rb +165 -0
- data/Lanes/actions/previews.rb +157 -0
- data/Scripts/Sources/Common/Api.swift +142 -0
- data/Scripts/Sources/Common/Array.swift +8 -0
- data/Scripts/Sources/Common/Error.swift +10 -0
- data/Scripts/Sources/Common/MD5.swift +34 -0
- data/Scripts/Sources/Resources/Api+Figma.swift +43 -0
- data/Scripts/Sources/Resources/Deploy.swift +133 -0
- data/Scripts/Sources/Resources/Device.swift +42 -0
- data/Scripts/Sources/Resources/DownloadBatch.swift +108 -0
- data/Scripts/Sources/Resources/FigmaPages.swift +58 -0
- data/Scripts/Sources/Resources/Images.swift +5 -0
- data/Scripts/Sources/Resources/PreviewDownloader.swift +80 -0
- data/Scripts/Sources/Resources/ResourcesParser.swift +25 -0
- data/Scripts/Sources/Resources/ScreenshotDownloader.swift +150 -0
- data/Scripts/Sources/Resources/main.swift +58 -0
- metadata +25 -2
@@ -0,0 +1,180 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
class LokaliseAction < Action
|
4
|
+
def self.run(params)
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
token = params[:api_token]
|
8
|
+
project_identifier = params[:project_identifier]
|
9
|
+
destination = params[:destination]
|
10
|
+
clean_destination = params[:clean_destination]
|
11
|
+
include_comments = params[:include_comments] ? 1 : 0
|
12
|
+
use_original = params[:use_original] ? 1 : 0
|
13
|
+
|
14
|
+
request_data = {
|
15
|
+
original_filenames: true,
|
16
|
+
export_sort: "first_added",
|
17
|
+
format: "strings",
|
18
|
+
directory_prefix: "",
|
19
|
+
}
|
20
|
+
languages = params[:languages]
|
21
|
+
if languages.kind_of? Array then
|
22
|
+
request_data["langs"] = languages.to_json
|
23
|
+
end
|
24
|
+
request_data["include_comments"] = true
|
25
|
+
tags = params[:tags]
|
26
|
+
if tags.kind_of? Array then
|
27
|
+
request_data["include_tags"] = tags.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
uri = URI("https://api.lokalise.com/api2/projects/#{project_identifier}/files/download")
|
31
|
+
request = Net::HTTP::Post.new(uri)
|
32
|
+
request.body = request_data.to_json
|
33
|
+
request['X-Api-Token'] = token
|
34
|
+
request['Content-Type'] = 'application/json'
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
http.use_ssl = true
|
37
|
+
response = http.request(request)
|
38
|
+
|
39
|
+
jsonResponse = JSON.parse(response.body)
|
40
|
+
puts(jsonResponse.to_s)
|
41
|
+
UI.error "Bad response 🉐\n#{response.body}" unless jsonResponse.kind_of? Hash
|
42
|
+
fileURL = jsonResponse["bundle_url"]
|
43
|
+
if fileURL.kind_of?(String) then
|
44
|
+
UI.message "Downloading localizations archive 📦"
|
45
|
+
FileUtils.mkdir_p("lokalisetmp")
|
46
|
+
uri = URI(fileURL)
|
47
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
48
|
+
http.use_ssl = true
|
49
|
+
zipRequest = Net::HTTP::Get.new(uri)
|
50
|
+
response = http.request(zipRequest)
|
51
|
+
if response.content_type == "application/zip" or response.content_type == "application/octet-stream" then
|
52
|
+
FileUtils.mkdir_p("lokalisetmp")
|
53
|
+
open("lokalisetmp/a.zip", "wb") { |file|
|
54
|
+
file.write(response.body)
|
55
|
+
}
|
56
|
+
unzip_file("lokalisetmp/a.zip", destination, clean_destination)
|
57
|
+
FileUtils.remove_dir("lokalisetmp")
|
58
|
+
UI.success "Localizations extracted to #{destination} 📗 📕 📘"
|
59
|
+
copy_fr_folder(File.join(destination, "Fitness/Resources"))
|
60
|
+
copy_fr_folder(File.join(destination, "Watch Extension/Resources"))
|
61
|
+
else
|
62
|
+
UI.error "Response did not include ZIP"
|
63
|
+
end
|
64
|
+
elsif jsonResponse["response"]["status"] == "error"
|
65
|
+
code = jsonResponse["response"]["code"]
|
66
|
+
message = jsonResponse["response"]["message"]
|
67
|
+
UI.error "Response error code #{code} (#{message}) 📟"
|
68
|
+
else
|
69
|
+
UI.error "Bad response 🉐\n#{jsonResponse}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.copy_fr_folder(destination)
|
74
|
+
fr_path = File.join(destination, "fr.lproj")
|
75
|
+
puts fr_path
|
76
|
+
if File.exist?(fr_path)
|
77
|
+
FileUtils.copy_entry(fr_path, File.join(destination, "fr-CA.lproj"))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.unzip_file(file, destination, clean_destination)
|
82
|
+
require 'zip'
|
83
|
+
require 'rubygems'
|
84
|
+
Zip::File.open(file) { |zip_file|
|
85
|
+
if clean_destination then
|
86
|
+
UI.message "Cleaning destination folder ♻️"
|
87
|
+
FileUtils.remove_dir(destination)
|
88
|
+
FileUtils.mkdir_p(destination)
|
89
|
+
end
|
90
|
+
UI.message "Unarchiving localizations to destination 📚"
|
91
|
+
zip_file.each { |f|
|
92
|
+
f_path= File.join(destination, f.name)
|
93
|
+
FileUtils.mkdir_p(File.dirname(f_path))
|
94
|
+
FileUtils.rm(f_path) if File.file? f_path
|
95
|
+
zip_file.extract(f, f_path)
|
96
|
+
}
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
#####################################################
|
102
|
+
# @!group Documentation
|
103
|
+
#####################################################
|
104
|
+
|
105
|
+
def self.description
|
106
|
+
"Download Lokalise localization"
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.available_options
|
110
|
+
[
|
111
|
+
FastlaneCore::ConfigItem.new(key: :api_token,
|
112
|
+
env_name: "LOKALISE_API_TOKEN",
|
113
|
+
description: "API Token for Lokalise",
|
114
|
+
verify_block: proc do |value|
|
115
|
+
UI.user_error! "No API token for Lokalise given, pass using `api_token: 'token'`" unless (value and not value.empty?)
|
116
|
+
end),
|
117
|
+
FastlaneCore::ConfigItem.new(key: :project_identifier,
|
118
|
+
env_name: "LOKALISE_PROJECT_ID",
|
119
|
+
description: "Lokalise Project ID",
|
120
|
+
verify_block: proc do |value|
|
121
|
+
UI.user_error! "No Project Identifier for Lokalise given, pass using `project_identifier: 'identifier'`" unless (value and not value.empty?)
|
122
|
+
end),
|
123
|
+
FastlaneCore::ConfigItem.new(key: :destination,
|
124
|
+
description: "Localization destination",
|
125
|
+
verify_block: proc do |value|
|
126
|
+
UI.user_error! "Things are pretty bad" unless (value and not value.empty?)
|
127
|
+
UI.user_error! "Directory you passed is in your imagination" unless File.directory?(value)
|
128
|
+
end),
|
129
|
+
FastlaneCore::ConfigItem.new(key: :clean_destination,
|
130
|
+
description: "Clean destination folder",
|
131
|
+
optional: true,
|
132
|
+
is_string: false,
|
133
|
+
default_value: false,
|
134
|
+
verify_block: proc do |value|
|
135
|
+
UI.user_error! "Clean destination should be true or false" unless [true, false].include? value
|
136
|
+
end),
|
137
|
+
FastlaneCore::ConfigItem.new(key: :languages,
|
138
|
+
description: "Languages to download",
|
139
|
+
optional: true,
|
140
|
+
is_string: false,
|
141
|
+
verify_block: proc do |value|
|
142
|
+
UI.user_error! "Language codes should be passed as array" unless value.kind_of? Array
|
143
|
+
end),
|
144
|
+
FastlaneCore::ConfigItem.new(key: :include_comments,
|
145
|
+
description: "Include comments in exported files",
|
146
|
+
optional: true,
|
147
|
+
is_string: false,
|
148
|
+
default_value: false,
|
149
|
+
verify_block: proc do |value|
|
150
|
+
UI.user_error! "Include comments should be true or false" unless [true, false].include? value
|
151
|
+
end),
|
152
|
+
FastlaneCore::ConfigItem.new(key: :use_original,
|
153
|
+
description: "Use original filenames/formats (bundle_structure parameter is ignored then)",
|
154
|
+
optional: true,
|
155
|
+
is_string: false,
|
156
|
+
default_value: false,
|
157
|
+
verify_block: proc do |value|
|
158
|
+
UI.user_error! "Use original should be true of false." unless [true, false].include?(value)
|
159
|
+
end),
|
160
|
+
FastlaneCore::ConfigItem.new(key: :tags,
|
161
|
+
description: "Include only the keys tagged with a given set of tags",
|
162
|
+
optional: true,
|
163
|
+
is_string: false,
|
164
|
+
verify_block: proc do |value|
|
165
|
+
UI.user_error! "Tags should be passed as array" unless value.kind_of? Array
|
166
|
+
end),
|
167
|
+
|
168
|
+
]
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.authors
|
172
|
+
"Fedya-L"
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.is_supported?(platform)
|
176
|
+
[:ios, :mac].include? platform
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,624 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
|
4
|
+
class LokaliseMetadataAction < Action
|
5
|
+
@params
|
6
|
+
def self.run(params)
|
7
|
+
@params = params
|
8
|
+
action = params[:action]
|
9
|
+
|
10
|
+
case action
|
11
|
+
when "update_itunes"
|
12
|
+
key_file = metadata_key_file_itunes()
|
13
|
+
metadata = get_metadata_from_lokalise_itunes()
|
14
|
+
run_deliver_action(metadata)
|
15
|
+
when "update_googleplay"
|
16
|
+
release_number = params[:release_number]
|
17
|
+
UI.user_error! "Release number is required when using `update_googleplay` action (should be an integer and greater that 0)" unless (release_number and release_number.is_a?(Integer) and release_number > 0)
|
18
|
+
key_file = metadata_key_file_googleplay
|
19
|
+
metadata = get_metadata_from_lokalise_googleplay()
|
20
|
+
save_metadata_to_files(metadata, release_number)
|
21
|
+
run_supply_action(params[:validate_only])
|
22
|
+
when "update_lokalise_itunes"
|
23
|
+
metadata = get_metadata_itunes_connect()
|
24
|
+
add_languages = params[:add_languages]
|
25
|
+
override_translation = params[:override_translation]
|
26
|
+
if add_languages == true
|
27
|
+
create_languages(metadata.keys, true)
|
28
|
+
end
|
29
|
+
if override_translation == true
|
30
|
+
upload_metadata_itunes(metadata) unless metadata.empty?
|
31
|
+
else
|
32
|
+
lokalise_metadata = get_metadata_from_lokalise_itunes()
|
33
|
+
filtered_metadata = filter_metadata(metadata, lokalise_metadata)
|
34
|
+
upload_metadata_itunes(filtered_metadata) unless filtered_metadata.empty?
|
35
|
+
end
|
36
|
+
when "update_lokalise_googleplay"
|
37
|
+
metadata = get_metadata_google_play()
|
38
|
+
add_languages = params[:add_languages]
|
39
|
+
override_translation = params[:override_translation]
|
40
|
+
if add_languages == true
|
41
|
+
create_languages(metadata.keys, false)
|
42
|
+
end
|
43
|
+
if override_translation == true
|
44
|
+
upload_metadata_google_play(metadata) unless metadata.empty?
|
45
|
+
else
|
46
|
+
lokalise_metadata = get_metadata_from_lokalise_googleplay()
|
47
|
+
filtered_metadata = filter_metadata(metadata, lokalise_metadata)
|
48
|
+
upload_metadata_google_play(filtered_metadata) unless filtered_metadata.empty?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.create_languages(languages, for_itunes)
|
54
|
+
data = {
|
55
|
+
iso: languages.map { |language| fix_language_name(language, for_itunes, true) } .to_json
|
56
|
+
}
|
57
|
+
make_request("language/add", data)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.filter_metadata(metadata, other_metadata)
|
61
|
+
filtered_metadata = {}
|
62
|
+
metadata.each { |language, translations|
|
63
|
+
other_translations = other_metadata[language]
|
64
|
+
filtered_translations = {}
|
65
|
+
|
66
|
+
if other_translations != nil && other_translations.empty? == false
|
67
|
+
translations.each { |key, value|
|
68
|
+
other_value = other_translations[key]
|
69
|
+
filtered_translations[key] = value unless other_value != nil && other_value.empty? == false
|
70
|
+
}
|
71
|
+
else
|
72
|
+
filtered_translations = translations
|
73
|
+
end
|
74
|
+
|
75
|
+
filtered_metadata[language] = filtered_translations unless filtered_translations.empty?
|
76
|
+
}
|
77
|
+
return filtered_metadata
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def self.run_deliver_action(metadata)
|
82
|
+
config = FastlaneCore::Configuration.create(Actions::DeliverAction.available_options, {})
|
83
|
+
config.load_configuration_file("Deliverfile")
|
84
|
+
config[:metadata_path] = "./fastlane/no_metadata"
|
85
|
+
config[:screenshots_path] = "./fastlane/no_screenshot"
|
86
|
+
config[:skip_screenshots] = true
|
87
|
+
config[:run_precheck_before_submit] = false
|
88
|
+
config[:skip_binary_upload] = true
|
89
|
+
config[:skip_app_version_update] = true
|
90
|
+
config[:force] = true
|
91
|
+
|
92
|
+
metadata_key_file_itunes().each { |key, parameter|
|
93
|
+
final_translations = {}
|
94
|
+
|
95
|
+
metadata.each { |lang, translations|
|
96
|
+
if translations.empty? == false
|
97
|
+
translation = translations[key]
|
98
|
+
final_translations[lang] = translation if translation != nil && translation.empty? == false
|
99
|
+
end
|
100
|
+
}
|
101
|
+
|
102
|
+
config[parameter.to_sym] = final_translations
|
103
|
+
}
|
104
|
+
|
105
|
+
Actions::DeliverAction.run(config)
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.run_supply_action(validate_only)
|
109
|
+
config = FastlaneCore::Configuration.create(Actions::SupplyAction.available_options, {})
|
110
|
+
config[:skip_upload_apk] = true
|
111
|
+
config[:skip_upload_aab] = true
|
112
|
+
config[:skip_upload_screenshots] = true
|
113
|
+
config[:skip_upload_images] = true
|
114
|
+
config[:validate_only] = validate_only
|
115
|
+
|
116
|
+
Actions::SupplyAction.run(config)
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.save_metadata_to_files(metadata, release_number)
|
120
|
+
|
121
|
+
translations = {}
|
122
|
+
|
123
|
+
metadata_key_file_googleplay().each { |key, parameter|
|
124
|
+
final_translations = {}
|
125
|
+
|
126
|
+
metadata.each { |lang, translations|
|
127
|
+
if translations.empty? == false
|
128
|
+
translation = translations[key]
|
129
|
+
final_translations[lang] = translation if translation != nil && translation.empty? == false
|
130
|
+
end
|
131
|
+
}
|
132
|
+
|
133
|
+
translations[parameter.to_sym] = final_translations
|
134
|
+
}
|
135
|
+
|
136
|
+
FileUtils.rm_rf(Dir['fastlane/metadata/android/*'])
|
137
|
+
|
138
|
+
translations.each { |key, parameter|
|
139
|
+
parameter.each { |lang, text|
|
140
|
+
path = "fastlane/metadata/android/#{lang}/#{key}.txt"
|
141
|
+
if "#{key}" == "changelogs"
|
142
|
+
path = "fastlane/metadata/android/#{lang}/changelogs/#{release_number}.txt"
|
143
|
+
end
|
144
|
+
dirname = File.dirname(path)
|
145
|
+
unless File.directory?(dirname)
|
146
|
+
FileUtils.mkdir_p(dirname)
|
147
|
+
end
|
148
|
+
File.write(path, text)
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.make_request(path, data)
|
155
|
+
require 'net/http'
|
156
|
+
|
157
|
+
request_data = {
|
158
|
+
api_token: @params[:api_token],
|
159
|
+
id: @params[:project_identifier]
|
160
|
+
}.merge(data)
|
161
|
+
|
162
|
+
uri = URI("https://api.lokalise.com/api/#{path}")
|
163
|
+
request = Net::HTTP::Post.new(uri)
|
164
|
+
request.set_form_data(request_data)
|
165
|
+
|
166
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
167
|
+
http.use_ssl = true
|
168
|
+
response = http.request(request)
|
169
|
+
|
170
|
+
jsonResponse = JSON.parse(response.body)
|
171
|
+
raise "Bad response 🉐\n#{response.body}" unless jsonResponse.kind_of? Hash
|
172
|
+
if jsonResponse["response"]["status"] == "success" then
|
173
|
+
UI.success "Response #{jsonResponse} 🚀"
|
174
|
+
elsif jsonResponse["response"]["status"] == "error"
|
175
|
+
code = jsonResponse["response"]["code"]
|
176
|
+
message = jsonResponse["response"]["message"]
|
177
|
+
raise "Response error code #{code} (#{message}) 📟"
|
178
|
+
else
|
179
|
+
raise "Bad response 🉐\n#{jsonResponse}"
|
180
|
+
end
|
181
|
+
return jsonResponse
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.upload_metadata(metadata_keys, for_itunes, metadata)
|
185
|
+
|
186
|
+
keys = []
|
187
|
+
|
188
|
+
metadata_keys.each do |key, value|
|
189
|
+
key = make_key_object_from_metadata(key, metadata, for_itunes)
|
190
|
+
if key
|
191
|
+
keys << key
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
data = {
|
196
|
+
data: keys.to_json
|
197
|
+
}
|
198
|
+
|
199
|
+
make_request("string/set", data)
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.upload_metadata_itunes(metadata)
|
203
|
+
upload_metadata(metadata_key_file_itunes, true, metadata)
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.upload_metadata_google_play(metadata)
|
207
|
+
upload_metadata(metadata_key_file_googleplay, false, metadata)
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.make_key_object_from_metadata(key, metadata, for_itunes)
|
211
|
+
key_data = {
|
212
|
+
"key" => key,
|
213
|
+
"platform_mask" => 16,
|
214
|
+
"translations" => {}
|
215
|
+
}
|
216
|
+
metadata.each { |iso_code, data|
|
217
|
+
translation = data[key]
|
218
|
+
unless translation == nil || translation.empty?
|
219
|
+
key_data["translations"][fix_language_name(iso_code, for_itunes, true)] = translation
|
220
|
+
end
|
221
|
+
}
|
222
|
+
unless key_data["translations"].empty?
|
223
|
+
return key_data
|
224
|
+
else
|
225
|
+
return nil
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.get_metadata_google_play()
|
230
|
+
available_languages = google_play_languages
|
231
|
+
return get_metadata(available_languages, "fastlane/metadata/android/", false)
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.get_metadata_itunes_connect()
|
235
|
+
available_languages = itunes_connect_languages
|
236
|
+
return get_metadata(available_languages, "fastlane/metadata/", true)
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.get_metadata(available_languages, folder, for_itunes)
|
240
|
+
complete_metadata = {}
|
241
|
+
|
242
|
+
available_languages.each { |iso_code|
|
243
|
+
language_directory = "#{folder}#{iso_code}"
|
244
|
+
if Dir.exist? language_directory
|
245
|
+
language_metadata = {}
|
246
|
+
if for_itunes
|
247
|
+
metadata_key_file_itunes().each { |key, file|
|
248
|
+
populate_hash_key_from_file(language_metadata, key, language_directory + "/#{file}.txt")
|
249
|
+
}
|
250
|
+
else
|
251
|
+
metadata_key_file_googleplay().each { |key, file|
|
252
|
+
if file == "changelogs"
|
253
|
+
changelog_directory = "#{folder}#{iso_code}/changelogs"
|
254
|
+
files = Dir.entries("#{changelog_directory}")
|
255
|
+
collectedFiles = files.collect { |s| s.partition(".").first.to_i }
|
256
|
+
sortedFiles = collectedFiles.sort
|
257
|
+
populate_hash_key_from_file(language_metadata, key, language_directory + "/changelogs/#{sortedFiles.last}.txt")
|
258
|
+
else
|
259
|
+
populate_hash_key_from_file(language_metadata, key, language_directory + "/#{file}.txt")
|
260
|
+
end
|
261
|
+
}
|
262
|
+
end
|
263
|
+
complete_metadata[iso_code] = language_metadata
|
264
|
+
end
|
265
|
+
}
|
266
|
+
|
267
|
+
return complete_metadata
|
268
|
+
end
|
269
|
+
|
270
|
+
def self.get_metadata_from_lokalise(valid_keys, for_itunes)
|
271
|
+
|
272
|
+
data = {
|
273
|
+
platform_mask: 16,
|
274
|
+
keys: valid_keys.to_json,
|
275
|
+
}
|
276
|
+
|
277
|
+
response = make_request("string/list", data)
|
278
|
+
|
279
|
+
if for_itunes
|
280
|
+
valid_languages = itunes_connect_languages_in_lokalise()
|
281
|
+
else
|
282
|
+
valid_languages = google_play_languages_in_lokalise()
|
283
|
+
end
|
284
|
+
metadata = {}
|
285
|
+
|
286
|
+
response["strings"].each { |lang, translation_objects|
|
287
|
+
if valid_languages.include?(lang)
|
288
|
+
translations = {}
|
289
|
+
translation_objects.each { |object|
|
290
|
+
key = object["key"]
|
291
|
+
translation = object["translation"]
|
292
|
+
if valid_keys.include?(key) && translation != nil && translation.empty? == false
|
293
|
+
translations[key] = translation
|
294
|
+
end
|
295
|
+
}
|
296
|
+
if translations.empty? == false
|
297
|
+
metadata[fix_language_name(lang, for_itunes)] = translations
|
298
|
+
end
|
299
|
+
end
|
300
|
+
}
|
301
|
+
return metadata
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
def self.get_metadata_from_lokalise_itunes()
|
306
|
+
|
307
|
+
valid_keys = metadata_keys_itunes()
|
308
|
+
return get_metadata_from_lokalise(valid_keys, true)
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.get_metadata_from_lokalise_googleplay()
|
313
|
+
|
314
|
+
valid_keys = metadata_keys_googleplay()
|
315
|
+
return get_metadata_from_lokalise(valid_keys, false)
|
316
|
+
|
317
|
+
end
|
318
|
+
|
319
|
+
def self.populate_hash_key_from_file(hash, key, filepath)
|
320
|
+
begin
|
321
|
+
text = File.read filepath
|
322
|
+
text.chomp!
|
323
|
+
hash[key] = text unless text.empty?
|
324
|
+
rescue => exception
|
325
|
+
raise exception
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def self.metadata_keys_itunes()
|
330
|
+
return metadata_key_file_itunes().keys
|
331
|
+
end
|
332
|
+
|
333
|
+
def self.metadata_keys_googleplay()
|
334
|
+
return metadata_key_file_googleplay().keys
|
335
|
+
end
|
336
|
+
|
337
|
+
def self.metadata_key_file_itunes()
|
338
|
+
return {
|
339
|
+
"appstore.app.name" => "name",
|
340
|
+
"appstore.app.description" => "description",
|
341
|
+
"appstore.app.keywords" => "keywords",
|
342
|
+
"appstore.app.promotional_text" => "promotional_text",
|
343
|
+
"appstore.app.release_notes" => "release_notes",
|
344
|
+
"appstore.app.subtitle" => "subtitle",
|
345
|
+
}
|
346
|
+
end
|
347
|
+
|
348
|
+
def self.metadata_key_file_googleplay()
|
349
|
+
return {
|
350
|
+
"googleplay.app.title" => "title",
|
351
|
+
"googleplay.app.full_description" => "full_description",
|
352
|
+
"googleplay.app.short_description" => "short_description",
|
353
|
+
"googleplay.app.changelogs" => "changelogs",
|
354
|
+
}
|
355
|
+
end
|
356
|
+
|
357
|
+
def self.itunes_connect_languages_in_lokalise()
|
358
|
+
return itunes_connect_languages().map { |lang|
|
359
|
+
fix_language_name(lang, true, true)
|
360
|
+
}
|
361
|
+
end
|
362
|
+
|
363
|
+
def self.google_play_languages_in_lokalise()
|
364
|
+
return google_play_languages().map { |lang|
|
365
|
+
fix_language_name(lang, false, true)
|
366
|
+
}
|
367
|
+
end
|
368
|
+
|
369
|
+
def self.itunes_connect_languages()
|
370
|
+
return [
|
371
|
+
"en-US",
|
372
|
+
"zh-Hans",
|
373
|
+
"zh-Hant",
|
374
|
+
"da",
|
375
|
+
"nl-NL",
|
376
|
+
"en-AU",
|
377
|
+
"en-CA",
|
378
|
+
"en-GB",
|
379
|
+
"fi",
|
380
|
+
"fr-FR",
|
381
|
+
"fr-CA",
|
382
|
+
"de-DE",
|
383
|
+
"el",
|
384
|
+
"id",
|
385
|
+
"it",
|
386
|
+
"ja",
|
387
|
+
"ko",
|
388
|
+
"ms",
|
389
|
+
"no",
|
390
|
+
"pt-BR",
|
391
|
+
"pt-PT",
|
392
|
+
"ru",
|
393
|
+
"es-MX",
|
394
|
+
"es-ES",
|
395
|
+
"sv",
|
396
|
+
"th",
|
397
|
+
"tr",
|
398
|
+
"vi"
|
399
|
+
]
|
400
|
+
end
|
401
|
+
|
402
|
+
def self.google_play_languages()
|
403
|
+
return [
|
404
|
+
'af',
|
405
|
+
'am',
|
406
|
+
'ar',
|
407
|
+
'hy',
|
408
|
+
'az-AZ',
|
409
|
+
'eu-ES',
|
410
|
+
'be',
|
411
|
+
'bn-BD',
|
412
|
+
'bg',
|
413
|
+
'my',
|
414
|
+
'ca',
|
415
|
+
'zh-CN',
|
416
|
+
'zh-TW',
|
417
|
+
'zh-HK',
|
418
|
+
'hr',
|
419
|
+
'cs',
|
420
|
+
'da',
|
421
|
+
'nl-NL',
|
422
|
+
'en-AU',
|
423
|
+
'en-CA',
|
424
|
+
'en-IN',
|
425
|
+
'en-SG',
|
426
|
+
'en-ZA',
|
427
|
+
'en-GB',
|
428
|
+
'en-US',
|
429
|
+
'et-EE',
|
430
|
+
'fil',
|
431
|
+
'fi',
|
432
|
+
'fr-CA',
|
433
|
+
'fr-FR',
|
434
|
+
'gl-ES',
|
435
|
+
'ka-GE',
|
436
|
+
'de-DE',
|
437
|
+
'el-GR',
|
438
|
+
'he',
|
439
|
+
'hi-IN',
|
440
|
+
'hu',
|
441
|
+
'is-IS',
|
442
|
+
'id',
|
443
|
+
'it-IT',
|
444
|
+
'ja',
|
445
|
+
'kn-IN',
|
446
|
+
'km-KH',
|
447
|
+
'ko',
|
448
|
+
'ky',
|
449
|
+
'lo',
|
450
|
+
'lv-LV',
|
451
|
+
'lt-LT',
|
452
|
+
'mk-MK',
|
453
|
+
'ms',
|
454
|
+
'ml-IN',
|
455
|
+
'mr',
|
456
|
+
'mn-MN',
|
457
|
+
'ne-NP',
|
458
|
+
'no',
|
459
|
+
'fa',
|
460
|
+
'pl',
|
461
|
+
'pt-BR',
|
462
|
+
'pt-PT',
|
463
|
+
'ro',
|
464
|
+
'ru-RU',
|
465
|
+
'sr',
|
466
|
+
'si',
|
467
|
+
'sk',
|
468
|
+
'sl-SI',
|
469
|
+
'es-419',
|
470
|
+
'es-ES',
|
471
|
+
'es-US',
|
472
|
+
'sw',
|
473
|
+
'sv-SE',
|
474
|
+
'ta-IN',
|
475
|
+
'te-IN',
|
476
|
+
'th',
|
477
|
+
'tr',
|
478
|
+
'uk',
|
479
|
+
'vi',
|
480
|
+
'zu'
|
481
|
+
]
|
482
|
+
end
|
483
|
+
|
484
|
+
def self.fix_language_name(name, for_itunes, for_lokalise = false)
|
485
|
+
if for_itunes
|
486
|
+
if for_lokalise
|
487
|
+
name = name.gsub("-","_")
|
488
|
+
name = "en" if name == "en_US"
|
489
|
+
name = "de" if name == "de_DE"
|
490
|
+
name = "es" if name == "es_ES"
|
491
|
+
name = "fr" if name == "fr_FR"
|
492
|
+
else
|
493
|
+
name = name.gsub("_","-")
|
494
|
+
name = "en-US" if name == "en"
|
495
|
+
name = "de-DE" if name == "de"
|
496
|
+
name = "es-ES" if name == "es"
|
497
|
+
name = "fr-FR" if name == "fr"
|
498
|
+
end
|
499
|
+
else
|
500
|
+
if for_lokalise
|
501
|
+
name = name.gsub("-","_")
|
502
|
+
name = "tr" if name == "tr_TR"
|
503
|
+
name = "hy" if name == "hy_AM"
|
504
|
+
name = "my" if name == "my_MM"
|
505
|
+
name = "ms" if name == "ms_MY"
|
506
|
+
name = "cs" if name == "cs_CZ"
|
507
|
+
name = "da" if name == "da_DK"
|
508
|
+
name = "et_EE" if name == "et"
|
509
|
+
name = "fi" if name == "fi_FI"
|
510
|
+
name = "he" if name == "iw_IL"
|
511
|
+
name = "hu" if name == "hu_HU"
|
512
|
+
name = "ja" if name == "ja_JP"
|
513
|
+
name = "ko" if name == "ko_KR"
|
514
|
+
name = "ky" if name == "ky_KG"
|
515
|
+
name = "lo" if name == "lo_LA"
|
516
|
+
name = "lv_LV" if name == "lv"
|
517
|
+
name = "lt_LT" if name == "lt"
|
518
|
+
name = "mr" if name == "mr_IN"
|
519
|
+
name = "no" if name == "no_NO"
|
520
|
+
name = "pl" if name == "pl_PL"
|
521
|
+
name = "si" if name == "si_LK"
|
522
|
+
name = "sl_SI" if name == "sl"
|
523
|
+
else
|
524
|
+
name = name.gsub("_","-")
|
525
|
+
name = "tr-TR" if name == "tr"
|
526
|
+
name = "hy-AM" if name == "hy"
|
527
|
+
name = "my-MM" if name == "my"
|
528
|
+
name = "ms-MY" if name == "ms"
|
529
|
+
name = "cs-CZ" if name == "cs"
|
530
|
+
name = "da-DK" if name == "da"
|
531
|
+
name = "et" if name == "et-EE"
|
532
|
+
name = "fi-FI" if name == "fi"
|
533
|
+
name = "iw-IL" if name == "he"
|
534
|
+
name = "hu-HU" if name == "hu"
|
535
|
+
name = "ja-JP" if name == "ja"
|
536
|
+
name = "ko-KR" if name == "ko"
|
537
|
+
name = "ky-KG" if name == "ky"
|
538
|
+
name = "lo-LA" if name == "lo"
|
539
|
+
name = "lv" if name == "lv-LV"
|
540
|
+
name = "lt" if name == "lt-LT"
|
541
|
+
name = "mr-IN" if name == "mr"
|
542
|
+
name = "no-NO" if name == "no"
|
543
|
+
name = "pl-PL" if name == "pl"
|
544
|
+
name = "si-LK" if name == "si"
|
545
|
+
name = "sl" if name == "sl-SI"
|
546
|
+
end
|
547
|
+
end
|
548
|
+
return name
|
549
|
+
end
|
550
|
+
|
551
|
+
#####################################################
|
552
|
+
# @!group Documentation
|
553
|
+
#####################################################
|
554
|
+
|
555
|
+
def self.description
|
556
|
+
"Upload metadata to lokalise."
|
557
|
+
end
|
558
|
+
|
559
|
+
def self.details
|
560
|
+
"This action scans fastlane/metadata folder and uploads metadata to lokalise.com"
|
561
|
+
end
|
562
|
+
|
563
|
+
def self.available_options
|
564
|
+
[
|
565
|
+
FastlaneCore::ConfigItem.new(key: :api_token,
|
566
|
+
env_name: "LOKALISE_API_TOKEN",
|
567
|
+
description: "API Token for Lokalise",
|
568
|
+
verify_block: proc do |value|
|
569
|
+
UI.user_error! "No API token for Lokalise given, pass using `api_token: 'token'`" unless (value and not value.empty?)
|
570
|
+
end),
|
571
|
+
FastlaneCore::ConfigItem.new(key: :project_identifier,
|
572
|
+
env_name: "LOKALISE_PROJECT_ID",
|
573
|
+
description: "Lokalise Project ID",
|
574
|
+
verify_block: proc do |value|
|
575
|
+
UI.user_error! "No Project Identifier for Lokalise given, pass using `project_identifier: 'identifier'`" unless (value and not value.empty?)
|
576
|
+
end),
|
577
|
+
FastlaneCore::ConfigItem.new(key: :add_languages,
|
578
|
+
description: "Add missing languages in lokalise",
|
579
|
+
optional: true,
|
580
|
+
is_string: false,
|
581
|
+
default_value: false,
|
582
|
+
verify_block: proc do |value|
|
583
|
+
UI.user_error! "Add languages should be true or false" unless [true, false].include? value
|
584
|
+
end),
|
585
|
+
FastlaneCore::ConfigItem.new(key: :override_translation,
|
586
|
+
description: "Override translations in lokalise",
|
587
|
+
optional: true,
|
588
|
+
is_string: false,
|
589
|
+
default_value: false,
|
590
|
+
verify_block: proc do |value|
|
591
|
+
UI.user_error! "Override translation should be true or false" unless [true, false].include? value
|
592
|
+
end),
|
593
|
+
FastlaneCore::ConfigItem.new(key: :action,
|
594
|
+
description: "Action to perform (can be update_lokalise_itunes or update_lokalise_googleplay or update_itunes or update_googleplay)",
|
595
|
+
optional: false,
|
596
|
+
is_string: true,
|
597
|
+
verify_block: proc do |value|
|
598
|
+
UI.user_error! "Action should be update_lokalise_googleplay or update_lokalise_itunes or update_itunes or update_googleplay" unless ["update_lokalise_itunes", "update_lokalise_googleplay", "update_itunes", "update_googleplay"].include? value
|
599
|
+
end),
|
600
|
+
FastlaneCore::ConfigItem.new(key: :release_number,
|
601
|
+
description: "Release number is required to update google play",
|
602
|
+
optional: true,
|
603
|
+
is_string: false),
|
604
|
+
FastlaneCore::ConfigItem.new(key: :validate_only,
|
605
|
+
description: "Only validate the metadata (works with only update_googleplay action)",
|
606
|
+
optional: true,
|
607
|
+
is_string: false,
|
608
|
+
default_value: false,
|
609
|
+
verify_block: proc do |value|
|
610
|
+
UI.user_error! "Validate only should be true or false" unless [true, false].include? value
|
611
|
+
end),
|
612
|
+
]
|
613
|
+
end
|
614
|
+
|
615
|
+
def self.authors
|
616
|
+
["Fedya-L"]
|
617
|
+
end
|
618
|
+
|
619
|
+
def self.is_supported?(platform)
|
620
|
+
platform == :ios
|
621
|
+
end
|
622
|
+
end
|
623
|
+
end
|
624
|
+
end
|