sanity-io / sanity-plugin-internationalized-array

A plugin to register array fields with a custom input component to store field values in multiple languages, queryable by using the language ID as an array `_key`.
MIT License
45 stars 11 forks source link

allow internationalizedArrayValue to be sortable (orderings) #51

Open williamli opened 1 year ago

williamli commented 1 year ago

Is there a way to use the internationalizedArrayValue as a ordering field?

For example, my document title are internationalizedArrayString and I am trying to order by field title[__key == "en-us"].value.

import {DocumentIcon} from '@sanity/icons'
import {defaultLanguage} from 'configs/locale'
import {defineField} from 'sanity'
import {isEmpty} from '../../utils/isEmpty'
import {translate} from '../../utils/translate'
import {validateSlug} from '../../utils/validateSlug'

// console.log({validateSlug, supportedLanguages})

export default defineField({
  name: 'page',
  title: 'Page',
  type: 'document',
  icon: DocumentIcon,
  groups: [
    {
      // default: true,
      name: 'editorial',
      title: 'Editorial',
    },
    {
      name: 'seo',
      title: 'SEO',
    },
  ],
  fields: [
    // Title
    defineField({
      name: 'title',
      title: 'Title',
      type: 'internationalizedArrayString',
      group: 'editorial',
      validation: (Rule) =>
        Rule.required().custom((title) =>
          !isEmpty(translate(title)) ? true : 'Title must be set for the default language',
        ),
    }),
    // Slug
    defineField({
      name: 'slug',
      type: 'slug',
      group: 'editorial',
      options: {
        source: `title[__key == "${defaultLanguage}"].value`,
      },
      // @ts-ignore - TODO - fix this TS error
      validation: validateSlug,
    }),
  ],
  orderings: [
    {
      name: 'titleAsc',
      title: 'Title (A-Z)',
      by: [{field: `title[__key == "${defaultLanguage}"].value`, direction: 'asc'}],
    },
    {
      name: 'titleDesc',
      title: 'Title (Z-A)',
      by: [{field: `title[__key == "${defaultLanguage}"].value`, direction: 'desc'}],
    },
    {
      name: 'slugAsc',
      title: 'Slug (A-Z)',
      by: [{field: 'slug.current', direction: 'asc'}],
    },
    {
      name: 'slugDesc',
      title: 'Slug (Z-A)',
      by: [{field: 'slug.current', direction: 'desc'}],
    },
  ],
  preview: {
    select: {
      active: 'active',
      slug: 'slug.current',
      title: 'title',
    },
    prepare(selection) {
      const {slug, title} = selection

      return {
        subtitle: `/${slug}`,
        title: translate(title),
      }
    },
  },
})

Right now titleAsc and titleDesc cannot use the field like this, but interestingly, slug can get the default title using

     options: {
        source: `title[__key == "${defaultLanguage}"].value`,
      },
christianalares commented 1 month ago

Is there a way to use the internationalizedArrayValue as a ordering field?

For example, my document title are internationalizedArrayString and I am trying to order by field title[__key == "en-us"].value.

import {DocumentIcon} from '@sanity/icons'
import {defaultLanguage} from 'configs/locale'
import {defineField} from 'sanity'
import {isEmpty} from '../../utils/isEmpty'
import {translate} from '../../utils/translate'
import {validateSlug} from '../../utils/validateSlug'

// console.log({validateSlug, supportedLanguages})

export default defineField({
  name: 'page',
  title: 'Page',
  type: 'document',
  icon: DocumentIcon,
  groups: [
    {
      // default: true,
      name: 'editorial',
      title: 'Editorial',
    },
    {
      name: 'seo',
      title: 'SEO',
    },
  ],
  fields: [
    // Title
    defineField({
      name: 'title',
      title: 'Title',
      type: 'internationalizedArrayString',
      group: 'editorial',
      validation: (Rule) =>
        Rule.required().custom((title) =>
          !isEmpty(translate(title)) ? true : 'Title must be set for the default language',
        ),
    }),
    // Slug
    defineField({
      name: 'slug',
      type: 'slug',
      group: 'editorial',
      options: {
        source: `title[__key == "${defaultLanguage}"].value`,
      },
      // @ts-ignore - TODO - fix this TS error
      validation: validateSlug,
    }),
  ],
  orderings: [
    {
      name: 'titleAsc',
      title: 'Title (A-Z)',
      by: [{field: `title[__key == "${defaultLanguage}"].value`, direction: 'asc'}],
    },
    {
      name: 'titleDesc',
      title: 'Title (Z-A)',
      by: [{field: `title[__key == "${defaultLanguage}"].value`, direction: 'desc'}],
    },
    {
      name: 'slugAsc',
      title: 'Slug (A-Z)',
      by: [{field: 'slug.current', direction: 'asc'}],
    },
    {
      name: 'slugDesc',
      title: 'Slug (Z-A)',
      by: [{field: 'slug.current', direction: 'desc'}],
    },
  ],
  preview: {
    select: {
      active: 'active',
      slug: 'slug.current',
      title: 'title',
    },
    prepare(selection) {
      const {slug, title} = selection

      return {
        subtitle: `/${slug}`,
        title: translate(title),
      }
    },
  },
})

Right now titleAsc and titleDesc cannot use the field like this, but interestingly, slug can get the default title using

     options: {
        source: `title[__key == "${defaultLanguage}"].value`,
      },

How are you translating the title? I see you're importing a translate-function, what does that do?