1

Version 1.1

This commit is contained in:
Kim Wittenburg
2014-04-01 13:33:09 +02:00
parent 5516fb1792
commit ba5f4c2f1a
19 changed files with 1599 additions and 4858 deletions

BIN
Localize Folder.icns Normal file

Binary file not shown.

View File

@@ -11,9 +11,13 @@
3BF045D017870AD800B36BD3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3BF045CE17870AD800B36BD3 /* InfoPlist.strings */; };
3BF045D217870AD800B36BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF045D117870AD800B36BD3 /* main.m */; };
3BF045D617870AD800B36BD3 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 3BF045D417870AD800B36BD3 /* Credits.rtf */; };
3BF045D917870AD800B36BD3 /* LFDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF045D817870AD800B36BD3 /* LFDocument.m */; };
3BF045DC17870AD800B36BD3 /* LFDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3BF045DA17870AD800B36BD3 /* LFDocument.xib */; };
3BF045DF17870AD900B36BD3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3BF045DD17870AD900B36BD3 /* MainMenu.xib */; };
3BF045E717870B0900B36BD3 /* LFFolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF045E617870B0900B36BD3 /* LFFolder.m */; };
3BF045ED17874F1800B36BD3 /* LFDocumentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF045EC17874F1800B36BD3 /* LFDocumentController.m */; };
3BF045F0178789F600B36BD3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3BF045EE178789F600B36BD3 /* Localizable.strings */; };
3BF045F71788A3EB00B36BD3 /* Localize Folder.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3BF045F61788A3EB00B36BD3 /* Localize Folder.icns */; };
3BF045F81788C6A600B36BD3 /* LFDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF045D817870AD800B36BD3 /* LFDocument.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -31,6 +35,17 @@
3BF045D817870AD800B36BD3 /* LFDocument.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LFDocument.m; sourceTree = "<group>"; };
3BF045DB17870AD800B36BD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/LFDocument.xib; sourceTree = "<group>"; };
3BF045DE17870AD900B36BD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
3BF045E517870B0900B36BD3 /* LFFolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFFolder.h; sourceTree = "<group>"; };
3BF045E617870B0900B36BD3 /* LFFolder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFFolder.m; sourceTree = "<group>"; };
3BF045EB17874F1800B36BD3 /* LFDocumentController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFDocumentController.h; sourceTree = "<group>"; };
3BF045EC17874F1800B36BD3 /* LFDocumentController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFDocumentController.m; sourceTree = "<group>"; };
3BF045EF178789F600B36BD3 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
3BF045F117878B4200B36BD3 /* de */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = de; path = de.lproj/LFDocument.xib; sourceTree = "<group>"; };
3BF045F217878B4200B36BD3 /* de */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = de; path = de.lproj/MainMenu.xib; sourceTree = "<group>"; };
3BF045F317878B4200B36BD3 /* de */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
3BF045F417878B4200B36BD3 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
3BF045F517878B4200B36BD3 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = de; path = de.lproj/Credits.rtf; sourceTree = "<group>"; };
3BF045F61788A3EB00B36BD3 /* Localize Folder.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "Localize Folder.icns"; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -84,10 +99,16 @@
3BF045CB17870AD800B36BD3 /* Localize Folder */ = {
isa = PBXGroup;
children = (
3BF045F61788A3EB00B36BD3 /* Localize Folder.icns */,
3BF045E517870B0900B36BD3 /* LFFolder.h */,
3BF045E617870B0900B36BD3 /* LFFolder.m */,
3BF045D717870AD800B36BD3 /* LFDocument.h */,
3BF045D817870AD800B36BD3 /* LFDocument.m */,
3BF045DA17870AD800B36BD3 /* LFDocument.xib */,
3BF045DD17870AD900B36BD3 /* MainMenu.xib */,
3BF045EB17874F1800B36BD3 /* LFDocumentController.h */,
3BF045EC17874F1800B36BD3 /* LFDocumentController.m */,
3BF045EE178789F600B36BD3 /* Localizable.strings */,
3BF045CC17870AD800B36BD3 /* Supporting Files */,
);
path = "Localize Folder";
@@ -141,6 +162,7 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
de,
);
mainGroup = 3BF045B917870AD700B36BD3;
productRefGroup = 3BF045C317870AD800B36BD3 /* Products */;
@@ -161,6 +183,8 @@
3BF045D617870AD800B36BD3 /* Credits.rtf in Resources */,
3BF045DC17870AD800B36BD3 /* LFDocument.xib in Resources */,
3BF045DF17870AD900B36BD3 /* MainMenu.xib in Resources */,
3BF045F0178789F600B36BD3 /* Localizable.strings in Resources */,
3BF045F71788A3EB00B36BD3 /* Localize Folder.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -172,7 +196,9 @@
buildActionMask = 2147483647;
files = (
3BF045D217870AD800B36BD3 /* main.m in Sources */,
3BF045D917870AD800B36BD3 /* LFDocument.m in Sources */,
3BF045E717870B0900B36BD3 /* LFFolder.m in Sources */,
3BF045ED17874F1800B36BD3 /* LFDocumentController.m in Sources */,
3BF045F81788C6A600B36BD3 /* LFDocument.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -183,6 +209,7 @@
isa = PBXVariantGroup;
children = (
3BF045CF17870AD800B36BD3 /* en */,
3BF045F417878B4200B36BD3 /* de */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
@@ -191,6 +218,7 @@
isa = PBXVariantGroup;
children = (
3BF045D517870AD800B36BD3 /* en */,
3BF045F517878B4200B36BD3 /* de */,
);
name = Credits.rtf;
sourceTree = "<group>";
@@ -199,6 +227,7 @@
isa = PBXVariantGroup;
children = (
3BF045DB17870AD800B36BD3 /* en */,
3BF045F117878B4200B36BD3 /* de */,
);
name = LFDocument.xib;
sourceTree = "<group>";
@@ -207,10 +236,20 @@
isa = PBXVariantGroup;
children = (
3BF045DE17870AD900B36BD3 /* en */,
3BF045F217878B4200B36BD3 /* de */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
3BF045EE178789F600B36BD3 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
3BF045EF178789F600B36BD3 /* en */,
3BF045F317878B4200B36BD3 /* de */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@@ -316,6 +355,7 @@
3BF045E417870AD900B36BD3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};

