Code Monkey home page Code Monkey logo

sanity-plugin-internationalized-array's Introduction

This is the Sanity Studio v3 version of sanity-plugin-internationalized-array.

For the v2 version, please refer to the v2-branch.

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.

Screenshot of an internationalized input

Installation

npm install --save sanity-plugin-internationalized-array

or

yarn add sanity-plugin-internationalized-array

Usage for simple field types

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

import {defineConfig} from 'sanity'
import {internationalizedArray} from 'sanity-plugin-internationalized-array'

 export const defineConfig({
  // ...
  plugins: [
    internationalizedArray({
      languages: [
        {id: 'en', title: 'English'},
        {id: 'fr', title: 'French'}
      ],
      defaultLanguages: ['en'],
      fieldTypes: ['string'],
    })
  ]
})

This will register two new fields to the schema, based on the settings passed into fieldTypes:

  • internationalizedArrayString an array field of:
  • internationalizedArrayStringValue an object field, with a single string field inside called value

The above config will also create an empty array item in new documents for each language in defaultLanguages. This is configured globally for all internationalized array fields.

You can pass in more registered schema-type names to generate more internationalized arrays. Use them in your schema like this:

// For example, in postType.ts

fields: [
  defineField({
    name: 'greeting',
    type: 'internationalizedArrayString',
  }),
]

Loading languages

Languages must be an array of objects with an id and title.

languages: [
  {id: 'en', title: 'English'},
  {id: 'fr', title: 'French'}
],

Or an asynchronous function that returns an array of objects with an id and title.

languages: async () => {
  const response = await fetch('https://example.com/languages')
  return response.json()
}

The async function contains a configured Sanity Client in the first parameter, allowing you to store Language options as documents. Your query should return an array of objects with an id and title.

languages: async (client) => {
  const response = await client.fetch(`*[_type == "language"]{ id, title }`)
  return response
},

Additionally, you can "pick" fields from a document, to pass into the query. For example, if you have a concept of "Markets" where only certain language fields are required in certain markets.

In this example, each language document has an array of strings called markets to declare where that language can be used. And the document being authored has a single market field.

select: {
  market: 'market'
},
languages: async (client, {market = ``}) => {
  const response = await client.fetch(
    `*[_type == "language" && $market in markets]{ id, title }`,
    {market}
  )
  return response
},

Configuring the "Add translation" buttons

The "Add translation" buttons can be positioned in one or multiple locations by configuring buttonLocations:

  • field (default) Below the internationalized array field
  • unstable__fieldAction Inside a Field Action (currently unstable)
  • document Above the document fields, these buttons will add a new language item to every internationalized array field that can be found at the root of the document. Nested internationalized arrays are not yet supported.

The "Add all languages" button can be hidden with buttonAddAll.

import {defineConfig} from 'sanity'
import {internationalizedArray} from 'sanity-plugin-internationalized-array'

 export const defineConfig({
  // ...
  plugins: [
    internationalizedArray({
      // ...other config
      buttonLocations: ['field', 'unstable__fieldAction', 'document'], // default ['field']
      buttonAddAll: false // default true
    })
  ]
})

Using complex field configurations

For more control over the value field, you can pass a schema definition into the fieldTypes array.

import {defineConfig} from 'sanity'
import {internationalizedArray} from 'sanity-plugin-internationalized-array'

 export const defineConfig({
  // ...
  plugins: [
    internationalizedArray({
      languages: [
        {id: 'en', title: 'English'},
        {id: 'fr', title: 'French'}
      ],
      fieldTypes: [
        defineField({
          name: 'featuredProduct',
          type: 'reference',
          to: [{type: 'product'}]
          hidden: (({document}) => !document?.title)
        })
      ],
    })
  ]
})

This would also create two new fields in your schema.

  • internationalizedArrayFeaturedProduct an array field of:
  • internationalizedArrayFeaturedProductValue an object field, with a single string field inside called value

Note that the name key in the field gets rewritten to value and is instead used to name the object field.

