> ## Documentation Index
> Fetch the complete documentation index at: https://hyperlocalise.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Localize Sanity Studio documents

> Connect Hyperlocalise from the Sanity Studio editor view or bulk tool, upload documents, translate, and write locale drafts.

Sanity does not translate. Hyperlocalise jobs do. Create a **Sanity Studio plugin** workspace connection, install `sanity-plugin-hyperlocalise`, then use the **Hyperlocalise** editor view or bulk tool to pick a [native project](/platform/projects/create-project), upload text, run translation jobs, and apply completed locales back into Studio.

Jobs use the project's source locale and target locales. `en` is not `en-US`. `zh-CN` is not `zh-TW`.

For batch import and **Push to Sanity** from the Content editor, use [Localize Sanity documents (automation)](/platform/connections/sanity) instead. That path uses a separate **Sanity** integration row (WorkOS Pipes) and does not require the Studio plugin.

## Prerequisites

| Requirement | Description |
| - | - |
| Native project | A [native project](/platform/projects/create-project) with a source locale and the target locales you will apply. |
| Personal access token | First **Allow** on the consent screen creates a **Sanity Studio plugin** token and connection if none exist. Integrations remains available to rename or disable the connection. |
| `sanity-plugin-hyperlocalise` | The plugin added to your Studio `sanity.config` (npm package or linked build). Sanity Studio v3 or later. |
| i18n setup | Document-level (`language` field) or field-level (`internationalizedArray*` fields), listed in plugin options. |

## Connect the workspace

Editors connect with **OAuth only** from Studio. Choose **Allow** on the consent screen. If the workspace already has an enabled Studio plugin connection, consent reuses it. If it has none, Hyperlocalise creates a **Sanity Studio plugin** personal access token and connection. Use **Integrations** only to rename or disable that connection.

Each grant is bound to the Studio **origin** (for example `https://your-project.sanity.studio` or `http://localhost:3333`). Hyperlocalise rejects API calls when the `Origin` header does not match the token.

## Install the plugin in Studio

```ts theme={null}
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {hyperlocalisePlugin, hyperlocaliseTool} from 'sanity-plugin-hyperlocalise'

const languages = [
  {id: 'en-US', title: 'English (US)'},
  {id: 'fr-FR', title: 'French (France)'},
]
const documentLevelTypes = ['post']
const fieldLevelTypes = ['product']

export default defineConfig({
  plugins: [
    structureTool({
      defaultDocumentNode: (S, {schemaType}) => {
        if ([...documentLevelTypes, ...fieldLevelTypes].includes(schemaType)) {
          return S.document().views([
            S.view.form(),
            hyperlocalisePlugin(S, {
              supportedLanguages: languages,
              documentLocalizationSchemaTypes: documentLevelTypes,
              fieldLocalizationSchemaTypes: fieldLevelTypes,
            }),
          ])
        }
        return S.document()
      },
    }),
  ],
  tools: [
    hyperlocaliseTool({
      supportedLanguages: languages,
      schemaTypes: documentLevelTypes,
    }),
  ],
})
```

* **`documentLocalizationSchemaTypes`**: document-level i18n (separate documents per locale, linked with `translation.metadata`).
* **`fieldLocalizationSchemaTypes`**: field-level i18n (internationalized array fields on one document).
* **`hyperlocaliseTool`**: bulk upload, translate, and apply for document-level types only.

A schema type cannot be listed in both arrays.

## Connect from Studio

1. Open a document in Sanity Studio.
2. Open the **Hyperlocalise** editor tab.
3. Choose **Connect Hyperlocalise** and complete OAuth in the browser.
4. On the consent screen, confirm the **Studio** origin and choose **Allow**.
5. Select the native project.

The **Hyperlocalise** top-level tool uses the same OAuth session.

## Project locales list

After you connect, the plugin loads each accessible native project from the Hyperlocalise session API (`GET /api/integrations/sanity/session`). Every project in that response includes a **source locale** and a **target locales** list—the same values you configure under **Settings → Locales** for that project. See [Manage project languages](/platform/projects/languages).

| Field | Meaning |
| - | - |
| `sourceLocale` | Language tag for source documents and collect/upload of source text (for example `en-US`). |
| `targetLocales` | Language tags you can translate into and apply back (for example `fr-FR`, `de-DE`). The source locale is never a target. |