View File

@@ -8,6 +8,12 @@
#import <Cocoa/Cocoa.h>
@interface LFDocument : NSDocument
#import "LFFolder.h"
@interface LFDocument : NSDocument <NSOpenSavePanelDelegate>
@property (strong, nonatomic) LFFolder *folder;
- (IBAction)applyTo:(id)sender;
@end

View File

@@ -8,52 +8,191 @@
#import "LFDocument.h"
@implementation LFDocument
void *const FolderNameChangedContext = @"FolderNameChangedContext";
void *const TranslationsChangedContext = @"TranslationsChangedContext";
@implementation LFDocument {
NSString *_lastSavePanelEnteredFilename;
NSString *_lastFolderName;
}
- (id)init
{
self = [super init];
if (self) {
// Add your subclass-specific initialization here.
self.folder = [[LFFolder alloc] init];
}
return self;
}
- (void)setFolder:(LFFolder *)f
{
[_folder removeObserver:self forKeyPath:@"translations"];
[_folder removeObserver:self forKeyPath:@"folderName"];
_folder = f;
[_folder addObserver:self forKeyPath:@"translations" options:NSKeyValueObservingOptionOld context:TranslationsChangedContext];
[_folder addObserver:self forKeyPath:@"folderName" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:FolderNameChangedContext];
}
- (void)dealloc
{
[_folder removeObserver:self forKeyPath:@"translations"];
[_folder removeObserver:self forKeyPath:@"folderName"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == TranslationsChangedContext) {
NSMutableDictionary *oldValue = change[NSKeyValueChangeOldKey];
[self.undoManager registerUndoWithTarget:self.folder selector:@selector(setTranslations:) object:oldValue];
} else if (context == FolderNameChangedContext) {
NSString *oldName = change[NSKeyValueChangeOldKey];
NSString *newName = change[NSKeyValueChangeNewKey];
[self renameFolderFrom:oldName to:newName];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)renameFolderFrom:(id)oldName to:(id)newName
{
if (oldName == [NSNull null] || !oldName) {
// Ignore initial change
return;
}
if ([oldName isEqual:newName]) {
return;
}
if ([newName isEqual:self.fileURL.lastPathComponent.stringByDeletingPathExtension]) {
return;
}
NSString *actualNewName = [newName stringByAppendingPathExtension:LFLocalizedFolderExtension];
NSURL *newURL = [self.fileURL.URLByDeletingLastPathComponent URLByAppendingPathComponent:actualNewName isDirectory:YES];
if ([[NSFileManager defaultManager] fileExistsAtPath:newURL.path]) {
_lastFolderName = oldName;
NSBeginAlertSheet(NSLocalizedString(@"The folder could not be renamed", nil), @"OK", nil, nil, self.windowForSheet, self, NULL, @selector(renameFolderSheetDidDismiss:returnCode:contextInfo:), NULL, NSLocalizedString(@"Another folder with the same name already exists at that location. Rename the existing folder or choose another name.", nil));
return;
}
[self moveToURL:newURL completionHandler:^(NSError *error) {
if (error) {
[self presentError:error];
}
}];
}
- (void)renameFolderSheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
self.folder.folderName = _lastFolderName;
}
- (NSString *)windowNibName
{
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return @"LFDocument";
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
- (NSString *)autosavingFileType
{
[super windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
+ (BOOL)autosavesInPlace
{
return YES;
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning nil.
// You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
NSException *exception = [NSException exceptionWithName:@"UnimplementedMethod" reason:[NSString stringWithFormat:@"%@ is unimplemented", NSStringFromSelector(_cmd)] userInfo:nil];
@throw exception;
// Autosave is disabled
return nil;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
- (void)saveDocumentWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void *)contextInfo
{
// Insert code here to read your document from the given data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
NSException *exception = [NSException exceptionWithName:@"UnimplementedMethod" reason:[NSString stringWithFormat:@"%@ is unimplemented", NSStringFromSelector(_cmd)] userInfo:nil];
@throw exception;
if (!self.fileURL) {
[super saveDocumentWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
} else {
NSString *title = NSLocalizedString(@"Do you want do delete the contents of the folder?", nil);
NSString *deleteButton = NSLocalizedString(@"Delete Folder's Contents", nil);
NSString *cancelButton = NSLocalizedString(@"Cancel", nil);
NSString *applyButton = NSLocalizedString(@"Apply to...", nil);
NSString *msgFormat = NSLocalizedString(@"If you save this document the contents of the folder will be deleted. If you want to keep the folder's contents select \"Apply to...\" and select the folder. In either way, this operation can not be undone.", nil);
NSBeginCriticalAlertSheet(title, applyButton, cancelButton, deleteButton, self.windowForSheet, self, NULL, @selector(saveWarningSheetDidDismiss:returnCode:contextInfo:), NULL, @"%@", msgFormat);
}
}
- (void)saveWarningSheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if (returnCode == NSAlertDefaultReturn) {
[self applyTo:self];
} else if (returnCode == NSAlertOtherReturn) {
[super saveDocumentWithDelegate:nil didSaveSelector:NULL contextInfo:NULL];
}
}
- (IBAction)applyTo:(id)sender
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
openPanel.canChooseDirectories = YES;
openPanel.canChooseFiles = NO;
openPanel.allowsMultipleSelection = NO;
openPanel.canCreateDirectories = YES;
openPanel.message = NSLocalizedString(@"Select a directory you want to apply the current translations to", nil);
openPanel.prompt = NSLocalizedString(@"Select", nil);
[openPanel beginSheetModalForWindow:self.windowForSheet completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton) {
[self applyToURL:openPanel.URL];
}
}];
}
- (void)applyToURL:(NSURL *)url
{
NSError *error;
NSURL *actualURL = url;
if (![actualURL.lastPathComponent hasSuffix:LFLocalizedFolderExtensionWithPeriod]) {
actualURL = [actualURL URLByAppendingPathExtension:LFLocalizedFolderExtension];
if ([[NSFileManager defaultManager] fileExistsAtPath:actualURL.path]) {
NSRunAlertPanel(NSLocalizedString(@"The folder could not be localized", nil), NSLocalizedString(@"Another folder with the name \"%@\" already exists", nil), NSLocalizedString(@"OK", nil), nil, nil, actualURL.lastPathComponent);
return;
}
[[NSFileManager defaultManager] moveItemAtURL:url toURL:actualURL error:&error];
if (error) {
[self presentError:error];
return;
}
}
LFFolder *folder = [[LFFolder alloc] initWithURL:actualURL error:&error];
if (error) {
[self presentError:error];
return;
}
folder.translations = self.folder.translations.copy;
[folder saveTranslationsToURL:actualURL error:&error];
if (error) {
[self presentError:error];
}
}
- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel
{
savePanel.directoryURL = self.fileURL.URLByDeletingLastPathComponent;
savePanel.delegate = self;
return YES;
}
- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
{
NSString *newName = filename;
if (![newName hasSuffix:LFLocalizedFolderExtensionWithPeriod]) {
newName = [newName stringByAppendingPathExtension:LFLocalizedFolderExtension];
}
_lastSavePanelEnteredFilename = newName;
return newName;
}
- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
if (!self.folder.folderName) {
self.folder.folderName = _lastSavePanelEnteredFilename.stringByDeletingPathExtension;
}
return [self.folder saveTranslationsToURL:url error:outError];
}
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
self.folder = [[LFFolder alloc] init];
return [self.folder loadTranslationsFromURL:url error:outError];
}
@end

