fastlane-plugin-google_sheet_localize 0.1.6 → 0.1.20

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: 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