ad_localize 3.4.0 → 3.5.0

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: a4a46683de0e489838b53aae0ddd3a4e7e52a0089013fac5b49a07a558bfd322
4
- data.tar.gz: 11523ebff556f015ae9e0a7ec76bf50f75d9317b9fd272e2f0b28e84ae0a070d
3
+ metadata.gz: e814ce7a840c1c9da11fc1f34574929e7ad4805f410319b3c6f79e8f8027024e
4
+ data.tar.gz: 65864cb313e53121a7d9fc06028f944853f3842ee3eb060b7ccdff099b3477a2
5
5
  SHA512:
6
- metadata.gz: 7432f6a5dd72d4635b3c07215ffb2d7afe357a5f93aca0d04635c20c15494571d580af9572ce38b0805afb1762d714dc73ef71ae8f5bd855ebfdfb8dbe9eef0d
7
- data.tar.gz: 5e726801cb6f26bf2c58787297a1e0639cd403f7d9d22c3a8ce82d04fb65a8e3d8cd3b6a94cf1057f9d0b32ebcab9d79ba00867f50d3add3815cd450b945b097
6
+ metadata.gz: f84b9f8ef16b073e98c4e41a87575e35c5881586e1bebe44c226005bbdcf3b9704bc6b869ae4cb6fb4162866560a2e6c69e154b505b058f6923d852093ba1624
7
+ data.tar.gz: 02fe755026fad1ef4bca910a6457ef7d2806b40077fe3acbfc4d7b469372b7382bb7c98098c3220d6fc977cef40255e2c3cf85cc8f927cc1b3f78d9bf7ff31b7
@@ -1,6 +1,6 @@
1
1
  name: Ruby
2
2
 
3
- on: [push]
3
+ on: [push, pull_request]
4
4
 
5
5
  jobs:
6
6
  build:
data/.gitignore CHANGED
@@ -9,4 +9,5 @@ ad_localize/tmp/
9
9
  .idea
10
10
  .byebug_history
11
11
  .ruby-version
