Skip to main content

Handle Grammatical Gender in Personalized App Messages

2026-09-28

Handle Grammatical Gender in Personalized App Messages

Grammatical gender localization fails when an app inserts a person, role, or object into an English-shaped sentence and expects every translated word to remain correct. A notification such as "Appointment updated" may need a different adjective ending from "Payment updated" in Spanish. A message addressed to a user may also need several forms in French. String concatenation, a single neutral fallback, or a profile field passed straight into copy will not produce a reliable result.

Make grammar part of the message contract. Pass typed grammatical inputs, give translators complete variants, keep a safe form for missing data, and run the same fixtures through each platform and delivery path.

Why ordinary placeholders are not enough

A placeholder replaces a span of text. It does not tell the formatter which surrounding words must change. Consider a booking app that builds this notification:

{object_name} {object_id} {status}

The source language can use one value for status=updated. In another language, the form of "updated" may depend on the grammatical gender of object_name. Translating the three fragments separately leaves the translator without control over agreement or word order. That is the agreement-level version of the argument for message formatting over string concatenation.

A practitioner building Spanish booking notifications reported this exact problem in a Stack Overflow question about gettext context and grammatical gender. The noun for appointment required a feminine adjective ending, while the noun for payment required a masculine one. The failure was not a bad dictionary entry. The data model treated reusable fragments as though they formed a complete translatable message.

A message may address a user directly or refer to someone else. These require different inputs. Android's grammatical inflection guidance distinguishes the viewer whose app resources are being selected from another person mentioned by the text. If one field silently handles both jobs, a form that works on one screen can be wrong on another.

Define a grammatical message contract

Start with message intent, not translated fragments. Every message should declare which runtime values can affect grammar and what the app does when a value is unknown.

One possible contract looks like this:

MessageContract {
  id: "booking.status_changed"
  arguments: {
    item_kind: enum("appointment", "payment")
    item_id: opaque_string
    status: enum("created", "updated", "cancelled")
    actor_reference: enum("viewer", "other", "none")
    grammatical_form: enum("feminine", "masculine", "neutral", "unknown")
  }
  unknown_policy: "use complete neutral variant"
  delivery: ["in_app", "push"]
}

This is a product schema, not a platform API. Its purpose is to keep grammatical choices explicit while preventing arbitrary user data from becoming a translation key.

Use stable enums for application concepts. Do not send a localized noun such as "cita" and ask the client to infer its gender. Keep item_kind=appointment, let each locale own the noun and its agreement, and reject unexpected values before formatting.

Treat grammatical form as language data, not as a universal description of a person. The categories needed by one locale may not match another locale's grammar, and some messages can avoid referring to gender entirely. Store only the value required for the declared copy behavior. Offer an unknown or undisclosed path rather than forcing a choice that the product does not need.

Give translators complete variants

A translator needs control of the whole clause that changes. The ICU MessageFormat guide recommends putting select and plural logic around complete submessages. That lets each language change word order, repeat a noun, move the identifier, or choose a neutral construction.

An ICU-style message could use complete branches:

{item_kind, select,
  appointment {{item_id}: appointment updated}
  payment {{item_id}: payment updated}
  other {{item_id}: booking item updated}
}

The target-language translator changes each branch as a sentence-level unit. If grammatical form also affects a personalized clause, nest it only when the language requires that distinction:

{grammatical_form, select,
  feminine {You are subscribed. [feminine form]}
  masculine {You are subscribed. [masculine form]}
  other {Your subscription is active.}
}

The bracketed phrases above describe where approved target-language copy belongs. Production resources should contain the actual reviewed translations, not labels or machine-generated suffixes.

Do not force every locale to mirror the source branches. A language without the distinction may use identical text in several branches or collapse them during its resource build. A language with additional agreement may need a broader message design. The contract specifies available inputs; translators decide which inputs matter to their locale.

Use platform inflection behind an adapter

Platform grammar APIs can reduce resource duplication, but they should sit behind the same product contract as explicit variants. This keeps copy behavior testable when a platform, operating system version, or language does not support automatic inflection.

Android 14 provides a grammatical inflection API for selecting resources based on the viewer's grammatical gender. Its official implementation guide shows gender-specific resources, GrammaticalInflectionManager, and a separate recommendation to use ICU selection when the message concerns something other than the viewer. The guide also notes that changing the requested grammatical gender can recreate an activity unless the app handles that configuration change.

Before formatting, an Android adapter should answer these questions:

  1. Is the message addressing the viewer, or referring to another entity?
  2. Does this operating system and locale support the intended resource behavior?
  3. Which complete fallback message applies when the requested form is absent?

