How to format localised strings in Swift?
Solution 1
You can use %@
in Swift's String(format:...)
, it can be substituted
by a Swift String
or any instance of a NSObject
subclass.
For example, if the Localizable.strings file contains the definition
"From %@, %@" = "从 %@, %@ 得出";
then
let x = 1.2
let y = 2.4
let text = String(format: NSLocalizedString("From %@, %@", comment: ""), "\(x)", "\(y)")
// Or alternatively:
let text = String(format: NSLocalizedString("From %@, %@", comment: ""), NSNumber(double: x), NSNumber(double: y))
produces "从 1.2, 2.4 得出". Another option would be to use the
%f
format for double floating point numbers:
"From %f, %f" = "从 %f, %f 得出";
with
let text = String(format: NSLocalizedString("From %f, %f", comment: ""), x, y)
See Niklas' answer for an even better solution which localizes the number representation as well.
Solution 2
From WWDC 2017:
let format = NSLocalizedString("%d popular languages", comment:"Number of popular languages")
label.text = String.localizedStringWithFormat(format, popularLanguages.count)
Solution 3
One more simple example
let changeable = "something"
let result = String(format: NSLocalizedString("stringId", comment: ""), arguments: [changeable]) // Hello World and something
localizable.strings with
"stringId" = "Hello World and %@";
-
comment
parameter doesn't have effect on result and is used for translators and bygenstrings
code-gen as comment
Solution 4
New in iOS 15 and macOS Monterey you can use the new refined method for String.
String(localized: "From \(x), \(y)", comment: "The result is computed from x and y")
They did a lot of updates in 2021 for localization with Xcode. Check this video from WWDC21 for more info.
Sweeper
I specialise in four programming languages: C#, Java, Kotlin and Swift. I don't know what to say here, so let me show you some of my apps, as well as my blog. Also you can donate to me if you'd like :D iOS Apps: Pocket Cheque Helper CusTimer Pushy Squares Math Toolbox Free Color Bible EZDiary TZoney Directional Snake LongLatMap Not Really Color Blind? 城迹单
Updated on July 09, 2022Comments
-
Sweeper almost 2 years
I am learning to localise my app to Simplified Chinese. I am following this tutorial on how to do this.
Because the tutorial is based on Obj-C, formatted strings can be written like this:
"Yesterday you sold %@ apps" = "Ayer le vendió %@ aplicaciones";
"You like?" = "~Es bueno?~";
But I am using Swift. And in Swift I don't think you can use
%@
to indicate that there is something to be placed there. We have string interpolation right?My app is kind of related to maths. And I want to display which input(s) is used to compute the result in a detailed label of a table view cell. For example
-------------- 1234.5678 From x, y <---- Here is the detailed label --------------
Here,
From x, y
means "The result is computed from x and y". I want to translate this to Chinese:从 x, y 得出
Before, I can just use this:
"From \(someVariable)"
with the strings file:
"From" = "从 得出";
And this is how I would use it in code
"\(NSLocalizedString("From", comment: "")) \(someVariable)"
But if this were used in the Chinese version, the final string will be like this:
"从 得出 x, y"
I mean I can put the
从
and得出
in two different entries in the strings file. But is there a better way to do it? -
Suragch over 6 yearsIs there a way to specify the order of the parameters or insert a single parameter multiple times? In some languages the insertion order might be reversed. Android allows this by using
%1
and%2
before the format specifier. -
Suragch over 6 yearsIs using
%@
better than%s
(for strings)? -
Martin R over 6 years@Suragch: There are encoding problems with
%s
, see stackoverflow.com/a/23672885 for an example. – I think that positional parameters like%1$s
work here as well. -
Wil Shipley over 6 yearsI believe this is the best answer because String.localizedStringWithFormat(_, ...) will localize the actual digits of the numbers (and swap commas and periods for German, for example), and String(format:...) will not. You can also use
String(format: "%f", locale: Locale.current, number)
. -
Wil Shipley over 6 yearsThis code won’t localize the numbers themselves — for example in German they use periods for commas and vice-versa, and in Arabic their digits are different codepoints. Use String.localizedStringWithFormat() or String(format: "%f", locale: Locale.current, number) instead.
-
Martin R over 6 years@WilShipley: You are completely right. Perhaps that method did not exist then or I did not think about it. I still think that I answered the question "I don't think you can use %@ to indicate that there is something to be placed there", but I have added a link to the better solution.
-
Wil Shipley over 6 yearsThanks Martin! I didn’t know about the other two methods but someone from that AppKit team pointed them out to me. So hopefully we can spread the word.
-
shakram02 over 5 yearswhat if the variables to be substituted are in CVarArg?
-
Sujit Baranwal almost 3 yearsI am literally suprised "You have successfully checked-in to %@ %@" = "%@ %@ のチェックインが完了しました"; let translatedText = NSLocalizedString("You have successfully checked-in to %@ %@", comment: "") let checkInMessage = String.localizedStringWithFormat(translatedText, spaceTypeName.localizedText(), spaceName) The above is not working…can someone help