
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeThe key issue you're encountering is that when you customize the Structure Builder, you need to work with the getFilteredDocumentTypeListItems() function rather than replacing it entirely. This function is what makes the internationalization plugin recognize translated documents as a single entity.
Based on a community answer from the Sanity team, here's how to organize your translated documents with custom structure:
The trick is to get the filtered items first, then manipulate that array to organize them into groups. Here's a working example:
import S from '@sanity/desk-tool/structure-builder'
import * as Structure from '@sanity/document-internationalization/lib/structure'
export default () => {
// Get the filtered document type list items from document-internationalization
const items = Structure.getFilteredDocumentTypeListItems()
// Group the items into different categories
const groupedItems = items.reduce(
(reduced, item) => {
// Check whether the item should be included in your custom group
if (item.id === 'page' || item.id === 'post') {
return {
...reduced,
mainPages: [...reduced.mainPages, item],
}
}
// Otherwise, add it to the general group
return {
...reduced,
other: [...reduced.other, item],
}
},
{
mainPages: [],
other: [],
}
)
return S.list()
.id('root')
.title('Content')
.items([
// Create a nested list for your main pages
S.listItem()
.title('Website Pages')
.child(
S.list()
.id('mainPages')
.title('Website Pages')
.items(groupedItems.mainPages)
),
S.divider(),
// Include the rest of the documents
...groupedItems.other,
])
}getFilteredDocumentTypeListItems() returns an array of list items that already have the translation logic baked inreduce(), filter(), or map() to reorganize these itemsitem.id to identify which document types should go whereS.listItem().child(S.list().items([...]))If you're using Studio v3, the import paths have changed slightly:
import {structureTool} from 'sanity/structure'
import * as Structure from '@sanity/document-internationalization/lib/structure'
export const structure = (S) => {
const items = Structure.getFilteredDocumentTypeListItems()
// ... same logic as above
}
// In sanity.config.ts
export default defineConfig({
plugins: [
structureTool({structure}),
documentInternationalization({
// your i18n config
})
]
})Yes, migrating to @sanity/document-internationalization is recommended because:
The migration shouldn't be too difficult since both plugins use similar concepts, and the structure customization approach described above works with both.
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store