FaPost has two language layers, and they are resolved differently. Getting them
mixed up is the most common multilingual bug in an extension.
Admin UI strings
Anything a staff member reads — a field label in the builder, a validation error,
a column heading — is an ordinary Laravel translation. Use lang files as you would
in any Laravel application.
Content strings
Anything the end user reads is content language, resolved at runtime for that
contact.
Never put a user-facing literal directly into a handler or a sender.
A bot-facing string must be either a system translation key or flow content
authored by the person who built the flow. A literal in a handler cannot be
translated, cannot be overridden per tenant, and will be sent in the developer’s
language to every contact regardless of theirs.
Values are not translated
Button and select values are language-agnostic identifiers. They are compared
against, stored in state, and branched on. Only the label or content is
translated.
Translating a value breaks every condition that tests it, and it breaks silently:
the flow keeps running and simply takes the wrong branch for contacts in one
language.
Practical consequence for extensions
If your node offers choices, define the value once as a stable identifier and let
the label carry the language. If your handler needs to tell the user something,
expose it as flow content the author can edit, or as a translation key — not as a
string in your PHP.