Localization
The SDK string catalog, the runtime locale, the inquiry language pick and the static helpers for text, countries, phone numbers, addresses and dates.
Preview
This page describes a pre-release version of the SDK. Names, versions and APIs on this page can change before the release.
The SDK carries its own string catalog. The SDK's own copy comes from it: the chrome of the inquiry
UI in InquiryUiModel.chrome, the failure notice in InquiryUiModel.failure and the error texts
the SDK writes itself, so that copy is translated
without any string files in your app. The content of an inquiry's steps, such as titles,
descriptions and field labels, comes from the inquiry that Folio serves. Your app can read the same
catalog through the static helpers on FolioSdk and through the runtime's current locale.
Supported languages
The catalog has eight languages. FolioSdk.availableLocales() returns them in this order:
| Code | Language |
|---|---|
en | English |
ru | Russian |
el | Greek |
es | Spanish |
fr | French |
it | Italian |
ja | Japanese |
sq | Albanian |
English is the default language. A text that has no translation in a language resolves to its English text.
How a locale string is matched
Every helper that takes a locale accepts a language tag such as fr, fr-CA or fr_CA. The SDK
trims it, replaces _ with - and compares it in lower case:
- A tag that equals a catalog code uses that language.
- Otherwise the primary subtag is used:
ru-GEresolves toru,en-GBtoen. - A tag that matches no language, and an empty string, resolve to English.
The runtime locale
The runtime keeps one current locale. It is resolved in this order:
- The language the user picked in the inquiry, saved on the device (see below).
- The device locale reported by the operating system or the browser.
en.
A blank value counts as missing. FolioSdk.create loads the saved pick before it returns, so the
first state of every store is already in the right language. When the saved pick changes, every
mounted store publishes its state again, and texts in the new state are in the new language. A
change of the device locale while the runtime runs does not make the stores publish again.
The runtime has no member that returns the code of its current locale. Use localizeCurrent for
its texts; a helper that takes a locale needs a code your app chooses, such as the device language
or one of availableLocales().
localizeCurrent(key) on the runtime returns the text of a TextKey in the current locale:
let title = try sdk.localizeCurrent(key: .inquiryErrorTitle)Inside the SDK provider, a view reaches the runtime without passing it down:
On iOS, FolioSDKProvider puts the runtime into the environment as an environment object.
struct ErrorTitle: View {
@EnvironmentObject var sdk: FolioSdk
var body: some View {
Text((try? sdk.localizeCurrent(key: .inquiryErrorTitle)) ?? "")
}
}The inquiry language pick
An inquiry step can contain a language selector. When the user picks a language, the inquiry UI
sends InquiryIntent.SetLocale with the chosen locale: .setLocale(locale:) in Swift,
InquiryIntent.SetLocale(locale) in Kotlin and InquiryIntent.setLocale(locale) in TypeScript. The
SDK:
- Saves the pick on the device first.
- Sets it as the runtime locale, so every mounted store publishes its state in the new language.
- Sends the pick to the inquiry.
If the pick cannot be saved, the intent fails with InquiryError.LocaleNotSaved and a message
(.localeNotSaved(message:) in Swift, the type 'LOCALE_NOT_SAVED' in TypeScript). The error is
shown as a retryable banner, the locale stays as it was and nothing is sent. See
Inquiry store and Errors.
The pick is stored in the device scope, not in the account scope, so it survives sign-out and applies to the next runtime created on the device. See Storage.
The Localizing interface
Localizing is the interface for "localize a key in the current locale". It has one member, which
returns the text of key in the runtime's current locale:
| Platform | Member |
|---|---|
| Swift | func localizeCurrent(key: TextKey) throws -> String |
| Kotlin | fun localizeCurrent(key: TextKey): String |
| TypeScript | localizeCurrent(key: TextKey): string |
FolioSdk implements it. The inquiry UI does not need it: its own copy arrives already localized
in the inquiry store's state, in InquiryUiModel.chrome and InquiryUiModel.failure. See
Inquiry store.
TextKey
TextKey is the enum of every string in the catalog. Its cases follow the platform naming style:
| Platform | Example |
|---|---|
| Swift | .inquiryErrorTitle |
| Kotlin | TextKey.INQUIRY_ERROR_TITLE |
| TypeScript | TextKey.INQUIRY_ERROR_TITLE |
In Swift a TextKey has a numeric rawValue and in Kotlin a numeric value. These numbers are
not stable between releases: a key can have another number in the next version of the SDK. Refer
to a key by its name, and do not store or send its number. In TypeScript a TextKey is its name.
The inquiry store fills InquiryUiModel.chrome from keys such as INQUIRY_ERROR_TITLE,
INQUIRY_ERROR_DESCRIPTION, INQUIRY_ERROR_RETRY, INQUIRY_ERROR_CLOSE, INQUIRY_LOADING,
INQUIRY_CLEAR_SELECTION and the INQUIRY_NFC_* keys. It fills the
failure notice InquiryUiModel.failure from the
INQUIRY_ERROR_* keys, from the INQUIRY_LAUNCH_CODE_INVALID_* keys for a launch code that was
already used, has expired or is not valid, from the INQUIRY_INVALID_LINK_* keys for another link
that was rejected, and from the INQUIRY_CANNOT_RESUME_* keys for a resume that cannot continue.
The full list is the TextKey enum in your package.
Static helpers
Stateless helpers are static members of FolioSdk. They need no runtime and can be called before
FolioSdk.create, which only sets the host of the flag URLs they return (see
Countries and phone numbers). In Swift every helper throws
FolioSDKError, and its argument labels are the parameter names. In Kotlin they are @JvmStatic
members of the companion object and throw FolioSDKException. In TypeScript they are static
methods and throw FolioSDKError. On the web they need the WebAssembly module loaded with
initializeFolioWasm first (see Runtime); before that, a call throws a plain
Error with the message WASM not initialized, not a FolioSDKError.
Signatures
The Kotlin and TypeScript signatures take the same parameters in the same order as Swift.
| Swift | Kotlin | TypeScript |
|---|---|---|
localize(key: TextKey, locale: String) throws -> String | localize(key: TextKey, locale: String): String | localize(key: TextKey, locale: string): string |
localizeWithArgs(key: TextKey, locale: String, args: LocalizeArguments) throws -> String | localizeWithArgs(key: TextKey, locale: String, args: LocalizeArguments): String | localizeWithArgs(key: TextKey, locale: string, args: LocalizeArguments): string |
localizePlural(group: String, count: UInt32, locale: String) throws -> String | localizePlural(group: String, count: UInt, locale: String): String | localizePlural(group: string, count: number, locale: string): string |
localizeCount(group: String, count: UInt32, locale: String) throws -> String | localizeCount(group: String, count: UInt, locale: String): String | localizeCount(group: string, count: number, locale: string): string |
localizeWithCount(key: TextKey, group: String, count: UInt32, locale: String) throws -> String | localizeWithCount(key: TextKey, group: String, count: UInt, locale: String): String | localizeWithCount(key: TextKey, group: string, count: number, locale: string): string |
formatFileSize(bytes: UInt64, locale: String) throws -> String | formatFileSize(bytes: ULong, locale: String): String | formatFileSize(bytes: bigint, locale: string): string |
availableLocales() throws -> AvailableLocales | availableLocales(): AvailableLocales | availableLocales(): AvailableLocales |
countries() throws -> CountryCatalog | countries(): CountryCatalog | countries(): CountryCatalog |
country(code: Country) throws -> CountryInfo | country(code: Country): CountryInfo | country(code: Country): CountryInfo |
parseCountry(code: String) throws -> Country? | parseCountry(code: String): Country? | parseCountry(code: string): Country | undefined |
countryFlag(country: Country) throws -> CountryFlag | countryFlag(country: Country): CountryFlag | countryFlag(country: Country): CountryFlag |
countryByPhone(phone: String) throws -> Country? | countryByPhone(phone: String): Country? | countryByPhone(phone: string): Country | undefined |
phoneDialCode(country: Country) throws -> String? | phoneDialCode(country: Country): String? | phoneDialCode(country: Country): string | undefined |
formatPhoneNational(raw: String, country: Country) throws -> String? | formatPhoneNational(raw: String, country: Country): String? | formatPhoneNational(raw: string, country: Country): string | undefined |
phoneCountryOptions() throws -> [PhoneCountryOption] | phoneCountryOptions(): List<PhoneCountryOption> | phoneCountryOptions(): PhoneCountryOption[] |
subdivisions(country: Country) throws -> SubdivisionCatalog | subdivisions(country: Country): SubdivisionCatalog | subdivisions(country: Country): SubdivisionCatalog |
addressForm(address: Address, fallbackCountryCode: String, locale: String) throws -> AddressForm | addressForm(address: Address, fallbackCountryCode: String, locale: String): AddressForm | addressForm(address: Address, fallbackCountryCode: string, locale: string): AddressForm |
addressLayout(format: AddressFormat, locale: String) throws -> AddressLayout | addressLayout(format: AddressFormat, locale: String): AddressLayout | addressLayout(format: AddressFormat, locale: string): AddressLayout |
addressEmpty() throws -> Address | addressEmpty(): Address | addressEmpty(): Address |
addressDisplay(address: Address) throws -> String | addressDisplay(address: Address): String | addressDisplay(address: Address): string |
addressChangePart(address: Address, key: AddressKey, value: String) throws -> Address | addressChangePart(address: Address, key: AddressKey, value: String): Address | addressChangePart(address: Address, key: AddressKey, value: string): Address |
addressChangeCountry(address: Address, country: Country?) throws -> Address | addressChangeCountry(address: Address, country: Country?): Address | addressChangeCountry(address: Address, country: Country | undefined): Address |
applyDateInputMask(input: String, format: String) throws -> String | applyDateInputMask(input: String, format: String): String | applyDateInputMask(input: string, format: string): string |
decodeLink(link: String) throws -> LinkRoute | decodeLink(link: String): LinkRoute | decodeLink(link: string): LinkRoute |
In Kotlin, a u32 parameter of these functions, such as count, is a UInt and a u64 one is a
ULong, while a u32 field of an SDK struct, such as sizeBytes of FileMeta, is a Long.
FolioSdk.mrtdDataGroupsStandard() and FolioSdk.mrtdDataGroupsAll() are static as well; see
NFC. So are inquiryTheme(), sdkBuildInfo(), currencies(), iconAsset(icon),
statusPalette(), isValidEmail(value), extractRecoveryCode(text), loggingConfig(consoleLevel)
and the image helpers barcodeImage, computeMetrics and rotateImage; see
Static functions.
Text
| Helper | Returns | What it does |
|---|---|---|
localize(key, locale) | String | The text of key in locale. |
localizeWithArgs(key, locale, args) | String | The text of key with its named placeholders filled from args. |
localizePlural(group, count, locale) | String | The noun of a plural group in the form that fits count, without the number. |
localizeCount(group, count, locale) | String | count, a space and the noun from localizePlural, for example 1 selected. |
localizeWithCount(key, group, count, locale) | String | The text of key with its first placeholder replaced by localizeCount, or by the bare number when group is empty. |
formatFileSize(bytes, locale) | String | A size such as 512 B or 1.5 MB, with a localized unit. |
availableLocales() | AvailableLocales | The catalog languages, see Supported languages. |
Placeholders. A catalog text marks a placeholder as ${name}. localizeWithArgs takes
LocalizeArguments, whose items is a list of LocalizeArgument with name and value. Each
placeholder whose name matches an argument is replaced by its value. A placeholder whose name has a
space and whose first word matches an argument is replaced by the value, a space and the rest of
the name. A placeholder with no matching argument stays in the text as written.
Plural groups. group is one of DAYS, DOCS, DOCUMENTS, ITEMS, MINUTES,
MINUTES_ACCUSATIVE, NIGHTS, PHOTOS, ROOMS, SEC and SELECTED, in any letter case. An
unknown group is returned unchanged. Each group has three forms, and the SDK picks one by the count
and the language of locale (the part before the first - or _, in any letter case). For Russian
(ru), Belarusian (be) and Ukrainian (uk) it picks the first form when the count ends in 1 but
not in 11, the second when it ends in 2, 3 or 4 but not in 12, 13 or 14, and the third otherwise.
For French (fr) it picks the first form for a count of 0 or 1 and the third otherwise. For
Japanese (ja), Chinese (zh) and Korean (ko) it always picks the third form. For every other
language it picks the first form for a count of 1 and the third otherwise. Each language's catalog
fills these forms with its own words. MINUTES_ACCUSATIVE differs from MINUTES only in Russian,
where it has the accusative forms a count takes after a preposition. Pass MINUTES to
localizeWithCount: for the two texts that read "try again in N minutes",
TextKey.APP_ACC_VERIFY_EMAIL_PLEASE_TRY_AGAIN_IN_N_MINUTES and
TextKey.MANUAL_ACC_VERIFY_EMAIL_TOO_MANY_FAILED_ATTEMPTS_PLEASE_TRY_AGAIN_IN_N_MINUTES in Kotlin
and TypeScript, the SDK uses MINUTES_ACCUSATIVE on its own.
File sizes. formatFileSize divides by 1024 and uses B, KB, MB or GB. The number is
rounded to two decimals and trailing zeros are removed. A size above zero never shows as 0.
AvailableLocales and LocaleInfo:
| Type | Field | Type | Meaning |
|---|---|---|---|
AvailableLocales | locales | list of LocaleInfo | The catalog languages |
LocaleInfo | code | String | The catalog code, such as fr |
LocaleInfo | nativeName | String | The language name in its own language |
LocaleInfo | englishName | String | The language name in English |
Countries and phone numbers
Country is the shared enum: Country::US in Rust, Country.us in Swift and
Country.US in Kotlin and TypeScript. Its 250 values come from ISO 3166-1 plus Kosovo
(XK / XKX). JSON uses alpha-2 strings such as "US".
| Helper | Returns | What it does |
|---|---|---|
countries() | CountryCatalog | All country metadata records in items, sorted by display name, ignoring letter case and accents. |
country(code) | CountryInfo | Metadata for a typed Country. |
parseCountry(code) | optional Country | Parses alpha-2 or alpha-3 codes, ignoring letter case and surrounding whitespace. Unknown codes return no value. |
countryFlag(country) | CountryFlag | Raster and vector flag URLs for a typed country. See Flag URLs below. |
countryByPhone(phone) | optional Country | Resolves an international phone number using phone metadata, including regions sharing a calling code. Unresolved numbers return no value. |
phoneDialCode(country) | optional string | The country's calling code from phonenumber metadata, such as +1 or +49. No value when phone metadata is unavailable. |
formatPhoneNational(raw, country) | optional string | Keeps the digits of raw and formats them using phone metadata without truncating them. Pass the national number without the trunk prefix (for example without the leading 0 of a French number). Digits that match no format of the country come back as plain digits; missing country metadata returns no value. |
phoneCountryOptions() | list of PhoneCountryOption | One option per country that has a calling code, in the order of countries(), by display name. Countries without a calling code are left out. |
subdivisions(country) | SubdivisionCatalog | ISO 3166-2 subdivisions with code and name, sorted by name, ignoring letter case and accents. Empty when the country has none in the source library. |
A phone selector keeps the selected Country separately from its calling code: both
Country.US and Country.CA use +1.
CountryInfo fields:
| Field | Type | Meaning |
|---|---|---|
country | Country | The typed country identifier |
alpha2 | string | ISO 3166-1 alpha-2 code |
alpha3 | string | ISO 3166-1 alpha-3 code |
displayName | string | The English display name |
phoneCode | optional string | The calling code |
profile | optional CountryProfile | Product metadata, where available |
CountryProfile contains denonyms (demonyms), languages, localNames (each with
language and name) and addressFormat.
PhoneCountryOption fields:
| Field | Type | Meaning |
|---|---|---|
country | string | ISO 3166-1 alpha-2 code; pass it to parseCountry for the typed Country |
name | string | The English display name, the same as CountryInfo.displayName |
dialCode | string | The calling code, such as +49 |
label | string | The name, a space and the calling code in parentheses, such as Germany (+49) |
flag | optional CountryFlag | The flag URLs, set for every option |
phoneCountryOptions() takes no locale, so its names are always English. The inquiry UI's
PhoneDialCodeOptionView has the same fields, so one picker component
can render both.
Flag URLs. CountryFlag has rasterUrl and vectorUrl, the files
https://<domain>/flags/4x3/<code>.png and .svg, where <code> is the alpha-2 code in lowercase.
The domain is folio.mobi until FolioSdk.create is first called. Every call with a valid
organization sets it from baseUrl for the whole process, even a call that fails later:
folio.id, folio.mobi or foliostage.net when the host of baseUrl is that domain or a
subdomain of it, and folio.mobi for any other base URL. The latest call wins, and closing a
runtime does not reset it. It applies to countryFlag, the
flag of phoneCountryOptions() and the flags of the inquiry UI's country and calling code
options.
Addresses
The address helpers work on the Address value. Its parts are optional strings: street, city,
state, zip, country, apartment, area, neighborhood, townshipOrDistrict, county,
furtherDivisions, furtherDivisionsLine2, postalDistrict, suburb, islandName, district
and districtOrSubdivision. addressEmpty() returns an address with no parts. In Swift the
memberwise initializer takes every part, so start from addressEmpty(). In Kotlin every part
defaults to null, so Address() is an empty address. In TypeScript it is a plain object whose
type declares every part as string | undefined; an unset part is absent from the object and reads
as undefined, so test a part by its value, not with in or Object.keys.
| Helper | Returns | What it does |
|---|---|---|
addressEmpty() | Address | An address with no parts. |
addressForm(address, fallbackCountryCode, locale) | AddressForm | The form for editing address: the country resolved from address.country, else from fallbackCountryCode, and its rows of fields with their current values and labels in locale. |
addressLayout(format, locale) | AddressLayout | The rows of fields for an AddressFormat, such as StrCityCountry, with labels in locale. |
addressDisplay(address) | String | The present parts, trimmed, joined by , in the order shown below the table. |
addressChangePart(address, key, value) | Address | address with the part of the AddressKey key set to value. An empty value clears the part. |
addressChangeCountry(address, country) | Address | address with country set to the displayName of the Country, or cleared when country is absent. |
addressDisplay writes the parts in this order, whatever the country: street, apartment,
area, neighborhood, townshipOrDistrict, county, furtherDivisions, furtherDivisionsLine2,
postalDistrict, suburb, islandName, district, districtOrSubdivision, city, state,
zip and country. An address with street, city, suburb and county reads as street,
county, suburb, city.
addressForm resolves the country from an alpha-2 or alpha-3 code, the ISO name or the display name
of a country, in any letter case. AddressForm has countryCode, countryName, rows and
display (the same text as addressDisplay). Each row is an AddressFormRow with fields, and
each field is an AddressFormField with an AddressKey key, label, value and country,
which is true for the country field. The labels of both helpers are catalog texts in locale,
matched like every other locale string. AddressLayout has
rows of AddressRow, each with fields of AddressFieldSpec, which has an AddressKey key
and a label.
In both helpers the row with the Country field always comes first, whatever the format. The other
rows follow in the order of the format: the format of the country of the address for
addressForm, the given format for addressLayout. For example StrPostalCityCountry gives the
rows Country, Street1, Street2, PostalCode and City. When no country resolves, or the
country has no address format, addressForm uses the rows of StrCityCountry: Country,
Street1, Street2 and City, one per row. When no country resolves, countryCode is empty and
countryName is the text it was resolved from.
AddressKey values: Street1, Street2, Area, PostalCode, Postcode, Neighborhood,
PrefectureLevelCity, City, TownOrCity, TownshipOrDistrict, CountyOrCity, County,
Department, FurtherDivisions, FurtherDivisionsLine2, PostalDistrict, Governorate,
Suburb, IslandName, State, Province, Region, SubjectOfFederation, Zip, District,
DistrictOrSubdivision, Country and Prefecture. A key reads and writes one part of Address:
Street1 the street, Street2 the apartment, the city keys (City, TownOrCity,
PrefectureLevelCity, CountyOrCity) the city, the state keys (State, Province, Region,
Prefecture, Governorate, SubjectOfFederation, Department) the state, the postal keys
(PostalCode, Postcode, Zip) the zip, and every other key the part of the same name.
AddressKey and AddressFormat are spelled by platform:
| Platform | AddressKey | AddressFormat |
|---|---|---|
| Swift | .street1, .postalCode | .strCityCountry |
| Kotlin | AddressKey.Street1, AddressKey.PostalCode | AddressFormat.StrCityCountry |
| TypeScript | { type: 'STREET1' }, AddressKey.street1 | { type: 'STR_CITY_COUNTRY' }, AddressFormat.strCityCountry |
Date and time input
| Helper | Returns | What it does |
|---|---|---|
applyDateInputMask(input, format) | String | Formats one keystroke state of a date or time field. |
format is a named format, MM_YYYY, DD_MM_YYYY or HH_MM, in any letter case, or a pattern
made of dd, mm, yyyy and hh with any separator characters between them, such as
dd/mm/yyyy or yyyy-mm-dd. In a pattern, mm right after hh is the minute. The helper keeps
only digits, up to the length of the format, and inserts the separators: 122026 becomes 12.2026
and 31122026 becomes 31.12.2026. Time fields use :, so 2359 becomes 23:59. With the
pattern dd/mm/yyyy, 31122026 becomes 31/12/2026. A format with any other run of letters, or
with no letters at all, returns input unchanged.
The helper corrects impossible values as they are typed:
- A month above 12, a day above 31, an hour above 23 or a minute above 59 keeps only its first
digit with a leading zero:
13as a month becomes01, and2460becomes02:06. - A month or day of
00becomes01. - A day past the end of its month becomes the last day of that month:
3104becomes30.04and30022026becomes28.02.2026. Until the year is complete, February allows the 29th.
Calendar values
CalendarDate, CalendarMonth and ClockTime are SDK objects for a calendar date, a month of a
year and a time of day, without a time zone. Each has two static constructors: new from its parts
and parse from ISO 8601 text.
| Type | new | Valid parts | parse accepts |
|---|---|---|---|
CalendarDate | new(year, month, day) | year 0 to 9999, month 1 to 12, day 1 to the last day of the month, so 29 February only in a leap year | YYYY-MM-DD |
CalendarMonth | new(year, month) | year 0 to 9999, month 1 to 12 | YYYY-MM |
ClockTime | new(hour, minute, second, millisecond) | hour 0 to 23, minute and second 0 to 59, millisecond 0 to 999 | HH:MM, HH:MM:SS, or HH:MM:SS followed by . and 1 to 3 digits of a second; HH:MM means second 0 |
new never corrects a part: when one is out of range, it throws, as a
failed call. parse takes exactly the formats above, with ASCII
digits, and throws the same way for any other text or for a value out of range.
The parts are read back with year(), month() and day() on a date, year() and month() on a
month, and hour(), minute(), second() and millisecond() on a time. iso8601() returns the
text form: YYYY-MM-DD, YYYY-MM, and HH:MM:SS with . and three digits of milliseconds only
when the millisecond is not 0.
| Platform | Parameter and part types | Release |
|---|---|---|
| Swift | UInt16 for year and millisecond, UInt8 for the others; every call throws | release(), also on deinit |
| Kotlin | UShort for year and millisecond, UByte for the others | close(), the object is AutoCloseable |
| TypeScript | number | dispose() or [Symbol.dispose]() |
let leapDay = try CalendarDate.new(year: 2028, month: 2, day: 29)
let month = try CalendarMonth.parse(value: "2026-10")
let time = try ClockTime.new(hour: 23, minute: 59, second: 0, millisecond: 0)
let text = try time.iso8601()2028 is a leap year, so leapDay is 29 February 2028, and text is 23:59:00. The same call for
2026 throws, because 2026 is not a leap year: a failed call whose
message is the InvalidCalendarValue text
"2026-02-29" is not a calendar date.
Instant is an SDK object for a point in time. Its static constructor
fromEpochMillis(epochMillis) takes milliseconds since 1970-01-01 UTC, an Int64 in Swift, a
Long in Kotlin and a bigint in TypeScript, and throws a failed call with an
InvalidCalendarValue message for an instant outside the years
0000 to 9999. epochMillis() returns that number, utc() returns a WallClock, the record of a date
(CalendarDate) and a time (ClockTime) in UTC, and iso8601() returns
YYYY-MM-DDTHH:MM:SS.mmmZ. Instant is released like the other calendar values.
A date and time value of a field is a DateTimeValue: Absolute { instant }, an Instant, or
WallClock { local }, a WallClock without a time zone.
Links
| Helper | Returns | What it does |
|---|---|---|
decodeLink(link) | LinkRoute | The route a link asks for. It never throws for a bad link. |
decodeLink removes trailing / characters and parses the link. A link whose host is inq, as
in <scheme>://inq/<launch code> with any scheme, or a link on a Folio host whose path is
/inq/<launch code>, returns LinkRoute.Inquiry with that launchCode. Such a link without a
launch code is not an inquiry link. A link that cannot be parsed, or that asks for nothing the SDK
knows, returns LinkRoute.Unknown. The cases are spelled .inquiry(launchCode:) and .unknown in
Swift, LinkRoute.Inquiry and LinkRoute.Unknown in Kotlin, and have the type 'INQUIRY' and
'UNKNOWN' in TypeScript.
A link with the path /rp/action and an extract query, on a Folio domain such as folio.id or
on a Folio link host such as gl-lnk.folio.id, for example
https://folio.id/rp/action?extract=IMG_0001.jpeg%3B%3B%3Bscan%20one.pdf, returns
LinkRoute.SharedFiles with names, the file names that extract lists: the SDK splits its
decoded value at ;;;, trims each name and drops empty ones, so this link gives IMG_0001.jpeg and
scan one.pdf. When no name is left, the link returns Unknown. The case is spelled
.sharedFiles(names:) in Swift, LinkRoute.SharedFiles(names) in Kotlin and
{ type: 'SHARED_FILES', value: { names } } in TypeScript, where names is a list of strings.
A link with the content scheme, an Android content URI, returns LinkRoute.Media with that
url, whatever its host. The other routes (Entity, Sharing, Interaction, Screen,
Preference and External) describe Folio's own links.
Examples
let french = try FolioSdk.localize(key: .inquiryErrorTitle, locale: "fr")
let languages = try FolioSdk.availableLocales().locales
let countries = try FolioSdk.countries().items
let selected = try FolioSdk.country(code: .us)
let dialCode = try FolioSdk.phoneDialCode(country: .fr)
let national = try FolioSdk.formatPhoneNational(raw: "612345678", country: .fr)
let states = try FolioSdk.subdivisions(country: .us).items
let size = try FolioSdk.formatFileSize(bytes: 1536, locale: "fr")
let expiry = try FolioSdk.applyDateInputMask(input: "122026", format: "MM_YYYY")
let empty = try FolioSdk.addressEmpty()
let located = try FolioSdk.addressChangeCountry(address: empty, country: .fr)
let address = try FolioSdk.addressChangePart(address: located, key: .city, value: "Paris")
let form = try FolioSdk.addressForm(address: address, fallbackCountryCode: "FR", locale: "fr")