Creating internationalized objects

Due to how fields are created, you cannot use anonymous objects in the fieldTypes array. You must register the object type in your Studio's schema as an "alias type".

// ./schemas/seoType.ts

import {defineField} from 'sanity'

export const seoType = defineField({
  name: 'seo',
  title: 'SEO',
  type: 'object',
  fields: [
    defineField({name: 'title', type: 'string'}),
    defineField({name: 'description', type: 'string'}),
  ],
})

Then in your plugin configuration settings, add the name of your alias type to the fieldTypes setting.

internationalizedArray({
  languages: [
    //...languages
  ],
  fieldTypes: ['seo'],
})

Lastly, add the field to your schema.

// ./schemas/post.ts

import {defineField, defineType} from 'sanity'

export default defineType({
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    defineField({
      name: 'seo',
      type: 'internationalizedArraySeo',
    }),
  ],
})

Validation of individual array items

You may wish to validate individual language fields for various reasons. From the internationalized array field, add a validation rule that can look through all the array items, and return item-specific validation messages at the path of that array item.

defineField({
  name: 'title',
  type: 'internationalizedArrayString',
  description: `Use fewer than 5 words.`,
  validation: (rule) =>
    rule.custom<{value: string; _type: string; _key: string}[]>((value) => {
      if (!value) {
        return 'Title is required'
      }

      const invalidItems = value.filter(
        (item) => item.value.split(' ').length > 5,
      )

      if (invalidItems.length) {
        return invalidItems.map((item) => ({
          message: `Title is too long. Must be 5 words or fewer.`,
          path: [{_key: item._key}, 'value'],
        }))
      }

      return true
    }),
}),

Usage with @sanity/language-filter

If you have many languages and authors that predominately write in only a few, @sanity/language-filter can be used to reduce the number of language fields shown in the document form.

Internationalized array field filtered with language-filter

Configure both plugins in your sanity.config.ts file:

// ./sanity.config.ts

import {defineConfig, isKeySegment} from 'sanity'
import {languageFilter} from '@sanity/language-filter'

export default defineConfig({
  // ... other config
  plugins: [
    // ... other plugins
    languageFilter({
      // Use the same languages as the internationalized array plugin
      supportedLanguages: SUPPORTED_LANGUAGES,
      defaultLanguages: [],
      documentTypes: ['post'],
      filterField: (enclosingType, member, selectedLanguageIds) => {
        // Filter internationalized arrays
        if (
          enclosingType.jsonType === 'object' &&
          enclosingType.name.startsWith('internationalizedArray') &&
          'kind' in member
        ) {
          // Get last two segments of the field's path
          const pathEnd = member.field.path.slice(-2)
          // If the second-last segment is a _key, and the last segment is `value`,
          // It's an internationalized array value
          // And the array _key is the language of the field
          const language =
            pathEnd[1] === 'value' && isKeySegment(pathEnd[0])
              ? pathEnd[0]._key
              : null

          return language ? selectedLanguageIds.includes(language) : false
        }

        // Filter internationalized objects if you have them
        // `localeString` must be registered as a custom schema type
        if (
          enclosingType.jsonType === 'object' &&
          enclosingType.name.startsWith('locale')
        ) {
          return selectedLanguageIds.includes(member.name)
        }

        return true
      },
    }),
  ],
})

Shape of stored data

The custom input contains buttons which will add new array items with the language as the _key value. Data returned from this array will look like this:

"greeting": [
  { "_key": "en", "value": "hello" },
  { "_key": "fr", "value": "bonjour" },
]

Querying data

Using GROQ filters you can query for a specific language key like so:

*[_type == "person"] {
  "greeting": greeting[_key == "en"][0].value
}

Migrate from objects to arrays

See the migration script inside ./migrations/transformObjectToArray.ts of this Repo.

Follow the instructions inside the script and set the _type and field name you wish to target.

Please take a backup first!

Why store localized field data like this?

