ad_localize 4.0.8 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +122 -55
  3. data/Gemfile.lock +42 -44
  4. data/README.md +1 -0
  5. data/ad_localize.gemspec +1 -1
  6. data/lib/ad_localize/entities/key.rb +5 -0
  7. data/lib/ad_localize/entities/translation.rb +12 -0
  8. data/lib/ad_localize/interactors/export_g_spreadsheet.rb +5 -1
  9. data/lib/ad_localize/interactors/export_wording.rb +9 -5
  10. data/lib/ad_localize/interactors/platforms/export_android_locale_wording.rb +4 -0
  11. data/lib/ad_localize/interactors/platforms/export_csv_locale_wording.rb +25 -0
  12. data/lib/ad_localize/interactors/platforms/export_ios_locale_wording.rb +4 -0
  13. data/lib/ad_localize/interactors/platforms/export_json_locale_wording.rb +4 -0
  14. data/lib/ad_localize/interactors/platforms/export_platform_factory.rb +6 -0
  15. data/lib/ad_localize/interactors/platforms/export_properties_locale_wording.rb +4 -0
  16. data/lib/ad_localize/interactors/platforms/export_yaml_locale_wording.rb +4 -0
  17. data/lib/ad_localize/mappers/android_translation_mapper.rb +9 -1
  18. data/lib/ad_localize/mappers/csv_path_to_wording.rb +5 -8
  19. data/lib/ad_localize/mappers/locale_wording_to_hash.rb +8 -0
  20. data/lib/ad_localize/mappers/value_range_to_wording.rb +6 -8
  21. data/lib/ad_localize/requests/export_request.rb +15 -2
  22. data/lib/ad_localize/serializers/strings_serializer.rb +4 -2
  23. data/lib/ad_localize/validators/key_validator.rb +31 -0
  24. data/lib/ad_localize/version.rb +1 -1
  25. data/lib/ad_localize/view_models/translation_group_view_model.rb +4 -0
  26. data/lib/ad_localize/view_models/translation_view_model.rb +4 -0
  27. data/lib/ad_localize.rb +2 -1
  28. metadata +10 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c46c9d2fd0ef0b980ac43804c9f063d52b36be6083de7193c3e65dde9447030
4
- data.tar.gz: 3a6eac4fe189d7e6de30220b410f0331d8b3a3a90a72c970a9e7ee4aa727c67c
3
+ metadata.gz: 1971516fa956f4228c8a1c7e8d3b06e635ef6a6e609d784af4596d3d84761d1c
4
+ data.tar.gz: 63b3fd447704657f10b76485710ceb75a5b945b92b8c40eb5f3c16e5466b381b
5
5
  SHA512:
6
- metadata.gz: 59fcc792844bf2558f2323f99de099709bae2145ae399231509855230268dd85756cc85145d38b5bdceb908b10635d59f6a2a7067ba32de51bae754c1e99af4a
7
- data.tar.gz: 795f9239b4548412ba8f251d6328c5240d387e6089fa389e0d9c4581673dd40eb3dbc7808cc0c07b3cc8fe2c4935cc427d9c51b689bc57fb897b9b01bf8f77a6
6
+ metadata.gz: 7e34444bd5440e40fd667b6a904c6871382bffc74461011801e120dd95380c256b42f4ed61dc740695805819abe137294b5071446a158e82e27090fa747c7a19
7
+ data.tar.gz: a062eac8f10ba7f2e3a85d88ee9f02c5f9b1c8fde4de560155c517e69b63010da6d7113c14f18c7e635a0831839ae0a66aacd74ba756ff8c6c5b1d813c892e8a
data/CHANGELOG.md CHANGED
@@ -1,147 +1,214 @@
1
1
  # Changelog
2
+
2
3
  All notable changes to this project will be documented in this file.
3
4
 
4
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
7
 
