aboutsummaryrefslogtreecommitdiff
path: root/iPhone
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2011-10-28 15:00:21 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2011-10-28 15:00:21 +0000
commitf62c657740d40e71c9fd6192e14d3b371970f4b3 (patch)
treebfc21eb1dd77d6d0ebe9b18382ea0527e14a6f01 /iPhone
parent56a2b11be338d2ed249a6cbc956166312df2dbb3 (diff)
[Author: qsr]
Implements GTMUILocalizer for iOS. The interface is exactly the same, the implementation does walk the UIKit view hierarchy, instead of the Cocoa one. R=thomasvl APPROVED=thomasvl
Diffstat (limited to 'iPhone')
-rw-r--r--iPhone/GTMUILocalizer.h94
-rw-r--r--iPhone/GTMUILocalizer.m207
-rw-r--r--iPhone/GTMUILocalizerTest.h29
-rw-r--r--iPhone/GTMUILocalizerTest.m87
-rw-r--r--iPhone/GTMUILocalizerTest.xib467
5 files changed, 884 insertions, 0 deletions
diff --git a/iPhone/GTMUILocalizer.h b/iPhone/GTMUILocalizer.h
new file mode 100644
index 0000000..2917e61
--- /dev/null
+++ b/iPhone/GTMUILocalizer.h
@@ -0,0 +1,94 @@
+//
+// GTMUILocalizer.h
+//
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import <UIKit/UIKit.h>
+
+// A class for localizing nibs by doing simple string replacement.
+// To use this, make an instance of GTMUILocalizer in your nib. Connect the
+// owner_ outlet of the your instance to the File Owner of the nib. It expects
+// the owner_ outlet to be an instance or subclass of NSWindowController,
+// NSViewController or NSApplication. Using the bundle of the nib it will then
+// localize any items in the NSWindowController's window and subviews, or the
+// NSViewController's view and subviews or the NSApplication's main menu
+// and dockmenu at when awakeFromNib is called on the GTMUILocalizer instance.
+// You can optionally hook up otherObjectToLocalize_ and
+// yetAnotherObjectToLocalize_ and those will also be localized. Strings in the
+// nib that you want localized must start with ^ (shift-6). The strings will
+// be looked up in the Localizable.strings table without the caret as the
+// key.
+// Things that will be localized are:
+// - Titles and altTitles (for menus, buttons, windows, menuitems, tabViewItem)
+// - stringValue (for labels)
+// - tooltips
+// - accessibility help
+// - menus
+//
+// Due to technical limitations, accessibility description cannot be localized.
+// See http://lists.apple.com/archives/Accessibility-dev/2009/Dec/msg00004.html
+// and http://openradar.appspot.com/7496255 for more information.
+//
+// As an example if I wanted to localize a button with the word "Print" on
+// it, I would put it in a window controlled by a NSWindowController that was
+// the owner of the nib. I would set it's title to be "^Print". I would then
+// create an instance of GTMUILocalizer and set it's owner_ to be the owner
+// of the nib.
+// In my Localizable.strings file in my fr.lproj directory for the bundle
+// I would put "Print" = "Imprimer";
+// Then when my app launched in French I would get a button labeled
+// "Imprimer". Note that GTMUILocalizer is only for strings, and doesn't
+// resize, move or change text alignment on any of the things it modifies.
+// If you absolutely need a caret at the beginning of the string
+// post-localization, you can put "Foo" = "^Foo"; in your strings file and
+// it will work.
+// Your nib could be located in a variety of places depending on what you want
+// to do. I would recommend having your "master" nib directly in Resources.
+// If for some reason you needed to do some custom localization of the
+// nib you could copy the master nib into your specific locale folder, and
+// then you only need to adjust the items in the nib that you need to
+// customize. You can leave the strings in the "^Foo" convention and they
+// will localize properly. This keeps the differences between the nibs down
+// to the bare essentials.
+//
+// NOTE: NSToolbar localization support is limited to only working on the
+// default items in the toolbar. We cannot localize items that are on of the
+// customization palette but not in the default items because there is not an
+// API for NSToolbar to get all possible items. You are responsible for
+// localizing all non-default toolbar items by hand.
+//
+@interface GTMUILocalizer : NSObject {
+ @private
+ IBOutlet id owner_;
+ IBOutlet id otherObjectToLocalize_;
+ IBOutlet id yetAnotherObjectToLocalize_;
+ NSBundle *bundle_;
+}
+- (id)initWithBundle:(NSBundle *)bundle;
+
+// Localize |object|. If |recursive| is true, it will attempt
+// to localize objects owned/referenced by |object|.
+- (void)localizeObject:(id)object recursively:(BOOL)recursive;
+
+// A method for subclasses to override in case you have a different
+// way to go about getting localized strings.
+// If |string| does not start with ^ you should return nil.
+// If |string| is nil, you should return nil
+- (NSString *)localizedStringForString:(NSString *)string;
+
+// Allows subclasses to override how the bundle is picked up
++ (NSBundle *)bundleForOwner:(id)owner;
+@end
diff --git a/iPhone/GTMUILocalizer.m b/iPhone/GTMUILocalizer.m
new file mode 100644
index 0000000..5eff255
--- /dev/null
+++ b/iPhone/GTMUILocalizer.m
@@ -0,0 +1,207 @@
+//
+// GTMUILocalizer.m
+//
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import "GTMDefines.h"
+#import "GTMUILocalizer.h"
+
+@interface GTMUILocalizer (GTMUILocalizerPrivate)
+- (void)localizeAccessibility:(id)object;
+
+// Never recursively call any of these methods. Always call
+// -[self localizeObject:recursively:] otherwise bindings will not be
+// localized properly.
+- (void)localizeToolbar:(UIToolbar *)toolbar;
+- (void)localizeView:(UIView *)view recursively:(BOOL)recursive;
+
+@end
+
+@implementation GTMUILocalizer
+- (id)initWithBundle:(NSBundle *)bundle {
+ if ((self = [super init])) {
+ bundle_ = [bundle retain];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [bundle_ release];
+ [super dealloc];
+}
+
+- (void)awakeFromNib {
+ if (owner_) {
+ NSBundle *newBundle = [[self class] bundleForOwner:owner_];
+ bundle_ = [newBundle retain];
+ [self localizeObject:owner_ recursively:YES];
+ [self localizeObject:otherObjectToLocalize_ recursively:YES];
+ [self localizeObject:yetAnotherObjectToLocalize_ recursively:YES];
+ } else {
+ _GTMDevLog(@"Expected an owner_ set for %@", self);
+ }
+}
+
++ (NSBundle *)bundleForOwner:(id)owner {
+ NSBundle *newBundle = nil;
+ if (owner) {
+ if ([owner isKindOfClass:[UIViewController class]]) {
+ newBundle = [(UIViewController *)owner nibBundle];
+ }
+ if (!newBundle) {
+ newBundle = [NSBundle mainBundle];
+ }
+ }
+ return newBundle;
+}
+
+- (NSString *)localizedStringForString:(NSString *)string {
+ NSString *localized = nil;
+ if (bundle_ && [string hasPrefix:@"^"]) {
+ NSString *notFoundValue = @"__GTM_NOT_FOUND__";
+ NSString *key = [string substringFromIndex:1];
+ localized = [bundle_ localizedStringForKey:key
+ value:notFoundValue
+ table:nil];
+ if ([localized isEqualToString:notFoundValue]) {
+ localized = nil;
+ }
+ }
+ return localized;
+}
+
+- (void)localizeObject:(id)object recursively:(BOOL)recursive {
+ if (object) {
+ if ([object isKindOfClass:[UIViewController class]]) {
+ UIView *view = [object view];
+ [self localizeView:view recursively:recursive];
+ } else if ([object isKindOfClass:[UIView class]]) {
+ [self localizeView:(UIView *)object recursively:recursive];
+ } else if ([object isKindOfClass:[UIToolbar class]]) {
+ [self localizeToolbar:(UIToolbar*)object];
+ }
+ }
+}
+
+- (void)localizeToolbar:(UIToolbar *)toolbar {
+ // NOTE: Like the header says, -items only gives us what is in the toolbar
+ // which is usually the default items, if the toolbar supports customization
+ // there is no way to fetch those possible items to tweak their contents.
+ for (UIBarItem* item in [toolbar items]) {
+ NSString *title = [item title];
+ if (title) {
+ title = [self localizedStringForString:title];
+ if (title) {
+ [item setTitle:title];
+ }
+ }
+ }
+}
+
+- (void)localizeView:(UIView *)view recursively:(BOOL)recursive {
+ if (view) {
+ // Do accessibility on views.
+ [self localizeAccessibility:view];
+
+ if (recursive) {
+ for (UIView *subview in [view subviews]) {
+ [self localizeObject:subview recursively:recursive];
+ }
+ }
+
+ // Then do all possible strings.
+ if ([view respondsToSelector:@selector(title)]
+ && [view respondsToSelector:@selector(setTitle:)]) {
+ NSString *title = [view performSelector:@selector(title)];
+ if (title) {
+ NSString *localizedTitle = [self localizedStringForString:title];
+ if (localizedTitle) {
+ [view performSelector:@selector(setTitle:) withObject:localizedTitle];
+ }
+ }
+ }
+
+ if ([view respondsToSelector:@selector(text)]
+ && [view respondsToSelector:@selector(setText:)]) {
+ NSString *text = [view performSelector:@selector(text)];
+ if (text) {
+ NSString *localizedText = [self localizedStringForString:text];
+ if (localizedText) {
+ [view performSelector:@selector(setText:) withObject:localizedText];
+ }
+ }
+ }
+
+ if ([view respondsToSelector:@selector(placeholder)]
+ && [view respondsToSelector:@selector(setPlaceholder:)]) {
+ NSString *placeholder = [view performSelector:@selector(placeholder)];
+ if (placeholder) {
+ NSString *localizedPlaceholder =
+ [self localizedStringForString:placeholder];
+ if (localizedPlaceholder) {
+ [view performSelector:@selector(setPlaceholder:)
+ withObject:localizedPlaceholder];
+ }
+ }
+ }
+ }
+}
+
+- (void)localizeAccessibility:(id)object {
+ if ([object respondsToSelector:@selector(accessibilityHint)]
+ && [object respondsToSelector:@selector(setAccessibilityHint:)]) {
+ NSString *accessibilityHint =
+ [object performSelector:@selector(accessibilityHint)];
+ if (accessibilityHint) {
+ NSString *localizedAccessibilityHint =
+ [self localizedStringForString:accessibilityHint];
+ if (localizedAccessibilityHint) {
+ [object performSelector:@selector(setAccessibilityHint:)
+ withObject:localizedAccessibilityHint];
+ }
+ }
+ }
+
+ if ([object respondsToSelector:@selector(accessibilityLabel)]
+ && [object respondsToSelector:@selector(setAccessibilityLabel:)]) {
+ NSString *accessibilityLabel =
+ [object performSelector:@selector(accessibilityLabel)];
+ if (accessibilityLabel) {
+ NSString *localizedAccessibilityLabel =
+ [self localizedStringForString:accessibilityLabel];
+ if (localizedAccessibilityLabel) {
+ [object performSelector:@selector(setAccessibilityLabel:)
+ withObject:localizedAccessibilityLabel];
+ }
+ }
+ }
+
+ if ([object respondsToSelector:@selector(accessibilityValue)]
+ && [object respondsToSelector:@selector(setAccessibilityValue:)]) {
+ NSString *accessibilityValue =
+ [object performSelector:@selector(accessibilityValue)];
+ if (accessibilityValue) {
+ NSString *localizedAccessibilityValue =
+ [self localizedStringForString:accessibilityValue];
+ if (localizedAccessibilityValue) {
+ [object performSelector:@selector(setAccessibilityValue:)
+ withObject:localizedAccessibilityValue];
+ }
+ }
+ }
+}
+
+@end
diff --git a/iPhone/GTMUILocalizerTest.h b/iPhone/GTMUILocalizerTest.h
new file mode 100644
index 0000000..041444d
--- /dev/null
+++ b/iPhone/GTMUILocalizerTest.h
@@ -0,0 +1,29 @@
+//
+// GTMUILocalizerTest.h
+//
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#import <UIKit/UIKit.h>
+
+#import "GTMUILocalizer.h"
+
+@interface GTMUILocalizerTestViewController : UIViewController {
+ @private
+ UILabel *label_;
+}
+
+@property(nonatomic, retain)IBOutlet UILabel *label;
+
+@end
diff --git a/iPhone/GTMUILocalizerTest.m b/iPhone/GTMUILocalizerTest.m
new file mode 100644
index 0000000..116d170
--- /dev/null
+++ b/iPhone/GTMUILocalizerTest.m
@@ -0,0 +1,87 @@
+//
+// GTMUILocalizerTest.m
+//
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#import "GTMUILocalizerTest.h"
+#import "GTMSenTestCase.h"
+
+@interface TestUILocalizer : GTMUILocalizer
+- (void)localize:(id)object;
+@end
+
+@implementation TestUILocalizer
+- (NSString *)localizedStringForString:(NSString *)string{
+ return [string substringFromIndex:5];
+}
+
+- (void)localize:(id)object {
+ [self localizeObject:object recursively:YES];
+}
+@end
+
+
+@implementation GTMUILocalizerTestViewController
+
+@synthesize label = label_;
+
+- (id)init {
+ NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+ return [self initWithNibName:@"GTMUILocalizerTest" bundle:bundle];
+}
+@end
+
+@interface GTMUILocalizerTest : GTMTestCase
+@end
+
+@implementation GTMUILocalizerTest
+- (void)testLocalization {
+ GTMUILocalizerTestViewController* controller =
+ [[GTMUILocalizerTestViewController alloc] init];
+
+ // Load the view.
+ [controller view];
+
+ STAssertEqualStrings(@"^IDS_FOO", [[controller label] text], nil);
+
+// Accessibility label seems to not be working at all. They always are nil.
+// Even when setting those explicitely there, the getter always returns nil.
+// This might cause because the gobal accessibility switch is not on during the
+// tests.
+#if 0
+ STAssertEqualStrings(@"^IDS_FOO", [[controller view] accessibilityLabel],
+ nil);
+ STAssertEqualStrings(@"^IDS_FOO", [[controller view] accessibilityHint],
+ nil);
+ STAssertEqualStrings(@"^IDS_FOO", [[controller label] accessibilityLabel],
+ nil);
+ STAssertEqualStrings(@"^IDS_FOO", [[controller label] accessibilityHint],
+ nil);
+#endif
+
+ TestUILocalizer *localizer = [[TestUILocalizer alloc] init];
+ [localizer localize:[controller view]];
+
+ STAssertEqualStrings(@"FOO", [[controller label] text], nil);
+
+// Accessibility label seems to not be working at all. They always are nil.
+#if 0
+ STAssertEqualStrings(@"FOO", [[controller view] accessibilityLabel], nil);
+ STAssertEqualStrings(@"FOO", [[controller view] accessibilityHint], nil);
+ STAssertEqualStrings(@"FOO", [[controller label] accessibilityLabel], nil);
+ STAssertEqualStrings(@"FOO", [[controller label] accessibilityHint], nil);
+#endif
+}
+@end
diff --git a/iPhone/GTMUILocalizerTest.xib b/iPhone/GTMUILocalizerTest.xib
new file mode 100644
index 0000000..ed6a8a4
--- /dev/null
+++ b/iPhone/GTMUILocalizerTest.xib
@@ -0,0 +1,467 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1056</int>
+ <string key="IBDocument.SystemVersion">10K549</string>
+ <string key="IBDocument.InterfaceBuilderVersion">851</string>
+ <string key="IBDocument.AppKitVersion">1038.36</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">141</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="5"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBProxyObject" id="371349661">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBUIView" id="971589104">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">292</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUILabel" id="505819666">
+ <reference key="NSNextResponder" ref="971589104"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{115, 182}, {136, 21}}</string>
+ <reference key="NSSuperview" ref="971589104"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <int key="IBUIContentMode">7</int>
+ <bool key="IBUIUserInteractionEnabled">NO</bool>
+ <object class="IBUIAccessibilityConfiguration" key="IBUIAccessibilityConfiguration">
+ <string key="IBUIAccessibilityHint">^IDS_FOO</string>
+ <string key="IBUIAccessibilityLabel">^IDS_FOO</string>
+ <boolean value="YES" key="IBUIIsAccessibilityElement"/>
+ </object>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <string key="IBUIText">^IDS_FOO</string>
+ <object class="NSColor" key="IBUITextColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MCAwIDAAA</bytes>
+ </object>
+ <object class="NSColor" key="IBUIHighlightedColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <int key="IBUIBaselineAdjustment">1</int>
+ <float key="IBUIMinimumFontSize">10</float>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 460}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ <object class="IBUIAccessibilityConfiguration" key="IBUIAccessibilityConfiguration">
+ <string key="IBUIAccessibilityHint">^IDS_FOO</string>
+ <string key="IBUIAccessibilityLabel">^IDS_FOO</string>
+ <boolean value="YES" key="IBUIIsAccessibilityElement"/>
+ </object>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="971589104"/>
+ </object>
+ <int key="connectionID">7</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">label</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="505819666"/>
+ </object>
+ <int key="connectionID">13</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="371349661"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="971589104"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="505819666"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="505819666"/>
+ <reference key="parent" ref="971589104"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>5.IBEditorWindowLastContentRect</string>
+ <string>5.IBPluginDependency</string>
+ <string>5.IBViewBoundsToFrameTransform</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>GTMUILocalizerTestViewController</string>
+ <string>UIResponder</string>
+ <string>{{870, 485}, {320, 460}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAAAAAAAAw+UAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">15</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMUILocalizerTestViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">label</string>
+ <string key="NS.object.0">UILabel</string>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <string key="NS.key.0">label</string>
+ <object class="IBToOneOutletInfo" key="NS.object.0">
+ <string key="name">label</string>
+ <string key="candidateClassName">UILabel</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">iPhone/GTMUILocalizerTest.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Foundation/GTMNSObject+KeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMCALayer+UnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="NSMutableDictionary" key="actions">
+ <string key="NS.key.0">gtm_unitTestEncoderWillEncode:inCoder:</string>
+ <string key="NS.object.0">id</string>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <string key="NS.key.0">gtm_unitTestEncoderWillEncode:inCoder:</string>
+ <object class="IBActionInfo" key="NS.object.0">
+ <string key="name">gtm_unitTestEncoderWillEncode:inCoder:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMNSObject+UnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMUIKit+UnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">iPhone/GTMUIView+SubtreeDescription.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="30994948">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UILabel</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UILabel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="30994948"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIPrintFormatter.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIPopoverController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISplitViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="1056" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../GTMiPhone.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">141</string>
+ </data>
+</archive>