Customization
Language and localization
ReceptionKit includes built-in chat text for 48 languages and regional variants. It follows your app’s selected localization automatically, supports an override for your own language picker, and uses the same language matching as Reception’s push and review templates.
Automatic app language
Leave Reception.shared.languageOverride at its default, nil, when your app uses iOS language selection. ReceptionKit reads the first preferred localization from Bundle.main, then matches it to its supported languages. If no app localization is available, it uses English.
This follows the host app’s selected localization. An English-only app stays English on a German device. To offer automatic German selection, your host app must include German among its supported localizations. ReceptionKit’s bundled translations do not add localizations to your app.
The device’s reported locale comes separately from Locale.current.identifier; its region is a device setting, not physical location. ReceptionKit does not choose chat language directly from the device’s preferred-language list. Setting a SwiftUI .environment(\.locale, ...) on your own view is also not the SDK’s language-selection API: use the override for custom in-app selection.
Override the language
Reception.shared.languageOverride
The public property is @MainActor public var languageOverride: String? { get set }. Set a BCP 47 language tag such as fr-CA, pt-BR, or zh-Hant. The default is nil.
For an existing custom language picker, restore its saved selection at startup, before presenting support. Apply every later selection change too. The host app owns persistence; ReceptionKit does not save this setting across launches. There is no need to add a separate support-language picker.
After your normal Reception configuration, restore the saved language selection (nil for automatic mode). This helper belongs in your app’s startup integration:
import ReceptionKit
@MainActor
func restoreSupportLanguage(_ savedAppLanguage: String?) {
Reception.shared.languageOverride = savedAppLanguage
}Put these assignments in the main-actor handlers for your existing language picker. Each line represents a separate selection:
// The user selects Canadian French.
Reception.shared.languageOverride = "fr-CA"
// The user later selects Arabic.
Reception.shared.languageOverride = "ar"
// The user returns to automatic app-language selection.
Reception.shared.languageOverride = nilUse nil, not an empty string or "system", for automatic selection. Invalid identifiers resolve to English. A language override changes ReceptionKit; your app must update its own UI separately.
Changing the override updates built-in labels, default appearance text, the chat’s locale and layout direction, and translations from the active remote appearance snapshot. It does not translate custom strings you already assigned. Language configuration survives Reception.shared.logout() within the running app; update it yourself when an account change also changes your app’s language preference.
Server synchronization
Selecting a language does not activate unused support or register a device solely to choose a language. Registration includes the current app language when support starts. Once support has started, language changes synchronize through device updates while the app is active, with retries after failures and later lifecycle updates.
The dashboard, push delivery, and review templates use the last successfully reported app language. An offline change can update the chat immediately while the server still uses the previous language. The server uses the new language after a successful device update.
The reported app tag is separate from the matched built-in language. For example, es-MX remains the reported app language while the SDK uses es-419 text. A valid unsupported tag such as is-IS remains reportable even though built-in text falls back to English.
Supported languages
ReceptionKit supports these 48 language identifiers. Use the identifier in code; names are included for readable language menus. Regional entries are distinct translations.
| Identifier | English name | Native name |
|---|---|---|
en | English | English |
de | German | Deutsch |
fr | French | français |
fr-CA | French (Canada) | français canadien |
es | Spanish | español |
es-419 | Spanish (Latin America) | español latinoamericano |
it | Italian | italiano |
pt-BR | Portuguese (Brazil) | português (Brasil) |
pt-PT | Portuguese (Portugal) | português europeu |
ca | Catalan | català |
ro | Romanian | română |
nl | Dutch | Nederlands |
sv | Swedish | svenska |
da | Danish | dansk |
nb | Norwegian Bokmål | norsk bokmål |
fi | Finnish | suomi |
pl | Polish | polski |
cs | Czech | čeština |
sk | Slovak | slovenčina |
hu | Hungarian | magyar |
sl | Slovenian | slovenščina |
hr | Croatian | hrvatski |
el | Greek | Ελληνικά |
uk | Ukrainian | українська |
ru | Russian | русский |
tr | Turkish | Türkçe |
ja | Japanese | 日本語 |
ko | Korean | 한국어 |
zh-Hans | Chinese (Simplified) | 简体中文 |
zh-Hant | Chinese (Traditional) | 繁體中文 |
zh-HK | Chinese (Hong Kong) | 中文(香港) |
th | Thai | ไทย |
vi | Vietnamese | Tiếng Việt |
id | Indonesian | Bahasa Indonesia |
ms | Malay | Bahasa Melayu |
hi | Hindi | हिन्दी |
bn | Bengali (Bangla) | বাংলা |
gu | Gujarati | ગુજરાતી |
kn | Kannada | ಕನ್ನಡ |
ml | Malayalam | മലയാളം |
mr | Marathi | मराठी |
or | Odia | ଓଡ଼ିଆ |
pa | Punjabi | ਪੰਜਾਬੀ |
ta | Tamil | தமிழ் |
te | Telugu | తెలుగు |
ur | Urdu | اردو |
ar | Arabic | العربية |
he | Hebrew | עברית |
Regional matching and fallback
Identifiers are trimmed and normalized, including underscores to hyphens and canonical casing. For example, fr_CA matches fr-CA. Language extensions do not select another translation: en-US-u-ca-gregory reduces to en-US for matching and reporting. Exact supported tags match first, case-insensitively. Otherwise these rules apply:
| App language | Built-in language selected |
|---|---|
French with region CA | fr-CA |
Other French, including fr-BE | fr |
Spanish with no region or region ES | es |
Spanish with any other region, including es-MX and es-US | es-419 |
Portuguese with region PT | pt-PT |
Other Portuguese, including plain pt and pt-AO | pt-BR |
Chinese with explicit Hans script, even zh-Hans-HK | zh-Hans |
Other Chinese with region HK or MO, including zh-Hant-MO | zh-HK |
Remaining Chinese with Hant script or region TW | zh-Hant |
Remaining Chinese, including plain zh | zh-Hans |
Norwegian no, nn, or nb variants | nb |
Other supported base languages, such as de-AT or en-GB | Base language: de or en |
Unsupported or malformed identifiers, such as is-IS, xx, or invalid! | en |
An unsupported app language falls back to English; it does not try another language from the device’s preferences. The backend consults device locale only for older devices that have no reported app language. It does not use that legacy fallback when an unsupported app language is present.
Built-in, local, and remote text
Built-in text
Keep the default appearance strings when you do not need custom copy. title, welcomeTitle, and welcomeText resolve to localized built-in values. Composer controls, connection and delivery labels, accessibility text, and the App Store review button also use SDK resources.
The English appearance defaults are “Support”, “Questions, feedback, or a bug?”, and “You're chatting directly with our team.” Assigning those English strings yourself makes them literal overrides; leaving the defaults untouched allows automatic localization.
Custom local strings
You own translations for strings assigned through Reception.shared.appearance. Store them in your app’s string catalog and resolve them using your app’s localization system. ReceptionKit does not translate those values or your app’s support entry-point label.
Put this helper alongside your app’s localization integration. Pass the bundle your app uses for the selected language, or .main for ordinary iOS app-language selection. Add the three keys to your app’s Localizable.xcstrings, with a source value and translations:
import Foundation
import ReceptionKit
@MainActor
func applyCustomSupportCopy(from localizedBundle: Bundle) {
Reception.shared.appearance.title = String(
localized: "support.title", bundle: localizedBundle
)
Reception.shared.appearance.welcomeTitle = String(
localized: "support.welcome.title", bundle: localizedBundle
)
Reception.shared.appearance.welcomeText = String(
localized: "support.welcome.text", bundle: localizedBundle
)
}Call this at startup and again whenever your app’s selection changes. Set Reception.shared.languageOverride in the same selection handler. Setting the override alone does not change .main bundle lookup for your custom text. See Appearance for the complete local customization API.
Remote translations
With Reception.shared.usesRemoteAppearance enabled (the default), published remote text can override your local appearance strings. For each text field, ReceptionKit checks the exact canonical app tag, then its matched built-in language, then keeps the local value. Matching translation keys is case-insensitive; blank or oversized remote values are ignored.
For example, es-MX checks remote es-MX, then es-419. A German app with no German remote translation keeps its local German text even if an English remote translation exists. An unsupported app language can use remote text for its exact tag, or English through its matched fallback. Absent local overrides, the local value is the built-in translation.
The dashboard’s language selector chooses which translation to edit or preview; it does not change a customer’s language. After the SDK downloads a published appearance, it applies it the next time the chat opens. Changing the app language can select another translation from the already active snapshot immediately. Set Reception.shared.usesRemoteAppearance = false on the main actor to use only local appearance. See Remote appearance for publishing and caching.
Right-to-left layout
Arabic (ar), Hebrew (he), and Urdu (ur) select right-to-left layout in ReceptionChatView; other supported languages select left-to-right layout. Regional tags that match those languages receive the same direction. The chat also receives a locale derived from the matched language for localized formatting.
ReceptionKit scopes these settings to its chat view. Your own navigation, support button, and other host UI still need your app’s normal localization and layout handling. Mixed-language messages retain their original text; switching direction does not translate them.
The Arabic example below shows both sides of a conversation. Outgoing bubbles, incoming replies, the composer, and message alignment follow the selected layout direction. The messages are authored example content; changing the language does not translate messages.
Push notifications and review requests
Push titles, default sender text, photo descriptions and plural forms, and hidden-message copy use the server’s matched app language. Custom title/body templates apply only for that matched language; missing overrides use its built-in defaults. The optional custom sender name is shared across all languages. Reply text inserted into a notification remains the agent’s original text. See Push notifications.
Review templates use the same server language matching. Each scenario uses its override for the matched language or its built-in translation; {app} in custom copy is replaced with the app name. The agent can edit the draft before sending. If the effective recipient language changes, the composer asks the agent to keep the draft or use the current language’s template. See Reviews.
Verify and troubleshoot
With the override set to
nil, run an English-only host app on a device configured for German. Confirm that the chat remains English. Then test a host app localization supported by both your app and ReceptionKit.Exercise your existing picker with
fr-CA,es-MX,zh-Hant, andar. Confirm labels, regional matching, and Arabic layout; return toniland relaunch to verify your saved preference handling.If custom text stays in the old language, re-resolve and reassign all three local appearance strings. If unexpected copy appears, check the published remote translation or temporarily disable remote appearance in your development build.
On a device that has used support, change language offline, then reconnect with the app active. Confirm that App language in the dashboard eventually reflects the selection; Device locale and Region can remain different.
In your test project, inspect push and review previews for the matched language. Use a configured iPhone for push verification. Check that a review draft survives a language change and requires explicit review before sending.
If an identifier unexpectedly produces English, compare it with the table and matching rules above. Use the app’s selected tag rather than a display name such as "German". If only the dashboard or a push uses the old language, confirm that the device has successfully synchronized since the change. See Troubleshooting for connection checks.