The most popular way to store field-level translated content is in an object using the method prescribed in @sanity/language-filter. This works well and creates tidy object structures, but also creates a unique field path for every unique field name, multiplied by the number of languages in your dataset.

For most people, this won't become an issue. On a very large dataset with a lot of languages, the Attribute Limit can become a concern. This plugin's arrays will use fewer attributes than an object once you have more than three languages.

The same content as above, plus a third language, structured as an object of string fields looks like this:

"greeting" {
  "en": "hello",
  "fr": "bonjour",
  "es": "hola"
}

Which creates four unique query paths, one for the object and one for each language.

greeting
greeting.en
greeting.fr
greeting.es

Every language you add to every object that uses this structure will add to the number of unique query paths.

The array created by this plugin creates four query paths by default, but is not affected by the number of languages:

greeting
greeting[]
greeting[]._key
greeting[].value

By using this plugin you can safely extend the number of languages without adding any additional query paths.

MIT © Sanity.io See LICENSE

License

MIT-licensed. See LICENSE.

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.

License

MIT © Simeon Griggs

sanity-plugin-internationalized-array's People

Contributors

d4v1d82 avatar gaauwe avatar kenjonespizza avatar renovate[bot] avatar robinpyon avatar semantic-release-bot avatar simeongriggs avatar stipsan avatar thebiggianthead avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

sanity-plugin-internationalized-array's Issues

Slate editor error from fields with array of type "block"

Error when using portable text (array of type block) fields

I am experiencing an error when editing formattable text within internationalized arrays. The studio runs and the fields appear without issues, but when editing the text I get the following error when attempting to edit the field:

Uncaught error: Cannot resolve a Slate point from DOM point: [object Text]

This is how the field is set up:

export const internationalizedArrayConfig = {
    languages,
    fieldTypes: [
        'string',
        defineField({
            name: 'formattedText',
            type: 'array',
            of: [{type: 'block'}]
        })
    ],
}

const plugins = [
  internationalizedArray(internationalizedArrayConfig),
]

// Inside the schema
		defineField({
			name: "formattedTextField",
			title: "Weight example",
			type: "internationalizedArrayFormattedText",
		}),

I do not get any issues with string fields of the type internationalizedArrayString, so the problem seems related to the default portable text editor. Is portable text currently incompatible with this plugin?

image
image

`defaultLanguages` option causes weird behaviours (duplicate keys, unable to delete documents)

Hey there,

thanks for the plugin, it worked nicely while not using the defaultLanguages config option. 😅

Issues

When using it, I encountered some problems:

Issue 1 - Duplicate keys

Creating a new document via the UI and with the option configured, this is the result for all translated fields:
image

Looking at the data (*[_type == "project"] { translatedString1, translatedString2, translatedStringText } - same for every field):

"translatedString1": [
    {
        "_key": "en",
        "_type": "internationalizedArrayStringValue"
    },
    {
        "_type": "internationalizedArrayStringValue",
        "_key": "en"
    }
],

When creating a document, there are two POST requests

https://<id>.api.sanity.io/v2022-09-09/data/mutate/production?tag=sanity.studio.document.commit&returnIds=true&visibility=async&skipCrossDatasetReferenceValidation=true

containing sth. like the snippet below, so makes sense that keys are duplicated (I also observed the same field being patched twice in the same request, e.g. translatedString2[-1]):

{
    "patch": {
        "insert": {
            "after": "translatedString2[-1]",
            "items": [
                {
                    "_type": "internationalizedArrayStringValue",
                    "_key": "en"
                }
            ]
        },
        "id": "drafts.<same-id>"
    }
},
{
    "patch": {
        "insert": {
            "after": "translatedString2[-1]",
            "items": [
                {
                    "_type": "internationalizedArrayStringValue",
                    "_key": "en"
                }
            ]
        },
        "id": "drafts.<same-id>"
    }
},

I can generate unique keys and fix the "deduped" key to be of a valid language via the UI, but… for now I'll go without the config option and having to click the languages every time

