@@ -16,10 +16,10 @@ let version = "0.9.2"
16
16
struct Locheck : ParsableCommand {
17
17
static let configuration = CommandConfiguration (
18
18
abstract: """
19
- Validate your Xcode localization files. Currently only works on .strings. The different
20
- commands have different amounts of automation. `discover` operates on a directory of
21
- .lproj files, `lproj` operates on specific .lproj files, and `strings` operates on
22
- specific .strings files.
19
+ Validate your Xcode localization files. The different commands have
20
+ different amounts of automation. `discover` operates on a directory of
21
+ .lproj files, `lproj` operates on specific .lproj files, and `strings`
22
+ operates on specific .strings files.
23
23
""" ,
24
24
subcommands: [
25
25
DiscoverLproj . self,
@@ -36,10 +36,11 @@ private func withProblemReporter(
36
36
root: String ,
37
37
ignore: [ String ] ,
38
38
ignoreWarnings: Bool ,
39
+ treatWarningsAsErrors: Bool ,
39
40
_ block: ( ProblemReporter ) -> Void ) {
40
41
let problemReporter = ProblemReporter ( root: root, ignoredProblemIdentifiers: ignore, ignoreWarnings: ignoreWarnings)
41
42
block ( problemReporter)
42
- if problemReporter. hasError {
43
+ if problemReporter. hasError || ( treatWarningsAsErrors && problemReporter . hasWarning ) {
43
44
print ( " Errors found " )
44
45
Darwin . exit ( 1 )
45
46
}
@@ -53,6 +54,9 @@ private let ignoreMissingHelpText: ArgumentHelp =
53
54
54
55
private let ignoreWarningsHelpText : ArgumentHelp = " Ignore all warning-level issues. "
55
56
57
+ private let treatWarningsAsErrorsHelpText : ArgumentHelp =
58
+ " Return a non-zero exit code if any warnings, not just errors, were encountered. "
59
+
56
60
private protocol HasIgnoreWithShorthand {
57
61
var ignore : [ String ] { get }
58
62
var ignoreMissing : Bool { get }
@@ -81,24 +85,31 @@ struct XCStrings: HasIgnoreWithShorthand, ParsableCommand {
81
85
@Flag ( help: ignoreWarningsHelpText)
82
86
fileprivate var ignoreWarnings = false
83
87
88
+ @Flag ( help: treatWarningsAsErrorsHelpText)
89
+ fileprivate var treatWarningsAsErrors = false
90
+
84
91
func validate( ) throws {
85
92
try stringsFiles. forEach { try $0. validate ( ext: " strings " ) }
86
93
}
87
94
88
95
func run( ) {
89
- withProblemReporter ( root: " " , ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
90
- let base = stringsFiles [ 0 ]
91
- let translationFiles = stringsFiles. dropFirst ( )
92
- for file in translationFiles {
93
- let translationFile = try ! File ( path: file. argument)
94
- parseAndValidateXCStrings (
95
- base: try ! File ( path: base. argument) ,
96
- translation: translationFile,
97
- translationLanguageName: translationFile. nameExcludingExtension,
98
- problemReporter: problemReporter)
96
+ withProblemReporter (
97
+ root: " " ,
98
+ ignore: ignoreWithShorthand,
99
+ ignoreWarnings: ignoreWarnings,
100
+ treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
101
+ let base = stringsFiles [ 0 ]
102
+ let translationFiles = stringsFiles. dropFirst ( )
103
+ for file in translationFiles {
104
+ let translationFile = try ! File ( path: file. argument)
105
+ parseAndValidateXCStrings (
106
+ base: try ! File ( path: base. argument) ,
107
+ translation: translationFile,
108
+ translationLanguageName: translationFile. nameExcludingExtension,
109
+ problemReporter: problemReporter)
110
+ }
111
+ problemReporter. printSummary ( )
99
112
}
100
- problemReporter. printSummary ( )
101
- }
102
113
}
103
114
}
104
115
@@ -119,32 +130,39 @@ struct AndroidStrings: HasIgnoreWithShorthand, ParsableCommand {
119
130
@Flag ( help: ignoreWarningsHelpText)
120
131
fileprivate var ignoreWarnings = false
121
132
133
+ @Flag ( help: treatWarningsAsErrorsHelpText)
134
+ fileprivate var treatWarningsAsErrors = false
135
+
122
136
func validate( ) throws {
123
137
try stringsFiles. forEach { try $0. validate ( ext: " xml " ) }
124
138
}
125
139
126
140
func run( ) {
127
- withProblemReporter ( root: " " , ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
128
- let baseFile = stringsFiles [ 0 ]
129
- let translationFiles = stringsFiles. dropFirst ( )
130
- if translationFiles. isEmpty {
131
- // Just do what we can with the base language, i.e. validate plurals
132
- _ = AndroidStringsFile ( path: baseFile. argument, problemReporter: problemReporter)
133
- }
134
- for file in translationFiles {
135
- let translationFile = try ! File ( path: file. argument)
136
- var translationLanguageName = translationFile. parent!. nameExcludingExtension
137
- if translationLanguageName. hasPrefix ( " values- " ) {
138
- translationLanguageName = String ( translationLanguageName. dropFirst ( " values- " . count) )
141
+ withProblemReporter (
142
+ root: " " ,
143
+ ignore: ignoreWithShorthand,
144
+ ignoreWarnings: ignoreWarnings,
145
+ treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
146
+ let baseFile = stringsFiles [ 0 ]
147
+ let translationFiles = stringsFiles. dropFirst ( )
148
+ if translationFiles. isEmpty {
149
+ // Just do what we can with the base language, i.e. validate plurals
150
+ _ = AndroidStringsFile ( path: baseFile. argument, problemReporter: problemReporter)
151
+ }
152
+ for file in translationFiles {
153
+ let translationFile = try ! File ( path: file. argument)
154
+ var translationLanguageName = translationFile. parent!. nameExcludingExtension
155
+ if translationLanguageName. hasPrefix ( " values- " ) {
156
+ translationLanguageName = String ( translationLanguageName. dropFirst ( " values- " . count) )
157
+ }
158
+ parseAndValidateAndroidStrings (
159
+ base: try ! File ( path: baseFile. argument) ,
160
+ translation: translationFile,
161
+ translationLanguageName: translationLanguageName,
162
+ problemReporter: problemReporter)
139
163
}
140
- parseAndValidateAndroidStrings (
141
- base: try ! File ( path: baseFile. argument) ,
142
- translation: translationFile,
143
- translationLanguageName: translationLanguageName,
144
- problemReporter: problemReporter)
164
+ problemReporter. printSummary ( )
145
165
}
146
- problemReporter. printSummary ( )
147
- }
148
166
}
149
167
}
150
168
@@ -164,30 +182,38 @@ struct Stringsdict: HasIgnoreWithShorthand, ParsableCommand {
164
182
@Flag ( help: ignoreWarningsHelpText)
165
183
fileprivate var ignoreWarnings = false
166
184
185
+ @Flag ( help: treatWarningsAsErrorsHelpText)
186
+ fileprivate var treatWarningsAsErrors = false
187
+
167
188
func validate( ) throws {
168
189
try stringsdictFiles. forEach { try $0. validate ( ext: " stringsdict " ) }
169
190
}
170
191
171
192
func run( ) {
172
- withProblemReporter ( root: " " , ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
173
- let baseFile = stringsdictFiles [ 0 ]
174
- let translationFiles = stringsdictFiles. dropFirst ( )
175
- // Just do what we can with the base language, i.e. validate plurals
176
- if translationFiles. isEmpty, let stringsdictFile = StringsdictFile (
177
- path: baseFile. argument,
178
- problemReporter: problemReporter) {
179
- stringsdictFile. entries. forEach { _ = $0. getCanonicalArgumentList ( problemReporter: problemReporter) }
180
- }
181
- for file in translationFiles {
182
- let translationFile = try ! File ( path: file. argument)
183
- parseAndValidateStringsdict (
184
- base: try ! File ( path: baseFile. argument) ,
185
- translation: translationFile,
186
- translationLanguageName: translationFile. nameExcludingExtension,
187
- problemReporter: problemReporter)
193
+ withProblemReporter (
194
+ root: " " ,
195
+ ignore: ignoreWithShorthand,
196
+ ignoreWarnings: ignoreWarnings,
197
+ treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
198
+ let baseFile = stringsdictFiles [ 0 ]
199
+ let translationFiles = stringsdictFiles. dropFirst ( )
200
+ // Just do what we can with the base language, i.e. validate plurals
201
+ if translationFiles. isEmpty, let stringsdictFile = StringsdictFile (
202
+ path: baseFile. argument,
203
+ problemReporter: problemReporter) {
204
+ stringsdictFile. entries
205
+ . forEach { _ = $0. getCanonicalArgumentList ( problemReporter: problemReporter) }
206
+ }
207
+ for file in translationFiles {
208
+ let translationFile = try ! File ( path: file. argument)
209
+ parseAndValidateStringsdict (
210
+ base: try ! File ( path: baseFile. argument) ,
211
+ translation: translationFile,
212
+ translationLanguageName: translationFile. nameExcludingExtension,
213
+ problemReporter: problemReporter)
214
+ }
215
+ problemReporter. printSummary ( )
188
216
}
189
- problemReporter. printSummary ( )
190
- }
191
217
}
192
218
}
193
219
@@ -207,6 +233,9 @@ struct Lproj: HasIgnoreWithShorthand, ParsableCommand {
207
233
@Flag ( help: ignoreWarningsHelpText)
208
234
fileprivate var ignoreWarnings = false
209
235
236
+ @Flag ( help: treatWarningsAsErrorsHelpText)
237
+ fileprivate var treatWarningsAsErrors = false
238
+
210
239
func validate( ) throws {
211
240
try lprojFiles. forEach { try $0. validate ( ext: " lproj " ) }
212
241
}
@@ -219,21 +248,25 @@ struct Lproj: HasIgnoreWithShorthand, ParsableCommand {
219
248
" Validating \( translationFiles. count) lproj files against \( try ! Folder ( path: baseFile. argument) . name) " )
220
249
}
221
250
222
- withProblemReporter ( root: " " , ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
223
- // Same as in DiscoverLproj command below
224
- if translationFiles. isEmpty {
225
- // Just do what we can with the base language, i.e. validate plurals
226
- let lprojFiles = LprojFiles ( folder: try ! Folder ( path: baseFile. argument) )
227
- lprojFiles. validateInternally ( problemReporter: problemReporter)
228
- }
229
- for translation in translationFiles {
230
- validateLproj (
231
- base: LprojFiles ( folder: try ! Folder ( path: baseFile. argument) ) ,
232
- translation: LprojFiles ( folder: try ! Folder ( path: translation. argument) ) ,
233
- problemReporter: problemReporter)
251
+ withProblemReporter (
252
+ root: " " ,
253
+ ignore: ignoreWithShorthand,
254
+ ignoreWarnings: ignoreWarnings,
255
+ treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
256
+ // Same as in DiscoverLproj command below
257
+ if translationFiles. isEmpty {
258
+ // Just do what we can with the base language, i.e. validate plurals
259
+ let lprojFiles = LprojFiles ( folder: try ! Folder ( path: baseFile. argument) )
260
+ lprojFiles. validateInternally ( problemReporter: problemReporter)
261
+ }
262
+ for translation in translationFiles {
263
+ validateLproj (
264
+ base: LprojFiles ( folder: try ! Folder ( path: baseFile. argument) ) ,
265
+ translation: LprojFiles ( folder: try ! Folder ( path: translation. argument) ) ,
266
+ problemReporter: problemReporter)
267
+ }
268
+ problemReporter. printSummary ( )
234
269
}
235
- problemReporter. printSummary ( )
236
- }
237
270
}
238
271
}
239
272
@@ -258,6 +291,9 @@ struct DiscoverLproj: HasIgnoreWithShorthand, ParsableCommand {
258
291
@Flag ( help: ignoreWarningsHelpText)
259
292
fileprivate var ignoreWarnings = false
260
293
294
+ @Flag ( help: treatWarningsAsErrorsHelpText)
295
+ fileprivate var treatWarningsAsErrors = false
296
+
261
297
func validate( ) throws {
262
298
for directory in directories {
263
299
try directory. validate ( )
@@ -296,7 +332,8 @@ struct DiscoverLproj: HasIgnoreWithShorthand, ParsableCommand {
296
332
withProblemReporter (
297
333
root: directory. argument,
298
334
ignore: ignoreWithShorthand,
299
- ignoreWarnings: ignoreWarnings) { problemReporter in
335
+ ignoreWarnings: ignoreWarnings,
336
+ treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
300
337
// Same as in Lproj command above
301
338
if translationLproj. isEmpty {
302
339
// Just do what we can with the base language, i.e. validate plurals
@@ -329,6 +366,9 @@ struct DiscoverValues: HasIgnoreWithShorthand, ParsableCommand {
329
366
@Flag ( help: ignoreWarningsHelpText)
330
367
fileprivate var ignoreWarnings = false
331
368
369
+ @Flag ( help: treatWarningsAsErrorsHelpText)
370
+ fileprivate var treatWarningsAsErrors = false
371
+
332
372
func validate( ) throws {
333
373
for directory in directories {
334
374
try directory. validate ( )
@@ -378,7 +418,8 @@ struct DiscoverValues: HasIgnoreWithShorthand, ParsableCommand {
378
418
withProblemReporter (
379
419
root: directory. argument,
380
420
ignore: ignoreWithShorthand,
381
- ignoreWarnings: ignoreWarnings) { problemReporter in
421
+ ignoreWarnings: ignoreWarnings,
422
+ treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
382
423
for translation in translationValues {
383
424
parseAndValidateAndroidStrings (
384
425
base: primaryValues,
0 commit comments