A multilingual sticker pack or Messages collaboration feature can look finished in the containing iOS app and still sound English inside Messages. The app drawer shows an English extension name. Compact and expanded iMessage chrome keeps English buttons and empty states. Stickers with embedded text never switch language. VoiceOver still reads an English sticker description. Interactive message balloons keep English titles and captions. Translators finished the host screens. Messages still drifted because the Messages .appex bundle, MSSticker accessibility strings, and MSMessageTemplateLayout fields own copy that never entered the ordinary host catalog.
Give Messages the same release discipline as checkout or permissions. Inventory drawer names, extension UI, sticker assets, accessibility descriptions, and transcript captions apart from host screens, localize them on purpose, then prove the drawer and balloon after real Language and Region changes. A host-only QA pass that never opens the Messages app will miss every failure mode in this article.
Why Messages surfaces drift from the app language
iMessage apps and sticker packs are Messages framework extensions, not ordinary screens in the containing app. Apple's Messages framework overview states that you create sticker packs and iMessage apps as standalone apps or as app extensions within a containing iOS app. Coded iMessage apps present a custom interface with MSMessagesAppViewController, can host a dynamic sticker browser with MSStickerBrowserViewController, and can insert interactive messages whose transcript appearance comes from MSMessageTemplateLayout.
The localization gap shows up in five places:
- Host screens live in the main String Catalog or
Localizable.strings. Messages drawer naming uses the extension target'sCFBundleDisplayNameandInfoPlist.strings. - Compact and expanded iMessage UI strings resolve from the Messages extension bundle. Host catalogs do not automatically appear there.
- A static Sticker Pack ships one asset set. Locale-specific sticker art with embedded text needs an iMessage Application that selects assets in code.
- Every
MSStickercarries alocalizedDescriptionused as the accessibility description. An English literal stays English for VoiceOver. - Interactive message balloons expose title, subtitle, caption, subcaption, and trailing caption fields on
MSMessageTemplateLayout. Those strings are assigned in code when you build the message.
Apple's App Extension Programming Guide states that the displayed name of an app extension comes from the extension target's CFBundleDisplayName, and it instructs you to localize the app extension's name when you ship a localized extension. Apple's iMessage Apps and Stickers product page describes packaging for the App Store for iMessage, including standalone sticker and iMessage apps. Localizing and varying text with a string catalog and Preparing your app's text for translation cover catalogs and looking up strings in bundles outside the main target. They do not replace a Messages-specific inventory.
Practitioner materials line up with that split. A public Stack Overflow thread on how to localize iMessage stickers shows an author building a Sticker Pack Extension with text inside sticker images who finds no Xcode localization option for those assets. Answers report that locale-dependent sticker assets require an iMessage Application with code rather than a static Sticker Pack. Another Stack Overflow thread asks whether app extensions need their own Localizable.strings and documents that extension strings must be present for the extension target. Phrase's iOS localization overview and the live i18nAgent iOS localization guide cover catalogs and note that extensions need their own bundle resources. They do not connect Messages drawer naming, sticker localizedDescription, and interactive message captions into one release checklist. Share extensions, Notification Content Extension chrome, and general multi-target catalog membership covered elsewhere are different problems: a translated share sheet or notification action button is not the same as shipping a localized Messages drawer entry and sticker browser.
Localize the Messages drawer display name
Localize the Messages extension CFBundleDisplayName with InfoPlist.strings on the extension target: Apple's App Extension Programming Guide says to localize the extension name, and host-app InfoPlist.strings do not rename the Messages drawer entry.
For each Messages extension target, record:
| Field | Why it matters |
|---|---|
Extension CFBundleDisplayName |
Name shown in the Messages app drawer |
Extension InfoPlist.strings per language |
Localized drawer name values |
| Target membership | Strings must belong to the Messages .appex, not only the host |
| Compact and expanded UI keys | User-visible chrome inside MSMessagesAppViewController |
| Sticker accessibility strings | MSSticker localizedDescription values |
| Template layout captions | Transcript balloon text on interactive messages |
Put CFBundleDisplayName translations in the Messages extension's language-specific InfoPlist.strings, and confirm those files are in the built .appex. Do not assume the containing app's localized display name propagates into the Messages drawer. After translators deliver host screens, open Messages, switch device language, and verify the drawer label before you call the release done.
Prefer coded iMessage apps for locale-specific stickers
Prefer an iMessage Application with code when sticker artwork embeds language-specific text: a static Sticker Pack has no locale-switching path, while MSStickerBrowserViewController can load locale-specific assets at runtime.
Static Sticker Packs are fine when stickers are language-neutral illustrations. They fail when the sticker itself contains words, slogans, or culturally specific typography that must change per locale. In that case, ship an iMessage Application, subclass or embed MSStickerBrowserViewController, and choose file URLs from locale-qualified folders or catalogs at runtime based on the effective language. Keep one stable sticker identity per concept so analytics and content updates do not fragment when the rendered asset changes by language.
func stickerURL(named name: String, languageCode: String) -> URL {
let folder = Bundle.main.resourceURL!
.appendingPathComponent(languageCode, isDirectory: true)
return folder.appendingPathComponent("\(name).png")
}
func makeSticker(named name: String) throws -> MSSticker {
let language = Locale.current.language.languageCode?.identifier ?? "en"
let url = stickerURL(named: name, languageCode: language)
let description = String(localized: "sticker.\(name).accessibility")
return try MSSticker(contentsOfFileURL: url, localizedDescription: description)
}
Release-check both a Latin locale and a locale whose sticker assets include different glyph coverage. Confirm the browser peels and inserts the expected asset, not a leftover English PNG from the default folder.
Localize sticker accessibility descriptions
Pass a succinct localized localizedDescription when creating every MSSticker: Apple documents it as the accessibility description (150 Unicode characters), so English literals leave VoiceOver stuck even when the containing app is translated.
Build that string with String(localized:) or a catalog key from the Messages extension bundle. Do not paste English marketing copy into the initializer and call the work done.
let thanks = try MSSticker(
contentsOfFileURL: thanksURL,
localizedDescription: String(localized: "sticker.thanks.accessibility", bundle: .main)
)
Keep descriptions short, concrete, and free of layout instructions. When stickers vary by locale, keep the accessibility string in sync with the visible asset so VoiceOver does not describe English text on a Japanese sticker. Include accessibility review in the same Messages checklist as the drawer name.
Localize interactive message template captions
Interactive messages use MSMessageTemplateLayout for the transcript balloon. The template exposes image or media plus text elements: title, subtitle, caption, subcaption, trailing caption, and trailing subcaption. Assign localized strings when you build the layout. Stable identifiers in MSMessage URL query items or session data stay untranslated; only user-visible template fields are localized.
let layout = MSMessageTemplateLayout()
layout.caption = String(localized: "imessage.poll.caption")
layout.subcaption = String(localized: "imessage.poll.subcaption")
layout.trailingCaption = String(localized: "imessage.poll.status.open")
let message = MSMessage(session: session)
message.layout = layout
After an in-app or device language change, rebuild outgoing templates with the new locale and verify existing transcript balloons that your app updates through MSSession refresh their visible captions when your product promises live updates. Do not treat a translated host paywall as proof that Messages balloons are localized.
Keep extension UI strings inside the Messages bundle
Compact and expanded presentations of MSMessagesAppViewController load resources from the Messages extension. Add a String Catalog or Localizable.strings to the extension target's Copy Bundle Resources phase. When code lives in a shared framework, pass the correct bundle into String(localized:bundle:) as described in Apple's preparation guide for text outside the main bundle. The live iOS localization guide already warns that widgets and extensions show raw keys when catalogs are missing from the extension target. Apply that warning to Messages before you invent a second workflow.
Verify:
- Drawer name in Messages after changing device language.
- Compact presentation labels and empty states.
- Expanded presentation labels, buttons, and errors.
- Sticker browser assets for at least two locales when assets embed text.
- VoiceOver reading of
localizedDescriptionfor representative stickers. - Interactive message balloons for caption and trailing caption fields.
- Fresh install and English fallback after host translations ship.
Treat the Messages extension as its own localization package in vendor handoffs. Export XLIFF or String Catalogs that include the Messages target, not only the host app. Call out drawer display names and sticker accessibility strings as required fields so translators do not skip them because they never appear in a simulator screenshot of the host UI. When a product manager signs off "app is localized," require a Messages-specific sign-off that lists drawer language, compact UI, expanded UI, sticker assets, VoiceOver descriptions, and at least one interactive balloon.
If your containing app supports an in-app language that can differ from the device language, document the Messages limitation clearly. Many Messages surfaces follow the device Language and Region settings rather than a custom in-app override. Do not promise that changing language inside the host settings screen will relocalize the Messages drawer until you have verified that behavior on a physical device. Prefer aligning the host language picker with system settings when Messages is a primary surface, or warn users that Conversations UI follows the system language.
What not to confuse with this workflow
Do not reuse the share-extension checklist as a Messages checklist. Share targets, Notification Content Extension action buttons, and generic multi-target String Catalog membership solve different boundaries. Messages owns the drawer label, sticker browser, sticker accessibility text, and transcript template captions inside the Messages framework. Finish those surfaces even when the containing app already looks fully translated in TestFlight screenshots.
