fastlane-plugin-google_sheet_localize 0.1.6 → 0.1.20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87a4897b4267a2b1ec85e0decd035d4bbcaeec53b481a9c9d672476aad6065b6
4
- data.tar.gz: ea0718e1d745c797e1ccf9c79d08dd299f8848381521652f4a524ad5f2a2ff47
3
+ metadata.gz: 3e981832345e489a2346adcc3901d5fae7700b379b1e02009cca1e55e8ab5fc6
4
+ data.tar.gz: df90ee04b2d43aac2229738b8b06f85426331771730acbbbbd83b036e313b70e
5
5
  SHA512:
6
- metadata.gz: e252a54b79b9728660ad3307d99caaec6500219fd11dbd4ffbf437340a9ae791be4e2879278c2f77fadfb1ecc5c787eac168883f0db2ced044ffeca68d67e031
7
- data.tar.gz: 06e2fbf3ab587f03d94fd915abd7268daabaeef07a3a4bc9738aaf78eb87a48bb940de0ecfc3524ac9a123138cc64f01d8696d592bd2ee915660ec8361a023c8
6
+ metadata.gz: 293d36b523297fd849f035d85709610f9c8760774b64604d47b30480d117a236243c0b0cbe1d78f578af6045989d3857ea6e63fba07717b30e73b24957581577
7
+ data.tar.gz: 1b493e47d984de4e389fefad74eca3692dea3bd9d82eb4b25fb1d6834321a2fb4a8ed8fbe65f8838b0592e57e4d1c49b76b668d67c57102870f1fcc8a014dc67
data/README.md CHANGED
@@ -14,13 +14,30 @@ fastlane add_plugin google_sheet_localize
14
14
 
15
15
  Creates .strings files for iOS and strings.xml files for Android
16
16
 
17
- **Note to author:** Add a more detailed description about this plugin here. If your plugin contains multiple actions, make sure to mention them here.
17
+ to use our plugin you have to duplicate this google sheet: https://docs.google.com/spreadsheets/d/1fwRj1ZFPu2XlrDqkaqmIpJulqR5OVFEZnN35a9v37yc/edit?usp=sharing
18
+
19
+ Google Drive access token:
20
+ https://medium.com/@osanda.deshan/getting-google-oauth-access-token-using-google-apis-18b2ba11a11a
21
+
22
+ * The language_titles (the columns which should be exported)
23
+ * The default_language (If a string is not present in a specific language, this is the fallback)
24
+ * The base_language (The language which is placed in the base values folder)
18
25
 
19
26
  ## Example
20
27
 
21
- Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
28
+ ```ruby
29
+ lane :localize do
30
+ google_sheet_localize(service_account_path: "./fastlane/google_drive_credentials.json",
31
+ sheet_id: "sheet id",
32
+ platform: "ios",
33
+ tabs: ["3TV"], #array of tab titles in google sheet
34
+ localization_path: "./Kit/TVKit",
35
+ language_titles: ["de", "en"], #language titles in google sheet
36
+ default_language: "de", #default language for google sheet
37
+ base_language: "en") #ios: Base.lproj android: values
38
+ end
39
+ ```
22
40
 
23
- **Note to author:** Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary)
24
41
 
25
42
  ## Run tests for this plugin
26
43
 
@@ -15,6 +15,7 @@ module Fastlane
15
15
  path = params[:localization_path]
16
16
  language_titles = params[:language_titles]
17
17
  default_language = params[:default_language]
18
+ base_language = params[:base_language]
18
19
 
19
20
  spreadsheet = session.spreadsheet_by_url(spreadsheet_id)
20
21
  worksheet = spreadsheet.worksheets.first
@@ -48,7 +49,7 @@ module Fastlane
48
49
  result.push(language)
49
50
  end
50
51
  end
51
- self.createFiles(result, platform, path, default_language)
52
+ self.createFiles(result, platform, path, default_language, base_language)
52
53
  end
53
54
 
54
55
  def self.generateJSONObject(contentRows, index)
@@ -82,15 +83,15 @@ module Fastlane
82
83
 
83
84
  end
84
85
 
85
- def filterUnusedRows(items, identifier)
86
+ def self.filterUnusedRows(items, identifier)
86
87
  return items.select { |item|
87
- iosIdentifier = item[identifier]
88
- iosIdentifier != "NR" && iosIdentifier != ""
88
+ currentIdentifier = item[identifier]
89
+ currentIdentifier != "NR" && currentIdentifier != "" && currentIdentifier != "TBD"
89
90
  }
90
91
  end
91
92
 
