I spent a fair amount of time today trying to figure out how to add multi-langauge support to my Address Book plug-in Relationship Completer. This adventure was started when a few users requested a German version of the plug-in. After reading Apple’s documentation on the matter it seemed like a fairly easy task. My first try, however, didn’t work. Either did my second, third, or fourth.
I soon found myself turning to Google. Obviously someone has had the same problem as me. Indeed they have. I found this thread discussing the same problem I was having. The question that I needed the answer to was asked:
Does CFCopyLocalizedString(…) work with plugins or applications? Or doesn’t it matter?
I had been trying to force CFCopyLocalizedString to work in my plug-in all day. I tired everything I could think of. Luckily, someone answered with this:
Definitely with applications, but indeed you probably need to specify the bundle if you’re a plug-in. In that case I’d use something like the following:
#define CopyMyLocalizedString(key) \
CFBundleCopyLocalizedString(MyGetBundle(), (key), (key), NULL)
Ah-ha. I hadn’t thought of that. All the documentation I was reading from Apple was pertaining to applications. When you use CFCopyLocalizedString in an application things are as simple as I tried the first time. However, for plug-ins things get a little complicated. When my plug-in calls CFCopyLocalizedString it is doing so as its parent (Address Book). That means it is using Address Book’s bundle and my strings aren’t in Address Book’s bundle… they are in mine. Therefore I would have to use CFBundleCopyLocalizedString.
The solution however simply uses MyGetBundle() as a generic call to get the plug-in’s bundle. I still didn’t know how to do that. A few minutes of searching through Apple’s documentation and I finally had the complete answer. In order to get my plug-in’s bundle I had to call CFBundleGetBundleWithIdentifier, passing it in my plug-in’s identifier. An example call to get the translation of “Relationship Completer” can now be made like:
CFBundleCopyLocalizedString(CFBundleGetBundleWithIdentifier(CFSTR("com.tl.software.relationshipcompleter")), CFSTR("Relationship Completer"), CFSTR("Relationship Completer"), NULL);
Of course I put this in a nice tidy macro and I can now finish making Relationship Completer support multiple langauges. That being said: If anyone would like to help translate Relationship Completer (to any language) please leave a comment, I will get it touch with you and provide the list of strings that need translation. I am sure others will thank you for your effort.