gt-sanity@3.0.0
Overview
gt-sanity v3 doubles down on native Sanity behaviour. Field-level localisation is now powered by sanity-plugin-internationalized-array — the reference Sanity plugin — instead of a GT-built Studio UI, and fields can now be excluded from translation directly in your schema using the same options-based pattern as the standard Sanity localisation plugins.
The goal: gt-sanity orchestrates the plugins the Sanity ecosystem already maintains (@sanity/document-internationalization for document-level, sanity-plugin-internationalized-array for field-level) and adds the translation workflow on top. Your Studio never behaves differently because GT is installed.
What's new
Field-level localisation runs on the reference plugin
Enabling fieldLevelLocalization (or its internationalizedArray alias) now automatically configures sanity-plugin-internationalized-array from your sourceLocale and locales. The native plugin owns the internationalizedArray* schema types and the Studio editing UI — per-language add buttons, language labels, field actions — so Studio behaviour always matches what Sanity users already know, and plugin updates arrive as soon as the upstream ships them.
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'fr', 'ja'],
translateDocuments: [{ type: 'post' }],
fieldLevelLocalization: { enabled: true },
translationLevel: 'internationalizedArray',
});Nothing about the stored data has changed: items are still { _key, _type, language, value }, so existing content needs no migration. The config has also gained native pass-through options: defaultLanguages, buttonLocations, buttonAddAll, languageDisplay, and apiVersion.
Bring your own plugin instance
If you already register sanity-plugin-internationalized-array yourself, keep your setup. Translation detection is shape-based — it reads and writes the stored data, regardless of who registered the schema types. Leave fieldLevelLocalization disabled so the types are only registered once, and opt documents into field-level translation with translationLevel:
plugins: [
internationalizedArray({
languages: [
{ id: 'en', title: 'English' },
{ id: 'es', title: 'Spanish' },
],
fieldTypes: ['string'],
}),
gtPlugin({
sourceLocale: 'en',
locales: ['es'],
translateDocuments: [{ type: 'post' }],
translationLevel: 'internationalizedArray',
}),
],gt-sanity re-exports internationalizedArray, internationalizedArrayLanguageFilter, and isInternationalizedArrayItemType for direct use.
Exclude fields from translation in your schema
Mark a field — or a whole type — instead of maintaining a parallel list in the plugin config:
defineField({
name: 'internalNotes',
type: 'string',
options: { gt: { exclude: true } },
});The serialiser also honours the exclusion options of the standard Sanity localisation plugins, so one pattern covers everything:
options.gt.exclude— GT's own namespaceoptions.documentInternationalization.exclude—@sanity/document-internationalizationoptions.aiAssist.exclude—@sanity/assist
Exclusion applies at any nesting depth, and setting it on a custom type definition's options excludes every occurrence of that type — matching the native plugins' "field or type" semantics. options.gt is fully typed via declaration merging, and the id-based ignoreFields / skipFields / dedupeFields plugin options remain for cross-document rules such as slug deduplication.
Breaking changes
GT's field-level Studio UI is removed
The createInternationalizedArrayTypes export and the FieldLevelUIComponents type have been removed, along with the typePrefix, includeCompatibilityTypes, and components options on GTFieldLevelLocalizationConfig — none have a native equivalent. Passing a removed option logs a warning and it is ignored. Data created with a custom typePrefix is no longer detected; standard internationalizedArray* data is unaffected.
Deeper localize: false enforcement
Exclusion (schema options and the legacy localize: false) now also applies to fields within top-level object fields, which were previously not filtered out. Content that was previously sent for translation incorrectly is no longer sent — if a field seems to “go missing” from translations after upgrading, check whether it has an exclusion mark.