View File

@@ -0,0 +1,13 @@
//
// LFDocumentController.h
// Localize Folder
//
// Created by Kim Wittenburg on 05.07.13.
// Copyright (c) 2013 Kim Wittenburg. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface LFDocumentController : NSDocumentController
@end

View File

@@ -0,0 +1,23 @@
//
// LFDocumentController.m
// Localize Folder
//
// Created by Kim Wittenburg on 05.07.13.
// Copyright (c) 2013 Kim Wittenburg. All rights reserved.
//
#import "LFDocumentController.h"
@implementation LFDocumentController
- (NSInteger)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)types
{
// Allow the user only to open directories
openPanel.canChooseDirectories = YES;
openPanel.canChooseFiles = NO;
openPanel.treatsFilePackagesAsDirectories = NO;
openPanel.canCreateDirectories = YES;
return [super runModalOpenPanel:openPanel forTypes:types];
}
@end

114
Localize Folder/LFFolder.h Normal file
View File

@@ -0,0 +1,114 @@
//
// LFFolder.h
// Localize Folder
//
// Created by Kim Wittenburg on 05.07.13.
// Copyright (c) 2013 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString *const LFLocalizedFolderExtension;
extern NSString *const LFLocalizedFolderExtensionWithPeriod;
extern NSString *const LFLocalizedFolderSubdirName;
/* Use this class to represent and work with Localized Folders. Localized Folders are defined as the following:
1) A Localized Folder is a directory in the file system. For security reasons the default directories (such as /Applications/ or ~/Documents/) are not supported to be localized with custom translations. (Also a different localization technique is used by the system).
2) A Localized Folder must have the suffix .localized to be recognized by the system as Localized Folder.
3) Inside the folder there must be a subdirectory named .localized containing the translation files
A translation file is a file in the .strings format (using the Unicode UTF-16 encoding). The name of a translation file must match the represented locale identifier (for example de.strings or en.string for a German or English locale. You can also use exact locale identifiers as de_DE.strings for Germany or es_PE.strings for Spanish in Peru). Locale identifiers are based on the ISO 639-x/IETF BCP 47 standard.
The contents of a translation file is a single key-value-mapping in the strings file format. The key must be the actual name of the directory (exclusive the .localized extension) and the value the translation for the represented locale. The strings file de.strings in a directory named "Developer.localized" could for example contain the following:
"Developer" = "Entwickler";
*/
@interface LFFolder : NSObject
#pragma mark - *** Checking Directory Permissions ***
/* The following class methods are currently unsupported.
*/
/* Returns NO if neither writing nor reading operations can be performed on the passed file. To distinguish reading and writing permissions use canReadFromDirectoryAt...: and canWriteToDirectoryAt...:
*/
+ (BOOL)isDirectoryAtPathSupported:(NSString *)path;
+ (BOOL)isDirectoryAtURLSupported:(NSURL *)url;
/* Returns wether the given directory contents can be read. You may also want to check the writing permissions using canWriteToDirectoryAt...:
*/
+ (BOOL)canReadFromDirectoryAtPath:(NSString *)path;
+ (BOOL)canReadFromDirectoryAtURL:(NSURL *)url;
/* Returns wether you can use the given directory to write to.
*/
+ (BOOL)canWriteToDirectoryAtPath:(NSString *)path;
+ (BOOL)canWriteToDIrectoryAtURL:(NSURL *)url;
/* A dictionary of NSStrings identifying the translations for a specific locale. Use the locale identifier as key to store and receive the translated folder name.
*/
@property (strong, nonatomic) NSMutableDictionary *translations;
/* If specified this string is used as key in the localization .strings files. If not the save methods use the directory's current name. This property has no effect on the actual name of the directory the translations are written to.
*/
@property (strong, nonatomic) NSString *folderName;
#pragma mark *** Initialization ***
/* Initializer. Invoking any initializer other than the default init will cause LFFolder to send the corresponding loadTranslationsFrom...: or loadTranslationsFrom...:error: message to itself. All of the other initializers call init first.
*/
- (id)init;
- (id)initWithURL:(NSURL *)url;
- (id)initWithURL:(NSURL *)url error:(NSError *__autoreleasing *)error;
- (id)initWithFileWrapper:(NSFileWrapper *)fileWrapper;
- (id)initWithFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error;
#pragma mark *** Getting the File Manager
/* Returns the NSFileManager to be used when loading or saving translations. By default this returns the defaultManager of NSFileManager. Feel free to override this method as you need.
*/
- (NSFileManager *)fileManager;
#pragma mark *** Loading Translations ***
/* The following methods all do essentially the same: Load the translations table from a file representation. These methods expect the given directory file to be in the appropriate localized format (for a description about how to localize your folders in the appropriate format see above). If no localization files are found the translations dictionary is set to an empty dictionary (not nil) and the loading methods return successfully. If an error occurs during reading the translations NO is returned and the error parameter (if present) is set to the appropriate NSError object. If loading was successful YES is returned and the error parameter is left unmodified.
*/
- (BOOL)loadTranslationsFromURL:(NSURL *)url; // Invokes the method below with a NULL for the error parameter
- (BOOL)loadTranslationsFromURL:(NSURL *)url error:(NSError *__autoreleasing *)error;
- (BOOL)loadTranslationsFromFileWrapper:(NSFileWrapper *)fileWrapper; // Invokes the method below with a NULL for the error parameter
- (BOOL)loadTranslationsFromFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error;
/* These methods get called during the loading process but you can also call them on your own. These methods actually just call the addTranslationsFrom...:forLocale:error: methods with a locale identifer generated from the filename (that is the lastPathComponent of the url or the filename or preferredFilename of the file wrapper).
For a more detailed description see addTranslationFrom...:forLocale:error:
*/
- (BOOL)addTranslationFromURL:(NSURL *)url error:(NSError *__autoreleasing *)error;
- (BOOL)addTranslationFromFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error;
/* These methods are used to generate the locale identifier by a given file representation. The given file representation must represent one of the .strings files is the .localized subdirectory.
*/
- (NSString *)localeIdentifierForURL:(NSURL *)url;
- (NSString *)localeIdentifierForFileWrapper:(NSFileWrapper *)fileWrapper;
/* These methods get called during the loading process but you can also call them on your own. The given file representation (either an url or a file wrapper) is expected to be a .strings file. (The loadTranslationsFrom...: and loadTranslationsFrom...:error: methods expect a folder) The loaded translations are added to the translations dictionary (replacing any previous value for that locale).
*/
- (BOOL)addTranslationFromURL:(NSURL *)url forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error;
- (BOOL)addTranslationFromFileWrapper:(NSFileWrapper *)fileWrapper forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error;
/* This method gets called during the loading process but you can also call it on your own. The given strings file's contents are parsed and the first value is set in the translations dictionary for the given locale identifier (replacing any previous value for that locale).
*/
- (BOOL)addTranslationFromStringsFile:(NSString *)stringsFile forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error;
#pragma mark *** Saving Translations ***
/* The following methods all do essentially the same: Save the translations to a file representation. The translations are saved appropriately based on the corresponding locale identifier in the .strings file format. By default these methods replace the complete .localized subdirectory so any files stored there before will be deleted. If an error occurs NO is returned and the error parameter (if present) is set to the appropriate NSError object. If saving completes successfully YES is returned and the error parameter is left unmodified.
*/
- (BOOL)saveTranslationsToURL:(NSURL *)url; // Invokes the method below with a NULL for the error parameter
- (BOOL)saveTranslationsToURL:(NSURL *)url error:( NSError *__autoreleasing *)error;
- (BOOL)saveTranslationsToFileWrapper:(NSFileWrapper *)fileWrapper; // Invokes the method below with a NULL for the error parameter
- (BOOL)saveTranslationsToFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error;
/* These methods are used if the folderName property is nil or empty. They guess a name by the given file representation.
*/
- (NSString *)folderNameForURL:(NSURL *)url;
- (NSString *)folderNameForFileWrapper:(NSFileWrapper *) fileWrapper;
@end