8
+ ## [4.1.1] - 2022-04-15
9
+
10
+ ### Fixed
11
+
12
+ - Fix an issue with percent export in PR [#74](https://github.com/faberNovel/ad_localize/pull/74)
13
+
14
+ ## [4.1.0] - 2022-03-02
15
+
16
+ ### Changed
17
+
18
+ - Do not export empty translation on Android in PR [#72](https://github.com/faberNovel/ad_localize/pull/72)
19
+
20
+ ## [4.0.9] - 2021-09-05
21
+
22
+ ### Fixed
23
+
24
+ - Fix error warning when spreadsheet is empty. Fix [#58](https://github.com/applidium/ad_localize/issues/58) in PR [#69](https://github.com/applidium/ad_localize/pull/69)
25
+ - Add warning messages when input is corrupted. Fix [#59](https://github.com/applidium/ad_localize/issues/59) in PR [#69](https://github.com/applidium/ad_localize/pull/69)
26
+ - Fix performance issue and add warning messages. Fix [#61](https://github.com/applidium/ad_localize/issues/61) in PR [#69](https://github.com/applidium/ad_localize/pull/69)
27
+ - Update deprecated `google-api-client` gem. Fix [#63](https://github.com/applidium/ad_localize/issues/63) in PR [#70](https://github.com/applidium/ad_localize/pull/70)
28
+
7
29
  ## [4.0.8] - 2021-05-25
30
+
8
31
  ### Fixed
32
+
9
33
  - Add `NFCReaderUsageDescription` to InfoPlist keys for iOS
10
34
 
11
35
  ## [4.0.7] - 2021-05-18
36
+
12
37
  ### Changed
38
+
13
39
  - Support Ruby 3.x
14
40
 
15
41
  ## [4.0.6] - 2020-01-25
42
+
16
43
  ### Fixed
17
- - Fix google spreadsheet sheet id comparison with sheet_ids option value
44
+
45
+ - Fix google spreadsheet sheet id comparison with sheet_ids option value
18
46
 
19
47
  ## [4.0.5] - 2020-11-12
48
+
20
49
  ### Fixed
21
- - Fix csv file type check (also add compatibility with macOS Big Sur)
50
+
51
+ - Fix csv file type check (also add compatibility with macOS Big Sur)
22
52
 
23
53
  ## [4.0.4] - 2020-11-09
54
+
24
55
  ### Fixed
25
- - Fix android special character escaping [#56](https://github.com/applidium/ad_localize/issues/56)
26
- - Fix platform filter on export [#55](https://github.com/applidium/ad_localize/issues/55)
56
+
57
+ - Fix android special character escaping [#56](https://github.com/applidium/ad_localize/issues/56)
58
+ - Fix platform filter on export [#55](https://github.com/applidium/ad_localize/issues/55)
27
59
 
28
60
  ### Changed
29
- - Use default terminal color for debug log
61
+
62
+ - Use default terminal color for debug log
30
63
 
31
64
  ## [4.0.3] - 2020-10-27
65
+
32
66
  ### Fixed
33
- - Fix CSV detection and remove dependency to MimeType gem
34
- - Fix drive key detection in options
67
+
68
+ - Fix CSV detection and remove dependency to MimeType gem
69
+ - Fix drive key detection in options
35
70
 
36
71
  ## [4.0.2] - 2020-10-26
72
+
37
73
  ### Fixed
38
- - Use percent HTML char for escaping '%' on android. [#49](https://github.com/applidium/ad_localize/pull/49) by [flolom](https://github.com/flolom)
74
+
75
+ - Use percent HTML char for escaping '%' on android. [#49](https://github.com/applidium/ad_localize/pull/49) by [flolom](https://github.com/flolom)
39
76
 
40
77
  ## [4.0.1] - 2020-10-19
78
+
41
79
  ### Fixed
42
- - delete downloaded files even when any of them is a CSV file
80
+
81
+ - delete downloaded files even when any of them is a CSV file
43
82
 
44
83
  ## [4.0.0] - 2020-10-19
84
+
45
85
  ### Breaking change
46
- - Precedence to csv files. Only CSV files will be exported if both csv file and google spreadsheet are provided
47
- - In case of multiple CSVs or sheet ids, you should be aware that all sources will be merged. By default the merge policy to keep the first wording translation for each key
48
- - New architecture. Separate export process responsibilities in dedicated classes. Fixes [#48](https://github.com/applidium/ad_localize/issues/48), [#20](https://github.com/applidium/ad_localize/issues/20)
86
+
87
+ - Precedence to csv files. Only CSV files will be exported if both csv file and google spreadsheet are provided
88
+ - In case of multiple CSVs or sheet ids, you should be aware that all sources will be merged. By default the merge policy to keep the first wording translation for each key
89
+ - New architecture. Separate export process responsibilities in dedicated classes. Fixes [#48](https://github.com/applidium/ad_localize/issues/48), [#20](https://github.com/applidium/ad_localize/issues/20)
49
90
 
50
91
  ### Changed
51
- - it is now possible to provide an output path path that does not exist
52
- - if a service account configuration is provided, there won't be any files downloaded
53
- - it is now possible to provide a sheet id list
54
- - `ActiveSupport::TestCase` is now the base class of test classes
55
- - Only global constants are in the constant class
56
- - Replaced the Runner class file by a cli class
57
- - tests for ad_localize class are restricted to the minimum
58
- - No more file generated when there are no data to export
59
- - Less verbose logs. Now, they only describe the different steps of the export process
60
- - do not add `InfoPlist` translations to android `strings.xml`
92
+
93
+ - it is now possible to provide an output path path that does not exist
94
+ - if a service account configuration is provided, there won't be any files downloaded
95
+ - it is now possible to provide a sheet id list
96
+ - `ActiveSupport::TestCase` is now the base class of test classes
97
+ - Only global constants are in the constant class
98
+ - Replaced the Runner class file by a cli class
99
+ - tests for ad_localize class are restricted to the minimum
100
+ - No more file generated when there are no data to export
101
+ - Less verbose logs. Now, they only describe the different steps of the export process
102
+ - do not add `InfoPlist` translations to android `strings.xml`
61
103
 
62
104
  ### Added
63
- - -e, -export_all_sheets option export all sheets from a spreadsheet by [@sjcqs](https://github.com/sjcqs)
64
- - -m, --merge-option to select the merge policy (`keep` or `replace`) by [@sjcqs](https://github.com/sjcqs)
65
- - it is now possible to select which locales you want to export
66
- - key class is tested
67
- - option handler is tested
68
- - execute_export_request is tested (only csv)
69
- - export request is tested
70
- - dedicated folder for fixture files
71
- - add ability to use AdLocalize in a Ruby program
72
- - add documentation for JSON and YAML support. Fixes [#23](https://github.com/applidium/ad_localize/issues/23)
105
+
106
+ - -e, -export_all_sheets option export all sheets from a spreadsheet by [@sjcqs](https://github.com/sjcqs)
107
+ - -m, --merge-option to select the merge policy (`keep` or `replace`) by [@sjcqs](https://github.com/sjcqs)
108
+ - it is now possible to select which locales you want to export
109
+ - key class is tested
110
+ - option handler is tested
111
+ - execute_export_request is tested (only csv)
112
+ - export request is tested
113
+ - dedicated folder for fixture files
114
+ - add ability to use AdLocalize in a Ruby program
115
+ - add documentation for JSON and YAML support. Fixes [#23](https://github.com/applidium/ad_localize/issues/23)
73
116
 
74
117
  ### Fixed
75
- - comments will now be added to iOS and Android plural files
76
- - do not remove existing files in export output folder. Fixes [#40](https://github.com/applidium/ad_localize/issues/40)
118
+
119
+ - comments will now be added to iOS and Android plural files
120
+ - do not remove existing files in export output folder. Fixes [#40](https://github.com/applidium/ad_localize/issues/40)
77
121
 
78
122
  ### Removed
79
- - no more option -a option to indicate that a service account configuration will be provided. If set, the environment variable `GCLOUD_CLIENT_SECRET` content will be used
80
- - no more substitution of empty wording with by "Missing Translation" when using the option -d
81
- - no more Makefile, the Rakefile is sufficient. Use `bundle exec rake -T` to display the available commands
82
- - no more check for ordered interpolation variables in translations
123
+
124
+ - no more option -a option to indicate that a service account configuration will be provided. If set, the environment variable `GCLOUD_CLIENT_SECRET` content will be used
125
+ - no more substitution of empty wording with by "Missing Translation" when using the option -d
126
+ - no more Makefile, the Rakefile is sufficient. Use `bundle exec rake -T` to display the available commands
127
+ - no more check for ordered interpolation variables in translations
83
128
 
84
129
  ## [3.6.0] - 2020-06-23
130
+
85
131
  ### Added
86
- - add documentation for service account usage by [@sjcqs](https://github.com/sjcqs)
87
- - add compatibility with activesupport 6 by [@Hugo-Hache](https://github.com/Hugo-Hache)
132
+
133
+ - add documentation for service account usage by [@sjcqs](https://github.com/sjcqs)
134
+ - add compatibility with activesupport 6 by [@Hugo-Hache](https://github.com/Hugo-Hache)
88
135
 
89
136
  ### Changed
90
137
 
91
138
  ### Fixed
92
139
 
93
140
  ## [3.5.0] - 2020-05-12
141
+
94
142
  ### Added
95
- - 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)
96
- - add makefile for easier testing by [@felginep](https://github.com/felginep)
143
+
144
+ - 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)
145
+ - add makefile for easier testing by [@felginep](https://github.com/felginep)
97
146
 
98
147
  ### Changed
99
- - 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)
100
- - 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)
101
- - raise error when google spreadsheet key is invalid by [@felginep](https://github.com/felginep)
148
+
149
+ - 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)
150
+ - 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)
151
+ - raise error when google spreadsheet key is invalid by [@felginep](https://github.com/felginep)
102
152
 
103
153
  ### Fixed
104
- - auto escape strings in Localizable.strings by [@felginep](https://github.com/felginep). Fixes [#26](https://github.com/applidium/ad_localize/issues/26)
105
- - trim keys to prevent user error by [@felginep](https://github.com/felginep). Fixes [#16](https://github.com/applidium/ad_localize/issues/16)
154
+
155
+ - auto escape strings in Localizable.strings by [@felginep](https://github.com/felginep). Fixes [#26](https://github.com/applidium/ad_localize/issues/26)
156
+ - trim keys to prevent user error by [@felginep](https://github.com/felginep). Fixes [#16](https://github.com/applidium/ad_localize/issues/16)
106
157
 
107
158
  ## [3.4.0] - 2019-02-10
159
+
108
160
  ### Added
109
- - Rails folks, [@epaillous](https://github.com/epaillous) has improved the YAML support. You can now have multi-level wording.
161
+
162
+ - Rails folks, [@epaillous](https://github.com/epaillous) has improved the YAML support. You can now have multi-level wording.
110
163
 
111
164
  ## [3.3.0] - 2019-02-10
165
+
112
166
  ### Added
113
- - improve React support using keys with dots to generate nested JSON files by [@epaillous](https://github.com/epaillous)
167
+
168
+ - improve React support using keys with dots to generate nested JSON files by [@epaillous](https://github.com/epaillous)
114
169
 
115
170
  ## [3.2.0] - 2019-12-10
171
+
116
172
  ### Added
117
- - Add tests to compare reference exports by [@felginep](https://github.com/felginep)
118
- - [iOS only] Handle [adaptive strings](https://developer.apple.com/documentation/foundation/nsstring/1413104-variantfittingpresentationwidth) by [@felginep](https://github.com/felginep)
173
+
174
+ - Add tests to compare reference exports by [@felginep](https://github.com/felginep)
175
+ - [iOS only] Handle [adaptive strings](https://developer.apple.com/documentation/foundation/nsstring/1413104-variantfittingpresentationwidth) by [@felginep](https://github.com/felginep)
119
176
 
120
177
  ### Changed
121
- - Fix issue with Info.plist format by [@felginep](https://github.com/felginep)
122
- - Do not export plurals for android when there are no values by [@felginep](https://github.com/felginep)
178
+
179
+ - Fix issue with Info.plist format by [@felginep](https://github.com/felginep)
180
+ - Do not export plurals for android when there are no values by [@felginep](https://github.com/felginep)
123
181
 
124
182
  ## [3.1.0] - 2019-09-30
183
+
125
184
  ### Added
126
- - [iOS only] Info.plist generation support by [@felginep](https://github.com/felginep)
185
+
186
+ - [iOS only] Info.plist generation support by [@felginep](https://github.com/felginep)
127
187
 
128
188
  ### Changed
129
- - No more warning log for empty lines by [@felginep](https://github.com/felginep)
189
+
190
+ - No more warning log for empty lines by [@felginep](https://github.com/felginep)
130
191
 
131
192
  ## [3.0.0] - 2019-02-19
193
+
132
194
  TODO
133
195
 
134
196
  ## [2.1.0] - 2016-12-22
197
+
135
198
  TODO
136
199
 
137
200
  ## [2.0.0] - 2016-07-05
201
+
138
202
  TODO
139
203
 
140
204
  ## [1.1.0] - 2016-04-27
205
+
141
206
  TODO
142
207
 
143
208
  ## [1.0.0] - 2016-04-25
209
+
144
210
  TODO
145
211
 
146
212
  ## [0.1.0] - 2016-04-25
213
+
147
214
  TODO
data/Gemfile.lock CHANGED
@@ -1,80 +1,79 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ad_localize (4.0.8)
4
+ ad_localize (4.1.0)
5
5
  activesupport (>= 6.1.3.2, < 7.0)
6
6
  colorize (~> 0.8)
7
- google-api-client (~> 0.34)
7
+ google-apis-sheets_v4 (~> 0.9)
8
8
  googleauth (~> 0.12)
9
9
  nokogiri (~> 1.10)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activesupport (6.1.3.2)
14
+ activesupport (6.1.5)
15
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
16
  i18n (>= 1.6, < 2)
17
17
  minitest (>= 5.1)
18
18
  tzinfo (~> 2.0)
19
19
  zeitwerk (~> 2.3)
20
- addressable (2.7.0)
20
+ addressable (2.8.0)
21
21
  public_suffix (>= 2.0.2, < 5.0)
22
22
  ansi (1.5.0)
23
23
  builder (3.2.4)
24
24
  byebug (11.1.3)
25
25
  colorize (0.8.1)
26
- concurrent-ruby (1.1.8)
26
+ concurrent-ruby (1.1.9)
27
27
  declarative (0.0.20)
28
28
  diffy (3.3.0)
29
- faraday (1.4.2)
29
+ faraday (1.10.0)
30
30
  faraday-em_http (~> 1.0)
31
31
  faraday-em_synchrony (~> 1.0)
32
32
  faraday-excon (~> 1.1)
33
+ faraday-httpclient (~> 1.0)
34
+ faraday-multipart (~> 1.0)
33
35
  faraday-net_http (~> 1.0)
34
- faraday-net_http_persistent (~> 1.1)
35
- multipart-post (>= 1.2, < 3)
36
+ faraday-net_http_persistent (~> 1.0)
37
+ faraday-patron (~> 1.0)
38
+ faraday-rack (~> 1.0)
39
+ faraday-retry (~> 1.0)
36
40
  ruby2_keywords (>= 0.0.4)
37
41
  faraday-em_http (1.0.0)
38
42
  faraday-em_synchrony (1.0.0)
39
43
  faraday-excon (1.1.0)
44
+ faraday-httpclient (1.0.1)
45
+ faraday-multipart (1.0.3)
46
+ multipart-post (>= 1.2, < 3)
40
47
  faraday-net_http (1.0.1)
41
- faraday-net_http_persistent (1.1.0)
42
- gems (1.2.0)
43
- google-api-client (0.53.0)
44
- google-apis-core (~> 0.1)
45
- google-apis-generator (~> 0.1)
46
- google-apis-core (0.3.0)
48
+ faraday-net_http_persistent (1.2.0)
49
+ faraday-patron (1.0.0)
50
+ faraday-rack (1.0.0)
51
+ faraday-retry (1.0.3)
52
+ google-apis-core (0.4.2)
47
53
  addressable (~> 2.5, >= 2.5.1)
48
- googleauth (~> 0.14)
49
- httpclient (>= 2.8.1, < 3.0)
54
+ googleauth (>= 0.16.2, < 2.a)
55
+ httpclient (>= 2.8.1, < 3.a)
50
56
  mini_mime (~> 1.0)
51
57
  representable (~> 3.0)
52
- retriable (>= 2.0, < 4.0)
58
+ retriable (>= 2.0, < 4.a)
53
59
  rexml
54
- signet (~> 0.14)
55
60
  webrick
56
- google-apis-discovery_v1 (0.4.0)
57
- google-apis-core (~> 0.1)
58
- google-apis-generator (0.2.0)
59
- activesupport (>= 5.0)
60
- gems (~> 1.2)
61
- google-apis-core (~> 0.1)
62
- google-apis-discovery_v1 (~> 0.0)
63
- thor (>= 0.20, < 2.a)
64
- googleauth (0.16.2)
61
+ google-apis-sheets_v4 (0.11.0)
62
+ google-apis-core (>= 0.4, < 2.a)
63
+ googleauth (0.17.1)
65
64
  faraday (>= 0.17.3, < 2.0)
66
65
  jwt (>= 1.4, < 3.0)
67
66
  memoist (~> 0.16)
68
67
  multi_json (~> 1.11)
69
68
  os (>= 0.9, < 2.0)
70
- signet (~> 0.14)
69
+ signet (~> 0.15)
71
70
  httpclient (2.8.3)
72
- i18n (1.8.10)
71
+ i18n (1.10.0)
73
72
  concurrent-ruby (~> 1.0)
74
- jwt (2.2.3)
73
+ jwt (2.3.0)
75
74
  memoist (0.16.2)
76
- mini_mime (1.1.0)
77
- mini_portile2 (2.5.1)
75
+ mini_mime (1.1.2)
76
+ mini_portile2 (2.8.0)
78
77
  minitest (5.14.4)
79
78
  minitest-reporters (1.4.2)
80
79
  ansi
@@ -83,12 +82,12 @@ GEM
83
82
  ruby-progressbar
84
83
  multi_json (1.15.0)
85
84
  multipart-post (2.1.1)
86
- nokogiri (1.11.5)
87
- mini_portile2 (~> 2.5.0)
85
+ nokogiri (1.13.3)
86
+ mini_portile2 (~> 2.8.0)
88
87
  racc (~> 1.4)
89
- os (1.1.1)
88
+ os (1.1.4)
90
89
  public_suffix (4.0.6)
91
- racc (1.5.2)
90
+ racc (1.6.0)
92
91
  rake (12.3.3)
93
92
  representable (3.1.1)
94
93
  declarative (< 0.1.0)
@@ -97,19 +96,18 @@ GEM
97
96
  retriable (3.1.2)
98
97
  rexml (3.2.5)
99
98
  ruby-progressbar (1.10.1)
100
- ruby2_keywords (0.0.4)
101
- signet (0.15.0)
102
- addressable (~> 2.3)
103
- faraday (>= 0.17.3, < 2.0)
99
+ ruby2_keywords (0.0.5)
100
+ signet (0.16.1)
101
+ addressable (~> 2.8)
102
+ faraday (>= 0.17.5, < 3.0)
104
103
  jwt (>= 1.5, < 3.0)
105
104
  multi_json (~> 1.10)
106
- thor (1.1.0)
107
- trailblazer-option (0.1.1)
105
+ trailblazer-option (0.1.2)
108
106
  tzinfo (2.0.4)
109
107
  concurrent-ruby (~> 1.0)
110
108
  uber (0.1.0)
111
109
  webrick (1.7.0)
112
- zeitwerk (2.4.2)
110
+ zeitwerk (2.5.4)
113
111
 
114
112
  PLATFORMS
115
113
  ruby
@@ -124,4 +122,4 @@ DEPENDENCIES
124
122
  rake (~> 12.3)
125
123
 
126
124
  BUNDLED WITH
127
- 2.2.15
125
+ 2.2.26
data/README.md CHANGED
@@ -123,6 +123,7 @@ $ ad_localize -k <your-spreadsheet-drive-key> -s <comma-separated-sheet-id-list>
123
123
  - Any column after the `key` column will be considered as a locale column (except from the optional `comment` columns)
124
124
  - Keys should contain only letter, number, underscore and dot : [a-z0-9_.]+.
125
125
  - Format specifiers must be numeroted if there are more than one in a translation string (eg: `"%1$@ %2$@'s report"`).
126
+ - _Only for Android_ keys without translation won't be considered
126
127
 
127
128
  ### Comments
128
129
 
data/ad_localize.gemspec CHANGED
@@ -49,8 +49,8 @@ Gem::Specification.new do |spec|
49
49
  spec.add_dependency 'activesupport', '>= 6.1.3.2', '< 7.0'
50
50
  spec.add_dependency 'nokogiri', '~> 1.10'
51
51
  spec.add_dependency 'colorize', '~> 0.8'
52
- spec.add_dependency 'google-api-client', '~> 0.34'
53
52
  spec.add_dependency 'googleauth', '~> 0.12'
53
+ spec.add_dependency 'google-apis-sheets_v4', '~> 0.9'
54
54
 
55
55
  spec.required_ruby_version = '>= 2.3'
56
56
  end
@@ -46,6 +46,11 @@ module AdLocalize
46
46
  raw_label == key.raw_label
47
47
  end
48
48
 
49
+ def ==(o)
50
+ o.class == self.class &&
51
+ o.raw_label == raw_label
52
+ end
53
+
49
54
  private
50
55
 
51
56
  def compute_label
@@ -15,6 +15,18 @@ module AdLocalize
15
15
  @value = value
16
16
  @comment = comment
17
17
  end
18
+
19
+ def ==(o)
20
+ o.class == self.class &&
21
+ o.locale == locale &&
22
+ o.key == key &&
23
+ o.value == value &&
24
+ o.comment == comment
25
+ end
26
+
27
+ def has_value?
28
+ value.present?
29
+ end
18
30
  end
19
31
  end
20
32
  end
@@ -33,8 +33,12 @@ module AdLocalize
33
33
  export_request.csv_paths = downloaded_files.map(&:path)
34
34
  if export_request.has_csv_files?
35
35
  ExportCSVFiles.new.call(export_request: export_request)
36
+ elsif export_request.has_empty_files?
37
+ # When downloading an empty spreadsheet, the content type of the downloaded file is "inode/x-empty"
38
+ LOGGER.warn("Your spreadsheet is empty. Add content and retry.")
36
39
  else
37
- LOGGER.error("invalid export request. check the spreadsheet share configuration")
40
+ # When shared configuration is misconfigured, the content type of the downloaded file is "text/html"
41
+ LOGGER.error("Invalid export request. Check the spreadsheet share configuration")
38
42
  end
39
43
  downloaded_files.select { |downloaded_file| File.exist?(downloaded_file.path) }.each do |downloaded_file|
40
44
  downloaded_file.close
@@ -7,12 +7,16 @@ module AdLocalize
7
7
 
8
8
  def call(export_request:, wording:)
9
9
  LOGGER.debug("Starting export wording")
10
- locales = export_request.locales.size.zero? ? wording.locales : wording.locales & export_request.locales
11
10
  export_request.platforms.each do |platform|
12
- locales.each do |locale|
13
- platform_dir = compute_platform_dir(export_request: export_request, platform: platform)
14
- export_platform = @export_platform_factory.build(platform: platform)
15
- export_platform.call(wording: wording, locale: locale, platform_dir: platform_dir)
11
+ platform_dir = compute_platform_dir(export_request: export_request, platform: platform)
12
+ export_platform = @export_platform_factory.build(platform: platform)
13
+ if export_platform.should_export_locale_by_locale?
14
+ locales = export_request.locales.size.zero? ? wording.locales : wording.locales & export_request.locales
15
+ locales.each do |locale|
16
+ export_platform.call(wording: wording, locale: locale, platform_dir: platform_dir)
17
+ end
18
+ else
19
+ export_platform.call(export_request: export_request, platform_dir: platform_dir)
16
20
  end
17
21
  end
18
22
  end
@@ -23,6 +23,10 @@ module AdLocalize
23
23
  LOGGER.debug("#{STRINGS_FILENAME} done !")
24
24
  end
25
25
 
26
+ def should_export_locale_by_locale?
27
+ true
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def has_android_wording?(locale_wording:)
@@ -0,0 +1,25 @@
1
+ module AdLocalize
2
+ module Interactors
3
+ module Platforms
4
+ class ExportCSVLocaleWording
5
+ def initialize
6
+ @file_system_repository = Repositories::FileSystemRepository.new
7
+ end
8
+
9
+ def call(export_request:, platform_dir:)
10
+ LOGGER.debug("Starting export CSV wording")
11
+ @file_system_repository.create_directory(path: platform_dir)
12
+ export_request.csv_paths.each_with_index do |csv_path, i|
13
+ file = File.basename("localization_#{i}.csv")
14
+ FileUtils.cp(csv_path, platform_dir.join(file.to_s))
15
+ end
16
+ LOGGER.debug("CSV wording export done !")
17
+ end
18
+
19
+ def should_export_locale_by_locale?
20
+ false
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -27,6 +27,10 @@ module AdLocalize
27
27
  export_localizable_stringsdict(locale_wording: locale_wording, output_dir: output_dir)
28
28
  end
29
29
 
30
+ def should_export_locale_by_locale?
31
+ true
32
+ end
33
+
30
34
  private
31
35
 
32
36
  def has_ios_wording?(locale_wording:)
@@ -17,6 +17,10 @@ module AdLocalize
17
17
  @file_system_repository.write(content: content, path: platform_dir.join("#{locale}.json"))
18
18
  LOGGER.debug("#{locale}.json done !")
19
19
  end
20
+
21
+ def should_export_locale_by_locale?
22
+ true
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -14,6 +14,8 @@ module AdLocalize
14
14
  ios_builder
15
15
  when 'properties'
16
16
  properties_builder
17
+ when 'csv'
18
+ csv_builder
17
19
  else
18
20
  raise ArgumentError.new('Unknown platform for builder factory')
19
21
  end
@@ -38,6 +40,10 @@ module AdLocalize
38
40
  def properties_builder
39
41
  @properties_builder ||= ExportPropertiesLocaleWording.new
40
42
  end
43
+
44
+ def csv_builder
45
+ @csv_builder ||= ExportCSVLocaleWording.new
46
+ end
41
47
  end
42
48
  end
43
49
  end
@@ -18,6 +18,10 @@ module AdLocalize
18
18
  LOGGER.debug("#{locale}.properties done !")
19
19
  end
20
20
 
21
+ def should_export_locale_by_locale?
22
+ true
23
+ end
24
+
21
25
  private
22
26
 
23
27
  def has_properties_wording?(locale_wording:)
@@ -17,6 +17,10 @@ module AdLocalize
17
17
  @file_system_repository.write(content: content, path: platform_dir.join("#{locale}.yml"))
18
18
  LOGGER.debug("#{locale}.yml done !")
19
19
  end
20
+
21
+ def should_export_locale_by_locale?
22
+ true
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -9,9 +9,17 @@ module AdLocalize
9
9
  processedValue = processedValue.gsub(/(?<!\\)\"/, '&#34;') # match " unless there is a \ before
10
10
  processedValue = processedValue.gsub(">", '&gt;')
11
11
  processedValue = processedValue.gsub("<", '&lt;')
12
+ hasFormatting = processedValue.match(/(%(\d+\$)?@)/)
12
13
  processedValue = processedValue.gsub(/(%(\d+\$)?@)/, '%\2s') # should match values like %1$s and %s
14
+ hasFormatting = hasFormatting || processedValue.match(/(%((\d+\$)?(\d+)?)i)/)
13
15
  processedValue = processedValue.gsub(/(%((\d+\$)?(\d+)?)i)/, '%\2d') # should match values like %i, %3$i, %01i, %1$02i
14
- processedValue = processedValue.gsub(/%(?!((\d+\$)?(s|(\d+)?d)))/, '&#37;') # negative lookahead: identifies when user really wants to display a %
16
+ # On Android, '%' must be escaped with a second '%' if and only if the string has at least one formatting pattern. In this specific case,
17
+ # a Java formatting method will be used which interprets every non escaped '%' as the start of a formatting pattern.
18
+ if hasFormatting
19
+ processedValue = processedValue.gsub(/%(?!((\d+\$)?(s|(\d+)?d)))/, '%%') # negative lookahead: identifies when user really wants to display a %
20
+ else
21
+ processedValue = processedValue.gsub(/%(?!((\d+\$)?(s|(\d+)?d)))/, '%') # negative lookahead: identifies when user really wants to display a %
22
+ end
15
23
  processedValue = processedValue.gsub("\\U", "\\u")
16
24
  processedValue = processedValue.gsub(/&(?!((#\d+)|(\w+));)/, '&#38;')
17
25
  processedValue = processedValue.gsub(/&/) { |match| match.replace('\&') }
@@ -5,19 +5,16 @@ module AdLocalize
5
5
  @headers = CSV.foreach(csv_path).first
6
6
  return unless valid?(csv_path: csv_path)
7
7
  translations = []
8
+ validator = Validators::KeyValidator.new
8
9
 
9
10
  CSV.foreach(csv_path, headers: true, skip_blanks: true) do |row|
10
11
  row_translations = map_row(row: row, locales: locales)
11
12
  next if row_translations.blank?
12
13
 
13
- existing_keys = translations.map(&:key)
14
- new_translations = row_translations.reject do |translation|
15
- existing_keys.any? do |key|
16
- existing_plural_key = key.label == translation.key.label && key.plural? && translation.key.singular?
17
- key.same_as?(key: translation.key) || existing_plural_key
18
- end
19
- end
20
- translations.concat(new_translations)
14
+ current_key = row_translations.first.key
15
+ next if validator.has_warnings?(current_key)
16
+
17
+ translations.concat(row_translations)
21
18
  end
22
19
 
23
20
  locale_wordings = translations.group_by(&:locale).map do |locale, group|
@@ -10,6 +10,14 @@ module AdLocalize
10
10
  hash[translation.key.label] = {} unless hash.key? translation.key.label
11
11
  hash[translation.key.label][translation.key.plural_key] = translation.value
12
12
  else
13
+ unless hash.is_a?(Hash)
14
+ LOGGER.warn "Corrupted input. Trying to insert a value for key '#{translation.key.label}' but a value already exists for '#{inner_keys[0..index-1].join(".")}'. Skipping."
15
+ break # skip this corrupted key
16
+ end
17
+ previous_value = hash[inner_key.to_s]
18
+ if !previous_value.blank? && previous_value.is_a?(Hash)
19
+ LOGGER.warn "Corrupted input. Trying to insert a value for key '#{translation.key.label}' but values already exist for keys '#{translation.key.label}.*'. Previous values will be lost."
20
+ end
13
21
  hash[inner_key.to_s] = translation.value
14
22
  end
15
23
  else
@@ -17,18 +17,16 @@ module AdLocalize
17
17
 
18
18
  def map_rows(values:)
19
19
  translations = []
20
+ validator = Validators::KeyValidator.new
21
+
20
22
  values[1..-1].each do |row|
21
23
  row_translations = map_row(row: row)
22
24
  next if row_translations.blank?
23
25
 
24
- existing_keys = translations.map(&:key)
25
- new_translations = row_translations.reject do |translation|
26
- existing_keys.any? do |key|
27
- existing_plural_key = key.label == translation.key.label && key.plural? && translation.key.singular?
28
- key.same_as?(key: translation.key) || existing_plural_key
29
- end
30
- end
31
- translations.concat(new_translations)
26
+ current_key = row_translations.first.key
27
+ next if validator.has_warnings?(current_key)
28
+
29
+ translations.concat(row_translations)
32
30
  end
33
31
  translations
34
32
  end
@@ -1,9 +1,10 @@
1
1
  module AdLocalize
2
2
  module Requests
3
3
  class ExportRequest
4
- SUPPORTED_PLATFORMS = %w(ios android yml json properties).freeze
4
+ SUPPORTED_PLATFORMS = %w(ios android yml json properties csv).freeze
5
5
  DEFAULT_EXPORT_FOLDER = 'exports'.freeze
6
6
  CSV_CONTENT_TYPES = %w(text/csv text/plain application/csv).freeze
7
+ EMPTY_CONTENT_TYPE = 'inode/x-empty'.freeze
7
8
 
8
9
  def initialize(**args)
9
10
  @locales = Array(args[:locales].presence)
@@ -34,6 +35,10 @@ module AdLocalize
34
35
  !@csv_paths.blank? && @csv_paths.all? { |csv_path| File.exist?(csv_path) && is_csv?(path: csv_path) }
35
36
  end
36
37
 
38
+ def has_empty_files?
39
+ !@csv_paths.blank? && @csv_paths.all? { |csv_path| File.exist?(csv_path) && is_empty?(path: csv_path) }
40
+ end
41
+
37
42
  def has_g_spreadsheet_options?
38
43
  @g_spreadsheet_options.present?
39
44
  end
@@ -61,7 +66,15 @@ module AdLocalize
61
66
  end
62
67
 
63
68
  def is_csv?(path:)
64
- CSV_CONTENT_TYPES.include?(`file --brief --mime-type "#{path}"`.strip)
69
+ CSV_CONTENT_TYPES.include? content_type(path: path)
70
+ end
71
+
72
+ def is_empty?(path:)
73
+ content_type(path: path) == EMPTY_CONTENT_TYPE
74
+ end
75
+
76
+ def content_type(path:)
77
+ `file --brief --mime-type "#{path}"`.strip
65
78
  end
66
79
 
67
80
  def valid_g_spreadsheet_options?
@@ -22,11 +22,13 @@ module AdLocalize
22
22
  end
23
23
 
24
24
  def map_singulars(translations:)
25
- translations.map { |translation| @translation_mapper.map(translation: translation) }
25
+ translations.select(&:has_value?).map { |translation| @translation_mapper.map(translation: translation) }
26
26
  end
27
27
 
28
28
  def map_plurals(plurals:)
29
- plurals.map { |label, translations| @translation_group_mapper.map(label: label, translations: translations) }
29
+ plurals
30
+ .map { |label, translations| @translation_group_mapper.map(label: label, translations: translations.select(&:has_value?)) }
31
+ .select(&:has_translations?)
30
32
  end
31
33
  end
32
34
  end
@@ -0,0 +1,31 @@
1
+ module AdLocalize
2
+ module Validators
3
+ class KeyValidator
4
+
5
+ def initialize
6
+ @existing_key_for_label = {}
7
+ end
8
+
9
+ def has_warnings?(current_key)
10
+ current_label = current_key.label
11
+ existing_key = @existing_key_for_label[current_label]
12
+
13
+ has_warnings = false
14
+
15
+ unless existing_key.nil?
16
+ existing_plural_key = existing_key.label == current_key.label && existing_key.plural? && current_key.singular?
17
+ existing_singular_key = existing_key.label == current_key.label && existing_key.singular? && current_key.plural?
18
+ is_same_key = existing_key.same_as?(key: current_key)
19
+ LOGGER.warn "A plural value already exist for key '#{current_label}'. Remove duplicates." if existing_plural_key
20
+ LOGGER.warn "A singular value already exist for key '#{current_label}'. Remove duplicates." if existing_singular_key
21
+ LOGGER.warn "Some values already exist for key '#{current_label}'. Remove duplicates." if is_same_key
22
+ has_warnings = is_same_key || existing_plural_key || existing_singular_key
23
+ end
24
+
25
+ @existing_key_for_label[current_label] = current_key
26
+
27
+ has_warnings
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module AdLocalize
2
- VERSION = "4.0.8"
2
+ VERSION = "4.1.1"
3
3
  end
@@ -10,6 +10,10 @@ module AdLocalize
10
10
  @label = label
11
11
  @translation_view_models = translation_view_models
12
12
  end
13
+
14
+ def has_translations?
15
+ (translation_view_models || []).any?(&:has_value?)
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -14,6 +14,10 @@ module AdLocalize
14
14
  @value = value
15
15
  @comment = comment
16
16
  end
17
+
18
+ def has_value?
19
+ value.present?
20
+ end
17
21
  end
18
22
  end
19
23
  end
data/lib/ad_localize.rb CHANGED
@@ -53,6 +53,7 @@ require 'ad_localize/interactors/platforms/export_ios_locale_wording'
53
53
  require 'ad_localize/interactors/platforms/export_json_locale_wording'
54
54
  require 'ad_localize/interactors/platforms/export_yaml_locale_wording'
55
55
  require 'ad_localize/interactors/platforms/export_properties_locale_wording'
56
+ require 'ad_localize/interactors/platforms/export_csv_locale_wording'
56
57
  require 'ad_localize/interactors/platforms/export_platform_factory'
57
58
 
58
59
  require 'ad_localize/serializers/with_template'
@@ -64,7 +65,7 @@ require 'ad_localize/serializers/properties_serializer'
64
65
  require 'ad_localize/serializers/json_serializer'
65
66
  require 'ad_localize/serializers/yaml_serializer'
66
67
 
67
-
68
+ require 'ad_localize/validators/key_validator'
68
69
 
69
70
  module AdLocalize
70
71
  class Error < StandardError; 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: 4.0.8
4
+ version: 4.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edouard Siegel
@@ -161,33 +161,33 @@ dependencies:
161
161
  - !ruby/object:Gem::Version
162
162
  version: '0.8'
163
163
  - !ruby/object:Gem::Dependency
164
- name: google-api-client
164
+ name: googleauth
165
165
  requirement: !ruby/object:Gem::Requirement
166
166
  requirements:
167
167
  - - "~>"
168
168
  - !ruby/object:Gem::Version
169
- version: '0.34'
169
+ version: '0.12'
170
170
  type: :runtime
171
171
  prerelease: false
172
172
  version_requirements: !ruby/object:Gem::Requirement
173
173
  requirements:
174
174
  - - "~>"
175
175
  - !ruby/object:Gem::Version
176
- version: '0.34'
176
+ version: '0.12'
177
177
  - !ruby/object:Gem::Dependency
178
- name: googleauth
178
+ name: google-apis-sheets_v4
179
179
  requirement: !ruby/object:Gem::Requirement
180
180
  requirements:
181
181
  - - "~>"
182
182
  - !ruby/object:Gem::Version
183
- version: '0.12'
183
+ version: '0.9'
184
184
  type: :runtime
185
185
  prerelease: false
186
186
  version_requirements: !ruby/object:Gem::Requirement
187
187
  requirements:
188
188
  - - "~>"
189
189
  - !ruby/object:Gem::Version
190
- version: '0.12'
190
+ version: '0.9'
191
191
  description: |-
192
192
  AdLocalize produces localization files from platform agnostic wording.
193
193
  Supported wording format : CSV. Supported export format: iOS, Android, JSON and YAML
@@ -229,6 +229,7 @@ files:
229
229
  - lib/ad_localize/interactors/export_wording.rb
230
230
  - lib/ad_localize/interactors/merge_wordings.rb
231
231
  - lib/ad_localize/interactors/platforms/export_android_locale_wording.rb
232
+ - lib/ad_localize/interactors/platforms/export_csv_locale_wording.rb
232
233
  - lib/ad_localize/interactors/platforms/export_ios_locale_wording.rb
233
234
  - lib/ad_localize/interactors/platforms/export_json_locale_wording.rb
234
235
  - lib/ad_localize/interactors/platforms/export_platform_factory.rb
@@ -261,6 +262,7 @@ files:
261
262
  - lib/ad_localize/templates/ios/Localizable.strings.erb
262
263
  - lib/ad_localize/templates/ios/Localizable.stringsdict.erb
263
264
  - lib/ad_localize/templates/properties/template.properties.erb
265
+ - lib/ad_localize/validators/key_validator.rb
264
266
  - lib/ad_localize/version.rb
265
267
  - lib/ad_localize/view_models/translation_group_view_model.rb
266
268
  - lib/ad_localize/view_models/translation_view_model.rb
@@ -283,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
283
285
  - !ruby/object:Gem::Version
284
286
  version: '0'
285
287
  requirements: []
286
- rubygems_version: 3.0.3
288
+ rubygems_version: 3.2.26
287
289
  signing_key:
288
290
  specification_version: 4
289
291
  summary: AdLocalize helps with mobile and web applications wording