WWDC Internationalization

2012 V244 Internationalization Tips and Tricks

NSLocale
+ currentLocale: returns static object that doesn’t change
+ autoupdatingCurrentLocale: picks up any changes to dateformat settings, time to show in 12h format, etc.
NSCurrentLocaleDidChangeNotification: when the settings change, received this notification the UI should update to new locale

Localising Text
Generating Strings entries from source files
find . -name \*.m | xargs genstrings -o en.lproj/

Searches for NSLocalizedString(@”key”, @”description”) and translates to:
/* description */
“key” = “key”

Sorting
instead of -compare: use -localizedStandardCompare:

Searching
avoid -[NSString rangeOfString:] does not take into account user local it uses system local.
use -[NSString rangeOfString:options:range:locale:] passing currentLocale or the autoUpdatingCurrentLocale

Directionality
Arabic being RTL can contain LTR text e.g: Brand names
Visually text is shown RTL but when the string is stored in memory it is stored in a single logical order LTR. When searching through string character by character or word by word. This directionality needs to be taken in consideration

Parsing
Not all characters fit in a unichar. Affects when using methods like character at index.
Avoid:
-characterAtIndex:
-length
-precomposedStringWithCanonicalMapping

Use:
-enumerateSubstringsInRange:options:usingBlock:

Custom Macros
ITTRootViewControllerString(@"key", @"description");
NSString* ITTRootViewControllerSTring(NSString *key, NSString *comment){
NSBundle *b = [NSBundle mainBundle];
NSString *str = [b localizedStringForKey:key value:nil table:@"ITTRootViewController"];
#if DEBUG
str = ITTPseudolocalize(str);
#endif
return str;
}

Pseudolocalize: Rewrite the string with any type of mark to be sure the text has been localised e.g: My lovely label -> $$My lovely label$$

Date
easiest way to convert a date into a string:
+localizedStringFromDate:dateStyle:timeStyle:

Avoid:
NSDateFormatter *df
[df setDateFormat:@"M/dd/yyyy"];

this is correct only in some countries
Use:
[df setDateStyle:NSDateFormatterShortStyle];

If you only want to show the month of a date:
Avoid:
[df setDateFormat:@"MMM d"];
Use:
NSString *format = [NSDateFormatter dateFormatFromTemplate:@"MMM d" options:0 locale:[NSLocale currentLocale]];
[df setDateFormat:format];

follows: Unicode Standard 35

Parsing Date String
Tell the dateformatter what calendar is being used. NSCalendar
strptime_l parse a timestamp to a time interval which can be formatted by the calendar

Timezones
Add timezone to the dateformatter: [df setTimeZone:[NSTimeZone timeZoneWithSecondsFromGMT:0]]

NSTimeZone: instead of being relative to a specific point in time it is relative to coordinated universal time.

NSDateComponents
Portions of a calendrical date, the various parts of the formatted human readable date

Unit lengths
- [NSCalendar maximumRangeOfUnit:] How many months
- [NSCalendar rangeOfUnit:inUnit:forDate:] how many days are in that month

AM/PM
Use @”j” for formatting an hour
[NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:[NSLocale currentLocale]];

US: h a (1-12 am)
Japan: H (0-23 withouth am)
France: HH (00-23 without am)
China: ah (am before 1-12)

Localizing Numbers
NSNumberFormatter
+localizedStringFromNumber:numberStyle

Parsing Numbers
Avoid
-intValue, scanf, etc
Use
NSNumberFormatter *nf
[nf setNumberStyle:NSNumberFormatterDecimalStyle];

Avoid
+stringWithFormat:, printf, etc
Use
[NSNumberFormatter localizedStringFromNumber:myNumber numberSTyle:setNumberStyle:NSNumberFormatterDecimalStyle];
Will use the correct character set for arabic

Currency
[nf setNumberStyle:NSNumberFormatterCurrencyStyle];

No unit conversion but NSLocale can tell you what currency/unit should be used
Unlocalized numbers strto*_l for the same purposes as the NSCalendar

Images
[UIImage imageNamed]; Uses NSBundle and this one takes the language into account

2013 V219 Making Your App World-Ready

Use Base Internationalization
– Edit only one set of nib files
– String file is generated for each storyboard and nib file
– localizers only need to edit the strings file
– use autolayout with base internationalization

ibtool generates a strings file for you. When a nib file has changed, inside the Base.lproj folder:
ibtool ChangeNib.xib –generate-strings-file NewStrings.strings