294
Localize Folder/LFFolder.m Normal file
View File

@@ -0,0 +1,294 @@
//
// LFFolder.m
// Localize Folder
//
// Created by Kim Wittenburg on 05.07.13.
// Copyright (c) 2013 Kim Wittenburg. All rights reserved.
//
#import "LFFolder.h"
#import <Foundation/FoundationErrors.h>
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

View File

@@ -3,18 +3,21 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<string>de_DE</string>
<key>CFBundleDisplayName</key>
<string>Localize Folder</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>localized</string>
<string></string>
</array>
<key>CFBundleTypeIconFile</key>
<string></string>
<key>CFBundleTypeName</key>
<string>DocumentType</string>
<string>Localized Folder Document</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>????</string>
@@ -28,7 +31,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<string>Localize Folder</string>
<key>CFBundleIdentifier</key>
<string>wittenburg.kim.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
@@ -38,13 +41,15 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>23</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSHasLocalizedDisplayName</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>

View File

@@ -0,0 +1,24 @@
{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\f0\b\fs24 \cf0 Entwicklung:
\b0 \
Kim Wittenburg\
\
\b Design:
\b0 \
Kim Wittenburg\
\
\b Tests:
\b0 \
Kim Wittenburg\
\
\b Dokumentation:
\b0 \
Kim Wittenburg}

