[NSString stringWithFormat:] vs LeftToRight + RightToLeft

[Q] How is it possible to order the %@ parameters correctly when using both LeftToRight text and RightToLeft text in the same string?

Context: this needs to work for the title of a NSMenuItem.

In English, I have the following format string: @"%@ - %@" and I use the following code:

NSString *myString = [NSString stringWithFormat:@"%@ - %@", @"LTR Text", @"LTR Other Text"];

Which results in @"LTR Text - LTR Other Text".

In a RightToLeft language, the @"LTR Other Text" string is going to be a "RTL Other Text". And I would like the result to be:

@"RTL Other Text - LTR Text"

I tried playing with 1$ and 2$, it did not work. @"%2$@ - %1$@" results in @"LTR Text - RTL Other Text".

I tried using stringByAppendingString: or Format: to force the ordering. It does not work. The "LTR Text" string ends up in the middle of "RTL Other Text".

I tried using the ^0 or 0^ keywords apparently used by the Finder. But this is not supported by the standard Cocoa API.

This is on macOS 10.14.6 where support for RTL text is not good in Xcode v10.1 text editors when it comes to text selection, copy-paste, and typing.

Replies

Hi, [NSString localizedStringWithFormat:] should be used for user-facing text.

Using a format is right compared to appending, this way localizers can reorder parts of the strings if they need to.

It should make sure the text in each variable doesn’t have an impact on the parent string. Does it work for you?

You might find useful Pages, which is far more robust for bidirectional (LTR and RTL) text entry and selection, and UnicodeChecker from https://earthlingsoft.net to help envision the differences between byte order and display order. Note that if your string consists only of variables aside from weak characters, the visual ordering may not be correct unless running under an RTL locale, so keep that in mind when testing.

Thanks for the suggestion.

Unfortunately, localizedStringWithFormat: produces the same result as stringWithFormat:

For what it's worth, whatever the order of the parameters provided after the format string, I always get the "LFT Text - RTL Other Text" output.

The "RTL Other Text" is actually a localized NSDate (Date + Time) if that makes any difference.

unless running under an RTL locale

Not 100% sure I'm getting this. The app is run with a RTL language selected as the Preferred Language in System Preferences. Is this what you have in mind?

I found a solution from a webpage on the Apple's Developer site while looking for another problem with NSSearchField (not displaying the magnifying glass on the right side).

"\U200E%2$@ - \U200F%1$@"

Ref. https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html

Strangely, the example in the documentation is incorrect for macOS.

\u does not work. \U does work.