12
-
12
+ pkg/
13
+ exports/
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [3.5.0] - 2020-05-12
8
+ ### Added
9
+ - add support for private spreadsheet using google service acccount by [@sjcqs](https://github.com/sjcqs). Fixes [#31](https://github.com/applidium/ad_localize/issues/31)
10
+ - add makefile for easier testing by [@felginep](https://github.com/felginep)
11
+
12
+ ### Changed
13
+ - improve error message to have useful information in case of google spreadsheet use by [@felginep](https://github.com/felginep). Fixes [#27](https://github.com/applidium/ad_localize/issues/27)
14
+ - platform folder is no longer generated when there is only one platform selected. The files are directly generated in the output path. By [@felginep](https://github.com/felginep). Fixes [#29](https://github.com/applidium/ad_localize/issues/29)
15
+ - raise error when google spreadsheet key is invalid by [@felginep](https://github.com/felginep)
16
+
17
+ ### Fixed
18
+ - auto escape strings in Localizable.strings by [@felginep](https://github.com/felginep). Fixes [#26](https://github.com/applidium/ad_localize/issues/26)
19
+ - trim keys to prevent user error by [@felginep](https://github.com/felginep). Fixes [#16](https://github.com/applidium/ad_localize/issues/16)
20
+
7
21
  ## [3.4.0] - 2019-02-10
8
22
  ### Added
9
23
  - Rails folks, [@epaillous](https://github.com/epaillous) has improved the YAML support. You can now have multi-level wording.
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ad_localize (3.4.0)
5
+ activesupport (>= 4.2.10)
6
+ colorize (~> 0.8)
7
+ googleauth (~> 0.12.0)
8
+ nokogiri (~> 1.8, >= 1.8.2)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (6.0.2.2)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ zeitwerk (~> 2.2)
19
+ addressable (2.7.0)
20
+ public_suffix (>= 2.0.2, < 5.0)
21
+ ansi (1.5.0)
22
+ builder (3.2.4)
23
+ byebug (11.1.3)
24
+ colorize (0.8.1)
25
+ concurrent-ruby (1.1.6)
26
+ diffy (3.3.0)
27
+ faraday (0.17.3)
28
+ multipart-post (>= 1.2, < 3)
29
+ googleauth (0.12.0)
30
+ faraday (>= 0.17.3, < 2.0)
31
+ jwt (>= 1.4, < 3.0)
32
+ memoist (~> 0.16)
33
+ multi_json (~> 1.11)
34
+ os (>= 0.9, < 2.0)
35
+ signet (~> 0.14)
36
+ i18n (1.8.2)
37
+ concurrent-ruby (~> 1.0)
38
+ jwt (2.1.0)
39
+ memoist (0.16.2)
40
+ mini_portile2 (2.4.0)
41
+ minitest (5.14.0)
42
+ minitest-reporters (1.4.2)
43
+ ansi
44
+ builder
45
+ minitest (>= 5.0)
46
+ ruby-progressbar
47
+ multi_json (1.14.1)
48
+ multipart-post (2.0.0)
49
+ nokogiri (1.10.9)
50
+ mini_portile2 (~> 2.4.0)
51
+ os (1.1.0)
52
+ public_suffix (2.0.5)
53
+ rake (12.3.3)
54
+ ruby-progressbar (1.10.1)
55
+ signet (0.14.0)
56
+ addressable (~> 2.3)
57
+ faraday (>= 0.17.3, < 2.0)
58
+ jwt (>= 1.5, < 3.0)
59
+ multi_json (~> 1.10)
60
+ thread_safe (0.3.6)
61
+ tzinfo (1.2.7)
62
+ thread_safe (~> 0.1)
63
+ zeitwerk (2.3.0)
64
+
65
+ PLATFORMS
66
+ ruby
67
+
68
+ DEPENDENCIES
69
+ ad_localize!
70
+ bundler (>= 1.12.0, < 3.0.0)
71
+ byebug (~> 11.0)
72
+ diffy (~> 3.3)
73
+ minitest (~> 5.11)
74
+ minitest-reporters (~> 1.3)
75
+ rake (~> 12.3)
76
+
77
+ BUNDLED WITH
78
+ 2.1.4
@@ -0,0 +1,11 @@
1
+ build:
2
+ gem build ad_localize.gemspec
3
+
4
+ install: clean build
5
+ gem install ad_localize-*.gem
6
+
7
+ clean:
8
+ rm -f ad_localize-*.gem
9
+
10
+ tests:
11
+ bundle exec rake test
data/README.md CHANGED
@@ -29,15 +29,22 @@ $ gem install ad_localize
29
29
  $ bundle exec ad_localize -h
30
30
  ```
31
31
 
32
- * Export wording from a google drive spreadsheet, using the file key
32
+ * Export wording from a google spreadsheet, using the file key. Make sure to enable _Allow external access_ in sharing options.
33
33
  ```
34
34
  $ bundle exec ad_localize -k <your-spreadsheet-drive-key>
35
35
  ```
36
- * Export wording from a google drive spreadsheet, using the file key and specifying a sheet (useful when your file has multiple sheets)
36
+
37
+ * Export wording from a google spreadsheet, using the file key and specifying a sheet (useful when your file has multiple sheets)
37
38
  ```
38
39
  $ bundle exec ad_localize -k <your-spreadsheet-drive-key> -s <your-specific-sheet-id>
39
40
  ```
40
41
 
42
+ * Export wording from a private google spreadsheet using an authorized google account
43
+ ```
44
+ $ export GCLOUD_CLIENT_SECRET=$(cat <client-secret.json>)
45
+ $ bundle exec ad_localize -k <your-spreadsheet-drive-key> -a
46
+ ```
47
+
41
48
  * Only generate wording files for the specified platforms
42
49
  ```
43
50
  $ bundle exec ad_localize -o ios
@@ -62,10 +69,11 @@ $ bundle exec ad_localize -d
62
69
  | favorites | Mes favoris | My favorites |
63
70
  | from_to | du %1$@ au %2$@ | from %1$@ to %2$@ |
64
71
 
65
- - Any column after the `key` column will be considered as a locale column (except from the optional `comment columns)
72
+ - Any column after the `key` column will be considered as a locale column (except from the optional `comment columns)
66
73
  - Keys should be written in Android format : [a-z0-9_]+
67
74
  - Format specifiers must be numeroted if there are more than one in a translation string (eg: "%1$@ %2$@'s report").
68
75
 
76
+
69
77
  #### Comment columns
70
78
 
71
79
  In iOS (and only iOS) you can add a comment to a missing translation.
@@ -111,6 +119,8 @@ exports/
111
119
  └── fr.yml
112
120
  ```
113
121
 
122
+ NB: If you select only one platform, the wording files will directly be generated in the output path. The output path is the `exports` folder in the current directory by default and you can change it using the option `-o`.
123
+
114
124
  ## Plurals
115
125
 
116
126
  Plurals are supported for iOS and Android.
@@ -19,14 +19,16 @@ Gem::Specification.new do |spec|
19
19
  'Nicolas Braun',
20
20
  'Corentin Huard',
21
21
  'Claire Peyron',
22
- 'Claire Dufetrelle'
22
+ 'Claire Dufetrelle',
23
+ 'Pierre Felgines',
24
+ 'Satyan Jacquens'
23
25
  ]
24
26
  spec.email = %w(joanna.vigne@fabernovel.com hugo.hache@fabernovel.com edouard.siegel@fabernovel.com)
25
27
 
26
28
  spec.summary = %q{AdLocalize helps with mobile and web applications wording}
27
29
  spec.description = %q{AdLocalize produces localization files from platform agnostic wording.
28
30
  Supported wording format : CSV. Supported export format: iOS, Android, JSON and YAML}
29
- spec.homepage = 'https://technologies.fabernovel.com'
31
+ spec.homepage = 'https://github.com/applidium/ad_localize'
30
32
 
31
33
  # Specify which files should be added to the gem when it is released.
32
34
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -44,9 +46,10 @@ Gem::Specification.new do |spec|
44
46
  spec.add_development_dependency 'minitest-reporters', '~> 1.3'
45
47
  spec.add_development_dependency 'diffy', '~> 3.3'
46
48
 
47
- spec.add_dependency 'activesupport', '>= 4.2.10'
48
- spec.add_dependency 'nokogiri', '~> 1.8', '>= 1.8.2'
49
+ spec.add_dependency 'activesupport', '~> 5.2'
50
+ spec.add_dependency 'nokogiri', '~> 1.10'
49
51
  spec.add_dependency 'colorize', '~> 0.8'
52
+ spec.add_dependency 'googleauth', '~> 0.12'
50
53
 
51
54
  spec.required_ruby_version = '~> 2.3'
52
55
  end
@@ -8,6 +8,8 @@ require 'csv'
8
8
  require 'logger'
9
9
  require 'colorize'
10
10
  require 'open-uri'
11
+ require 'stringio'
12
+ require 'googleauth'
11
13
  require 'optparse'
12
14
  require 'nokogiri'
13
15
 
@@ -8,13 +8,20 @@ module AdLocalize
8
8
  end
9
9
 
10
10
  # Returns the downloaded file name (it is located in the current directory)
11
- def download_from_drive(key, sheet)
11
+ def download_from_drive(key, sheet, use_service_account=false)
12
12
  LOGGER.log(:info, :green, "Downloading file from google drive...")
13
13
  download_string_path = "./#{key}.csv"
14
14
  begin
15
15
  File.open(download_string_path, "wb") do |saved_file|
16
+ download_url = drive_download_url(key, sheet)
17
+ headers = {}
18
+ if use_service_account
19
+ LOGGER.log(:debug, :green, "Using a service account...")
20
+ token = service_account_access_token()
21
+ headers["Authorization"] = "#{token["token_type"]} #{token["access_token"]}"
22
+ end
16
23
  # the following "open" is provided by open-uri
17
- open(drive_download_url(key, sheet), "rb") do |read_file|
24
+ open(download_url, "rb", headers) do |read_file|
18
25
  saved_file.write(read_file.read)
19
26
  end
20
27
  File.basename saved_file
@@ -42,6 +49,16 @@ module AdLocalize
42
49
  query_id = sheet ? "gid=#{sheet}" : "id=#{key}"
43
50
  "https://docs.google.com/spreadsheets/d/#{key}/export?format=csv&#{query_id}"
44
51
  end
52
+ private
53
+ def service_account_access_token()
54
+ scope = "https://www.googleapis.com/auth/drive.readonly"
55
+ json_key_io = StringIO.new ENV["GCLOUD_CLIENT_SECRET"]
56
+ authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
57
+ json_key_io: json_key_io,
58
+ scope: scope
59
+ )
60
+ authorizer.fetch_access_token!
61
+ end
45
62
  end
46
63
  end
47
64
  end
@@ -99,7 +99,7 @@ module AdLocalize
99
99
  end
100
100
 
101
101
  def parse_key(row)
102
- key = row.field(CSV_WORDING_KEYS_COLUMN)
102
+ key = row.field(CSV_WORDING_KEYS_COLUMN).strip
103
103
  plural_prefix = key.match(PLURAL_KEY_REGEXP)
104
104
  plural_identifier = nil
105
105
  invalid_plural = false
@@ -20,11 +20,15 @@ module AdLocalize
20
20
  end
21
21
  opts.on("-k", "--drive-key #{GOOGLE_DRIVE_DOCUMENT_ID.dig(:length)}_characters", String, "Use google drive spreadsheets") do |key|
22
22
  is_valid_drive_key = !!(key =~ GOOGLE_DRIVE_DOCUMENT_ID.dig(:regexp)) && (key.size >= GOOGLE_DRIVE_DOCUMENT_ID.dig(:length))
23
- args[:drive_key] = is_valid_drive_key ? key : nil
23
+ raise ArgumentError.new("Invalid google drive spreadsheet key \"#{key}\"") unless is_valid_drive_key
24
+ args[:drive_key] = key
24
25
  end
25
26
  opts.on("-s", "--drive-sheet SHEET_ID", String, "Use a specific sheet id for Google Drive spreadsheets with several sheets") do |value|
26
27
  args[:sheet_id] = value
27
28
  end
29
+ opts.on("-a", "--use-service-account", "Use a Google Cloud Service Account to access the file. An GCLOUD_CLIENT_SECRET environment variable containting the client_secret.json content is needed.") do
30
+ args[:use_service_account] = true
31
+ end
28
32
  opts.on("-o", "--only platform1,platform2", Array, "Only generate localisation files for the specified platforms. Supported platforms : #{Constant::SUPPORTED_PLATFORMS.join(', ')}") do |platforms|
29
33
  args[:only] = filter_option_args("-o", platforms) { |platform| !!Constant::SUPPORTED_PLATFORMS.index(platform) }
30
34
  end
@@ -44,6 +48,7 @@ module AdLocalize
44
48
  LOGGER.log(:error, :red, "Missing argument for option #{e.args.join(',')}")
45
49
  rescue ArgumentError => e
46
50
  LOGGER.log(:error, :red, e.message)
51
+ raise e
47
52
  end
48
53
  args
49
54
  end
@@ -90,11 +90,16 @@ module AdLocalize::Platform
90
90
 
91
91
  private
92
92
 
93
+ def escape_quotes_if_needed(value)
94
+ value.gsub(/(?<!\\)\"/, "\\\"") # match " unless there is a \ before
95
+ end
96
+
93
97
  def write_localizable(locale:, singulars:, wording_type:, filename:)
94
98
  locale = locale.to_sym
95
99
 
96
100
  singulars.each do |key, locales_wording|
97
101
  value = locales_wording.dig(locale, wording_type)
102
+ value = escape_quotes_if_needed(value)
98
103
  comment = locales_wording.dig(locale, AdLocalize::Constant::COMMENT_KEY_SYMBOL)
99
104
  export_dir(locale).join(filename).open("a") do |file|
100
105
  line = ""
@@ -5,12 +5,13 @@ module AdLocalize::Platform
5
5
  OPTIONS = {output_path: ".."}
6
6
 
7
7
  attr_accessor :platform_dir
8
- attr_reader :default_locale, :output_path
8
+ attr_reader :default_locale, :output_path, :add_intermediate_platform_dir
9
9
 
10
- def initialize(default_locale, output_path)
10
+ def initialize(default_locale, output_path, add_intermediate_platform_dir)
11
11
  @default_locale = default_locale.to_sym
12
12
  @output_path = output_path # Must be set before platform_dir
13
- @platform_dir = export_base_directory.join(platform.to_s)
13
+ @platform_dir = add_intermediate_platform_dir ? export_base_directory.join(platform.to_s) : export_base_directory
14
+ @add_intermediate_platform_dir = add_intermediate_platform_dir
14
15
  create_platform_dir
15
16
  end
16
17
 
@@ -52,7 +53,7 @@ module AdLocalize::Platform
52
53
  end
53
54
 
54
55
  def create_platform_dir
55
- if platform_dir.directory?
56
+ if platform_dir.directory? && add_intermediate_platform_dir
56
57
  FileUtils.rm_rf("#{platform_dir}/.", secure: true)
57
58
  else
58
59
  platform_dir.mkpath
@@ -15,10 +15,14 @@ module AdLocalize
15
15
  file_to_parse = args.first
16
16
  LOGGER.log(:warn, :yellow, "Only one CSV can be treated - the priority goes to #{file_to_parse}") if input_files.length > 1
17
17
  if args.empty?
18
- options[:drive_file] = CsvFileManager.download_from_drive(options.dig(:drive_key), options.dig(:sheet_id))
18
+ options[:drive_file] = CsvFileManager.download_from_drive(options.dig(:drive_key), options.dig(:sheet_id), options.dig(:use_service_account))
19
19
  file_to_parse = options.dig(:drive_file)
20
20
  end
21
- CsvFileManager.csv?(file_to_parse) ? export(file_to_parse) : LOGGER.log(:error, :red, "#{file_to_parse} is not a csv")
21
+ if CsvFileManager.csv?(file_to_parse)
22
+ export(file_to_parse)
23
+ else
24
+ LOGGER.log(:error, :red, "#{file_to_parse} is not a csv. Make sure to enable \"Allow external access\" in sharing options.")
25
+ end
22
26
  CsvFileManager.delete_drive_file(options[:drive_file]) if options[:drive_file]
23
27
  end
24
28
  end
@@ -34,8 +38,13 @@ module AdLocalize
34
38
  LOGGER.log(:error, :red, "No data were found in the file - check if there is a key column in the file")
35
39
  else
36
40
  export_platforms = options.dig(:only) || Constant::SUPPORTED_PLATFORMS
41
+ add_intermediate_platform_dir = export_platforms.length > 1
37
42
  export_platforms.each do |platform|
38
- platform_formatter = "AdLocalize::Platform::#{platform.to_s.camelize}Formatter".constantize.new(parser.locales.first, options.dig(:output_path))
43
+ platform_formatter = "AdLocalize::Platform::#{platform.to_s.camelize}Formatter".constantize.new(
44
+ parser.locales.first,
45
+ options.dig(:output_path),
46
+ add_intermediate_platform_dir
47
+ )
39
48
  parser.locales.each do |locale|
40
49
  platform_formatter.export(locale, data)
41
50
  end
@@ -1,3 +1,3 @@
1
1
  module AdLocalize
2
- VERSION = "3.4.0"
2
+ VERSION = "3.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ad_localize
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edouard Siegel
@@ -15,6 +15,8 @@ authors:
15
15
  - Corentin Huard
16
16
  - Claire Peyron
17
17
  - Claire Dufetrelle
18
+ - Pierre Felgines
19
+ - Satyan Jacquens
18
20
  autorequire:
19
21
  bindir: exe
20
22
  cert_chain: []
@@ -114,36 +116,30 @@ dependencies:
114
116
  name: activesupport
115
117
  requirement: !ruby/object:Gem::Requirement
116
118
  requirements:
117
- - - ">="
119
+ - - "~>"
118
120
  - !ruby/object:Gem::Version
119
- version: 4.2.10
121
+ version: '5.2'
120
122
  type: :runtime
121
123
  prerelease: false
122
124
  version_requirements: !ruby/object:Gem::Requirement
123
125
  requirements:
124
- - - ">="
126
+ - - "~>"
125
127
  - !ruby/object:Gem::Version
126
- version: 4.2.10
128
+ version: '5.2'
127
129
  - !ruby/object:Gem::Dependency
128
130
  name: nokogiri
129
131
  requirement: !ruby/object:Gem::Requirement
130
132
  requirements:
131
133
  - - "~>"
132
134
  - !ruby/object:Gem::Version
133
- version: '1.8'
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- version: 1.8.2
135
+ version: '1.10'
137
136
  type: :runtime
138
137
  prerelease: false
139
138
  version_requirements: !ruby/object:Gem::Requirement
140
139
  requirements:
141
140
  - - "~>"
142
141
  - !ruby/object:Gem::Version
143
- version: '1.8'
144
- - - ">="
145
- - !ruby/object:Gem::Version
146
- version: 1.8.2
142
+ version: '1.10'
147
143
  - !ruby/object:Gem::Dependency
148
144
  name: colorize
149
145
  requirement: !ruby/object:Gem::Requirement
@@ -158,6 +154,20 @@ dependencies:
158
154
  - - "~>"
159
155
  - !ruby/object:Gem::Version
160
156
  version: '0.8'
157
+ - !ruby/object:Gem::Dependency
158
+ name: googleauth
159
+ requirement: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: '0.12'
164
+ type: :runtime
165
+ prerelease: false
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - "~>"
169
+ - !ruby/object:Gem::Version
170
+ version: '0.12'
161
171
  description: |-
162
172
  AdLocalize produces localization files from platform agnostic wording.
163
173
  Supported wording format : CSV. Supported export format: iOS, Android, JSON and YAML
@@ -176,7 +186,9 @@ files:
176
186
  - CHANGELOG.md
177
187
  - CODE_OF_CONDUCT.md
178
188
  - Gemfile
189
+ - Gemfile.lock
179
190
  - LICENSE.txt
191
+ - Makefile
180
192
  - README.md
181
193
  - Rakefile
182
194
  - ad_localize.gemspec
@@ -197,7 +209,7 @@ files:
197
209
  - lib/ad_localize/platform/yml_formatter.rb
198
210
  - lib/ad_localize/runner.rb
199
211
  - lib/ad_localize/version.rb
200
- homepage: https://technologies.fabernovel.com
212
+ homepage: https://github.com/applidium/ad_localize
201
213
  licenses:
202
214
  - MIT
203
215
  metadata: {}