Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Localizing a naturally-formatted list of API data

Say I've downloaded this list of data from an API:

[
    "Anita",
    "Jean",
    "Peter"
]

I'd like to list this data in a natural sentece format. For example, in US English, this string should be displayed to the user:

Anita, Jean, and Peter

However, if the user is Swedish for example, they should see this string:

Anita, Jean och Peter

Notice that the Oxford comma is missing, and Swedish uses a different word for "and", which is what a Swedish user would expect to see. How can I format this data in a natural-language way that would respect the user's locality? There can be a variable amount of data, not necessarily just 3 items. My instinct is to subclass Formatter/NSFormatter, but I'd like to build this in a way I can easily expand it to support languages that I don't speak, so I'm wondering if there's an iOS-standard or 3rd party formatter that I haven't been able to find in my searches

like image 989
Michael Hulet Avatar asked Oct 28 '25 07:10

Michael Hulet


2 Answers

Starting with iOS 13, Foundation has a ListFormatter type. According to your needs, you can use it in different ways to get a textual representation of your array.


The simplest way to use ListFormatter is to use its static localizedString(byJoining:) method. The following Swift 5.1 / iOS 13 Playground sample code shows how to implement this method in order to convert your array into a localized string representation:

import Foundation

let array = [
    "Anita",
    "Jean",
    "Peter"
]

let string = ListFormatter.localizedString(byJoining: array)
print(string) // prints: Anita, Jean, and Peter (for en_US locale)

As an alternative to localizedString(byJoining:), you can create an instance of ListFormatter and use string(from:) method. This can be useful if you need to specify a locale for your textual representation:

import Foundation

let array = [
    "Anita",
    "Jean",
    "Peter"
]

let listFormatter = ListFormatter()
listFormatter.locale = Locale(identifier: "fr_FR") // set only if necessary

let string = listFormatter.string(from: array)
print(String(describing: string)) // prints: Optional("Anita, Jean et Peter")

If needed, you can also set the itemFormatter property of your ListFormatter instance with a specialized formatter type:

import Foundation

let array = [
    55,
    112,
    8
]

let locale = Locale(identifier: "es_ES") // set only if necessary

let numberFormatter = NumberFormatter()
numberFormatter.locale = locale
numberFormatter.numberStyle = NumberFormatter.Style.spellOut

let listFormatter = ListFormatter()
listFormatter.locale = locale
listFormatter.itemFormatter = numberFormatter

let string = listFormatter.string(from: array)
print(String(describing: string)) // prints: Optional("cincuenta y cinco, ciento doce y ocho")
like image 161
Imanou Petit Avatar answered Oct 30 '25 23:10

Imanou Petit


In previous versions of iOS, this question remains unsolved and I'd still appreciate an answer if you have one. However, iOS 13 exposes NSListFormatter, which can be used to do exactly this. For example:

Swift:

ListFormatter.localizedString(byJoining: ["Anita", "Jean", "Peter"])

Objective-C:

[NSListFormatter localizedStringByJoiningStrings:@[@"Anita", @"Jean", @"Peter"]];
like image 23
Michael Hulet Avatar answered Oct 31 '25 00:10

Michael Hulet