New in iOS7
stringsdict to take into account plurality and/or gender
Localized propertylist:
result = [NSString localizedStringWithFormat:NSLocalizedString(@”%d file(s) remaining”, @”comment”, n] -> research more on this check foundation release notes and What’s new in Cocoa WWDC 2013

Testing
Run the app with the argument
-AppleLanguages "(Korean)"

NSDataDetector to detect phone numbers, Addresses, make them into links

2014 V201 Advanced topics in internationalization
Language and Region Settings
– Primary language
– Specify preferred languages in order
– User can specify preferred language although it isn’t available in the OS but your app can be localised with that language
– Specify the region independently of the localization

iOS8 – when the text encoding type is not provided it can be abled to guess with the API
+ (NSStringEncoding) stringEncodingFromData:(NSData *)data
encodingOptions:(NSDictionary *)opts
convertedString:(NSString **)string
usedLossyConversion:(BOOL *)usedLossyConversion

iOS8 – NSDateComponentsFormatter
For displaying duration or amounts of time (1 hour, 50 minutes)

iOS8 – NSDateIntervalFormatter
For displaying time intervals (9:00 AM – 4:30 PM)

iOS8 – NSEnergyFormatter, NSLengthFormatter, NSMassFormatter

iOS8 – Formatting Context
Tells how the formatted text should be written, depending on how and where it appears:
– NSFormattingContextStandAlone
– NSFormattingContextListItem
– NSFormattingContextBeginningOfSentence
– NSFormattingContextMiddleOfSentence
– NSFormattingContextDynamic, once it is inserted in the formatted string it resolves beginning, middle of sentence.

Tip
In case you need to know the language the app is running because you want to show something running in Japanese but not in english. Put a localised resource in the NSBundle with value YES or NO on the required resource

Locale Change eg
- (void userChangeLocale: (NSNotification *) notification{
myFormatter.locale = [NSLocale currentLocale];
myFormatter.dateFormat = [NSDateFormatter dateFormatFromTemplate: myTemplate option:0 locale:myFormatter.locale]

[myView setNeedsDisplay];
}

Names
Don’t assume “First Last”
Avoid
NSString *displayName = [NSString stringWithFormat:@"%@ %@", firstName, lastname];
Use when used with Addressbook
NSString *diplayName= (NSString *) ABRecordCopyCompositeName(record);
When not form the Addressbook
ABRecordRef record = ABPersonCreate();
ABRecordSetValue(record, kABPersonFirstNameProperty, (CFStringRef) firstName, NULL);
ABRecordSetValue(record, kABPersonLastNameProperty, (CFStringRef)lastName, NULL);
NSString *displayname = (NSString *)ABRecordCopyCompositeName(record);
CFRelease(record);

Right-To-left
Avoid:
[textView setAlignment:NSTextAlignmentLeft]
Use:
[textView setAlignment:NSTextAlignmentNatural]

Text Directionality
Avoid:
[textField setBaseWritingDirection: NSWritingDirectionRightToLeft forRange:range];
Use:
[textField setBaseWritingDriection: NSWritingDirectionNatural forRange:range];
This guesses the directionality of the text, analyses the first characters and decides the direction.
In case this can not be used, because text is actually in arabic but begins with LTR letter: need to insert invisible character/mark that indicates the direction:
LRM: U+200E
RLM: U+200F

ios 6
In Scheme->Options->Aplication Language -> Right to Left Pseudo-Language

Keyboard
To make Keyboard and other UI Elements move in tandem, informatino we have:
Frame
UIKeyboardFrameBeginUserInfoKey
UIKeyboardFrameEndUserInfoKey
Animatin
UIKeyboardAnimationCurveUserInfoKey
UIKeyboardAnimationDurationUserInfoKey

Specify KeyboardType as not all Locales are going to show the same characters

Some localizations like chinese, the user types in the phonetic representations, the predictable text shows the options and then the user selects the correct option. This is indicated with -markedTextRange if it exists most likely the live search or similar won’t work as the typed in text is not the final text the user wants to input.

2014 V201 Localising with Xcode6
Export/import xliff format
Preview localizations

Recap for project
– use comments on NSLocalizedString
– use a different strings file per ViewController/Screen
– Pseudolocalize with macros
– use .stringsdict for plurals and gender control good resource http://www.objc.io/issue-9/string-localization.html
– listen to localeDidChange notification or use +[NSLocale autoupdatingCurrentLocale]. What should be done:
1)Listen to NSCurrentLocaleDidChangeNotification
2) If you keep formatters/locales around, use +[NSLocale autoupdatingCurentLocale]
3) Redo template formats
4) Invalidate any active views that contain locale-derived information
– ABRecordRef to display names
– Right-To-Left use: [textView setAlignment:NSTextAlignmentNatural]
– Directionality use: [textField setBAseWritingDriection: NSWritingDirectionNatural forRange:range]; With LRM/RLM marks

Leave a Reply

Your email address will not be published. Required fields are marked *