Localizing a Managed Object Model not working

I want to localize a Fruits entity a name and type attributes. The static data is initially stored in a NSArray, and then loaded into core data. Here is an example of the static data: Apple, Pear, Grapes, Kiwi, etc., and they are stored inside of the Fruits entity. Unfortunately, when using NSLocalizedStringFromFile on the static array, and then setup


en.strings file:

"Property/Apple" = "Apple";

"Property/Pear" = "Pear";


es.strings file:

"Property/Apple" = "Manzana";

"Property/Pear" = "Pera";


fr.strings file:

"Property/Apple" = "Pomme";

"Property/Pear" = "Poire";


How do I configure NSLocalizedStringFromFile to read the data from the language specific strings file (en = English, es = Spanish, and fr = French) Fruits entity? How do I configure a NSFetchedResultsController to display the localized languages, once the Application Language is changed inside of the simulator?



Thank you for any suggestions, links, and program code to help me resolve this issue.


Note: The above strings file syntax came from Page 36 of the Core Data Programming Guide.

Answered by NotMyName in 87256022

It works exactly the same for Core Data as it does for the rest of Objective-C or Swift. That's the point. That's why the section of the documentation you're asking about no longer exists in the latest version of the document.


Sit down and create a simple Objective-C (or Swift, but I'm going to type in Objective-C) project with a class with a method like so:

- (NSString *) localizedValue {

return NSLocaledStringFromTable(self.unlocalizedValue, @"ValueLocalizationTable", @"Localized value for unlocalized value");

}


and get that to work. Once you figure out how to get that to work, you'll understand how to use the NSLocaliedStringFromTable functions in Xcode.


On the other hand, stop and ask yourself what you're trying to accomplish "internationalizing" a managed object model. If you want to have multiple read-only different versions of your database for different locals, you don't accomplish that using NSLocalizedStringFromTable. You accomplish that by creating multiple different read-only versions of your database and choosing between them at run time (creating a resource bundle and specifying the different versions for different language values).

What version of the Core Data Programming Guide are you reading?

There's no such standard method NSLocalizedStringFromFile.


Edit: And you don't configure an NSFetchedResultsController to display localized values. What you have to do, instead, is call the appropriate NSLocalizedString______ macros to replace the standard value you've stored in the attribute with the localized value you want to display to user, and you do that in all of your code for displaying the results--your UITableView cellForRowAtIndexPath or wherever else you display the value.

I am reading Page 36 from the Core Data Programming Guide that was written on 2014-07-15.


I made an error in providing the name of the macro, it should have been NSLocalizedStringFromTable. I have used NSLocalizedStringFromTable to produce the strings file in French, and Spanish. The languages change only when the data is contained in a NSDictionary and NSArray combination. I used an instance variable to extract the NSDictionary keys. Here is the code:


self.sectionsArraySorted = [[_mySubjectsDictionary allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];//obtain all of the the keys inside of the dictionary; they are being used as the sections for the tableview. Then sorting the values in alphabetical order


Thus, localization works fine, if I store the data inside of a static NSDictionary. I can store that static data, that is written in English, inside of my Fruits entity. I have not been able to localize the Fruits entity with the information that is provided from Page 36 from the Core Data Programming Guide that was written on 2014-07-15.



Below is a method that I used to that changes the language inside of my Fruits entity. after changes are made via Xcode (version 6.4 (6E35b ) --> Product (menu item) --> Edit Scheme --> Edit Scheme option. I then change the Application Language. My showCoreDataLocalization is called from within the AppDelegate.m file's - (BOOL)application:didFinishLaunchingWithOptions:


-(void)showCoreDataLocalization

{

/

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Fruits"];


NSSortDescriptor *sortDescriptorSection = [[NSSortDescriptor alloc] initWithKey:@"type"

ascending:YES];

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"word" ascending:YES];

[fetchRequest setSortDescriptors:@[sortDescriptorSection,sortDescriptor]];


NSError *fetchError = nil;

NSArray *result = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];


if (!fetchError) {

for (Fruits *showFruits in result) {

NSString *verbType = showFruits.type;

NSString *verbWord = showFruits.word;

showFruits.word = NSLocalizedStringFromTable (verbWord, @"CDLocalizedTable", @"reading from CDLocalizedTable.strings table");

showFruits.type = NSLocalizedStringFromTable (verbType, @"CDLocalizedTable", @"reading from CDLocalizedTable.strings table");

}

} else {

NSLog(@"Error fetching data.");

NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);

}

}


