Localised string array join?

let skills = ["nunchuck", "bow hunting", "computer hacking"]
let notLocalizedJoined = skills.joined(separator: ", ")

// nunchuck, bow hunting, computer hacking

How do I create a localised join?

To be sure, it is not sufficient to pass a localised variation of ", " as the separator.

Do you have an example of the output produced by such a localized join?

This is available in ICU (C++) and CLDR, but maybe not in Foundation yet.

2 Likes

I see, so this is about localizing the final and and possibly leaving out the separator:

let skills = ["nunchuck", "bow hunting", "computer hacking"]
let localizedJoin = skills.hypotheticalLocalizedJoined(separator: ", ")
// en: nunchuck, bow hunting, and computer hacking
// fr: nunchuck, bow hunting et computer hacking

I don’t think this is currently offered by the iOS/macOS SDKs.

1 Like

NSLocale/Locale has a groupingSeparator property that you could use

@lancep That's a numeric grouping separator, used by the NumberFormatter class.

  1> import Foundation
  2> Locale(identifier: "en").groupingSeparator
$R0: String? = ","
  3> Locale(identifier: "fr").groupingSeparator 
$R1: String? = " "

Suggestion filed for CoreFoundation and Swift Foundation on radar as 37880652.

I essentially asked for a CFListFormatter to wrap icu::ListFormatter.

3 Likes

There's also a C API which wraps the C++ API. But the ICU list formatters don't appear to support the non-standard list types such as or-short and unit-narrow.

The "/usr/lib/libicucore.dylib" on Apple platforms is mostly private APIs, except for the headers listed in minimalapis.txt (the macOS SDK doesn't have any ICU headers). Projects such as swift-corelibs-foundation and WebKit can use their own copy of the ICU headers, but an App Store app might be rejected.

I built a library that uses the CLDR data to get around this - GitHub - liamnichols/ListItemFormatter: NSFormatter subclass that can format lists based on locale following the Unicode CLDR specification

FormatterKit also has it's own version however its not built to the Unicode spec whereas this version is

1 Like

Isn't this solved by ListFormatter since WWDC 2019? Specifically, you can do this:

ListFormatter.localizedString(byJoining: ["nunchuck", "bow hunting", "computer hacking"])
3 Likes

I wanted to share my experience. I was looking to get access to "the appropriate separator" mentioned in the ListFormatter's documentation, to provide my own custom formatting (CNPostalAddressFormatterStyle that uses single line localized comma separated components).

The only way I could retrieve it is using dummy data and retrieving the separator from the formatted list like this:

private lazy var localizedSentenceSeparator: String = {
    // There's no direct way to get a reliable localized sentence separator other than utilizing
    // dummy data with `ListFormatter` and getting first separator.
    // This is until Apple provides this API publicly.
    let separatorExposer = ListFormatter.localizedString(byJoining: ["x", "y", "z", "u", "t"])
    let index = separatorExposer.firstIndex(of: "x")!
    let separatorIndex = separatorExposer.index(after: index)
    let firstSeparator = String(separatorExposer[separatorIndex])
    return firstSeparator
}()

I just wish Apple would provide this as a property either under ListFormatter or Locale.

I tested my code in Arabic and English and it's working for me as expected.