Skip to content

Commit edf2b5f

Browse files
committed
i18n upgrade from v4 to v6
1 parent 8e390ca commit edf2b5f

8 files changed

Lines changed: 3787 additions & 3252 deletions

File tree

.github/skills/SKILL.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
name: i18n-array-groq-query-migration
3+
description: Detect and update legacy GROQ patterns where language is read from _key for sanity-plugin-internationalized-array when users mention v4 to v5 migration, or @sanity/document-internationalization from v5 to v6. GROQ query updates, localized arrays, or patterns like `_key == "en"` and `_key == $language`.
4+
---
5+
6+
# Internationalized Array GROQ Migration
7+
8+
## Goal
9+
10+
Help users find GROQ queries that still read locale from `_key` and rewrite them safely for v5.
11+
12+
## When To Use
13+
14+
Use this skill when a user asks to:
15+
16+
- migrate `sanity-plugin-internationalized-array` from v4 to v5
17+
- migrate `@sanity/document-internationalization` from v5 to v6 alongside `sanity-plugin-internationalized-array` language field changes
18+
- find queries that still use `_key` for language lookup
19+
<!-- - update GROQ filters like `_key == "en"` or `_key == $language` -->
20+
21+
## Detection Workflow
22+
23+
Detection commands below use `grep`. If your environment differs, use your editor's global search with equivalent patterns.
24+
25+
1. Search for direct language comparisons on `_key`:
26+
27+
```bash
28+
grep -REn --exclude-dir=node_modules "_key[[:space:]]*==[[:space:]]*(\"[^\"]+\"|'[^']+'|\\$[A-Za-z_][A-Za-z0-9_]*)" .
29+
```
30+
31+
1. Search for any localized-array filters that mention `_key`:
32+
33+
```bash
34+
grep -REn --exclude-dir=node_modules "\[[^]]*_key[^]]*\]" .
35+
```
36+
37+
1. Prioritize matches that look like localized-value reads, for example:
38+
39+
- `field[_key == ...][0].value`
40+
- `select(...)` branches that compare `_key` to a language value
41+
42+
1. Check for uses of `groq` and verify if they use `_key` as the language, if it is using it, update them.
43+
44+
1. Explicitly check for template-interpolated language expressions and keep the same operand, for example:
45+
- `_key == "${language}"`
46+
- `_key == "${locale}"`
47+
48+
1. Review each match to avoid false positives where `_key` is used for unrelated array item identity.
49+
50+
## Rewrite Rules
51+
52+
Use the same language operand from the original query. The language operand can be a string literal (for example `"en"`), a variable (for example `$language`), or a template-interpolated expression (for example `"${language}"`).
53+
54+
- **Before data migration is executed (backwards compatible):**
55+
- `_key == <languageExpr>` -> `language == <languageExpr> || _key == <languageExpr>`
56+
- **After migration is complete:**
57+
- `language == <languageExpr> || _key == <languageExpr>` -> `language == <languageExpr>`
58+
59+
## Examples
60+
61+
Legacy:
62+
63+
```groq
64+
*[_type == "person"]{
65+
"greeting": greeting[_key == $language][0].value
66+
}
67+
```
68+
69+
Backwards compatible:
70+
71+
```groq
72+
*[_type == "person"]{
73+
"greeting": greeting[language == $language || _key == $language][0].value
74+
}
75+
```
76+
77+
Post-migration final form:
78+
79+
```groq
80+
*[_type == "person"]{
81+
"greeting": greeting[language == $language][0].value
82+
}
83+
```
84+
85+
## Response Template
86+
87+
When reporting findings to a user:
88+
89+
1. List each query location that still uses `_key` as language source.
90+
2. Show the exact replacement using the same language expression.
91+
3. Label each replacement as:
92+
- `backwards-compatible` (pre-migration), or
93+
- `final` (post-migration complete).
94+
4. Label each match category as `runtime`, `docs/example`, or `ambiguous`.
95+
5. Call out any ambiguous `_key` usage that needs manual review.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { migrateToLanguageField } from 'sanity-plugin-internationalized-array/migrations'
2+
3+
// Migrates translation.metadata documents from the old format where language
4+
// was stored in `_key` to the new format with a dedicated `language` field.
5+
// Required for @sanity/document-internationalization v6 compatibility.
6+
//
7+
// Steps:
8+
// 1. Backup: pnpm sanity dataset export <dataset>
9+
// 2. Dry run: pnpm sanity migration run i18n-doc-v6 --project=<PROJECT_ID> --dataset=<DATASET>
10+
// 3. Migrate: pnpm sanity migration run i18n-doc-v6 --project=<PROJECT_ID> --dataset=<DATASET> --no-dry-run
11+
// 4. After confirming data is correct, simplify GROQ queries:
12+
// Remove `|| _key == $lang` fallbacks from translations[] filters.
13+
14+
const DOCUMENT_TYPES: string[] = ['translation.metadata']
15+
16+
export default migrateToLanguageField(DOCUMENT_TYPES)