View File

@@ -0,0 +1,4 @@
/* Localized versions of Info.plist keys */
"CFBundleDisplayName" = "Ordner Übersetzen";
"Localize Folder" = "Ordner Übersetzen";

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="LFDocument">
<connections>
<outlet property="window" destination="5" id="18"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="5" userLabel="Window">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="133" y="235" width="544" height="408"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1028"/>
<value key="minSize" type="size" width="94" height="86"/>
<view key="contentView" id="6">
<rect key="frame" x="0.0" y="0.0" width="544" height="408"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100027">
<rect key="frame" x="111" y="366" width="413" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="100028">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="enabled" keyPath="folder.folderName" id="100099">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
<binding destination="-2" name="value" keyPath="folder.folderName" id="100103"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100033">
<rect key="frame" x="18" y="368" width="87" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Ordnername:" id="100034">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="100043">
<rect key="frame" x="20" y="61" width="504" height="297"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" id="Iw4-bx-JY2">
<rect key="frame" x="1" y="17" width="502" height="279"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" headerView="100046" id="100044">
<rect key="frame" x="0.0" y="0.0" width="502" height="279"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="116" minWidth="40" maxWidth="1000" id="100048">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Sprach-ID">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="100051">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<connections>
<binding destination="100040" name="value" keyPath="arrangedObjects.key" id="100087"/>
</connections>
</tableColumn>
<tableColumn width="380" minWidth="40" maxWidth="1000" id="100049">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Übersetzung">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="100050">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<connections>
<binding destination="100040" name="value" keyPath="arrangedObjects.value" id="100088"/>
</connections>
</tableColumn>
</tableColumns>
</tableView>
</subviews>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="100045">
<rect key="frame" x="1" y="119" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="37" horizontal="NO" id="100047">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" id="100046">
<rect key="frame" x="0.0" y="0.0" width="502" height="17"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100056">
<rect key="frame" x="14" y="13" width="114" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Hinzufügen" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="100057">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="add:" target="100040" id="100089"/>
<binding destination="100040" name="enabled" keyPath="canAdd" id="100092"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100076">
<rect key="frame" x="128" y="13" width="101" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Entfernen" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="100077">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="remove:" target="100040" id="100090"/>
<binding destination="100040" name="enabled" keyPath="canRemove" id="100091"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100080">
<rect key="frame" x="387" y="13" width="143" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Anwenden auf…" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="100081">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="applyTo:" target="-2" id="100094"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="100027" secondAttribute="trailing" constant="20" symbolic="YES" id="100029"/>
<constraint firstItem="100027" firstAttribute="top" secondItem="6" secondAttribute="top" constant="20" symbolic="YES" id="100030"/>
<constraint firstItem="100033" firstAttribute="baseline" secondItem="100027" secondAttribute="baseline" id="100036"/>
<constraint firstItem="100033" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="100068"/>
<constraint firstItem="100027" firstAttribute="leading" secondItem="100033" secondAttribute="trailing" constant="8" symbolic="YES" id="100069"/>
<constraint firstItem="100043" firstAttribute="top" secondItem="100027" secondAttribute="bottom" constant="8" symbolic="YES" id="100071"/>
<constraint firstItem="100043" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="100072"/>
<constraint firstAttribute="bottom" secondItem="100056" secondAttribute="bottom" constant="20" symbolic="YES" id="100074"/>
<constraint firstItem="100056" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="100075"/>
<constraint firstAttribute="bottom" secondItem="100076" secondAttribute="bottom" constant="20" symbolic="YES" id="100078"/>
<constraint firstItem="100076" firstAttribute="leading" secondItem="100056" secondAttribute="trailing" constant="12" symbolic="YES" id="100079"/>
<constraint firstAttribute="trailing" secondItem="100080" secondAttribute="trailing" constant="20" symbolic="YES" id="100082"/>
<constraint firstAttribute="bottom" secondItem="100080" secondAttribute="bottom" constant="20" symbolic="YES" id="100083"/>
<constraint firstItem="100056" firstAttribute="top" secondItem="100043" secondAttribute="bottom" constant="20" symbolic="YES" id="100085"/>
<constraint firstAttribute="trailing" secondItem="100043" secondAttribute="trailing" constant="20" symbolic="YES" id="100086"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="17"/>
</connections>
</window>
<dictionaryController objectClassName="_NSControllerKeyValuePair" preservesSelection="NO" id="100040">
<connections>
<binding destination="-2" name="contentDictionary" keyPath="folder.translations" id="100042"/>
</connections>
</dictionaryController>
<customObject id="-3" userLabel="Application"/>
</objects>
</document>

