Skip to content
This repository was archived by the owner on Feb 3, 2026. It is now read-only.

Commit 6089b8b

Browse files
authored
Revert "feat(SAPP-2780): Use dedicated language field instead of _key for lan…" (#113)
This reverts commit 2a19fa0.
1 parent 2a19fa0 commit 6089b8b

14 files changed

+74
-552
lines changed

README.md

Lines changed: 15 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
# sanity-plugin-internationalized-array
66

7-
A plugin to register array fields with a custom input component to store field values in multiple languages, queryable by the `language` field.
7+
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`.
88

99
![Screenshot of an internationalized input](./img/internationalized-array.png)
1010

@@ -19,7 +19,6 @@ A plugin to register array fields with a custom input component to store field v
1919
- [Usage with @sanity/language-filter](#usage-with-sanitylanguage-filter)
2020
- [Shape of stored data](#shape-of-stored-data)
2121
- [Querying data](#querying-data)
22-
- [Migrate from v3 to v4](#migrate-from-v3-to-v4)
2322
- [Migrate from objects to arrays](#migrate-from-objects-to-arrays)
2423
- [Why store localized field data like this?](#why-store-localized-field-data-like-this)
2524
- [License](#license)
@@ -309,14 +308,15 @@ export default defineConfig({
309308
enclosingType.name.startsWith('internationalizedArray') &&
310309
'kind' in member
311310
) {
312-
// Get the language from the member's parent value
313-
// In v4+, language is stored in a dedicated `language` field
314-
const parentValue = member.field.path.length >= 2
315-
? member.field.document?.[member.field.path[0]]?.find(
316-
(item: any) => item._key === member.field.path[1]?._key
317-
)
318-
: null
319-
const language = parentValue?.language
311+
// Get last two segments of the field's path
312+
const pathEnd = member.field.path.slice(-2)
313+
// If the second-last segment is a _key, and the last segment is `value`,
314+
// It's an internationalized array value
315+
// And the array _key is the language of the field
316+
const language =
317+
pathEnd[1] === 'value' && isKeySegment(pathEnd[0])
318+
? pathEnd[0]._key
319+
: null
320320

321321
return language ? selectedLanguageIds.includes(language) : false
322322
}
@@ -339,93 +339,25 @@ export default defineConfig({
339339

340340
## Shape of stored data
341341

342-
The custom input contains buttons which will add new array items with a `language` field identifying the language. Data returned from this array will look like this:
342+
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:
343343

344344
```json
345345
"greeting": [
346-
{ "_key": "abc123", "language": "en", "value": "hello" },
347-
{ "_key": "def456", "language": "fr", "value": "bonjour" }
346+
{ "_key": "en", "value": "hello" },
347+
{ "_key": "fr", "value": "bonjour" },
348348
]
349349
```
350350

351-
> **Note:** In versions prior to v4, the language ID was stored in the `_key` field. See [Migrate from v3 to v4](#migrate-from-v3-to-v4) if you're upgrading from an earlier version.
352-
353351
## Querying data
354352

355-
Using GROQ filters you can query for a specific language like so:
353+
Using GROQ filters you can query for a specific language key like so:
356354

357355
```js
358356
*[_type == "person"] {
359-
"greeting": greeting[language == "en"][0].value
357+
"greeting": greeting[_key == "en"][0].value
360358
}
361359
```
362360

363-
> **Migrating queries from v3:** If upgrading from v3, replace `_key == "en"` with `language == "en"` in your GROQ queries.
364-
365-
## Migrate from v3 to v4
366-
367-
Version 4 changes how language identification is stored. Previously, the language ID was stored in the array item's `_key` field. Now, a dedicated `language` field is used, and `_key` contains a random identifier.
368-
369-
**Before (v3):**
370-
```json
371-
{ "_key": "en", "value": "hello" }
372-
```
373-
374-
**After (v4):**
375-
```json
376-
{ "_key": "abc123", "language": "en", "value": "hello" }
377-
```
378-
379-
### Why this change?
380-
381-
The `_key` field in Sanity arrays is meant for tracking item identity across edits, not for storing semantic data. Using it for language IDs caused issues with:
382-
- Array reordering and diffing in the Studio
383-
- Portable Text operations that rely on stable keys
384-
- Edge cases when copying/pasting between documents
385-
386-
### Migration steps
387-
388-
1. **Take a backup first!**
389-
```bash
390-
npx sanity@latest dataset export
391-
```
392-
393-
2. **Update the plugin** to v4
394-
395-
3. **Update your GROQ queries** to use `language` instead of `_key`:
396-
```js
397-
// Before
398-
greeting[_key == "en"][0].value
399-
400-
// After
401-
greeting[language == "en"][0].value
402-
```
403-
404-
4. **Run the migration script** to update existing documents:
405-
406-
Edit `migrations/keyToLanguage.ts` to configure your document types and field names:
407-
```ts
408-
const DOCUMENT_TYPES = ['post', 'page'] // Your document types
409-
const FIELD_NAMES = ['title', 'description'] // Your internationalized fields
410-
```
411-
412-
First, run in dry-run mode to preview changes:
413-
```bash
414-
npx sanity@latest exec ./migrations/keyToLanguage.ts --with-user-token
415-
```
416-
417-
Then set `DRY_RUN = false` and run again to apply changes.
418-
419-
5. **Handle drafts and published documents** - The migration script processes all documents. Run it twice if needed: once for production, once after publishing any pending drafts.
420-
421-
### Migration script details
422-
423-
The migration script (`migrations/keyToLanguage.ts`):
424-
- Processes documents in batches of 100
425-
- Uses optimistic locking (`ifRevisionID`) for safe concurrent execution
426-
- Is idempotent - safe to run multiple times
427-
- Skips items that already have a `language` field
428-
429361
## Migrate from objects to arrays
430362

431363
[See the migration script](https://github.com/sanity-io/sanity-plugin-internationalized-array/blob/main/migrations/transformObjectToArray.ts) inside `./migrations/transformObjectToArray.ts` of this Repo.

0 commit comments

Comments
 (0)