studio/package.json

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,49 @@
1616
"sanity"
1717
],
1818
"dependencies": {
19+
"@energyvision/shared": "workspace:*",
1920
"@equinor/eds-icons": "^0.17.0",
21+
"@portabletext/react": "^5.0.0",
2022
"@reach/auto-id": "^0.18.0",
21-
"@sindresorhus/slugify": "^3.0.0",
2223
"@sanity/asset-utils": "^2.3.0",
23-
"@sanity/dashboard": "^5.0.1",
24-
"@sanity/document-internationalization": "4.1.0",
25-
"@sanity/client": "^7.16.0",
24+
"@sanity/client": "^7.23.1",
2625
"@sanity/cross-dataset-duplicator": "^1.5.1",
27-
"@sanity/icons": "^3.7.4",
28-
"@sanity/ui": "^3.1.13",
29-
"@sanity/uuid": "^3.0.2",
26+
"@sanity/dashboard": "^5.0.1",
27+
"@sanity/document-internationalization": "6.2.19",
28+
"@sanity/icons": "^3.8.0",
29+
"@sanity/ui": "^3.3.5",
30+
"@sanity/uuid": "^3.0.3",
3031
"@sanity/vision": "5.12.0",
31-
"@portabletext/react": "^5.0.0",
32+
"@sindresorhus/slugify": "^3.0.0",
3233
"blob-util": "^2.0.2",
3334
"buffer": "^6.0.3",
34-
"date-fns": "^4.1.0",
35-
"hls.js": "^1.6.13",
35+
"date-fns": "^4.4.0",
36+
"hls.js": "^1.6.16",
3637
"mime": "^4.1.0",
37-
"papaparse": "^5.5.3",
38-
"react": "^19.2.4",
39-
"react-dom": "^19.2.4",
40-
"react-icons": "^5.5.0",
41-
"react-is": "^19.2.4",
42-
"recharts": "^3.3.0",
43-
"rxjs": "^7.8.0",
38+
"papaparse": "^5.5.4",
39+
"react": "^19.2.7",
40+
"react-dom": "^19.2.7",
41+
"react-icons": "^5.7.0",
42+
"react-is": "^19.2.7",
43+
"recharts": "^3.9.2",
44+
"rxjs": "^7.8.2",
4445
"sanity": "5.12.0",
4546
"sanity-plugin-documents-pane": "^3.0.2",
46-
"sanity-plugin-iframe-pane": "^5.0.6",
47-
"sanity-plugin-media": "^4.1.1",
47+
"sanity-plugin-iframe-pane": "^5.0.25",
48+
"sanity-plugin-media": "^4.3.6",
4849
"sanity-plugin-utils": "^1.8.0",
49-
"styled-components": "^6.3.11",
50+
"styled-components": "^6.4.3",
5051
"vite-plugin-svgr": "^4.5.0",
51-
"@energyvision/shared": "workspace:*"
52+
"sanity-plugin-internationalized-array": "^5.1.19"
5253
},
5354
"devDependencies": {
55+
"@repo/typescript-config": "workspace:*",
5456
"@sanity/eslint-config-studio": "^6.0.0",
55-
"@types/react": "^19.2.14",
57+
"@types/react": "^19.2.17",
5658
"@types/react-dom": "^19.2.3",
57-
"@types/styled-components": "^5.1.34",
58-
"nanoid": "^5.0.9",
59+
"@types/styled-components": "^5.1.36",
60+
"nanoid": "^5.1.16",
5961
"typescript": "^5.9.3",
60-
"vite-tsconfig-paths": "^5.1.4",
61-
"@repo/typescript-config": "workspace:*"
62+
"vite-tsconfig-paths": "^5.1.4"
6263
}
6364
}

0 commit comments

Comments
 (0)