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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +122 -55
- data/Gemfile.lock +42 -44
- data/README.md +1 -0
- data/ad_localize.gemspec +1 -1
- data/lib/ad_localize/entities/key.rb +5 -0
- data/lib/ad_localize/entities/translation.rb +12 -0
- data/lib/ad_localize/interactors/export_g_spreadsheet.rb +5 -1
- data/lib/ad_localize/interactors/export_wording.rb +9 -5
- data/lib/ad_localize/interactors/platforms/export_android_locale_wording.rb +4 -0
- data/lib/ad_localize/interactors/platforms/export_csv_locale_wording.rb +25 -0
- data/lib/ad_localize/interactors/platforms/export_ios_locale_wording.rb +4 -0
- data/lib/ad_localize/interactors/platforms/export_json_locale_wording.rb +4 -0
- data/lib/ad_localize/interactors/platforms/export_platform_factory.rb +6 -0
- data/lib/ad_localize/interactors/platforms/export_properties_locale_wording.rb +4 -0
- data/lib/ad_localize/interactors/platforms/export_yaml_locale_wording.rb +4 -0
- data/lib/ad_localize/mappers/android_translation_mapper.rb +9 -1
- data/lib/ad_localize/mappers/csv_path_to_wording.rb +5 -8
- data/lib/ad_localize/mappers/locale_wording_to_hash.rb +8 -0
- data/lib/ad_localize/mappers/value_range_to_wording.rb +6 -8
- data/lib/ad_localize/requests/export_request.rb +15 -2
- data/lib/ad_localize/serializers/strings_serializer.rb +4 -2
- data/lib/ad_localize/validators/key_validator.rb +31 -0
- data/lib/ad_localize/version.rb +1 -1
- data/lib/ad_localize/view_models/translation_group_view_model.rb +4 -0
- data/lib/ad_localize/view_models/translation_view_model.rb +4 -0
- data/lib/ad_localize.rb +2 -1
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1971516fa956f4228c8a1c7e8d3b06e635ef6a6e609d784af4596d3d84761d1c
|
4
|
+
data.tar.gz: 63b3fd447704657f10b76485710ceb75a5b945b92b8c40eb5f3c16e5466b381b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
61
|
+
|
62
|
+
- Use default terminal color for debug log
|
30
63
|
|
31
64
|
## [4.0.3] - 2020-10-27
|
65
|
+
|
32
66
|
### Fixed
|
33
|
-
|
34
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
76
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
87
|
-
|
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
|
-
|
96
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
105
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
118
|
-
|
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
|
-
|
122
|
-
|
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
|
-
|
185
|
+
|
186
|
+
- [iOS only] Info.plist generation support by [@felginep](https://github.com/felginep)
|
127
187
|
|
128
188
|
### Changed
|
129
|
-
|
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
|
4
|
+
ad_localize (4.1.0)
|
5
5
|
activesupport (>= 6.1.3.2, < 7.0)
|
6
6
|
colorize (~> 0.8)
|
7
|
-
google-
|
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.
|
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.
|
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.
|
26
|
+
concurrent-ruby (1.1.9)
|
27
27
|
declarative (0.0.20)
|
28
28
|
diffy (3.3.0)
|
29
|
-
faraday (1.
|
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.
|
35
|
-
|
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.
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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 (
|
49
|
-
httpclient (>= 2.8.1, < 3.
|
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.
|
58
|
+
retriable (>= 2.0, < 4.a)
|
53
59
|
rexml
|
54
|
-
signet (~> 0.14)
|
55
60
|
webrick
|
56
|
-
google-apis-
|
57
|
-
google-apis-core (
|
58
|
-
|
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.
|
69
|
+
signet (~> 0.15)
|
71
70
|
httpclient (2.8.3)
|
72
|
-
i18n (1.
|
71
|
+
i18n (1.10.0)
|
73
72
|
concurrent-ruby (~> 1.0)
|
74
|
-
jwt (2.
|
73
|
+
jwt (2.3.0)
|
75
74
|
memoist (0.16.2)
|
76
|
-
mini_mime (1.1.
|
77
|
-
mini_portile2 (2.
|
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.
|
87
|
-
mini_portile2 (~> 2.
|
85
|
+
nokogiri (1.13.3)
|
86
|
+
mini_portile2 (~> 2.8.0)
|
88
87
|
racc (~> 1.4)
|
89
|
-
os (1.1.
|
88
|
+
os (1.1.4)
|
90
89
|
public_suffix (4.0.6)
|
91
|
-
racc (1.
|
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.
|
101
|
-
signet (0.
|
102
|
-
addressable (~> 2.
|
103
|
-
faraday (>= 0.17.
|
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
|
-
|
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
|
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.
|
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
|
@@ -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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
@@ -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
|
@@ -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
|
@@ -9,9 +9,17 @@ module AdLocalize
|
|
9
9
|
processedValue = processedValue.gsub(/(?<!\\)\"/, '"') # match " unless there is a \ before
|
10
10
|
processedValue = processedValue.gsub(">", '>')
|
11
11
|
processedValue = processedValue.gsub("<", '<')
|
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
|
-
|
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+));)/, '&')
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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?(
|
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
|
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
|
data/lib/ad_localize/version.rb
CHANGED
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.
|
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:
|
164
|
+
name: googleauth
|
165
165
|
requirement: !ruby/object:Gem::Requirement
|
166
166
|
requirements:
|
167
167
|
- - "~>"
|
168
168
|
- !ruby/object:Gem::Version
|
169
|
-
version: '0.
|
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.
|
176
|
+
version: '0.12'
|
177
177
|
- !ruby/object:Gem::Dependency
|
178
|
-
name:
|
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.
|
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.
|
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.
|
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
|