Issue 2 - Document deletion not possible

Deleting a document in this state is not possible, the delete request gets aborted and a POST request with createIfNotExists for every translated field follows. Removing the defaultLanguages option will delete it successfully. I know there were issues before that covered this, but it's still happening for me (in this state)

Reproduction

I created a reproduction repo based on this template with a few added fields in the project document where this behaviour should be observable (it is for me every time, using Firefox). You should only have to enter valid API credentials.

Using the latest version of the plugin (1.10.3). If you have any further questions, let me know!

Thanks for your input!

String input is rendered for markdown field

I'm using https://www.sanity.io/plugins/sanity-plugin-markdown for rendering Markdown inputs. To make them translatable, I added fieldTypes: ['string', 'markdown'] to Sanity config.

I'm assuming I have to use internationalizedArrayMarkdown as type when I create schemas for translatable Markdown fields now, although I didn't find any examples in the docs for custom input types.

I'm expecting to see a markdown input, but I still get a regular string input for internationalizedArrayMarkdown fields:

image

So my question is: is it possible at all to render custom field types with this plugin? If yes, what could I be doing wrong?

Edit: I tried using text and internationalizedArrayText just to check that it's possible to render any input fields other than a regular string inputs, and it works, I'm getting a nice textarea. So this problem must be only for rendering custom fields.

Error using plugin with blockContent

I can't use internationalizedArrayBlockContent without getting the following error everytime I type something.

image

It works properly with the text field, so thanks for that! But it's a very annoying bug, even not blocking me to continue producing content.

This is my config:

  internationalizedArray({
    languages,
    fieldTypes: ['string', 'blockContent'], // internationalizedArray<type>
  }),

String field with limited possible values (list): “Value did not match any allowed values”

I’m trying to set a string-type field with a dropdown for possible values (list). Though, the input appears to be invalid as it’s expecting a string value but instead getting an object ([object Object]) and it prevents saving the user input.

image

My custom field type looks like this:

// localeSelect.js
export default {
  name: "localeSelect",
  type: "string",
  options: {
    list: [
      {
        title: "English (United States)",
        value: "en_US"
      },
      {
        title: "Spanish (Latin America)",
        value: "es_LA"
      }
    ]
  }
}
// documentSchema.js
{
  name: "locale",
  type: "internationalizedArrayLocaleSelect"
}

Note how there is no custom field validation in place. The string/list field is performing its inherent value check.

Hide "+ Add missing language"?

While I can see this rather big button being useful in some cases, I have had requests from our users to hide it since it's just taking up valuable space. If a site only has 2 langs and one is currently filled out, for example, there's two buttons doing the same thing 🤷‍♂️

An option to hide this would be great! Or if someone could help me how to target these with css to hide manually?

🙏🏻

Using a shared languages state

We are currently using objects for translations but for good reasons we are considering moving to arrays and specific this plugin.

In our Studio we have quite a few translatable fields and we would like to limit some clicks and some possible mistakes from our editors.

We see now that it's possible to add a title field in en and da, while adding da, it, es to a description field. Since our editors already know from the start what languages the document should be translated into, it's many click to add x amount of languages to x amount of fields - instead of adding them from the beginning.

If it instead would be possible to have a shared languages across all translatable field with this plugin that would solve our needs better.

Something like adding a shared languages field once (using same UI):
image

That then would add the translateable fields:
image

Internationalized Array String still not editable if existing instance does not exist

Describe the bug

When using an internationalized string field in an array field, the field is uneditable and says This internationalized field currently has no translations.

This issue has been reported previously here #37 and appears to have been fixed #40, but it still exists for me on the latest release
A clear and concise description of what the bug is.

Expected behavior

When you add an internationalizesArrayString field to an array component, the field should allow you add translations

Screenshots
If applicable, add screenshots to help explain your problem.
Screenshot 2023-11-01 at 22 32 18

Which versions of Sanity are you using?

Run sanity versions in the terminal and copy-paste the result here.