Binary file not shown.

View File

@@ -0,0 +1,245 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="Ordner Übersetzen" id="56">
<menu key="submenu" title="Ordner Übersetzen" systemMenu="apple" id="57">
<items>
<menuItem title="Über Ordner Übersetzen" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Dienste" id="131">
<menu key="submenu" title="Dienste" systemMenu="services" id="130"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Ordner Übersetzen ausblenden" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="Andere ausblenden" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="Alle einblenden" id="150">
<connections>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Ordner Übersetzen beenden" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="448"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ablage" id="83">
<menu key="submenu" title="Ablage" id="81">
<items>
<menuItem title="Neuer Ordner" keyEquivalent="n" id="537">
<connections>
<action selector="newDocument:" target="-1" id="538"/>
</connections>
</menuItem>
<menuItem title="Öffnen…" keyEquivalent="o" id="72">
<connections>
<action selector="openDocument:" target="-1" id="372"/>
</connections>
</menuItem>
<menuItem title="Benutzte Dokumente" id="124">
<menu key="submenu" title="Benutzte Dokumente" systemMenu="recentDocuments" id="125">
<items>
<menuItem title="Clear Menu" id="126">
<connections>
<action selector="clearRecentDocuments:" target="-1" id="127"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="79">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Schließen" keyEquivalent="w" id="73">
<connections>
<action selector="performClose:" target="-1" id="193"/>
</connections>
</menuItem>
<menuItem title="Sichern…" keyEquivalent="s" id="75">
<connections>
<action selector="saveDocument:" target="-1" id="536"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Bearbeiten" id="217">
<menu key="submenu" title="Bearbeiten" id="205">
<items>
<menuItem title="Widerrufen" keyEquivalent="z" id="207">
<connections>
<action selector="undo:" target="-1" id="223"/>
</connections>
</menuItem>
<menuItem title="Wiederholen" keyEquivalent="Z" id="215">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="redo:" target="-1" id="231"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="206">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Ausschneiden" keyEquivalent="x" id="199">
<connections>
<action selector="cut:" target="-1" id="228"/>
</connections>
</menuItem>
<menuItem title="Kopieren" keyEquivalent="c" id="197">
<connections>
<action selector="copy:" target="-1" id="224"/>
</connections>
</menuItem>
<menuItem title="Einsetzen" keyEquivalent="v" id="203">
<connections>
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="Löschen" id="202">
<connections>
<action selector="delete:" target="-1" id="235"/>
</connections>
</menuItem>
<menuItem title="Alle auswählen" keyEquivalent="a" id="198">
<connections>
<action selector="selectAll:" target="-1" id="232"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="214">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Transformationen" id="449">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformationen" id="450">
<items>
<menuItem title="Großbuchstaben" id="451">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="456"/>
</connections>
</menuItem>
<menuItem title="Kleibuchstaben" id="452">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="455"/>
</connections>
</menuItem>
<menuItem title="Großschreiben" id="453">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="454"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Sprachausgabe" id="211">
<menu key="submenu" title="Sprachausgabe" id="212">
<items>
<menuItem title="Sprachausgabe starten" id="196">
<connections>
<action selector="startSpeaking:" target="-1" id="233"/>
</connections>
</menuItem>
<menuItem title="Sprachausgabe stoppen" id="195">
<connections>
<action selector="stopSpeaking:" target="-1" id="227"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Darstellung" id="295">
<menu key="submenu" title="Darstellung" id="296">
<items>
<menuItem title="Symbolleiste einblenden" keyEquivalent="t" id="297">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="366"/>
</connections>
</menuItem>
<menuItem title="Symbolleiste anpassen…" id="298">
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Fenster" id="19">
<menu key="submenu" title="Fenster" systemMenu="window" id="24">
<items>
<menuItem title="Im Dock ablegen" keyEquivalent="m" id="23">
<connections>
<action selector="performMiniaturize:" target="-1" id="37"/>
</connections>
</menuItem>
<menuItem title="Zoomen" id="239">
<connections>
<action selector="performZoom:" target="-1" id="240"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Alle nach vorne bringen" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Hilfe" id="491">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Hilfe" systemMenu="help" id="492">
<items>
<menuItem title="Ordner Übersetzen Hilfe" keyEquivalent="?" id="493">
<connections>
<action selector="showHelp:" target="-1" id="494"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<customObject id="419" customClass="NSFontManager"/>
<customObject id="534" customClass="LFDocumentController"/>
</objects>
</document>

