sanity-i18n-translate

Guides correct usage of the Sanity Translate i18n component with stable components maps and componentProps.

6.3k|550|Updated Jan 18, 2017
One-click install
npx skills add https://github.com/sanity-io/sanity --skill sanity-i18n-translate
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: sanity-i18n-translate
Source: https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-i18n-translate
Command: npx skills add https://github.com/sanity-io/sanity --skill sanity-i18n-translate

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Locale strings that contain markup (like '<Red>{{keyword}}</Red>') need the <Translate> component, but defining the components map inline during render creates new component identities every render, causing React to unmount and remount subtrees and lose state, DOM, and focus.

Core Features & Use Cases

  • Stable components map patterns: Shows how to map locale tags to intrinsic HTML strings, hoisted module-scope components, or components receiving data via componentProps.
  • Lint rule alignment: Explains the @repo/i18n/no-inline-translate-components oxlint rule and why useMemo or factory calls do not fix the identity problem.
  • Gotcha coverage: Documents TypeScript generic widening in componentProps, children behavior for wrapping vs self-closing tags, and RECOGNIZED_HTML_TAGS fallback behavior.
  • Use Case: When adding a search UI message like 'Search for "<Emphasis>{{keyword}}</Emphasis>"', use this Skill to write a compliant <Translate> usage that passes review and lint.

Quick Start

Ask the assistant to review or write a <Translate> usage for a locale string containing markup, following the hoisted-components and componentProps patterns.

Frequently Asked Questions about sanity-i18n-translate

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I use the Sanity Translate component with markup in locale strings?

Pass a components map that maps tag names in the locale string to React components or intrinsic HTML tag names, for example components={{Emphasis: 'em'}}. Use the plain t() function instead when the message contains no markup.

Why does the no-inline-translate-components lint rule fire on my Translate usage?

The rule fires because the components map is defined inline in the JSX attribute, creating a new component identity every render. React then unmounts and remounts the subtree, losing state and focus; hoist the components to module scope to fix it.

Does useMemo fix the inline components problem in Translate?

No, useMemo does not fix the component identity problem because dependency changes still recreate the components. Hoist the components to module scope and pass render-time data through the componentProps prop instead.

How do I pass data to components in the Translate components map?

Use the componentProps prop, which is forwarded to every non-string component in the map. Use 'as const' on literal values to prevent TypeScript from widening the generic, and declare children as optional in the component props.

When should I use t() instead of the Translate component?

Use the plain t() function whenever the locale message contains no markup or embedded components. <Translate> is more expensive to render, so it should be reserved for strings with tags that need mapping to components.