@sanity/cli (global)                   3.19.0 (up to date)
@sanity/document-internationalization   2.0.1 (up to date)
@sanity/eslint-config-studio            2.0.4 (latest: 3.0.1)
@sanity/icons                           2.4.1 (latest: 2.6.0)
@sanity/scheduled-publishing            1.2.1 (up to date)
@sanity/ui                              1.7.8 (latest: 1.8.3)
@sanity/vision                         3.19.0 (up to date)
sanity                                 3.19.0 (up to date)

sanity-plugin-internationalized-array 1.10.3

What operating system are you using?

Which versions of Node.js / npm are you running?
node v18.16.1

Error when importing internationalizedArray

I just installed the plugin and got this error when import {internationalizedArray} from 'sanity-plugin-internationalized-array' in sanity.config.js:

[1] ✘ [ERROR] No matching export in "node_modules/sanity/lib/index.esm.js" for import "defineDocumentFieldAction"
[1] 
[1]     node_modules/sanity-plugin-internationalized-array/lib/index.esm.js:1:215:
[1]       1 │ ...ient,useFormBuilder,defineDocumentFieldAction,useFormValue,set,A...
[1]         ╵                        ~~~~~~~~~~~~~~~~~~~~~~~~~
[1] 
[1] 10:18:01 AM [vite] error while updating dependencies:
[1] Error: Build failed with 1 error:
[1] node_modules/sanity-plugin-internationalized-array/lib/index.esm.js:1:215: ERROR: No matching export in "node_modules/sanity/lib/index.esm.js" for import "defineDocumentFieldAction"

Versions:
"sanity": "^3.10.3",
"sanity-plugin-internationalized-array": "^1.10.3",

Toggle or hide translation fields

Hi, and thanks for a great plugin!

I was wondering if there is any way to implement some sort of toggle or expand/collapse view for translations other that the default language? On content types with a lot of fields, it quickly gets a bit cluttered when all translations for all fields are displayed simultaneously, especially if there are many translations. To be able to expand/show a translation for a field, edit it, then close/hide it for instance, would be great.

`select` does not select fields

Describe the bug

When I add keys to the select object they are not selected. Regardless of what I try to select, the object is emply.

To Reproduce

My configuration looks like this:

	internationalizedArray({
		select: {
			market: "market",
			marketKey: "marketKey",
			availableMarkets: "availableMarkets",
		},
		languages: async (client, data) => {
                         // Added this to debug for now
			console.log("[data]", JSON.stringify(data));
			return supportedLanguages;
		},
		fieldTypes: ["string", "content"],
	})

The document I am trying to edit has the following fields:

[
   ....
    {
      name: 'market',
      type: 'marketKey',
      validation: (Rule) => Rule.required(),
    },
    {
      name: 'content',
      // I also tried string here
      type: 'internationalizedArrayContent',
    },
    ...
  ]

Nevertheless, in the console I only see: [data] {} being logged

Expected behavior

In this case, I would expect market to be present in the object, but it is not.

Which versions of Sanity are you using?

Run sanity versions in the terminal and copy-paste the result here.

@sanity/cli (global)     3.42.1 (latest: 3.43.0)
@sanity/assist            3.0.4 (up to date)
@sanity/cli              3.42.1 (latest: 3.43.0)
@sanity/dashboard         3.1.6 (up to date)
@sanity/icons            2.11.8 (up to date)
@sanity/image-url         1.0.2 (up to date)
@sanity/language-filter   4.0.2 (up to date)
@sanity/types            3.42.1 (latest: 3.43.0)
@sanity/ui               2.1.10 (latest: 2.1.11)
@sanity/vision           3.42.1 (latest: 3.43.0)
sanity                   3.42.1 (latest: 3.43.0)

What operating system are you using?

MacOS Sonoma

Which versions of Node.js / npm are you running?

pnpm 8.15.6

Node 20.10.0

Unable to use internationalizedArrayText

