@@ -83,13 +83,12 @@ class CrowdinSupportedLanguages {
8383 UserDefaults . standard. removeObject ( forKey: Keys . lastUpdatedDate. rawValue)
8484 UserDefaults . standard. synchronize ( )
8585
86+ // Only remove legacy (pre-hash) supported languages cache files.
87+ // Legacy files have the pattern "SupportedLanguages.json" (without a hash).
88+ let legacyFileName = Strings . supportedLanguages. rawValue + FileType. json. extension
8689 let folderPath = CrowdinFolder . shared. path + String. pathDelimiter + Strings. crowdin. rawValue
87- if let files = try ? FileManager . default. contentsOfDirectory ( atPath: folderPath) {
88- for file in files where file. starts ( with: Strings . supportedLanguages. rawValue) && !file. contains ( hash) {
89- let fullPath = folderPath + String. pathDelimiter + file
90- try ? FileManager . default. removeItem ( atPath: fullPath)
91- }
92- }
90+ let legacyFilePath = folderPath + String. pathDelimiter + legacyFileName
91+ try ? FileManager . default. removeItem ( atPath: legacyFilePath)
9392 }
9493
9594 func updateSupportedLanguagesIfNeeded( manifestTimestamp: TimeInterval ? , completion: ( ( ) -> Void ) ? = nil , error: ( ( Error ) -> Void ) ? = nil ) {
@@ -257,6 +256,12 @@ class CrowdinSupportedLanguages {
257256 if let languages = languages {
258257 self . _supportedLanguages = languages
259258 self . saveSupportedLanguages ( )
259+ } else if self . _supportedLanguages == nil {
260+ // On 304 (Not Modified), load from cache if we don't have it in memory yet
261+ let cachedData = try ? Data ( contentsOf: URL ( fileURLWithPath: self . filePath) )
262+ if let data = cachedData {
263+ self . _supportedLanguages = try ? JSONDecoder ( ) . decode ( [ DistributionLanguage ] . self, from: data)
264+ }
260265 }
261266 let completions = self . _completions
262267 self . _errors. removeAll ( )
@@ -278,8 +283,19 @@ class CrowdinSupportedLanguages {
278283 }
279284
280285 fileprivate func saveSupportedLanguages( ) {
281- guard let languages = _supportedLanguages as? [ DistributionLanguage ] ,
282- let data = try ? JSONEncoder ( ) . encode ( languages) else { return }
286+ // Read the current supported languages on the serial queue for thread safety
287+ let currentLanguages : [ CrowdinLanguage ] ? = queue. sync { _supportedLanguages }
288+
289+ guard let crowdlanguages = currentLanguages else { return }
290+
291+ // Cast each element individually to DistributionLanguage. A direct cast from
292+ // [CrowdinLanguage] to [DistributionLanguage] will always fail for existential arrays.
293+ let distributionLanguages = crowdlanguages. compactMap { $0 as? DistributionLanguage }
294+
295+ // Ensure all elements were successfully cast; if not, avoid writing a partial cache.
296+ guard distributionLanguages. count == crowdlanguages. count,
297+ let data = try ? JSONEncoder ( ) . encode ( distributionLanguages) else { return }
298+
283299 try ? data. write ( to: URL ( fileURLWithPath: filePath) , options: Data . WritingOptions. atomic)
284300 }
285301
0 commit comments