Repository navigation
Allow passing a custom t() factory function via I18nOptions to support external translation libraries
#17332
MurzNN
started this conversation in
Feature Requests & Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Currently, Payload's translation function
t()is hardcoded throughout the core. There is no way to replace it with a function from an external i18n library (e.g. Lingui, i18next, FormatJS). This feature request proposes adding acreateTescape hatch toI18nOptionsthat would allow users to inject a custom translation function at the config level.Why it is needed
Many teams already have an established i18n stack in their project. When they adopt Payload, they are forced to maintain two parallel translation systems — one for their application and one for Payload's admin UI. This creates friction in several areas:
namespace:keystring lookup with basic variable interpolation, while libraries like Lingui and FormatJS support full ICU message format, gender, and ordinal plurals.@lingui/cliorformatjs extractcannot extract strings from Payload's internal components because they use a different API.useLingui()oruseTranslation()inside their own custom Payload components today. The only blocker is that Payload's own internal components cannot be driven by the same system.Why it is not hard to implement
The change is additive and backward-compatible. No existing behavior changes unless the user explicitly provides a
createTfactory. The required modifications touch five files:1.
packages/translations/src/types.ts— addcreateTtoI18nOptions2.
packages/translations/src/utilities/init.ts— usecreateTininitI18nwhen providedThe existing
initTFunctionpath is unchanged. The memoization cache key (currently['language', 'context']) should be extended or bypassed whencreateTis present, since the factory itself is not part of the cache key.3.
packages/ui/src/providers/Translation/index.tsx— accept an optionaltFunctionprop4.
packages/ui/src/providers/Root/index.tsx— forwardtFunctiontoTranslationProviderAdd
tFunction?: TFunctiontoRootProvider'sPropsand pass it through to<TranslationProvider>.5. Next.js / TanStack adapter root layouts — thread the factory from config to
RootProviderThe server component that calls
getNextRequestI18nand rendersRootProviderwould need to readconfig.i18n.createTand pass the resultingt(or the factory itself) down as a prop.Scope
createPayloadRequest,getLocalI18n,getNextRequestI18n) automatically benefit from theinitI18nchange since they all call it withconfig.i18n.TranslationProvider/RootProviderchanges.createTis optional and the default behavior is identical to today.Example usage (Lingui adapter)
Alternatives considered
@payloadcms/ui— possible today but requires maintaining a fork across every Payload release.Feel free to adjust the tone or trim sections before posting. The most important technical detail to keep is the five-file breakdown, since it demonstrates the change is genuinely small and non-breaking.
All reactions