My old code uses NSLocalizedString to display the following where outputText was an NSMutableString that contained many such lines in a single output session:
[outputText appendFormat: NSLocalizedString(#"\n\n%# and %# are identical. No comparison required.", #"\n\n%# and %# are identical. No comparison required."), self.ipAddress, secAddress.ipAddress];
I'm trying to change the color of the various ipAddress strings, but can't find a similar method when using NSMutableAttributedString.
The biggest problem I'm facing is that since this entire string will be localized, I can't reliably set the NSRange without breaking up each part of the formatted output.
Do I need to dissect each part of this string, convert it to NSAttributedString and append each piece to the outputText??
The answer is: yes.
Yes, you need to localize sections with different attributes separately.
Related
I'm running into problems with international (in this case Korean) NSString values.
The same input string is used in two different parts of the program. The first part finds a substring that needs highlighting, stores the NSString and the range for the highlighting into a database.
The second part of the program retrieves the string and displays the highlighting.
The marking part is done using an NSString that has been normalized in Unicode Normalization Form C using the precomposedStringWithCanonicalMapping method on NSString. An NSRange and an NSString are then stored into the Core Data database.
The graphical highlighting is performed by retrieving the NSRange and NSString from the database, putting the NSString into the same Form C using the same method, using this to initialize an NSMutableAttributedString and using the NSRange to set its text attributes.
At this stage, the program crashes because the NSMutableAttributedString is 80 characters long, whereas the NSString was 81 characters long..
NSAttributedString does not have a precomposedStringWithCanonicalMapping method and I assume it changes the representation internally resulting in a different encoding and thus length.
What can I do?
is the a way of forcing NSAttributedString to keep an underlying encoding?
is there a way of converting an NSRange from one encoding to another?
or is there anything else I can do?
Ok,
I did eventually find out what had happened. In one particular place in the program I mistakenly used decomposedStringWithCanonicalMapping rather than precomposedStringWithCanonicalMapping and that's where the "wrong" mapping came from.
I am currently working on Swift script that allows type-checks by compiler for localization strings, something that was sorely needed for a long time. If you are interested, you can check the project on GitHub to get better understanding.
The problem
Part of it is creation of methods from strings, when parser encounters special characters, that are meant to be changed in runtime (%d, %f, %# etc.). String like this:
"PROFILE_INFO" = "I am %#, I am %d years old and %.2fm in height!"
Will get converted to method with following signature:
func profileInfo(value1 : String, value2 : Int, value3 : Float { ...
What I am really curious about and what I could not find anywhere, not even in documentation, is what types are allowed in localization strings. I suspect it goes through default format and there is a lot of types to cover, in which case, I am curious what people used and what types can be omitted. I am using following regexp matching to find the special characters currently, and then converting them to appropriate data types:
let regexp = "%([0-9]*.[0-9]*(d|f|ld)|#|d)"
let matches = self.matchesForRegexInText("%([0-9]*.[0-9]*(d|f|ld)|#|d)", text: string)
I know this covers most of the usual cases, but obviously, I would like to have full coverage if possible.
TLDR:
Q1: What format specifiers are allowed in localization strings - are there any changes from classic string format or everything is the same?
Q2: Is there any better way to convert those characters to appropriate data type than using regexp to parse them out?
Thanks!
Browsing Attributed String Programming Guide and the documentation for NSAttributedString and NSMutableAttributedString, I can't see a straightforward way to take all the attributes from one string and apply them to another.
The only possibility I've found so far is to to use -[NSAttributedString enumerateAttributesInRange:options:usingBlock:] but that seems like a very long way around.
Am I missing something? Surely there must be a cleaner solution?
What I'm ultimately aiming to achieve is to take an attributed string from a static label I've configured in a Storyboard, change it to contain dynamic info and apply certain attributes over certain ranges.
Use - (NSDictionary *)attributesAtIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange to get the attributes at a specific index (e.g. 0 for the first character in string). Then use this attribute in - (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange to set this attributes for all characters in range.
Is there a simple way (a function, a method...) of validating a character that a user types to see if it's compatible with Mac OS Roman? I've read a few dozen topics to find out why an iOS application crashes in reference to CGContextShowTextAtPoint. I guess an application can crash if it tries to draw on an image a string (i.e. ©) containing a character that is not included in the Mac OS Roman set. There are 256 characters in this set. I wonder if there's a better way other than matching the selected character one by one with those 256 characters?
Thank you
You might give https://developer.apple.com/library/mac/#documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_text/dq_text.html a closer read.
You can draw any encoding using CGContextShowGlyphsAtPoint instead of CContextShowTextAtPoint so you can tell it what the encoding is. If the user types it then you'll be getting the string as an NSString which is a Unicode string underneath. Probably the easiest is going to be to get the utf8 encoding of that user entered string via NSString's UTF8String method.
If you really want to stick with the very limited MacRoman for some reason, then use NSString's cStringUsingEncoding: passing in NSMacOSRomanStringEncoding to get a MacRoman string. Read the documentation on this in NSString though. Will return null if the user string can't be encoded in MacRoman losslessly. As it discusses you can use dataUsingEncoding:allowLossyConversion: and canBeConvertedToEncoding: to check. Read the cautions in the Discussion for cStringUsingEncoding: about about lifecycle of the returned strings though. getCString:maxLength:encoding: might end up being a better choice for you. All discussed in the class documentation for NSString.
This doesn't directly answer the question but this answer may be a solution to your problem.
If you have an NSString, instead of using CGContextShowTextAtPoint, you can do:
[someStr drawAtPoint:somePoint withFont:someFont];
where someStr is an NSString containing any Unicode characters a user can type, somePoint is a CGPoint, and someFont is the UIFont to use to render the text.
NSString localizedStringWithFormat puts in comma for separating thousands. How do you keep it from doing that. For example return 5000.25 instead of 5,000.25 (only have decimal separator)
localizedStringWithFormat uses the system's locale to format the numbers. What you want is to override the default locale - use initWithFormat:locale: for that. Basically, it's the same function, but you also supply the locale for which to format the text.
Also, keep in mind that initWithFormat:locale: also retains the string (as opposed to localizedStringWithFormat.
Check both of them here https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
Managed to get the desired behavior by using NSNumberFormatter and setting its groupingSize property to 0. Then used stringFromNumber method.