// // LFFolder.m // Localize Folder // // Created by Kim Wittenburg on 05.07.13. // Copyright (c) 2013 Kim Wittenburg. All rights reserved. // #import "LFFolder.h" #import NSString *const LFLocalizedFolderExtension = @"localized"; NSString *const LFLocalizedFolderExtensionWithPeriod = @".localized"; NSString *const LFLocalizedFolderSubdirName = @".localized"; @implementation LFFolder #pragma mark *** Checking Directory Permissions + (BOOL)isDirectoryAtPathSupported:(NSString *)path { return [self canReadFromDirectoryAtPath:path]; } + (BOOL)isDirectoryAtURLSupported:(NSURL *)url { return [self canReadFromDirectoryAtURL:url]; } + (BOOL)canReadFromDirectoryAtPath:(NSString *)path { return [[NSFileManager defaultManager] isReadableFileAtPath:path]; } + (BOOL)canReadFromDirectoryAtURL:(NSURL *)url { return [[NSFileManager defaultManager] isReadableFileAtPath:url.absoluteString]; } + (BOOL)canWriteToDirectoryAtPath:(NSString *)path { return [[NSFileManager defaultManager] isWritableFileAtPath:path]; } + (BOOL)canWriteToDIrectoryAtURL:(NSURL *)url { return [[NSFileManager defaultManager] isWritableFileAtPath:url.absoluteString]; } #pragma mark *** Initialization *** - (id)init { self = [super init]; if (self) { self.translations = [NSMutableDictionary new]; } return self; } - (id)initWithURL:(NSURL *)url { self = [self init]; if (self) { [self loadTranslationsFromURL:url]; } return self; } - (id)initWithURL:(NSURL *)url error:(NSError *__autoreleasing *)error { self = [self init]; if (self) { [self loadTranslationsFromURL:url error:error]; } return self; } - (id)initWithFileWrapper:(NSFileWrapper *)fileWrapper { self = [self init]; if (self) { [self loadTranslationsFromFileWrapper:fileWrapper]; } return self; } - (id)initWithFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error { self = [self init]; if (self) { [self loadTranslationsFromFileWrapper:fileWrapper error:NULL]; } return self; } #pragma mark *** Getting the File Manager *** - (NSFileManager *)fileManager { return [NSFileManager defaultManager]; } #pragma mark *** Loading Translations *** - (BOOL)loadTranslationsFromURL:(NSURL *)url { return [self loadTranslationsFromURL:url error:NULL]; } - (BOOL)loadTranslationsFromURL:(NSURL *)url error:(NSError *__autoreleasing *)error { self.folderName = [self folderNameForURL:url]; NSURL *localizedDirectoryURL = [url URLByAppendingPathComponent:LFLocalizedFolderSubdirName isDirectory:YES]; if ([self.fileManager fileExistsAtPath:localizedDirectoryURL.path]) { NSArray *localizationFileURLs = [self.fileManager contentsOfDirectoryAtURL:localizedDirectoryURL includingPropertiesForKeys:nil options:0 error:error]; if (!localizationFileURLs) { return NO; } for (NSURL *localizationFile in localizationFileURLs) { if (![self addTranslationFromURL:localizationFile error:error]) { return NO; } } return YES; } else { // translations dictionary was initialized during [self init] return YES; } } - (BOOL)loadTranslationsFromFileWrapper:(NSFileWrapper *)fileWrapper { return [self loadTranslationsFromFileWrapper:fileWrapper error:NULL]; } - (BOOL)loadTranslationsFromFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error { self.folderName = [self folderNameForFileWrapper:fileWrapper]; NSFileWrapper *localizedDirectoryWrapper = fileWrapper.fileWrappers[LFLocalizedFolderSubdirName]; if (localizedDirectoryWrapper) { for (NSFileWrapper *localizationFile in localizedDirectoryWrapper.fileWrappers) { if (![self addTranslationFromFileWrapper:localizationFile error:error]) { return NO; } } return YES; } else { // translations dictionary was initialized during [self init] return YES; } } - (BOOL)addTranslationFromURL:(NSURL *)url error:(NSError *__autoreleasing *)error { NSString *localeID = [self localeIdentifierForURL:url]; return [self addTranslationFromURL:url forLocale:localeID error:error]; } - (BOOL)addTranslationFromFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error { NSString *localeID = [self localeIdentifierForFileWrapper:fileWrapper]; return [self addTranslationFromFileWrapper:fileWrapper forLocale:localeID error:error]; } - (NSString *)localeIdentifierForURL:(NSURL *)url { return url.lastPathComponent.stringByDeletingPathExtension; } - (NSString *)localeIdentifierForFileWrapper:(NSFileWrapper *)fileWrapper { NSString *localeID = fileWrapper.filename; if (localeID.length == 0) { localeID = fileWrapper.preferredFilename; } localeID = localeID.stringByDeletingPathExtension; return localeID; } - (BOOL)addTranslationFromURL:(NSURL *)url forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error { NSString *stringsFile = [NSString stringWithContentsOfURL:url usedEncoding:NULL error:error]; if (!stringsFile) { return NO; } return [self addTranslationFromStringsFile:stringsFile forLocale:localeID error:error]; } - (BOOL)addTranslationFromFileWrapper:(NSFileWrapper *)fileWrapper forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error { NSString *stringsFile = [[NSString alloc] initWithData:fileWrapper.serializedRepresentation encoding:NSUnicodeStringEncoding]; if (!stringsFile) { return NO; } return [self addTranslationFromStringsFile:stringsFile forLocale:localeID error:error]; } - (BOOL)addTranslationFromStringsFile:(NSString *)stringsFile forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error { NSDictionary *translationDict = stringsFile.propertyListFromStringsFileFormat; if (translationDict.count > 0) { NSString *value = translationDict.allValues[0]; self.translations[localeID] = value; } return YES; } #pragma mark *** Saving Translations *** - (BOOL)saveTranslationsToURL:(NSURL *)url { return [self saveTranslationsToURL:url error:NULL]; } - (BOOL)saveTranslationsToURL:(NSURL *)url error:(NSError *__autoreleasing *)error { NSURL *localizedDirectoryURL = [url URLByAppendingPathComponent:LFLocalizedFolderSubdirName isDirectory:YES]; [self.fileManager removeItemAtURL:localizedDirectoryURL error:NULL]; // If deleting fails continue, maybe we can just replace any existing subfiles. if (![self.fileManager createDirectoryAtURL:localizedDirectoryURL withIntermediateDirectories:YES attributes:nil error:error]) { return NO; } NSString *folderName; if (self.folderName.length > 0) { folderName = self.folderName; } else { folderName = [self folderNameForURL:url]; } for (NSString *localeID in self.translations.allKeys) { NSString *filename = [NSString stringWithFormat:@"%@.strings", localeID]; NSURL *fileURL = [localizedDirectoryURL URLByAppendingPathComponent:filename]; NSString *stringsFile = @{folderName: self.translations[localeID]}.descriptionInStringsFileFormat; if (![stringsFile writeToURL:fileURL atomically:YES encoding:NSUnicodeStringEncoding error:error]) { return NO; } } return YES; } - (BOOL)saveTranslationsToFileWrapper:(NSFileWrapper *)fileWrapper { return [self saveTranslationsToFileWrapper:fileWrapper error:NULL]; } - (BOOL)saveTranslationsToFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error { NSFileWrapper *localizedDirectoryWrapper = fileWrapper.fileWrappers[LFLocalizedFolderSubdirName]; if (localizedDirectoryWrapper) { [fileWrapper removeFileWrapper:localizedDirectoryWrapper]; } NSString *folderName; if (self.folderName.length > 0) { folderName = self.folderName; } else { folderName = [self folderNameForFileWrapper:fileWrapper]; } localizedDirectoryWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:@{}]; localizedDirectoryWrapper.preferredFilename = LFLocalizedFolderSubdirName; for (NSString *localeID in self.translations.allKeys) { NSString *filename = [NSString stringWithFormat:@"%@.strings", localeID]; NSString *stringsFile = @{folderName: self.translations[localeID]}.descriptionInStringsFileFormat; NSData *stringsData = [stringsFile dataUsingEncoding:NSUnicodeStringEncoding]; if (!stringsData) { return NO; } [localizedDirectoryWrapper addRegularFileWithContents:stringsData preferredFilename:filename]; } [fileWrapper addFileWrapper:localizedDirectoryWrapper]; return YES; } - (NSString *)folderNameForURL:(NSURL *)url { NSString *filename = url.lastPathComponent; if ([filename hasSuffix:LFLocalizedFolderExtensionWithPeriod]) { return filename.stringByDeletingPathExtension; } return filename; } - (NSString *)folderNameForFileWrapper:(NSFileWrapper *)fileWrapper { NSString *filename = fileWrapper.filename; if (filename.length == 0) { filename = fileWrapper.preferredFilename; } if ([filename hasSuffix:LFLocalizedFolderExtensionWithPeriod]) { return filename.stringByDeletingPathExtension; } return filename; } @end