Example session fragment for one project:

```json theme={null}
{
  "session": {
    "projects": [
      {
        "id": "proj_…",
        "name": "Marketing site",
        "sourceLocale": "en-US",
        "targetLocales": ["fr-FR", "de-DE", "es-ES"]
      }
    ]
  }
}
```

**Translate to** (document view and bulk tool) only offer tags from that project's `targetLocales`. If you configure `supportedLanguages` in `sanity.config`, the plugin shows the **intersection**: a language must appear in both `supportedLanguages` and the project's `targetLocales`. When `supportedLanguages` is omitted, the plugin lists every project target locale.

Use locale tags from this list everywhere:

* Pick targets in the plugin only from the dropdown or checkboxes (do not type ad hoc tags in Studio-only config).
* Set Sanity document `language` values and Locales collection `tag` fields to the same BCP-47 tags as the native project (exact match preferred; the plugin and API treat `en` and `en-US` as different tags).
* After you add or remove targets in Hyperlocalise, reconnect or use **Change** on the project line so the plugin reloads the session list.

Upload and **Write {locale} version** labels reflect the selected locale (for example **Upload (fr-FR)** and **Write fr-FR version**) only when that tag is a project target and, when configured, listed in `supportedLanguages`.

## Upload target locale text

**Upload (locale)** imports existing Sanity content for the selected target locale into Hyperlocalise as translations for the collected source file. It is enabled when that locale already exists in Studio (a linked translation document for document-level i18n, or field-level content for the locale).

1. Pick a target locale from **Translate to** (document view or bulk tool). Only tags from the [project locales list](#project-locales-list) appear there.
2. Choose **Upload (locale)** when the label shows your locale and the control is enabled.

If the source document is not in Hyperlocalise yet, Upload collects the source first, then imports the target strings. Each source document is stored at `sanity-plugin/{sanityProjectId}/{dataset}/{documentType}/…json`. Segments use stamped keys `sanity.k.*` in the JSON file (same key format as [automation imports](/platform/connections/sanity), which use the `sanity/` path prefix).

## Translate

**Translate** starts an agent job for the locale selected under **Translate to**, then writes that locale into Sanity when generation finishes. Approval is not required. Draft or review-ready strings are enough.

* If the source is not collected yet, Translate sends source segments on the first run (same as before).
* When the job reaches **waiting for review** or **succeeded**, Hyperlocalise writes the Sanity locale draft automatically.
* You can still review strings in the [Content Editor](/platform/cat); that review is optional for Studio write-back.

## Write locale version in Studio

**Write {locale} version** (for example **Write fr-FR version**) writes Hyperlocalise translations back into Sanity as a draft for that locale without starting a new job. If a locale document already exists, the same action overwrites that linked draft. Approval is not required.

1. Pick the target locale under **Translate to**.
2. Choose **Write {locale} version** when Hyperlocalise has any translation content for that locale.

Behavior depends on i18n mode:

* **Field-level**: Hyperlocalise patches the open document draft with the target locale slot on internationalized fields.
* **Document-level**: Hyperlocalise writes a draft translation document and links it through `translation.metadata`, or overwrites the existing linked draft for that locale.

Writing a locale version does not publish in Sanity. Publish from Studio after you review drafts.

## Self-hosted and local Studio

* Register your Studio origin in Hyperlocalise `SANITY_CORS_ORIGINS` when it is not covered by defaults (`http://localhost:3333`, hosted `*.sanity.studio`).
* Local Hyperlocalise (`http://localhost:3000`) uses the same PKCE handoff flow as production.
* Package developers can run `pnpm dev` in `apps/sanity-studio-plugin` (in-repo Studio on port 3333), or use `link-watch` plus yalc to test in an external Studio.

See [Sanity Studio plugin OAuth](/contributing/sanity-studio-plugin-oauth) for authorization URLs and environment variables.

## Change or remove access

Remove Studio plugin connections from **Integrations** when this workspace should stop authorizing Studio OAuth.

When a member leaves the workspace, Hyperlocalise revokes their Sanity plugin OAuth tokens for that organization.

See [Connection troubleshooting](/platform/help/connections) if OAuth or apply fails.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.