I'm creating this iOS app, in which I use the PushWoosh (www.pushwoosh.com) notification service. Notification is working fine, but now I want to differentiate notification based upon the locale of the app: I want the users of the app running their OS in English to receive a notification in English, the German users in German, etc.
For that, I register this one app several times with PushWoosh, so each localization gets its own Pushwoosh App ID. For simplicity sake, I'm aiming to have all localization stuff in one file ("localizable.strings").
PushWoosh requires to have their APPID listed in the info.plist. So what would make sense to me, is to have the value of the PushWoosh .plist key localized. This is what I did:
In the .plist, I replaced
<key>Pushwoosh_APPID</key>
<string>2B46A-F82CC</string>
with
<key>Pushwoosh_APPID</key>
<string>PUSHWOOSH_ID</string>
Then, in the localizable.strings, I added the following entry:
"PUSHWOOSH_ID" = "2B46A-F82CC";
Finally, in the code, I replaced
[[NSUserDefaults standardUserDefaults] setObject:appCode forKey:#"Pushwoosh_APPID"];
with
[[NSUserDefaults standardUserDefaults] setObject:appCode forKey:NSLocalizedString(#"Pushwoosh_APPID", nil)];
Somehow, however, when running the app, "Pushwoosh_APPID" resolves into "PUSHWOOSH_ID", rather than in "2B46A-F82CC".
All other strings in localizable.strings are called just fine, so I guess it's a syntax thing.
Concrete question: what am I doing wrong, code-wise? Also, shoot me if this is an undesirable approach in general.
Thanks in advance!
For localizing Info.plist values, you will need to create a separate strings file called InfoPlist.strings under your language-specific project directory, such as en.lproj, etc, and put the key and the translated value there, for example:
Pushwoosh_APPID = "2B46A-F82CC";
Take a look at the reference of Information Property List Key:
... you store the values for a particular localization in a strings file
with the name InfoPlist.strings. You place this file in the same
language-specific project directory that you use to store other
resources for the same localization. The contents of the
InfoPlist.strings file are the individual keys you want localized and
the appropriately translated value. The routines that look up key
values in the Info.plist file take the user’s language preferences
into account and return the localized version of the key (from the
appropriate InfoPlist.strings file) when one exists. If a localized
version of a key does not exist, the routines return the value stored
in the Info.plist file.
FYI Pushwoosh provides the Multi-language support for sending notifications in the language, which is set in the OS. Its based on Tags, and can be used both via the Control Panel and API. I suppose it would be way easier not to reinvent the wheel :)
Related
I am working on a Mac app. I ultimately want to use default app icons within my app. From the Info.plist and the Resource folder of an app I can get the .icns file and convert that to the image format I need. But I need to know the default application associated with the particular file extension, if any.
So how to get the default application that the system currently associates with a given file extension?
Don't go digging in other apps' bundles. It's always best to work at the level of abstraction that suits the question you want to ask. If you want to get the icon that the Finder (or a Mail attachment, etc) would display for a file of a particular type, use the NSWorkspace iconForFileType: method.
I think what you're looking for is part of the OSX Launch Services: LSCopyDefaultApplicationURLForContentType API. This returns the info on apps that can open specific Uniform Type Identifiers. There's also a similar API called LSCopyDefaultApplicationURLForURL to check which app opens a specific known file.
I have setup an OSX service based on an Automator workflow that contains (among others) an Obj-C action.
I have successfully localized the Obj-C action, but I am not able to localize the service menu entry.
The Services implementation guide says one has to create a ServicesMenu.strings file for every localization. Other docs, e.g. this, say the same, and this SO entry suggests in an answer to apply some console commands to refresh a system file, but I am afraid to do so without understanding.
I have created the localized ServicesMenu.strings files in the Xcode project of the Obj-C action (because the Automator does not have an localization function), but these files are surely in the wrong bundle.
The problem is that I don't know where to place these files.
Any help is appreciated.
EDIT:
One of the links cited above says:
Adding a Localized ServicesMenu.strings file
To localize this text, you will need to add a UTF-16 encoded strings file named ServicesMenu.strings to your application project or Automator workflow bundle resources (details on how to do this are below). This strings file will contain, for each service menu item you are providing, an entry that uses the default text as the key, and the translated text as the value. For each language you wish to support, you will provide a translated ServicesMenu.strings file in a language-specific project (.lproj) directory in your project resources.
...
If you are providing a service from an Automator created workflow, you will need to manually add the strings files and .lproj resource directories to the workflow bundle. You can find Automator created workflow bundles in your home directory under ~/Library/Services.
I have done exactly this, but the localization does not work.
Below I added my Info.plist content, the folder structure and the ServiceMenu.strings file contents.
Here is my own solution. Maybe it helps somebody else.
The 1st problem was that I did not read the docs carefully enough. The text cited in my question continues:
Refreshing the Services menu
Once you have provided localized text for your service menu item title, you may need to refresh the Services menu list to see the changes. One way to refresh the list of services shown in the Services menu is by using the services debugging tool pbs. This is a command-line tool located in /System/Library/CoreServices that provides useful services debugging features, such as refreshing the list of services or printing out the current list of registered services. Listing 3 shows an example of a command-line you can enter into the Terminal application to refresh the list of services for English and French.
Listing 3 Example use of pbs to refresh services.
/System/Library/CoreServices/pbs -existing_languages en fr
The 2nd problem was that the command given in Listing 3 above did not work for me. However the command
/System/Library/CoreServices/pbs -update
actually updated the service menu and the localized menu entry was displayed.
Where can I find more information about the “related items” feature for sandboxed mac apps? The feature is briefly introduced in the video of the “WWDC 2012 Session 700: The OS X App Sandbox” (around time index 33:39-36:03). But I cannot find where in Apple's developer documentation the feature is discussed in more detail.
From what I understand from the explanation in the video, the feature would allow a sandboxed app to declare that, for example, “if a user gives me permission to read a file with name {X}.avi, the sandbox should automatically also give me permission to read a file with name {X}.srt in the same directory.” This would allow the app to read the subtitle file that's related to the movie file without having to present the user with an(other) NSOpenPanel for “opening” the subtitle file. But the video doesn't explain how to actually declare this.
Since I posted the question, Apple seems to have updated its documentation. The feature is now described in the “App Sandbox Design Guide” in the section “Related Items”:
The related items feature of App Sandbox lets your app access files that have the same name as a user-chosen file, but a different extension. This feature consists of two parts: a list of related extensions in the application’s Info.plist file and code to tell the sandbox what you’re doing.
There are two common scenarios where this makes sense:
[...]
In both scenarios, you must make a small change to the application’s Info.plist file. Your app should already declare a Document Types (CFBundleDocumentTypes) array that declares the file types your app can open.
For each file type dictionary in that array, if that file type should be treated as a potentially related type for open and save purposes, add the key NSIsRelatedItemType with a boolean value of YES.
To learn more about file presenters and file coordinators, read File System Programming Guide.
My application uses new proprietary file formats with extensions never been used before. I would like to associate specific icons to display my files in finder with nice iconography. As far as I know LaunchService is responsible to handle all these data, however I'm confused where, when and how shall I create associations.
Which entries I have to add to plist?
Where I need to actually register this extension - during installation? Is there any script for this?
Add a CFBundleDocumentTypes key to your plist, see
Storing Document Types Information in the Application's Property List
I am looking at using AquaticPrime for my key generator for a Cocoa shareware app. For those of you who don't know about it, you can check it out here: http://aquaticmac.com/. However, I am running into a problem when I attempt to implement it. I don't want my users to have to copy and paste a whole dictionary into my app (or select it from a file browser), I just want them to have some code like: 1111-1111-1111-1111-1111 that will unlock the app for them. Is there some way to do this in AquaticPrime? But assuming that it can't, is there some other framework that does do this or would I just have to hard code it?
The reason it uses license files is to make it cryptographically hard to make up licenses—you can't just write a keygen like you can with license numbers.
You can make this easy by making a custom file type for license files in your application's Info.plist. (This must be app-specific. When you begin your second product, you'll need to make a new type.) This type will have a custom, app-specific filename extension with it.
Then, when the user double-clicks on the license file (possibly in Mail), the OS will open it with your app. You'll handle this, probably in your app delegate, by feeding the license file to AquaticPrime to validate.
This way, the user does not even have to summon a dialog box, copy the license number, and paste it. All they have to do is double-click on the license file.
Thus, the license file makes it easier to register your application, not harder.
If you have a trial version of your application that is unlocked then you can do the following.
1) Create a custom url scheme.
Follow the instructions on this posting but instead of http and https make your application respond to something like activate-com-mycompany-myproduct.
Once the user has run your application once any link in a browser like activate-com-mycompany-myproduct://somedata will automatically open your application.
2) Provide a product activation link in your final buy page of your web store and your email receipt. To make it simple for the user and not for you, append a unique id to the URL. Map the ID in a database, generate a license plist on the fly and push it to the user seamlessly.
In case someone else stumbles on this question: you might also want to take a look at CocoaFob. The keys it generates are rather long, but closer to the format you were after and still easy enough to cut and paste.