Cannot load country-specific resource - iphone

I am loading text resources in different languages from text files using:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"txt"];
if(filePath) {
NSString *myText = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
}
Works very well with my language specific resources in English, German etc.
But I do also have some country-specific resources, like an English text for United Kingdom, an English text for USA, a German text for Austria etc.
I would expect these resources to be loaded if the phone is set to the specific country (Region Format), but they don't. The filepath will always be set to the file in the "pure" language folder.
So for example I have myfile.txt in the folders:
en.lproj
en-GB.lproj
en-US.lproj
but it always loads the one in en.lproj
Folders have been created using the localization function in Xcode and are all located in the same folder.
What is a bit odd is that these folders created by Xcode do seperate language and country by a hyphen, but according to the documentation it should be an underscore. I have tried to copy folders (with underscores) into the project manually, but it still doesn't work.
How do I manage to load the country-specific files?
Thanks.....

I created a "dutch-netherlands" translation of Localisations.string and set iPhone language to dutch, but NSLocalizedString always returned the English translation. The solution was to create a "dutch" translation (nl.lproj) instead of "dutch-netherlands" (nl-NL.lproj).
In the settings screen of iOS4 or iOS5, you can select Dutch language but there's no subselection for Dutch-Netherlands or Dutch-Belgium, even though these are available in XCode. It seems to me that XCode offers more translation options than that are actually supported by iOS.
I mean there's no way to make your app use "nl-NL" resources. I guess the same problem goes for German and Austria ("de-DE" and "de-AT").

Note: Your code sample is a complicated way of loading text resources. It's fine if you are loading non-string resources such as images or media files, but for simple strings it's much easier to just use one .strings file per language (containing multiple localized strings) and call NSLocalizedString to get the relevant language version of a given string.
Answer: The iOS setting under "Region Format" does not affect resource loading. Instead it controls how the system performs locale-dependent functionality (such as date/number formatting and parsing). The iOS setting that controls which language version of your localized resources gets loaded is the Language setting (General > International > Language). Currently, it includes only two English variants: "English" and "British English".

