@@ -40,7 +40,7 @@ struct LocalizableStrings : WhiteListedExtensionsResourceType {
40
40
let dictionary : [ String : ( params: [ StringParam ] , commentValue: String ) ]
41
41
switch url. pathExtension {
42
42
case " strings " ? :
43
- dictionary = try parseStrings ( nsDictionary , source: locale. withFilename ( " \( filename) .strings " ) )
43
+ dictionary = try parseStrings ( String ( contentsOfURL : url ) , source: locale. withFilename ( " \( filename) .strings " ) )
44
44
case " stringsdict " ? :
45
45
dictionary = try parseStringsdict ( nsDictionary, source: locale. withFilename ( " \( filename) .stringsdict " ) )
46
46
default :
@@ -53,37 +53,63 @@ struct LocalizableStrings : WhiteListedExtensionsResourceType {
53
53
}
54
54
}
55
55
56
- private func parseStrings( nsDictionary : NSDictionary , source: String ) throws -> [ String : ( params: [ StringParam ] , commentValue: String ) ] {
56
+ private func parseStrings( stringsFile : String , source: String ) throws -> [ String : ( params: [ StringParam ] , commentValue: String ) ] {
57
57
var dictionary : [ String : ( params: [ StringParam ] , commentValue: String ) ] = [ : ]
58
58
59
- for ( key, obj) in nsDictionary {
60
- if let
61
- key = key as? String ,
62
- val = obj as? String
63
- {
59
+ for entry in StringsEntry . parse ( stringsFile) {
64
60
var params : [ StringParam ] = [ ]
65
61
66
- for part in FormatPart . formatParts ( formatString: val) {
62
+ for part in FormatPart . formatParts ( formatString: entry . val) {
67
63
switch part {
68
64
case . Reference:
69
- throw ResourceParsingError . ParsingFailed ( " Non-specifier reference in \( source) : \( key) = \( val) " )
65
+ throw ResourceParsingError . ParsingFailed ( " Non-specifier reference in \( source) : \( entry . key) = \( entry . val) " )
70
66
71
67
case . Spec( let formatSpecifier) :
72
68
params. append ( StringParam ( name: nil , spec: formatSpecifier) )
73
69
}
74
70
}
75
71
76
-
77
- dictionary [ key] = ( params, val)
78
- }
79
- else {
80
- throw ResourceParsingError . ParsingFailed ( " Non-string value in \( source) : \( key) = \( obj) " )
81
- }
72
+ dictionary [ entry. key] = ( params, entry. val)
82
73
}
83
74
84
75
return dictionary
85
76
}
86
77
78
+ private struct StringsEntry {
79
+ let comment : String ?
80
+ let key : String
81
+ let val : String
82
+
83
+ static let regex : NSRegularExpression = {
84
+ let capturedTrimmedComment = " /[*] \\ s* (.*?) \\ s* [*]/ "
85
+ let whitespaceOrComment = " (?: \\ s | /[*] .*? [*]/) "
86
+ let slash = " \\ \\ "
87
+ let quotedString = " \" .*? (?<! \( slash) ) \" "
88
+ let unquotedString = " [^ \\ s \( slash) \" =]+ "
89
+ let string = " (?: \( quotedString) | \( unquotedString) ) "
90
+ let pattern = " (?: \( capturedTrimmedComment) )? \\ s* ( \( string) ) \( whitespaceOrComment) * = \( whitespaceOrComment) * ( \( string) ) \( whitespaceOrComment) * ; "
91
+ return try ! NSRegularExpression ( pattern: pattern, options: [ . AllowCommentsAndWhitespace, . DotMatchesLineSeparators] )
92
+ } ( )
93
+
94
+ init ( source: String , match: NSTextCheckingResult ) {
95
+ guard match. numberOfRanges == 4 else { fatalError ( " must be used with StringsEntry.regex " ) }
96
+ func extract( range: NSRange , unescape: Bool ) -> String ? {
97
+ guard range. location != NSNotFound else { return nil }
98
+ let raw = ( source as NSString ) . substringWithRange ( range)
99
+ if !unescape { return raw }
100
+ return try ! NSPropertyListSerialization . propertyListWithData ( raw. dataUsingEncoding ( NSUTF8StringEncoding) !, options: [ ] , format: nil ) as! String
101
+ }
102
+ comment = extract ( match. rangeAtIndex ( 1 ) , unescape: false )
103
+ key = extract ( match. rangeAtIndex ( 2 ) , unescape: true ) !
104
+ val = extract ( match. rangeAtIndex ( 3 ) , unescape: true ) !
105
+ }
106
+
107
+ static func parse( stringsFileContents: String ) -> [ StringsEntry ] {
108
+ return regex. matchesInString ( stringsFileContents, options: [ ] , range: NSRange ( 0 ..< stringsFileContents. utf16. count) )
109
+ . map { StringsEntry ( source: stringsFileContents, match: $0) }
110
+ }
111
+ }
112
+
87
113
private func parseStringsdict( nsDictionary: NSDictionary , source: String ) throws -> [ String : ( params: [ StringParam ] , commentValue: String ) ] {
88
114
89
115
var dictionary : [ String : ( params: [ StringParam ] , commentValue: String ) ] = [ : ]
0 commit comments