View File

@@ -1,29 +1,24 @@
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw9840\paperh8400
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\f0\b\fs24 \cf0 Engineering:
\b0 \
Some people\
Kim Wittenburg\
\
\b Human Interface Design:
\b0 \
Some other people\
Kim Wittenburg\
\
\b Testing:
\b0 \
Hopefully not nobody\
Kim Wittenburg\
\
\b Documentation:
\b0 \
Whoever\
\
\b With special thanks to:
\b0 \
Mom\
}
Kim Wittenburg}

View File

@@ -1,2 +1,4 @@
/* Localized versions of Info.plist keys */
"CFBundleDisplayName" = "Localize Folder";
"Localize Folder" = "Localize Folder";

View File

@@ -1,249 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1070</int>
<string key="IBDocument.SystemVersion">11C42</string>
<string key="IBDocument.InterfaceBuilderVersion">1938</string>
<string key="IBDocument.AppKitVersion">1138.17</string>
<string key="IBDocument.HIToolboxVersion">567.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">1938</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>NSTextField</string>
<string>NSTextFieldCell</string>
<string>NSWindowTemplate</string>
<string>NSView</string>
<string>IBNSLayoutConstraint</string>
<string>NSCustomObject</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="580458321">
<object class="NSCustomObject" id="512844837">
<string key="NSClassName">LFDocument</string>
</object>
<object class="NSCustomObject" id="613418571">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSWindowTemplate" id="275939982">
<int key="NSWindowStyleMask">15</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{133, 235}, {507, 413}}</string>
<int key="NSWTFlags">1886912512</int>
<string key="NSWindowTitle">Window</string>
<string key="NSWindowClass">NSWindow</string>
<string key="NSViewClass">View</string>
<nil key="NSUserInterfaceItemIdentifier"/>
<string key="NSWindowContentMinSize">{94, 86}</string>
<object class="NSView" key="NSWindowView" id="568628114">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="433022199">
<reference key="NSNextResponder" ref="568628114"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{119, 195}, {268, 22}}</string>
<reference key="NSSuperview" ref="568628114"/>
<reference key="NSWindow"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="566561048">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">138412032</int>
<string key="NSContents">Your document contents here</string>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">18</double>
<int key="NSfFlags">16</int>
</object>
<reference key="NSControlView" ref="433022199"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlTextColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
</object>
</object>
</object>
</object>
</array>
<string key="NSFrameSize">{507, 413}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
<string key="NSMinSize">{94, 108}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<bool key="NSWindowIsRestorable">YES</bool>
</object>
<object class="NSCustomObject" id="796877042">
<string key="NSClassName">NSApplication</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">window</string>
<reference key="source" ref="512844837"/>
<reference key="destination" ref="275939982"/>
</object>
<int key="connectionID">18</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="275939982"/>
<reference key="destination" ref="512844837"/>
</object>
<int key="connectionID">17</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="580458321"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="512844837"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="613418571"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="275939982"/>
<array class="NSMutableArray" key="children">
<reference ref="568628114"/>
</array>
<reference key="parent" ref="0"/>
<string key="objectName">Window</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="568628114"/>
<array class="NSMutableArray" key="children">
<reference ref="433022199"/>
<object class="IBNSLayoutConstraint" id="649349124">
<reference key="firstItem" ref="433022199"/>
<int key="firstAttribute">9</int>
<int key="relation">0</int>
<reference key="secondItem" ref="568628114"/>
<int key="secondAttribute">9</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<int key="scoringType">5</int>
<float key="scoringTypeFloat">22</float>
<int key="contentType">2</int>
<reference key="containingView" ref="568628114"/>
</object>
<object class="IBNSLayoutConstraint" id="215213155">
<reference key="firstItem" ref="433022199"/>
<int key="firstAttribute">10</int>
<int key="relation">0</int>
<reference key="secondItem" ref="568628114"/>
<int key="secondAttribute">10</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<int key="scoringType">5</int>
<float key="scoringTypeFloat">22</float>
<int key="contentType">2</int>
<reference key="containingView" ref="568628114"/>
</object>
</array>
<reference key="parent" ref="275939982"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">20</int>
<reference key="object" ref="433022199"/>
<array class="NSMutableArray" key="children">
<reference ref="566561048"/>
</array>
<reference key="parent" ref="568628114"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">100020</int>
<reference key="object" ref="566561048"/>
<reference key="parent" ref="433022199"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="796877042"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">100025</int>
<reference key="object" ref="649349124"/>
<reference key="parent" ref="568628114"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">100026</int>
<reference key="object" ref="215213155"/>
<reference key="parent" ref="568628114"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="100020.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="100025.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="100026.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="20.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="20.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="5.IBWindowTemplateEditedContentRect">{{133, 170}, {507, 413}}</string>
<array class="NSMutableArray" key="6.IBNSViewMetadataConstraints">
<reference ref="649349124"/>
<reference ref="215213155"/>
</array>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">100026</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<bool key="IBDocument.UseAutolayout">YES</bool>
</data>
</archive>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="LFDocument">
<connections>
<outlet property="window" destination="5" id="18"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="5" userLabel="Window">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="133" y="235" width="544" height="408"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1028"/>
<value key="minSize" type="size" width="94" height="86"/>
<view key="contentView" id="6">
<rect key="frame" x="0.0" y="0.0" width="544" height="408"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100027">
<rect key="frame" x="107" y="366" width="417" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="100028">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="enabled" keyPath="folder.folderName" id="100099">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
<binding destination="-2" name="value" keyPath="folder.folderName" id="100103"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100033">
<rect key="frame" x="18" y="368" width="83" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Foldername:" id="100034">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="100043">
<rect key="frame" x="20" y="61" width="504" height="297"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" id="dCp-JX-vYa">
<rect key="frame" x="1" y="17" width="502" height="279"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" headerView="100046" id="100044">
<rect key="frame" x="0.0" y="0.0" width="502" height="279"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="116" minWidth="40" maxWidth="1000" id="100048">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Locale ID">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="100051">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<connections>
<binding destination="100040" name="value" keyPath="arrangedObjects.key" id="100087"/>
</connections>
</tableColumn>
<tableColumn width="380" minWidth="40" maxWidth="1000" id="100049">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Translation">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="100050">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<connections>
<binding destination="100040" name="value" keyPath="arrangedObjects.value" id="100088"/>
</connections>
</tableColumn>
</tableColumns>
</tableView>
</subviews>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="100045">
<rect key="frame" x="1" y="119" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="37" horizontal="NO" id="100047">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" id="100046">
<rect key="frame" x="0.0" y="0.0" width="502" height="17"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100056">
<rect key="frame" x="14" y="13" width="66" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Add" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="100057">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="add:" target="100040" id="100089"/>
<binding destination="100040" name="enabled" keyPath="canAdd" id="100092"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100076">
<rect key="frame" x="80" y="13" width="90" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Remove" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="100077">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="remove:" target="100040" id="100090"/>
<binding destination="100040" name="enabled" keyPath="canRemove" id="100091"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="100080">
<rect key="frame" x="424" y="13" width="106" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Apply to…" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="100081">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="applyTo:" target="-2" id="100094"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="100027" secondAttribute="trailing" constant="20" symbolic="YES" id="100029"/>
<constraint firstItem="100027" firstAttribute="top" secondItem="6" secondAttribute="top" constant="20" symbolic="YES" id="100030"/>
<constraint firstItem="100033" firstAttribute="baseline" secondItem="100027" secondAttribute="baseline" id="100036"/>
<constraint firstItem="100033" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="100068"/>
<constraint firstItem="100027" firstAttribute="leading" secondItem="100033" secondAttribute="trailing" constant="8" symbolic="YES" id="100069"/>
<constraint firstItem="100043" firstAttribute="top" secondItem="100027" secondAttribute="bottom" constant="8" symbolic="YES" id="100071"/>
<constraint firstItem="100043" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="100072"/>
<constraint firstAttribute="bottom" secondItem="100056" secondAttribute="bottom" constant="20" symbolic="YES" id="100074"/>
<constraint firstItem="100056" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="100075"/>
<constraint firstAttribute="bottom" secondItem="100076" secondAttribute="bottom" constant="20" symbolic="YES" id="100078"/>
<constraint firstItem="100076" firstAttribute="leading" secondItem="100056" secondAttribute="trailing" constant="12" symbolic="YES" id="100079"/>
<constraint firstAttribute="trailing" secondItem="100080" secondAttribute="trailing" constant="20" symbolic="YES" id="100082"/>
<constraint firstAttribute="bottom" secondItem="100080" secondAttribute="bottom" constant="20" symbolic="YES" id="100083"/>
<constraint firstItem="100056" firstAttribute="top" secondItem="100043" secondAttribute="bottom" constant="20" symbolic="YES" id="100085"/>
<constraint firstAttribute="trailing" secondItem="100043" secondAttribute="trailing" constant="20" symbolic="YES" id="100086"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="17"/>
</connections>
</window>
<dictionaryController objectClassName="_NSControllerKeyValuePair" preservesSelection="NO" id="100040">
<connections>
<binding destination="-2" name="contentDictionary" keyPath="folder.translations" id="100042"/>
</connections>
</dictionaryController>
<customObject id="-3" userLabel="Application"/>
</objects>
</document>

Binary file not shown.

File diff suppressed because it is too large Load Diff