npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sanity-plugin-i18n-fields

v1.0.0

Published

A Sanity plugin to manage i18n at field level

Downloads

408

Readme

I18n fields

An alternative way to manage localization at field level in your Sanity Studio.

⚡️ Features

  • Sanity v3 plugin.
  • Field-level localization for the following Sanity types: string, text, and number.
  • Optional UI (slider or dropdown).
  • Locale visibility by user roles.
  • Locale read-only by user roles.
  • Object Validation.
  • Customization available also at field level.
  • Customizable types prefix.

🔌 Installation

npm install sanity-plugin-i18n-fields

🧑‍💻 Usage

Add it as a plugin in sanity.config.ts (or .js):

import {defineConfig} from 'sanity'
import {I18nFields} from 'sanity-plugin-i18n-fields'

export default defineConfig({
  //...
  plugins: [I18nFields({
    // your configuration here
  })],
})

The plugin will provide three new types: i18n.string, i18n.text, and i18n.number. All three types will be objects with a dynamic number of fields based on the localizations provided during configuration.

⚙️ Plugin Configuration

This is the main configuration of the plugin, and the available options are as follows:

{
  prefix?: string // You can configure the prefix of the types created by the plugin. If you are already using them or prefer a different name for any reason, you can change it. The default is 'i18n'.
  // The 'ui' option allows you to customize the appearance of the plugin's UI. By default, it is set to 'slider'.
  ui?: {
    type?: 'slider' | 'dropdown' // The UI of the plugin, Default is 'slider'
    position?: 'top' | 'bottom' // You can specify the position of the 'slider' above or below the input field, with the default being 'bottom'.
    selected?: 'border' | 'background' // For the 'slider' type, you can configure the UI of the selected locale, and the default setting is 'border'.
  },
  // The 'locales' option is the core of the configuration, enabling you to set up all available locales for your project.
  locales: [
    {
      code: string // the code of the locale
      label: ReactNode | ComponentType // the label of the locale
      title: string // the title of the locale
      default?: boolean // This is the flag to identify the default locale. If set to true, the locale is placed in the first position.
      visibleFor?: string[] // You can define a list of roles for which this locale is visible. By using the '!' operator, you can make it not visible.
      editableFor?: string[] // You can define a list of roles for which this locale is editable. The '!' operator allows you to specify the opposite condition.
    },
    // other locales
  ]
}

Sample configuration:

import {defineConfig} from 'sanity'
import {I18nFields} from 'sanity-plugin-i18n-fields'

export default defineConfig({
  //...
  plugins: [I18nFields({
    ui: {
      position: 'bottom'
    },
    locales: [
      {code: 'en', label: '🇬🇧', title: 'English', default: true},
      {code: 'en_us', label: '🇺🇸🇬🇧', title: 'American English'},
      {code: 'it', label: '🇮🇹', title: 'Italian', visibleFor: ['it_editor']}, // country visible only for administrator and it_editor roles
      {code: 'es', label: '🇪🇸', title: 'Spanish'},
    ]
  })],
})

🔧 Field Configuration

Other than global configuration, you can customize your configuration at field level. For example, for a specific field, you can have a dropdown layout or hide a particular locale.

import {ConditionalProperty, NumberOptions, StringOptions} from 'sanity'

export default defineType({
  type: 'document',
  name: 'myDocument',
  title: 'My Document',
  fields: [
    defineField({
      type: 'i18n.string' | 'i18n.text' | 'i18n.number',
      // ...
      options: {
        ui?: {
          type?: 'slider' | 'dropdown'
          position?: 'top' | 'bottom'
          selected?: 'border' | 'background'
        },
        locales?: [
            {
              code: string // the code of the locale. MUST be the same as the one used in the global configuration.
              readOnly?: ConditionalProperty
              hidden?: ConditionalProperty
              options?: StringOptions | { rows?:number } | NumberOptions
              visibleFor?: string[] // same as global configuration
              editableFor?: string[] // same as global configuration
            },
            // other locales
          ]
      }
    })
  ]
})

🗃️ Data model

  // sample with 'en', 'en_us', 'it' and 'es' locales

  {
    _type: 'i18n.string',
    en: string,
    en_us: string,
    it: string,
    es: string,
  }

  {
    _type: 'i18n.text',
    en: string,
    en_us: string,
    it: string,
    es: string,
  }

  {
    _type: 'i18n.number',
    en: number,
    en_us: number,
    it: number,
    es: number,
  }

🚨 Validation

Since the new types introduced by the plugin are objects, you can use children validation to apply specific validation to a particular locale. All error/warning messages are then collected and visible near the title of your field or in the right menu.

🤩 Examples Examples Examples

👀 Future features

  • New Sanity default types (boolean, date...)
  • Filters
    • Show all locales without slider/dropdown
    • Show only fulfilled translations
    • Show only empty translations
  • AI integration? 🤔
  • ...

While writing this documentation, I realized that with the 'prefix' option, you can define the plugin multiple times with different prefixes.

Codes and Labels are customizable, and this plugin could be used for other use cases, not only for internationalization.

So, perhaps the name 'I18N Fields' is already outdated? 😅 Should I find a different name? Any suggestions? 😂

📝 License

MIT © William Iommi

🧪 Develop & test

This plugin uses @sanity/plugin-kit with default configuration for build & watch scripts.

See Testing a plugin in Sanity Studio on how to run this plugin with hotreload in the studio.

Release new version

Run "CI & Release" workflow. Make sure to select the main branch and check "Release new version".

Semantic release will only release on configured branches, so it is safe to run release on any branch.