92
- def self.createFiles(languages, platform, destinationPath, defaultLanguage)
93
- self.createFilesForLanguages(languages, platform, destinationPath, defaultLanguage)
93
+ def self.createFiles(languages, platform, destinationPath, defaultLanguage, base_language)
94
+ self.createFilesForLanguages(languages, platform, destinationPath, defaultLanguage, base_language)
94
95
 
95
96
  if platform == "ios"
96
97
 
@@ -99,27 +100,37 @@ module Fastlane
99
100
 
100
101
  filteredItems = languages[0]["items"].select { |item|
101
102
  iosIdentifier = item['identifierIos']
102
- iosIdentifier != "NR" && iosIdentifier != "" && !iosIdentifier.include?('//')
103
+ iosIdentifier != "NR" && iosIdentifier != "" && !iosIdentifier.include?('//') && iosIdentifier != "TBD"
103
104
  }
104
105
 
105
106
  File.open(swiftFilepath, "w") do |f|
106
- f.write("import Foundation\n\n\npublic struct Localization {\n")
107
+ f.write("import Foundation\n\n// swiftlint:disable all\npublic struct Localization {\n")
107
108
  filteredItems.each { |item|
108
109
 
109
110
  identifier = item['identifierIos']
110
111
 
111
- values = identifier.dup.gsub('.', ' ').split(" ")
112
+ values = identifier.dup.split(".")
112
113
 
113
114
  constantName = ""
114
115
 
115
116
  values.each_with_index do |item, index|
116
117
  if index == 0
117
- constantName += item.downcase
118
+ item[0] = item[0].downcase
119
+ constantName += item
118
120
  else
119
- constantName += item.capitalize
121
+ item[0] = item[0].upcase
122
+ constantName += item
120
123
  end
121
124
  end
122
125
 
126
+ if constantName == "continue"
127
+ constantName = "`continue`"
128
+ end
129
+
130
+ if constantName == "switch"
131
+ constantName = "`switch`"
132
+ end
133
+
123
134
  text = self.mapInvalidPlaceholder(item['text'])
124
135
 
125
136
  arguments = self.findArgumentsInText(text)
@@ -137,7 +148,7 @@ module Fastlane
137
148
  end
138
149
  end
139
150
 
140
- def self.createFilesForLanguages(languages, platform, destinationPath, defaultLanguage)
151
+ def self.createFilesForLanguages(languages, platform, destinationPath, defaultLanguage, base_language)
141
152
 
142
153
  languages.each { |language|
143
154
 
@@ -145,10 +156,20 @@ module Fastlane
145
156
 
146
157
  filteredItems = self.filterUnusedRows(language["items"],'identifierIos')
147
158
 
148
- filename = "Localizable.strings"
149
- filepath = "#{destinationPath}/#{language['language']}.lproj/#{filename}"
150
- FileUtils.mkdir_p "#{destinationPath}/#{language['language']}.lproj"
151
- File.open(filepath, "w") do |f|
159
+ stringFileName = "Localizable.strings"
160
+ pluralsFileName = "Plurals.stringsdict"
161
+
162
+ languageName = language['language']
163
+
164
+ if languageName == base_language
165
+ languageName = "Base"
166
+ end
167
+
168
+ stringFilepath = "#{destinationPath}/#{languageName}.lproj/#{stringFileName}"
169
+ pluralsFilepath = "#{destinationPath}/#{languageName}.lproj/#{pluralsFileName}"
170
+ FileUtils.mkdir_p "#{destinationPath}/#{languageName}.lproj"
171
+
172
+ File.open(stringFilepath, "w") do |f|
152
173
  filteredItems.each_with_index { |item, index|
153
174
 
154
175
  text = self.mapInvalidPlaceholder(item['text'])
@@ -160,32 +181,86 @@ module Fastlane
160
181
  line = "\n\n#{identifier}\n"
161
182
  else
162
183
 
184
+ if !text.include?("one|")
185
+
186
+ if text == "" || text == "TBD"
187
+ default_language_object = languages.select { |languageItem| languageItem['language'] == defaultLanguage }.first["items"]
188
+ default_language_object = self.filterUnusedRows(default_language_object,'identifierIos')
189
+
190
+ defaultLanguageText = default_language_object[index]['text']
191
+ puts "found empty text for:\n\tidentifier: #{identifier}\n\tlanguage:#{language['language']}\n\treplacing it with: #{defaultLanguageText}"
192
+ text = self.mapInvalidPlaceholder(defaultLanguageText)
193
+ end
194
+
195
+ line = "\"#{identifier}\" = \"#{text}\";"
196
+ if !comment.to_s.empty?
197
+ line = line + " //#{comment}\n"
198
+ else
199
+ line = line + "\n"
200
+ end
201
+ end
202
+ end
203
+ f.write(line)
204
+ }
205
+ end
206
+
207
+ File.open(pluralsFilepath, "w") do |f|
208
+
209
+ f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
210
+ f.write("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n")
211
+ f.write("<plist version=\"1.0\">\n")
212
+ f.write("<dict>\n")
213
+
214
+ filteredItems.each_with_index { |item, index|
215
+
216
+ text = self.mapInvalidPlaceholder(item['text'])
217
+ identifier = item['identifierIos']
218
+
219
+ if !identifier.include?('//') && text.include?("one|")
163
220
  if text == "" || text == "TBD"
164
221
  default_language_object = languages.select { |languageItem| languageItem['language'] == defaultLanguage }.first["items"]
165
222
  default_language_object = self.filterUnusedRows(default_language_object,'identifierIos')
166
223
 
167
224
  defaultLanguageText = default_language_object[index]['text']
168
- puts "found empty text for identifier: #{identifier} for language:#{language['language']}, replaceing it with #{defaultLanguageText}"
225
+ puts "found empty text for:\n\tidentifier: #{identifier}\n\tlanguage:#{language['language']}\n\treplacing it with: #{defaultLanguageText}"
169
226
  text = self.mapInvalidPlaceholder(defaultLanguageText)
170
227
  end
171
228
 
172
- line = "\"#{identifier}\" = \"#{text}\";"
173
- if !comment.to_s.empty?
174
- line = line + " //#{comment}\n"
175
- else
176
- line = line + "\n"
177
- end
178
- end
229
+ text = text.gsub("\n", "|")
179
230
 
180
- f.write(line)
231
+ formatIdentifier = identifier.gsub(".", "")
232
+
233
+ f.write("\t\t<key>#{identifier}</key>\n")
234
+ f.write("\t\t<dict>\n")
235
+ f.write("\t\t\t<key>NSStringLocalizedFormatKey</key>\n")
236
+ f.write("\t\t\t<string>%#@#{formatIdentifier}@</string>\n")
237
+ f.write("\t\t\t<key>#{formatIdentifier}</key>\n")
238
+ f.write("\t\t\t<dict>\n")
239
+ f.write("\t\t\t\t<key>NSStringFormatSpecTypeKey</key>\n")
240
+ f.write("\t\t\t\t<string>NSStringPluralRuleType</string>\n")
241
+ f.write("\t\t\t\t<key>NSStringFormatValueTypeKey</key>\n")
242
+ f.write("\t\t\t\t<string>d</string>\n")
243
+
244
+ text.split("|").each_with_index { |word, wordIndex|
245
+ if wordIndex % 2 == 0
246
+ f.write("\t\t\t\t<key>#{word}</key>\n")
247
+ else
248
+ f.write("\t\t\t\t<string>#{word}</string>\n")
249
+ end
250
+ }
251
+ f.write("\t\t\t</dict>\n")
252
+ f.write("\t\t</dict>\n")
253
+ end
181
254
  }
255
+ f.write("</dict>\n")
256
+ f.write("</plist>\n")
182
257
  end
183
258
  end
184
259
 
185
260
  if platform == "android"
186
261
  languageDir = language['language']
187
262
 
188
- if languageDir == "en"
263
+ if languageDir == base_language
189
264
  languageDir = "values"
190
265
  else
191
266
  languageDir = "values-#{languageDir}"
@@ -195,23 +270,54 @@ module Fastlane
195
270
  File.open("#{destinationPath}/#{languageDir}/strings.xml", "w") do |f|
196
271
  f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
197
272
  f.write("<resources>\n")
198
- language["items"].each { |item|
273
+
274
+ filteredItems = self.filterUnusedRows(language["items"],'identifierAndroid')
275
+
276
+ filteredItems.each_with_index { |item, index|
199
277
 
200
278
  comment = item['comment']
201
279
  identifier = item['identifierAndroid']
202
280
  text = item['text']
203
281
 
204
- if !identifier.to_s.empty? && identifier != "NR"
205
- line = ""
282
+ line = ""
206
283
 
207
- if !comment.to_s.empty?
208
- line = line + "\t<!--#{comment}-->\n"
209
- end
284
+ if !comment.to_s.empty?
285
+ line = line + "\t<!--#{comment}-->\n"
286
+ end
210
287
 
211
- line = line + "\t<string name=\"#{identifier}\"><![CDATA[#{text}]]></string>\n"
288
+ if text == "" || text == "TBD"
289
+ default_language_object = languages.select { |languageItem| languageItem['language'] == defaultLanguage }.first["items"]
290
+ default_language_object = self.filterUnusedRows(default_language_object,'identifierAndroid')
212
291
 
213
- f.write(line)
292
+ defaultLanguageText = default_language_object[index]['text']
293
+ puts "found empty text for:\n\tidentifier: #{identifier}\n\tlanguage:#{language['language']}\n\treplacing it with: #{defaultLanguageText}"
294
+ text = defaultLanguageText
214
295
  end
296
+
297
+ text = text.gsub(/\\?'/, "\\\\'")
298
+
299
+ if text.include?("one|")
300
+
301
+ text = text.gsub("\n", "|")
302
+
303
+ line = line + "\t<plurals name=\"#{identifier}\">\n"
304
+
305
+ plural = ""
306
+
307
+ text.split("|").each_with_index { |word, wordIndex|
308
+ if wordIndex % 2 == 0
309
+ plural = "\t\t<item quantity=\"#{word}\">"
310
+ else
311
+ plural = plural + "<![CDATA[\"#{word}\"]]></item>\n"
312
+ line = line + plural
313
+ end
314
+ }
315
+ line = line + "\t</plurals>\n"
316
+ else
317
+ line = line + "\t<string name=\"#{identifier}\"><![CDATA[#{text}]]></string>\n"
318
+ end
319
+
320
+ f.write(line)
215
321
  }
216
322
  f.write("</resources>\n")
217
323
  end
@@ -220,14 +326,13 @@ module Fastlane
220
326
  end
221
327
 
222
328
  def self.createiOSFileEndString()
223
- return "\n\nextension Localization {\n\tprivate static func localized(identifier key: String, _ args: CVarArg...) -> String {\n\t\tlet format = NSLocalizedString(key, tableName: nil, bundle: Bundle.main, comment: \"\")\n\n\t\tguard !args.isEmpty else { return format }\n\n\t\treturn String(format: format, locale: Locale.current, arguments: args)\n\t}\n}"
329
+ return "\n\nprivate class LocalizationHelper { }\n\nextension Localization {\n\tprivate static func localized(identifier key: String, _ args: CVarArg...) -> String {\n\t\tlet format = NSLocalizedString(key, tableName: nil, bundle: Bundle(for: LocalizationHelper.self), comment: \"\")\n\n\t\tguard !args.isEmpty else { return format }\n\n\t\treturn String(format: format, locale: .current, arguments: args)\n\t}\n}"
224
330
  end
225
331
 
226
332
  def self.createiOSFunction(constantName, identifier, arguments, comment)
227
333
  functionTitle = "\n\t///Sheet comment: #{comment}\n\tpublic static func #{constantName}("
228
334
 
229
335
  arguments.each_with_index do |item, index|
230
- puts item
231
336
  functionTitle = functionTitle + "_ arg#{index}: #{item[:type]}"
232
337
  if index < arguments.count - 1
233
338
  functionTitle = functionTitle + ", "
@@ -249,6 +354,11 @@ module Fastlane
249
354
  end
250
355
 
251
356
  def self.findArgumentsInText(text)
357
+
358
+ if text.include?("one|")
359
+ text = text.dup.split("|")[1]
360
+ end
361
+
252
362
  result = Array.new
253
363
  filtered = self.mapInvalidPlaceholder(text)
254
364
 
@@ -319,7 +429,8 @@ module Fastlane
319
429
  FastlaneCore::ConfigItem.new(key: :tabs,
320
430
  env_name: "TABS",
321
431
  description: "Array of all Google Sheet Tabs",
322
- optional: false,
432
+ default_value: [],
433
+ optional: true,
323
434
  type: Array),
324
435
  FastlaneCore::ConfigItem.new(key: :language_titles,
325
436
  env_name: "LANGUAGE_TITLES",
@@ -331,6 +442,11 @@ module Fastlane
331
442
  description: "Default Language",
332
443
  optional: false,
333
444
  type: String),
445
+ FastlaneCore::ConfigItem.new(key: :base_language,
446
+ env_name: "BASE_LANGUAGE",
447
+ description: "Base language for Xcode projects",
448
+ optional: true,
449
+ type: String),
334
450
  FastlaneCore::ConfigItem.new(key: :localization_path,
335
451
  env_name: "LOCALIZATION_PATH",
336
452
  description: "Output path",
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module GoogleSheetLocalize
3
- VERSION = "0.1.6"
3
+ VERSION = "0.1.20"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-google_sheet_localize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Hahn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-05 00:00:00.000000000 Z
11
+ date: 2019-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: google_drive
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: pry
15
29
  requirement: !ruby/object:Gem::Requirement