Cocoa Programming for Mac OS X - Aaron Hillegass [77]
table:nil];
Fortunately, a macro is defined in NSBundle.h for this purpose:
#define NSLocalizedString(key, comment)
[[NSBundle mainBundle] localizedStringForKey:(key)
value:@""
table:nil]
(Note that this macro completely ignores the comment. It is, however, used by a tool called genstrings, which scans through your code for calls to the macro NSLocalizedString and creates a skeleton string table. This string table includes the comment.)
In RMDocument.m, find the place where you run the Alert panel. Replace that line with this one:
NSAlert *alert = [NSAlert
alertWithMessageText:NSLocalizedString(@"REMOVE_MSG", @"Remove")
defaultButton:NSLocalizedString(@"REMOVE", @"Remove")
alternateButton:NSLocalizedString(@"CANCEL", @"Cancel")
otherButton:nil
informativeTextWithFormat:NSLocalizedString(@"REMOVE_INF",
@"%d people will be removed."),
[selectedPeople count]];
Build the app. Change your preferred language back to French in System Preferences, and run the app again. When you delete a row from the table, you should get an Alert panel in French.
For the More Curious: ibtool
Clearly, as you develop and localize many applications, you will develop a set of common translations. It would be handy to have an automated way to get the translated strings into a XIB file. This is one of several uses for ibtool.
The ibtool command, which is run from the terminal, can list the classes or objects in a XIB and can also dump the localizable strings into a plist. Here is how you would dump the localizable strings from the en.lproj/RMDocument.xib file into a file named Doc.strings:
> cd RaiseMan/en.lproj
> ibtool --generate-stringsfile Doc.strings RMDocument.xib
The resulting Doc.strings file would have a bunch of entries something like this:
/* Class="NSTableColumn";headerCell.title="Name";ObjectID="100026"; */
"100026.headerCell.title" = "Name";
To create a Spanish dictionary for this XIB file, you could edit the file to have Spanish entries:
/* Class="NSTableColumn";headerCell.title="Name";ObjectID="100026"; */
"100026.headerCell.title" = "Nombre";
To substitute the strings in a XIB file with their Spanish equivalents from this dictionary, you could create a new NIB file like this:
> mkdir ../es.lproj
> ibtool --strings-file Doc.strings
--write ../es.lproj/RMDocument.xib RMDocument.xib
To learn more about ibtool, use Unix’s man command:
> man ibtool
For the More Curious: Explicit Ordering of Tokens in Format Strings
As text is moved from language to language, both the words and the order of the words change. For example, the words in one language may be laid out like this: “Ted wants a scooter.” In another, the order might be “A scooter is what Ted wants.” Suppose that you try to localize the format string to be used like this:
NSString * theFormat = NSLocalizedString(@"WANTS", @"%@ wants a %@");
x = [NSString stringWithFormat:theFormat, @"Ted", @"Scooter"];
The following will work fine for the first language:
"WANTS" = "%@ wants a %@";
For the second language, you would need to explicitly indicate the index of the token you want to insert. This is done with a number and the dollar sign:
"WANTS = "A %2$@ is what %1$@ wants".
Chapter 17. Custom Views
All visible objects in an application are either windows or views. In this chapter, you will create a subclass of NSView. From time to time, you may need to create a custom view to do custom drawing or event handling. Even if you do not plan to do custom drawing or event handling, you will learn a lot about how Cocoa works by learning how to create a new view class.
Windows are instances of the class NSWindow. Each window has a collection of views, each of which is responsible for a rectangle of the window. The view draws inside that rectangle and handles mouse events that occur there. A view may also handle keyboard events. You have worked with several subclasses of NSView already: NSButton, NSTextField, NSTableView, and NSColorWell are all views. (Note that