Describe the bug
It is not possible to add internationalizedArrayText. After registering the field type in sanity.config.ts and try to use it in my field it throws an runtime exception realted to textInputRepresentationStyle

No difference if I will try use defined type 'text' in fieldTypes or try to hack it with creating my own type with text inside, if only it contains text it is not able to create it after opening the internationalized field value.

To Reproduce

  1. internationalizedArray({
    languages: [
    {id: 'da', title: 'Danish'},
    {id: 'en', title: 'English'}
    ],
    defaultLanguages: ['da'],
    fieldTypes: ['string', 'text'],
    })

  2. defineField({
    name: 'content',
    type: 'internationalizedArrayText',
    title: 'Content',
    })

  3. try to insert content.

Expected behavior

The internationalized array of texts render, open and be able to consume text.

Screenshots
image

Which versions of Sanity are you using?

Run sanity versions in the terminal and copy-paste the result here.

@sanity/cli (global) 3.23.1 (latest: 3.28.0)
@sanity/eslint-config-studio 3.0.1 (up to date)
@sanity/vision 3.23.1 (latest: 3.28.0)
sanity 3.23.1 (latest: 3.28.0)

What operating system are you using?
windows

Which versions of Node.js / npm are you running?
Node.js v18.12.1.
yarn 1.22.19

add support for fetching `defaultLanguages` using async

Is your feature request related to a problem? Please describe.

languages can be fetched with async but you can't do the same with defaultLanguages.

Describe the solution you'd like

It would be good if defaultLanguages can also be fetched with async using Sanity client.

Describe alternatives you've considered

not using defaultLanguages at all

Additional context

allow internationalizedArrayValue to be sortable (orderings)

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`,
      },

Custom field not working

Hi! I'm trying to apply a custom field using 'internationalizedArrayString' and it's not working:

  return (
    <div style={{background: 'red'}}>
      <h1>TEST</h1>
      <label htmlFor="my-custom-field">My Custom Field:</label>
      <input
        id="my-custom-field"
        type="text"
        value={value}
        onChange={(e) => onChange(e.target.value)}
      />
    </div>
  )
}

defineField({
      name: 'title',
      title: 'Title',
      type: 'internationalizedArrayString',
      components: {
        input: MyCustomField,
      },
    }),```

Do you have any idea where the issue would be coming from? @andresclua

styled-components missmatch

Hey when using the latest Sanity, Sanity Presentation (which is part of the core Sanity Studio) requires styled-components@^6.1.1 while sanity-plugin-internationalized-array requires styled-components@^5.3.6.

image

BlockContent not working properly

Hi! I was trying to use the plugin for a blockContent field type and it throws the following error once you type in the field:

Captura de pantalla 2023-06-14 a la(s) 16 33 58

Any idea how I could fix this?

Error: Can't resolve 'sanity' in v3 branch

Using the v3 install (npm i sanity-plugin-internationalized-array@studio-v3), when I go to add the example on the plugin page I get the following error:

Failed to compile.

Error in ./node_modules/sanity-plugin-internationalized-array/lib/index.esm.js
Module not found: Error: Can't resolve 'sanity' in '~/sanity-demo/node_modules/sanity-plugin-internationalized-array/lib'
 @ ./node_modules/sanity-plugin-internationalized-array/lib/index.esm.js 1:695-842
 @ ./schemas/person.js
 @ ./schemas/schema.js (part:@sanity/base/schema)
 @ ./node_modules/@sanity/default-layout/lib/schemaErrors/SchemaErrorReporter.js
 @ ./node_modules/@sanity/default-layout/lib/defaultLayout/DefaultLayout.js
 @ ./node_modules/@sanity/default-layout/lib/defaultLayout/index.js
 @ ./node_modules/@sanity/default-layout/lib/Root.js (part:@sanity/default-layout/root)
 @ ./plugins/sanity-plugin-tutorial/CustomDefaultLayout.js (part:@sanity/base/root)
 @ ./node_modules/@sanity/base/lib/components/SanityRoot.js (part:@sanity/base/sanity-root)
 @ ./node_modules/@sanity/server/lib/browser/entry-dev.js
 @ multi ./node_modules/@sanity/server/lib/browser/entry-dev.js