Please provide a link to some sample code, or show me your own sample code, or modify the above code, so that I can localize my managed object modal (localizing Core Data).Thank you very, very much!

See the documentation for constructing the localized string tables:

xcdoc://?url=developer.apple.com/library/etc/redirect/xcode/ios/1151/documentation/MacOSX/Conceptual/BPInternational/MaintaingYourOwnStringsFiles/MaintaingYourOwnStringsFiles.html

(That's in the Internationalization and Localization Guide, "Maintaining Your Own Strings Files".)


And please be aware that you're quoting sample code from what is no longer the current version of the Core Data Programming Guide.

The revision dates:


2015-09-17 Significant update and rewrite of the guide to reflect current best practices and APIs.

2014-07-15 Updated various sections.

2014-03-10 Corrected Scalar Value Constraints section in Non-Standard Persistent Attributes. Custom structures other than NSPoint, NSSize, NSRect, and NSRange may be key-value coding and key-value observing compliant, and therefore may be supported by Core Data.

Thank you for your reponses! I have already exported, and then imported the strings file for each language, as described in the Internationalization and Localization Guide: Localizing Your App. After exporting the files, I modified each .xliff file with the correct <target> internationalized text in the other language</target>. This was done for each .xliff file (es, and fr). Then I imported each of those files back into Xcode. This process works perfectly fine as long as I am localizing the static NSDictionary information. Once the static NSDictionary data is stored to my Fruits entity, which displays nicely in English, I then have to used the previously shown method to force seeing the language changes in my TabelViewController. Unfortunately, that previously shown method is physically changing the Fruits entity attributes when ever I change the Application Language inside of the Simulator. This is not a desired result according to Step 3 under the Internationalization and Localization Guide: Creating Strings Files For User-Facing Text in Your Code: Step 3. That process indicates that one side should always be in your 'Base Internationalization' language, which is English in my case. My previously supplied method is changing the Fruits entity attributes, which cannot remain in its initial English language. Thus, localization of my Managed Object Model is not working once I change the language via Command + Shift + <. The localized text will show only once, and then will never change again.


P.S.: All of the other text that is inside of my project's view controllers are being displayed in their respective localied languges correctly. Its only Core Data that I cannot get to see the internationalization changes after the Application Language is changed via Command + Shift + <


I can email you the entire project so that you can have a visual of what I am staying. You can optionally, email me a sample project file that show how a Managed Object Model has been internationalized. Either situation will be greatly appreciated!!! Again, thank you very much for your time and expertise!

I think there's an important concept to keep in mind here: There isn't anything special with reguard to Core Data going on here.


You could generate any arbitrary array of abitrary values, or any Objective-C class, and pass it through a for loop of the form

for (Fruits *showFruits in result) {

NSString *verbType = showFruits.type;

NSString *verbWord = showFruits.word;

showFruits.word = NSLocalizedStringFromTable (verbWord, @"CDLocalizedTable", @"reading from CDLocalizedTable.strings table");

showFruits.type = NSLocalizedStringFromTable (verbType, @"CDLocalizedTable", @"reading from CDLocalizedTable.strings table");

}

to perform localization substitution on the values. And the those four lines of code are "Take the value for this attribute, and replace it with the localized value" which becomes permanent if you save the context or continue using the object. This is a terrible and bad thing to do, because it makes it destroys the ability to respond to future locale changes--the whole problem you're complaining about.


I strongly suspect that that is WHY that section of the programming guide was removed. Because the better approach isn't to try to modify the fetched entities. The better approaches are to either:

- Use one of the NSLocalizedString variants when you need to display the value. Do this manually each time it's appropriate.

- Define a simple custom attribute on the managed object subclass, like:


- (NSString *) localizedWord {

return NSLocaledStringFromTable(self.type, @"CDLocalizedTable", @"Localized Fruit type");

}


and then if you have performance issues with that you can apply the suggestions in the Core Data Programming Guide concerning custom attributes and lazy properties. In other words, the best thing you can do is completely eliminate that for loop, replace all of your references to the unlocalized property values to references to custom accessors you wrote like my example localizedWord accessor.

Thank you for your response, but I cannot see how NSLocaledStringFromTable can be used to access core data's attributes. Can I assume that there does not exist any sample code that demonstrates how to internationalize a Managed Object Model ? If it does exist, then I would love to have a link to it! Can you send me some sample code that will work on localizing one attribute for a Managed Object Model?


Thank you for your guidance!

Accepted Answer

It works exactly the same for Core Data as it does for the rest of Objective-C or Swift. That's the point. That's why the section of the documentation you're asking about no longer exists in the latest version of the document.


Sit down and create a simple Objective-C (or Swift, but I'm going to type in Objective-C) project with a class with a method like so:

- (NSString *) localizedValue {

return NSLocaledStringFromTable(self.unlocalizedValue, @"ValueLocalizationTable", @"Localized value for unlocalized value");

}


and get that to work. Once you figure out how to get that to work, you'll understand how to use the NSLocaliedStringFromTable functions in Xcode.


On the other hand, stop and ask yourself what you're trying to accomplish "internationalizing" a managed object model. If you want to have multiple read-only different versions of your database for different locals, you don't accomplish that using NSLocalizedStringFromTable. You accomplish that by creating multiple different read-only versions of your database and choosing between them at run time (creating a resource bundle and specifying the different versions for different language values).

I really appreciate your time and efforts to help me with this issue!!!

I attempted your suggestions on two separate projects. Unfortunately, I could not get it to work. I was able to get the UIButton text to change when the language changed to and from English to Spanish. That was never my issue, but I did it to ensure that NSLocalizedString( ) was working correctly.

One issue that I noticed with your suggested configuration of the extra entity attribute, was that upon "Export For Localization...", I did not see any place marker for the entity attribute inside of the .xliff file. I did see, and was able to edit my two button titles that are configured with NSLocalizedString( ). The Main.strings( Spanish ) files was generated by Xcode after the export, and then imported process. I modified the .xliff file and then impored it back into my project. As shown below, I edited the .xliff file to include the names of the fruits that should have been displayed in Spanish.

Xcode is configured to display the Spanish text via Command + <, then 'Application Language'. Thank you for your continued assistance, and advice!

Below is the code to the Managed Object Model:

Fruit.h ----

#import <Foundation/Foundation.h>

#import <CoreData/CoreData.h>

@interface Fruit : NSManagedObject

@property (nonatomic, retain) NSString * word;

@property (nonatomic, retain) NSString * localizedWord;

-(NSString *)localizedWord;

-(void)setLocalizedWord:(NSString *)localizedWord;

@end

Fruit.m ----

#import "Fruit.h"

@implementation Fruit

@dynamic word;

@dynamic localizedWord;

-(NSString *)localizedWord

{

return NSLocalizedString(self.word, @"localized in Managed Object Model");

}

-(void)setLocalizedWord:(NSString *)localizedWord

{

self.word = localizedWord;

}

@end

Thank you for your help! I was finally able to internationalize the managed object model. Thank you!

Hello! Can you explain how did you manage to get it work? If you have it in Swift, it would be great. Thanks

Localizing a Managed Object Model not working
 
 
Q