Possible to use variables and/or parameters with NSLocalizedString? - objective-c

I have tried using a variable as an input parameter to NSLocalizedString, but all I am getting back is the input parameter. What am I doing wrong? Is it possible to use a variable string value as an index for NSLocalized string?
For example, I have some strings that I want localized versions to be displayed. However, I would like to use a variable as a parameter to NSLocalizedString, instead of a constant string. Likewise, I would like to include formatting elements in the parameter for NSLocalizedString, so I would be able to retrieved a localized version of the string with the same formatting parameters. Can I do the following:
Case 1: Variable NSLocalizedstring:
NSString *varStr = #"Index1";
NSString *string1 = NSLocalizedString(varStr,#"");
Case 2: Formatted NSLocalizedString:
NSString *string1 = [NSString stringWithFormat:NSLocalizedString(#"This is an %#",#""),#"Apple"];
(Please note that the variable can contain anything, not just a fixed set of strings.)
Thanks!

If what you want is to return the localized version of "This is an Apple/Orange/whatever", you'd want:
NSString *localizedVersion = NSLocalizedString(([NSString stringWithFormat:#"This is an %#", #"Apple"]), nil);
(I.e., the nesting of NSLocalizedString() and [NSString stringWithFormat:] are reversed.)
If what you want is the format to be localized, but not the substituted-in value, do this:
NSString *finalString = [NSString stringWithFormat:NSLocalizedString(#"SomeFormat", nil), #"Apple"];
And in your Localizable.strings:
SomeFormat = "This is an %#";

I just want to add one very helpful definition which I use in many of my projects.
Inspired by androids possibility, I've added this function to my header prefix file:
#define NSLocalizedFormatString(fmt, ...) [NSString stringWithFormat:NSLocalizedString(fmt, nil), __VA_ARGS__]
This allows you to define a localized string like the following:
"ExampleScreenAuthorizationDescriptionLbl"= "I authorize the payment of %# to %#.";
and it can be used via:
self.labelAuthorizationText.text = NSLocalizedFormatString(#"ExampleScreenAuthorizationDescriptionLbl", self.formattedAmount, self.companyQualifier);

For swift :
let myString = String(format: NSLocalizedString("I authorize the payment of %d ", comment: ""), amount)

extension String {
public var localizedString: String {
return NSLocalizedString(self, comment: "")
}
public func localizedString(with arguments: [CVarArg]) -> String {
return String(format: localizedString, arguments: arguments)
}
}
Localizable.string:
"Alarm:Popup:DismissOperation:DeviceMessage" = "\"%#\" will send position updates on a regular basis again.";
"Global:Text:Ok" = "OK";
Usage:
let message = "Alarm:Popup:DismissOperation:DeviceMessage".localizedString(with: [name])
and
let title = "Global:Text:Ok".localizedString

It turns out that a missing target entry is to blame. Just checking that my current build target includes the Localizable.string file solved the problem!

If you have more than one variable in your localized string can you use this solution:
In Localizable.strings
"winpopup" = "#name# wins a #type# and get #points# points(s)";
And use stringByReplacingOccurrencesOfString to insert the values
NSString *string = NSLocalizedString(#"winpopup", nil); //"#name# wins a #type# and get #points# points(s)"
NSString *foo = [string stringByReplacingOccurrencesOfString:#"#name#" withString:gameLayer.turn];
NSString *fooo = [foo stringByReplacingOccurrencesOfString:#"#type#" withString:winMode];
NSString *msg = [fooo stringByReplacingOccurrencesOfString:#"#points#" withString:[NSString stringWithFormat:#"%i", pkt]];
NSLog(#"%#", msg);

Your ideas should work. But if you are getting back the input parameter, that means that the input parameter was not found as a key in your Localizable.strings file. Check the syntax and location of that file.

This works for me:
NSMutableString *testMessage = [NSMutableString stringWithString:NSLocalizedString(#"Some localized text", #"")];
testMessage = [NSMutableString stringWithString:[testMessage stringByAppendingString:someStringVariable]];

Related

How to Localize NSString with format [duplicate]

This question already has an answer here:
iOS: How to localize strings with multiple interpolated parameters?
(1 answer)
Closed 5 years ago.
How to localize the NSString with format.
int value = 20;
NSString *str = #"hello";
textLabel.text = [NSString stringWithFormat:#"%d %#", value, str];
I tried
textLabel.text = [NSString stringWithFormat:NSLocalizedString(#"%d %#", #"%d %#"), value, str];
but didn't work. Any help is appreciated.
Your localized string itself must be a format pattern:
"ValueAndStringFMT" = "Value %1$d and string %2$#";
And in your code:
textLabel.text = [NSString
stringWithFormat:NSLocalizedString(#"ValueAndStringFMT"),
value, str
];
Why %1$d and not just %d? So you can change the order. E.g. in some language you may like to have the order swapped:
"ValueAndStringFMT" = "Cadena %2$# y valor %1$d";
Of course, that is somewhat dangerous as if someone uses more placeholders than your string call offers or uses the wrong types, your app may crash. If you want to be safe, you do a search an replace instead:
"ValueAndStringFMT" = "Value [[VALUE]] and string [[STRING]]";
And in your code:
NSString * string = NSLocalizedString(#"ValueAndStringFMT");
string = [string stringByReplacingOccurrencesOfString:#"[[VALUE]]"
withString:#(value).stringValue
];
string = [string stringByReplacingOccurrencesOfString:#"[[STRING]]"
withString:str
];
textLabel.text = string;
That way the worst case scenario is that a placeholder is not expanded, meaning the placeholder is visibly printed on screen but at least your app won't crash because someone messed up the localization strings file.
If you need to localize one of the format variables, then you need to do that first in an own step:
NSString * str = NSLocalizedString(#"hello");

NSLocalizedString with format

How would I use NSLocalizedString for this string:
[NSString stringWithFormat:#"Is “%#“ still correct for “%#“ tap “OK“ otherwise tap “Change“ to choose new contact details", individual.contactInfo, individual.name];
When using stringWithFormat before I've used it in the following manner:
[NSString stringWithFormat:#"%d %#", itemCount, NSLocalizedString(#"number of items", nil)];
[NSString stringWithFormat:NSLocalizedString(#"Is “%#“ still correct for “%#“ tap “OK“ otherwise tap “Change“ to choose new contact details", #"Query if parm 1 is still correct for parm 2"), individual.contactInfo, individual.name];
Given sentences can be constructed with the variable parts in a different order in some languages then I think you should use positional arguments with [NSString stringWithFormat:]:
NSString *format = NSLocalizedString(#"number_of_items", #"Number of items");
Which would load the following string for English:
#"Is \"%1$#\" still correct for \"%2$#\" tap \"OK\" otherwise tap \"Change\" to choose new contact details"
And perhaps something else for French (I don't know French so I won't attempt a translation, but it could well have the first and second argument in a different order):
"French \"%2$#\" french \"%1$#\" french"
And you can safely format the string as normal:
NSString *translated = [NSString stringWithFormat:format individual.contactInfo, individual.name];
I just want to add one very helpful definition which I use in many of my projects.
I've added this function to my header prefix file:
#define NSLocalizedFormatString(fmt, ...) [NSString stringWithFormat:NSLocalizedString(fmt, nil), __VA_ARGS__]
This allows you to define a localized string like the following:
"ExampleScreenAuthorizationDescriptionLbl"= "I authorize the payment of %# to %#.";
and it can be used via:
self.labelAuthorizationText.text = NSLocalizedFormatString(#"ExampleScreenAuthorizationDescriptionLbl", self.formattedAmount, self.companyQualifier);
Swift
//Localizable.strings
"my-localized-string" = "foo %# baz";
Example:
myLabel.text = String(format: NSLocalizedString("my-localized-string",
comment: "foo %# baz"), "bar") //foo bar baz

How to check if NSString begins with a certain character

How do you check if an NSString begins with a certain character (the character *).
The * is an indicator for the type of the cell, so I need the contents of this NSString without the *, but need to know if the * exists.
You can use the -hasPrefix: method of NSString:
Objective-C:
NSString* output = nil;
if([string hasPrefix:#"*"]) {
output = [string substringFromIndex:1];
}
Swift:
var output:String?
if string.hasPrefix("*") {
output = string.substringFromIndex(string.startIndex.advancedBy(1))
}
You can use:
NSString *newString;
if ( [[myString characterAtIndex:0] isEqualToString:#"*"] ) {
newString = [myString substringFromIndex:1];
}
hasPrefix works especially well.
for example if you were looking for a http url in a NSString, you would use componentsSeparatedByString to create an NSArray and the iterate the array using hasPrefix to find the elements that begin with http.
NSArray *allStringsArray =
[myStringThatHasHttpUrls componentsSeparatedByString:#" "]
for (id myArrayElement in allStringsArray) {
NSString *theString = [myArrayElement description];
if ([theString hasPrefix:#"http"]) {
NSLog(#"The URL is %#", [myArrayElement description]);
}
}
hasPrefix returns a Boolean value that indicates whether a given string matches the beginning characters of the receiver.
- (BOOL)hasPrefix:(NSString *)aString,
parameter aString is a string that you are looking for
Return Value is YES if aString matches the beginning characters of the receiver, otherwise NO. Returns NO if aString is empty.
As a more general answer, try using the hasPrefix method. For example, the code below checks to see if a string begins with 10, which is the error code used to identify a certain problem.
NSString* myString = #"10:Username taken";
if([myString hasPrefix:#"10"]) {
//display more elegant error message
}
Use characterAtIndex:. If the first character is an asterisk, use substringFromIndex: to get the string sans '*'.
NSString *stringWithoutAsterisk(NSString *string) {
NSRange asterisk = [string rangeOfString:#"*"];
return asterisk.location == 0 ? [string substringFromIndex:1] : string;
}
Another approach to do it..
May it help someone...
if ([[temp substringToIndex:4] isEqualToString:#"http"]) {
//starts with http
}
This might help? :)
http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/characterAtIndex:
Just search for the character at index 0 and compare it against the value you're looking for!
This nice little bit of code I found by chance, and I have yet to see it suggested on Stack. It only works if the characters you want to remove or alter exist, which is convenient in many scenarios. If the character/s does not exist, it won't alter your NSString:
NSString = [yourString stringByReplacingOccurrencesOfString:#"YOUR CHARACTERS YOU WANT TO REMOVE" withString:#"CAN either be EMPTY or WITH TEXT REPLACEMENT"];
This is how I use it:
//declare what to look for
NSString * suffixTorRemove = #"</p>";
NSString * prefixToRemove = #"<p>";
NSString * randomCharacter = #"</strong>";
NSString * moreRandom = #"<strong>";
NSString * makeAndSign = #"&amp;";
//I AM INSERTING A VALUE FROM A DATABASE AND HAVE ASSIGNED IT TO returnStr
returnStr = [returnStr stringByReplacingOccurrencesOfString:suffixTorRemove withString:#""];
returnStr = [returnStr stringByReplacingOccurrencesOfString:prefixToRemove withString:#""];
returnStr = [returnStr stringByReplacingOccurrencesOfString:randomCharacter withString:#""];
returnStr = [returnStr stringByReplacingOccurrencesOfString:moreRandom withString:#""];
returnStr = [returnStr stringByReplacingOccurrencesOfString:makeAndSign withString:#"&"];
//check the output
NSLog(#"returnStr IS NOW: %#", returnStr);
This one line is super easy to perform three actions in one:
Checks your string for the character/s you do not want
Can replaces them with whatever you like
Does not affect surrounding code
NSString* expectedString = nil;
if([givenString hasPrefix:#"*"])
{
expectedString = [givenString substringFromIndex:1];
}

stringByAppendingFormat not working

I have an NSString and fail to apply the following statement:
NSString *myString = #"some text";
[myString stringByAppendingFormat:#"some text = %d", 3];
no log or error, the string just doesn't get changed. I already tried with NSString (as documented) and NSMutableString.
any clues most welcome.
I would suggest correcting to (documentation):
NSString *myString = #"some text";
myString = [myString stringByAppendingFormat:#" = %d", 3];
From the docs:
Returns a string made by appending to the receiver a string constructed from a given format string and the following arguments.
It's working, you're just ignoring the return value, which is the string with the appended format. (See the docs.) You can't modify an NSString — to modify an NSMutableString, use -appendFormat: instead.
Of course, in your toy example, you could shorten it to this:
NSString *myString = [NSString stringWithFormat:#"some text = %d", 3];
However, it's likely that you need to append a format string to an existing string created elsewhere. In that case, and particularly if you're appending multiple parts, it's good to think about and balance the pros and cons of using a mutable string or several immutable, autoreleased strings.
Creating strings with #"" always results in immutable strings. If you want to create a new NSMutableString do it as following.
NSMutableString *myString = [NSMutableString stringWithString:#"some text"];
[myString appendFormat:#"some text = %d", 3];
I had a similar warning message while appending a localized string. This is how I resolved it
NSString *msgBody = [msgBody stringByAppendingFormat:#"%#",NSLocalizedString(#"LOCALSTRINGMSG",#"Message Body")];

Is it necessary to assign a string to a variable before comparing it to another?

I want to compare the value of an NSString to the string "Wrong". Here is my code:
NSString *wrongTxt = [[NSString alloc] initWithFormat:#"Wrong"];
if( [statusString isEqualToString:wrongTxt] ){
doSomething;
}
Do I really have to create an NSString for "Wrong"?
Also, can I compare the value of a UILabel's text to a string without assigning the label value to a string?
Do I really have to create an NSString for "Wrong"?
No, why not just do:
if([statusString isEqualToString:#"Wrong"]){
//doSomething;
}
Using #"" simply creates a string literal, which is a valid NSString.
Also, can I compare the value of a UILabel.text to a string without assigning the label value to a string?
Yes, you can do something like:
UILabel *label = ...;
if([someString isEqualToString:label.text]) {
// Do stuff here
}
if ([statusString isEqualToString:#"Wrong"]) {
// do something
}
Brian, also worth throwing in here - the others are of course correct that you don't need to declare a string variable. However, next time you want to declare a string you don't need to do the following:
NSString *myString = [[NSString alloc] initWithFormat:#"SomeText"];
Although the above does work, it provides a retained NSString variable which you will then need to explicitly release after you've finished using it.
Next time you want a string variable you can use the "#" symbol in a much more convenient way:
NSString *myString = #"SomeText";
This will be autoreleased when you've finished with it so you'll avoid memory leaks too...
Hope that helps!
You can also use the NSString class methods which will also create an autoreleased instance and have more options like string formatting:
NSString *myString = [NSString stringWithString:#"abc"];
NSString *myString = [NSString stringWithFormat:#"abc %d efg", 42];