Can't delete document if defaultLanguages configured

Thanks for making this awesome plugin available! 🎉

We just found a bug that can be reproduced in this minimal test case: https://github.dev/israelroldan/sanity-i18nplugin-tc

Description of the issue

When an internationalized field is added to a document, documents of that type can't be fully deleted.

Steps to reproduce

  1. Create a new post
  2. Try to delete it
  3. The document is deleted but immediately recreated again (same id but with all fields empty)

Expected behaviour

The document is deleted

Actual result

The document is immediately recreated empty and can't be deleted

Additional information

The root cause is the code used by the plugin to add default languages. When a document is deleted the studio hooks are re-executed and the conditions present in src/components/InternationalizedArray.tsx#108-119 are applicable so the call to handleAddLanguages(defaultLanguages) takes place, effectively adding default languages to the just deleted document, forcing its re-creation.

Disabling defaultLanguages is a workaround at the moment.

Internationalized Array String in objects not editable

I have a document called Menu, and which among other fields has an array of a custom menuItem object. In the menuItem I have defined the title field as an internationalizedArrayString like so:

    defineField({
      name: 'title',
      title: 'Title',
      type: 'internationalizedArrayString',
    }),

When trying to create new or edit menuItems, it is not possible to add any translations.

image

In my defineConfig I have this:

    internationalizedArray({
      languages: [
          {id: 'nb', title: 'Norwegian (Bokmål)'},
          {id: 'nn', title: 'Norwegian (Nynorsk)'},
          {id: 'en', title: 'English'},
      ],
      defaultLanguages: ['nb'],
      fieldTypes: ['string', 'url', 'slug'],
      buttonAddAll: true,
      buttonLocations: ['field'],
    }),

Any obvious reason why this is happening?

Validation for translatable fields?

Is your feature request related to a problem? Please describe.
Is it possible to validate the entry of a translated field? For example:

  • One translation needs to be present?
  • All translations need to be present?

Describe the solution you'd like
Having validation: (Rule) => Rule.required(), work on the internationalizedArrayString field

Tab layout

Is your feature request related to a problem? Please describe.
Especially when using block content, adding languages takes up a lot of space.

Describe the solution you'd like
A tab layout would be perfect. You could set a default language that is displayed by default. Other languages would still be available quickly.
Bildschirmfoto 2024-02-01 um 12 07 43

Describe alternatives you've considered
Filtering languages is not as intuitive.

Default language

Is it possible to define a default language, so that the user does not need to click + EN?

i.e. when the document is rendered, get this:

Screenshot 2023-06-12 at 07 29 50

instead of this:

Screenshot 2023-06-12 at 07 29 43

Thanks!

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.


Using a curated preset maintained by


Sanity: The Composable Content Cloud

Pending Approval

These branches will be created by Renovate only once you click their checkbox below.

  • chore(deps): update non-major (@commitlint/cli, @commitlint/config-conventional, @sanity/icons, @sanity/pkg-utils, @sanity/plugin-kit, @sanity/ui, @types/lodash, @types/react, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-simple-import-sort, npm-run-all2, prettier-plugin-packagejson, react, react-dom, react-is, sanity, semantic-release, typescript)
  • chore(deps): update dependency @sanity/plugin-kit to v4
  • chore(deps): update dependency npm-run-all2 to v6
  • fix(deps): Update dependency @sanity/icons to v3
  • chore(deps): lock file maintenance
  • 🔐 Create all pending approval PRs at once 🔐

Detected dependencies

