NSLocalizedString using external sources in Objective C? - objective-c

Is there a way to make the localization or Localizable.strings read from directories outside NSBundle?
I am trying to make my app read localizations from a file that is downloaded via a server, is there a way good way to do this?
Thanks in advance.

You will have to write your own MyLocalizedString function which reads the file manually. A .strings file is actually an old type of property list, so it can be read using the NSPropertyListSerialization class like this:
id plist = [NSPropertyListSerialization
propertyListWithData:[NSData dataWithContentsOfFile:stringsFilePath]
options:0
format:NULL
error:&error];
plist is just an NSDictionary, so you can read a string value from the result like this:
[plist objectForKey:#"my_string"];
You should probably implement some sort of cache so that you aren't parsing the whole file for each string lookup.
Note that if you are using genstrings and the other related command line tools, you can use the following option to specify the name of your custom lookup function:
Usage: genstrings [OPTION] file1.[mc] ... filen.[mc]
...[snip]...
-s substring substitute 'substring' for NSLocalizedString.
If these strings files are being uploaded to a server, you can improve performance in the app a bit by first converting them to the binary plist format (this is what Xcode would normally do during a build):
plutil -convert binary1 myStrings.strings

You will have to put together the pieces yourself. There isn't any built-in facility to do that. Your localizations can just be serialized dictionaries with the development language string as the key and the localized string as the value. You can serialize as a plist, which may be most convenient to edit, or using a keyed archive, which may be more compact.

Related

Edit Dictionary String values in a .plist file

I know this must be very simple. But I can't figure it out.
I have a Help.plist file, it has a key and then a dictionary with string values.
Where is the content for these dictionarys generally held.
When I search the string value in XCODE it does not come up.
This is leading me to believe it in the /documents/ section of the app. Should I use something like text edit to edit the value?
Note : I know the .plist file is a file of XML type. I do not want to edit this. I want to edit the contents of the dictionary.
Thanks
First get the dictionary for editing
NSMutableDictionary* dict = [[NSDictionary dictionaryWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"Help" withExtension:#"plist"]] mutableCopy];
Then you can edit it with the functions in NSMutableDictionary...
I don't think you can edit the contents of a file in your app's resources, so you may want to save it to the Documents folder after editing...

Building a custom NSArchiver serialize to string

How does NSArchiver serialize to file? I assume it's serialized in binary format, is that correct? What if I want to store it in string so I can store into SQLite database? Do I need to write my own custom NSArchiver? If so, how do I go about doing that? Are there any tutorials out there?
p.s. I do realize Core Data can do this but let me cross that option out for now.
You can archive to an NSData object instead of to a file, if you want, with +archivedDataWithRootObject:. It won't be a "string," but that's fine, because an NSString in Cocoa represents a sequence of Unicode characters, while an NSData represents a sequence of bytes (which you could easily store wherever you want, including in a database).
Note that you really should be using NSKeyedArchiver instead:
+ (NSData *)archivedDataWithRootObject:(id)rootObject
+ (id)unarchiveObjectWithData:(NSData *)data

How to use NSFileHandle to read integer from file

I want to read a list of integers from a text file, I just want to write code like
int temp;
fin>>temp;
But when I read the Cocoa documentation, I found NSFileHandle is suggested, and there is no method like I assumed, only one related method:
- (NSData *)readDataOfLength:(NSUInteger)length
Is there any class/method can help me do this in Objective C? Thanks.
I want to read a list of integers from a text file, I just want to
write code like
int temp; fin>>temp;
You have a lot of choices for file access. If you want to use C++-style access, you can, but you naturally need to open the file using the appropriate C++ file or stream methods. If you use Objective-C++, though, you can easily mix C++ code into your Objective-C.
You can also use the C standard library file routines like fopen(), fread(), etc.
Using C or C++ to read files is often a good choice if the files are coming from a source other than your program, something beyond your control.
But when I read Cocoa document, I found NSFileHandle is suggested, and
there is no method like I assumed, only one related method:
Again, lots of choices. Yes, you can use NSFileHandle to read bytes from the file into a NSData object, and then you can get ranges of bytes out of the data object. A much more common way to write and read data, though, is to use NSKeyedArchiver and NSKeyedUnarchiver:
NSData *data = [NSData dataWithContentsOfFile:pathToFile];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
int age = [unarchiver decodeIntForKey:#"Age"];
int weight = [unarchiver decodeIntForKey:#"Weight"];
NSString *name = [unarchiver decodeObjectForKey:#"Name"];
That's just the tip of the iceberg, though. It seems like a lot of code compared to what you were looking for, but it can also be a lot less work. Because objects and their relationships can be stored and read, you can read in a complex graph of objects with very little code:
OrgChart *chart = [NSUnarchiver unarchiveObjectWithFile:pathToFile];
Another option is to use property lists, which are very easy to use, but limited in the data types that can be used.
If you want to learn more about these topics, read Archives and Serializations Programming Guide, Property List Programming Guide, and File System Programming Guide.
You could use Objective-C++ and iostreams as you're used to.
You could use the C I/O functions like fopen and fscanf. (Probably what I'd do.)
Apple provides NSScanner for parsing, but it only reads from a string, not from an input stream. If you really want to use it, first you'll have to read your whole file (or a large chunk) into an NSString (or an NSData and then convert that to NSString).
If you can require the text file to be in JSON format, you can read it in one gulp and use NSJSONSerialization to parse it.

Generating large NSString xml

I have a plist and i want to convert it to xml. The xml itself is going to be around 1.2mb in size. What the best way to generate this xml? Simply with a NSMutableString? I am just worried about the performance issues and wether there is a better way to generate xml.
Thanks
For those wondering, what I have right now is something like this:
NSString *xml = [NSString stringWithFormat:#"<Sheet>%#</Sheet>", [self getSheetXMLString]];
and then, in getSheetXMLString method, i have more methods like above which drill down deep until the plist is fully transversed.
Thanks again.
What do you plan to do with the XML, if it is to output over a network or write to a file then instead of creating a NSString you could just write straight out to the network/file. If you plan to do manipulation if the XML you may want to consider libxml2, which is a C library included in iOS.

Open .string files as an NSDictionary

How do I open a .string file as an NSDictionary?
Edit: I want to be able to use it like this:
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:#"dict.plist"];
NSDictionary *strings = [[NSDictionary alloc] initWithContentsOfFile:#"Strings.strings"];
If you really want it in a dictionary, you can load it using [NSDictionary dictionaryWithContentsOfFile:], since it is in “Old-style ASCII” format. I have used this technique before on Mac OS X, but I'm not sure you can do the same for iOS.
However, if you want a translation for a particular string, there are at least two ways to do it:
NSLocalizedStringFromTable() will allow you to load strings from files other than the normal Localizable.strings file. Provide the name of your strings file (without the extension).
NSBundle's localizedStringForKey:value:table: method. This essentially performs the same operations as the method above, and as above, provide the name of your strings file without the extension.
.string files just store key/value pairs, like:
"StringKey" = "some localized text";
you can get the text for a specific key using NSLocalizedString. If you want to get all the strings in a file, I suppose you could read the Localizable.strings file and parse it.