On Apple platforms, InflectionRule supports automatic grammar agreement for localized attributed strings. Apple also documents explicit runtime morphology for cases where the app knows grammatical information about another user. An Apple adapter can apply that mechanism where supported, then fall back to an approved localized message when inflection is unavailable.

Platform code should not invent copy. The adapter may choose a reviewed resource or apply a documented inflection rule. It should never splice pronouns, adjective endings, or translated fragments in application code.

Keep identity, privacy, and grammar separate

A grammatical form used by a sentence is not permission to infer identity. The message layer should receive the smallest value it needs, with a clear source and fallback.

For copy addressed to the viewer, let the person choose the app's grammatical form if the feature is useful and supported. Explain why the setting changes wording. Preserve an undisclosed choice. For copy about another person, use data supplied for that purpose or rewrite the message so it does not require the value.

Avoid deriving grammatical form from a name, avatar, title, email address, or language. Such inference is not necessary for correct architecture and creates an error path that translators cannot fix. When the value is missing, use the complete neutral or non-personal variant defined by the message contract.

Write and review the neutral path as complete copy instead of generating it by deleting a suffix. Android's French example changes the sentence rather than swapping one ending. That is a valid translation choice. The result needs to sound natural; it does not need to preserve the English structure.

Carry structured data across delivery boundaries

In-app rendering is only one surface. Push notifications, authentication emails, and server-generated activity updates may be formatted outside the mobile resource bundle. If a server sends final English prose, the client cannot repair its grammar. If it sends an arbitrary translation key, old clients may not recognize a new message.

Choose one owner for each delivery path:

  • Client-owned messages receive a stable message ID, typed arguments, and a schema version. The installed app formats them with its approved resources.
  • Server-owned messages resolve the recipient locale and grammatical inputs before selecting reviewed server resources.
  • System-owned prompts use the platform's localized behavior, while the app localizes any rationale it displays before or after the prompt.

Include a fallback payload only when the delivery system requires it. Treat that fallback as visible copy with its own review state. Do not expose internal enum names such as GRAMMATICAL_GENDER_FEMININE to users.

Version the contract when adding a required branch or changing argument meaning. An older client should use a known generic message instead of guessing how to format a newer payload. Keep identifiers and diagnostic fields separate from user-visible text so logs remain useful without becoming the source of copy.

Build a release test matrix

Unit tests should render every message contract against every supported grammatical input. Snapshot only after a language reviewer approves the fixtures. A passing snapshot proves stability, not linguistic quality.

For each affected locale, cover:

  • Every entity kind and status that changes agreement.
  • Viewer-directed and third-person messages.
  • Feminine, masculine, neutral, unknown, and undisclosed inputs supported by the product contract.
  • Unsupported platform or language inflection.
  • Runtime locale or grammatical-form changes.
  • In-app, push, offline, and restored-session delivery where the message appears.

Add structural checks before screenshots. Verify that each locale contains the required branch names, placeholders match the source contract, unknown values select the approved fallback, and no raw enum or message key reaches the UI. Then render the strings in realistic screens so reviewers can catch clipping and stale content after a settings change.

Test the release artifact rather than only a debug build. On Android, exercise the activity recreation path documented for a grammatical setting change. On Apple platforms, call the platform availability checks described by InflectionRule and verify the fallback on languages that cannot be inflected. Record which branch rendered in test diagnostics without recording sensitive message contents.

Avoid four implementation mistakes

Do not multiply keys without a contract. Keys such as welcome_male, welcome_female, and welcome_other may seem workable until another message needs entity gender, plurality, or a server-delivery variant. Define typed dimensions once and let each message declare the subset it uses.

Do not treat neutral wording as a string hack. Removing a pronoun or suffix can leave an unnatural or incomplete sentence. Give the neutral branch to the translator as complete copy.

No single platform API handles every grammatical case. Android separates viewer-directed resource inflection from messages about another entity. Apple's explicit morphology has language availability constraints. Neither API replaces message ownership or fallback design.

Testing one visible sentence is not enough. Agreement failures also appear in notifications, list rows, accessibility labels, and cached content. Use the message ID inventory to find every delivery surface, then run the same approved fixtures through each owner.

Put one message under contract now

Choose the personalized message with the most branches or support complaints. Replace its fragments with one stable message ID, typed arguments, full-sentence variants, and an explicit unknown policy. Add platform adapters only after the fallback message works on every supported version.

Then render the complete fixture matrix in the app and every external delivery path. Have a language reviewer approve the variants, store those fixtures with the message contract, and block the release if a raw key, missing branch, or unreviewed fallback appears.

References