I have the same problem with nl-NL.lproj (Netherland) and ca-ES.lproj (Catalan). The solution for me is add the language using Xcode. Go to Xcode Project, and then in Info Tab add the langugages. Automatically will create the folders nl-NL.lproj and ca-ES.lproj.
Then you can try this on Simulator (Xcode version 4.6) and these languages don't word, instead will load English language.
First rename manually the folder nl-NL.lproj to nl.lproj.
Finally go to file {MY_PROJECT}.xcodeproj/project.pbxproj and replace the PATH of the following lines:
C3D2888817108DDA00CE8AC2 /* nl-NL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nl-NL"; path = "nl.lproj/Localizable.strings"; sourceTree = "<group>"; };
C3D2888917108DE500CE8AC2 /* nl-NL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nl-NL"; path = "nl.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
That's all, now I can get these languages settings correctly.

Related

Loading text from a file

I am making an Iphone drinking card game app.
All the card mean something different and i want the user to be able to press an info button and then show a new screen with information about the current card. How can i make a document to load text from instead of using a bunch og long strings?
Thanks
You could look into plist files - they can be loaded quite easily into the various collection objects and edited with the plist editor in Xcode.
For instance, if you organize your data as a dictionary, the convenience constructor
+ (id)dictionaryWithContentsOfURL:(NSURL *)aURL
from NSDictionary would provide you with as many easily accessible strings as you need.
This method is useful if you consider your strings primarily data as opposed to UI elements.
Update:
As #Alex Nichol suggested, here is how you can do it in practice:
To create a plist file:
In your Xcode project, for instance in the Supporting Files group, select New File > Resource > Property List
You can save the file in en.lproj, to aid in localization
In the Property list editing pane, select Add Row (or just hit return)
Enter a key name (for instance user1) and a value (for instance "Joe")
To read the contents:
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:#"Property List" withExtension:#"plist"];
NSLog(#"URL: %#", plistURL);
NSDictionary *strings = [NSDictionary dictionaryWithContentsOfURL:plistURL];
NSString *user1 = [strings objectForKey:#"user1"];
NSLog(#"User 1: %#", user1);
A plist, a JSON string, and an SQLite database walked into a bar ...
Oops!! I mean those are the three most obvious alternatives. The JSON string is probably the easiest to create and "transport", though it's most practical to load the entire thing into an NSDictionary and/or NSArray, vs read from the file as each string is accessed.
The SQLite DB is the most general, and most speed/storage efficient for a very large number (thousands) of strings, but it takes some effort to set it up.
In my other answer, I suggest the use of a dictionary if your texts are mostly to be considered as data. However, if your strings are UI elements (alert texts, window titles, etc.) you might want to look into strings files and NSBundle's support for them.
Strings files are ideally suited for localization, the format is explained here.
To read them into you app, use something like this:
NSString *text1 = NSLocalizedStringFromTable(#"TEXT1", #"myStringsFile", #"Comment");
If you call your file Localizable.strings, you can even use a simpler form:
NSString *str1 = NSLocalizedString(#"String1", #"Comment on String1");
A useful discussion here - a bit old, but still useful.

Localization of a variable value on iOS

I have around 72 html files in my resource folder and I need to localize them. Now I have translated them in french. A file selection depends on user input so file name is created by a variable. Now the problem is how to localize the value of a variable.
For example, I have following 3 files in resource folder.
AAAAA0.html
BBBBB28.html
CCCCC33.html
I also have these files with in french in resource folder.
AAAAA0-French.html
BBBBB28-French.html
CCCCC33-French.html
Here is my code that is working fine without localization.
// ViewController.m File
appDelegate2=[[[UIApplication sharedApplication] delegate] retain];
NSString *getSign2=[appDelegate2.globalString stringByAppendingString:appDelegate2.globalindex];
NSString *filePath=[[NSBundle mainBundle] pathForResource:getSign2 ofType:#"html" ];
If user input causes the selection of AAAAA0.html then globalString will be "AAAAA",globalIndex will be "0" and getSign2 will Be "AAAAA0".
If user input causes the selection of BBBBB28.html then globalString will be "BBBBB",globalIndex will be "28" and getSign2 will Be "BBBBB28".
If user input causes the selection of CCCCC33.html then globalString will be "CCCCC",globalIndex will be "33" and getSign2 will Be "CCCCC33".
Now I already have a Localizable.string file and my .xib files are already localized(all labels,images and datepicker etc.).
I want to change the value of getSign2 from AAAAA0.html to AAAA0-French.html if user language is french. Similarly it should change to BBBB28-French.html and CCCC33-French.html for BBBB28.html and CCCC33.html respectively.
What should I add in localizable.string to do this? What change should I make in ViewController.m file?
I know I can use following
NSLocale *locale=[NSLocale currentLocale];
NSString *currentlocale =[locale displayNameForKey:NSLocaleIdentifier value:[locale localeIdentifier]];
NSLog(#"Complete Locale: %#",currentlocale);
if (currentocale==#"French") {
NSString *getSignNew=[getSign2 stringByAppendingString:#"-French"];
NSString *filePath=[[NSBundle mainBundle] pathForResource:getSignNew ofType:#"html" ];
}
But this method check conditions in ViewController.m file while I have done all other localization related coding in localizable.string. Will it cause problem when I will submit my application? If this is not the correct solution then please tell me how to fix this problem.
Please reply as soon as possible.
Thanks.
Localized file should be placed in the structure like this:
Your.app/
English.lproj/
AAAAA0.html // English localized file
....
French.lproj/
AAAAA0.html // French localized file
...
zh_TW.lproj/
AAAAA0.html // Chinese localized file
...
and then -pathForResource:ofType: will automatically look up the correct file matching the current locale.

How do I extract pixel data from DICOM files on iOS?

Does anyone know how I can extract the pixel data from a DICOM file and pass it to an image viewer on iOS?
Sorry if this is a simple question, but it seems to be a major component to a huge can of worms I have opened.
I'm using GDCM on iOS. I haven't pushed it very hard yet but it's working well so far. I basically followed the directions for hacking XCode projects to run in iOS in this excellent article on ITK.
Here's how I got it to compile for iOS:
Downloaded source from sourceforge, installed cmake via ports. You'll need a recent version of cmake (I'm using 2.8.2)
If the source is in a folder called gdcm-2.0.17/, then create another directory at that level (say gdcmbin), cd to that directory, and enter ccmake -GXCode ../gdcm-2.0.17/ in the terminal window. This creates the XCode project. When I did this I didn't create any of the example programs or create shared libraries (which won't work in iOS). Just run the defaults.
Follow the directions in the ITK paper on changing the build options (step #7 on page 4).
Then link GDCM into your project using the excellent instructions at Clint Harris' blog
When you're setting up the header search path in your project to GDCM - you have to enter two paths: blah/gdcm-2.0.17/Source/** and blah/gdcmbin/**. The trailing '/Source' on the first path is necessary - otherwise you get headers that aren't appropriate for your architecture.
One glitch (annoying but haven't spent the time to figure it out yet): you get a bunch of linking errors when you switch from simulator to device (or vice versa). This is because the gdcm project doesn't put the outputs into different directories for different targets. So - run a clean and rebuild in the gdcm project when you're switching. I'll probably get annoyed by this soon enough to change it :-).
Here's a rough snippet of how you'd call the library and put the results in an Objective-C dictionary:
NSMutableDictionary * imageDictionary = [[NSMutableDictionary alloc] initWithCapacity:40];
// The output of gdcm::Reader is a gdcm::File
gdcm::File &file = reader.GetFile();
// the dataset is the the set of element we are interested in:
gdcm::DataSet &ds = file.GetDataSet();
const Tag studyInstance(0x0020,0x000d); // Study Instance UID
const DataElement &dicomVal = ds.GetDataElement(studyInstance);
std::string stringVal( dicomVal.GetByteValue()->GetPointer(), dicomVal.GetByteValue()->GetLength() );
NSString *val = [NSString stringWithCString:stringVal.c_str() encoding:[NSString defaultCStringEncoding]];
[imageDictionary setObject:val forKey:#"studyInstanceUID"];
(Note: this is in an *.mm file that mixes C++ and ObjectiveC)
Imebra has an Objective-C wrapper that can be used also with Swift.
#import "imebraobjc/imebra.h"
// Get the DICOM dataset from file
NSError* error = nil;
ImebraDataSet* pDataSet = [ImebraCodecFactory loadFromFile:#"test.dcm" error:&error]
// CHeck the patient name (automatically convert from DICOM charsets to UTF-8)
NSString* checkPatientName = [pDataSet getString:[[ImebraTagId alloc] initWithGroup:0x10 tag:0x10] elementNumber:0 error:&error]; // Automatically converted to UTF-8 if necessary
// Get the frame 0
ImebraImage* pCheckImage = [pDataSet getImageApplyModalityTransform:0 error:&error];
// Get the image data
ImebraReadingDataHandlerNumeric* readingDataHandler = [pCheckImage getReadingDataHandler:&error];
// Scan the pixels. Access the data handler memory for faster data access
for(unsigned int pixel(0); pixel != readingDataHandler.size; ++pixel)
{
unsigned int pixelValue = [readingDataHandler getUnsignedLong:pixel error:&error];
}
ImebraDrawBitmap* pDrawBitmap = [[ImebraDrawBitmap alloc] init];
// Obtain a NSImage (UIImage on iOS)
NSImage* pNsImage = [pDrawBitmap getImebraImage:pCheckImage error:&pError];
If you want to find DICOM software, look at idoimaging.com, a clearinghouse for medical imaging software. You can choose your platform, input format, output format, language, etc. iOS isn't listed as a format, but much of the software listed there is available with source, useful in library form, and available for MacOS X. For example, I selected:
input format: DICOM
platform: Macintosh
language: C
and found several packages. Given the similarities between MacOS and iOS and the fact that some of these are cross-platform with source included, it shouldn't be too difficult to get one of them working on iOS.

Localization of strings in static lib

I have a project that uses a static library (SL). In that SL, there are a couple of strings I'd like to localize and the project includes all of the localization files. The localization works just fine when storing all text translations in the same file. The thing is that I'd like to separate the SL strings from the other strings. I have tried to put two different *.strings files (Localizable.strings and Localizable2.strings) in the language folder of interest but that did not work. I have also tried to use two *.strings file with the same name (Localizable.strings) but with different paths. It didn't work either. It seems that only one localization file is supported, right? Could anyone suggest a good way of doing this? I'm using SDK 3.2 beta 2.
It is not possible to bundle it in a static lib, but you can create new bundle like "MyStaticLibraryName.bundle", put inside all localizations and use the code below instead "NSLocalizedString()". All you need to do: add a static library and resource bundle.
NSString *MyLocalizedString(NSString* key, NSString* comment) {
static NSBundle* bundle = nil;
if (!bundle) {
NSString* path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"MyStaticLibraryName.bundle"];
bundle = [[NSBundle bundleWithPath:path] retain];
}
return [bundle localizedStringForKey:key value:key table:nil];
}
Putting files with the same name intro one project never works, because in the resulting app they end up all in the same location. (Xcode doesn't preserve your directory structure.)
But you can put part of your localization into Localizable2.strings and then use:
NSLocalizedStringFromTable(#"key", #"Localizable2", #"")
Make the localizable string for the static library, then place that string file in a folder "YourLibraryResource".
Rename the folder "YourLibraryResource.bundle".
Now you include this bundle also in the project along with the library. Then use the code given by abuharsky.

iPhone en_* sublanguage localization

I want to localize strings in my iphone app for en_GB and other 'en' sub-languages, but XCode and the iphone refuse to let this happen. I have created a localization of "Localizable.strings" for en_GB and en_US (I tried both hyphens and underscores) for testing purposes, but they just aren't recognized. The only language code that works is simply "en" (displayed as "English" in XCode).
I can't believe this isn't possible, so what am I doing wrong? I'm also hoping to get the typical 'cascading' behaviour where if a string isn't found in the sub-language e.g. "en_GB" then it should be taken from "en" if possible. Help?
When you choose 'English' from the list of languages on the iPhone preferences, that actually means the 'en_US' language.
So until apple update their software with additional sublanguages like "English (British)" etc. we are left with going by the locale region setting, and loading strings manually from another string table.
However, the language and regional locale are separated for a reason: a Spanish user in the UK may want dates/times formatted according to the local customs, but program strings in their native tongue. It would be incorrect to detect the regional locale (UK) and therefore display UK strings.
So basically there is no way to do this currently.
What you're doing should work according to the docs. But it appears that the iPhoneOS implementation is at odds with the documentation. According to Radar 6158876, there's no support for en_GB language, only locale (date formats and the like).
I found the same problem.
BTW, if you look at the iPhone Settings -> General -> International menu, it makes the distinction between language and region quite clear:
Languages:
-English
Region Format:
-United States
-United Kingdom
The localization framework only appears to pay attention to the language, not the region.
I'm tempted to raise an enhancement request for this with Apple, as IMO it is reasonable that a user might want to use British English (for the text) whilst being in the United States (where, say, phone numbers should be in US format).
This can actually be done - check my solution here - iPhone App Localization - English problems?
Create a separate string resource, say UKLocalization.strings, and create localizations for each of your supported languages. For all localizations other than en this file is empty. For en, it contains only the strings that have unique en_GB spelling.
Next, you create a replacement for NSLocalizationString that will first check the UKLocalization table before falling back to the standard localization table.
e.g.:
static NSString* _locTable = nil;
void RTLocalizationInit()
{
_locTable = nil;
NSString* country = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
if ([country isEqual:#"GB"])
{
_locTable = #"UKLocalization";
}
}
NSString* RTLocalizedString(NSString* key, NSString* ignored)
{
NSString* value = nil;
value = [[NSBundle mainBundle] localizedStringForKey:key value:nil table: _locTable];
if (value == key)
{
value = NSLocalizedString(key, #"");
}
return value;
}
I’m not sure in which version of iOS it was introduced, but iOS 7 definitely has a ‘British English’ language preference that will pick up resources from the en_GB.lproj directory. The various hacks floating around the web shouldn’t be necessary unless you’re after a more specialised* dialect.
*see what I did there ;)