github-actions
.github/workflows/main.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
npm
package.json
  • @sanity/icons ^2.11.7
  • @sanity/incompatible-plugin ^1.0.4
  • @sanity/language-filter ^4.0.2
  • @sanity/ui ^2.1.0
  • fast-deep-equal ^3.1.3
  • lodash ^4.17.21
  • suspend-react 0.1.3
  • @commitlint/cli ^19.2.1
  • @commitlint/config-conventional ^19.1.0
  • @sanity/pkg-utils ^6.1.0
  • @sanity/plugin-kit ^3.1.10
  • @sanity/semantic-release-preset ^4.1.7
  • @types/lodash ^4.17.0
  • @types/react ^18.2.75
  • @typescript-eslint/eslint-plugin ^7.6.0
  • @typescript-eslint/parser ^7.6.0
  • eslint ^8.57.0
  • eslint-config-prettier ^9.1.0
  • eslint-config-sanity ^7.1.2
  • eslint-plugin-prettier ^5.1.3
  • eslint-plugin-react ^7.34.1
  • eslint-plugin-react-hooks ^4.6.0
  • eslint-plugin-simple-import-sort ^12.0.0
  • npm-run-all2 ^5.0.0
  • prettier ^3.2.5
  • prettier-plugin-packagejson ^2.4.14
  • react ^18.2.0
  • react-dom ^18.2.0
  • react-is ^18.2.0
  • rimraf ^4.4.1
  • sanity ^3.36.4
  • semantic-release ^23.0.7
  • typescript ^5.4.4
  • @sanity/ui ^2.1.0
  • react ^18
  • react-dom ^18
  • sanity ^3.36.4
  • styled-components ^6.1
  • node >=14

  • Check this box to trigger a request for Renovate to run again on this repository

internationalizedArrayText crashes Studio with Error: Cannot read properties of undefined (reading 'default')

Describe the bug

I created several internationalized fields in my scheme. The internationalizedArrayString works well while internationalizedArrayText results in a Studio crash.

defineField({
      name: 'title',
      title: 'Title',
      type: 'internationalizedArrayString',
      validation: (rule) => rule.required(),
    }),
defineField({
      name: 'text',
      title: 'Text',
      type: 'internationalizedArrayText',
    }),

Error: Cannot read properties of undefined (reading 'default')

In sanity.config.js, I added a plugin, like that:

internationalizedArray({
      languages: [
        {id: 'en', title: 'English'},
        {id: 'lt', title: 'Lithuanian'},
      ],
      defaultLanguages: ['en'],
      fieldTypes: ['string', 'text'],
    }),

To Reproduce

Steps to reproduce the behavior:

Setup a scheme as above and run npm run dev to open localhost.

Expected behavior

Expect both string and text fields to be internationalized.

Screenshots

image

Which versions of Sanity are you using?

@sanity/cli (global) 3.23.4 (up to date)
@sanity/eslint-config-studio 3.0.1 (up to date)
@sanity/vision 3.23.4 (up to date)
sanity 3.23.4 (up to date)

What operating system are you using?

MacOS Ventura 13.4

Which versions of Node.js / npm are you running?

npm: 10.2.3
node: v20.10.0

Additional context

"sanity-plugin-internationalized-array": "^1.10.3",

Unable to resolve dependency tree

On NPM 8.19.2, installing the v3 of this branch with a basic Sanity setup (fresh sanity init), I get the following error:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^17.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^18" from @sanity/[email protected]
npm ERR! node_modules/@sanity/ui
npm ERR!   peer @sanity/ui@"1.0.0-beta.32" from [email protected]
npm ERR!   node_modules/sanity-plugin-internationalized-array
npm ERR!     sanity-plugin-internationalized-array@"1.2.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See ~/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     ~/.npm/_logs/2022-11-22T19_27_29_342Z-debug-0.log

Re-running with --legacy-peer-deps works, but it looks like there are two different versions of React now expected and this results in weird errors with alt package managers like pnpm

Translatable string list option

I may be missing something, but is there a solution for string list option to be translatable?

defineField({
  name: 'categories',
  title: 'Categories',
  type: 'string',
  options: {
    // This should be translatable
    list: [
      'Shirts',
      'Shorts',
      'Shoes',
    ]
  }
})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.