Discussion on dynamically loading languages in Sanity schemas
34 replies
Last updated: Apr 27, 2020
H
Hi there ☆I would like to change this `localeString.js`:
to make it point out instead of
In VISION I have this query:
giving this result:
In the Docs the query example is:
So I modify
I know that I miss the keys and everything with fields but I really don't know how I should do...
const supportedLanguages = [ { name: 'fr', title: 'Français', isDefault: true, // important }, { name: 'ja', title: '日本語', }, { name: 'en', title: 'English', }, ] export default { name: 'localeString', title: 'LocaleString', type: 'object', fieldsets: [ { title: 'Translations', name: 'translations', }, ], fields: supportedLanguages.map(langx => ( { name: langx.name, title: langx.title, type: 'text', fieldset: langx.isDefault ? null : 'translations', } )), }
const supportedLanguagesthe data that are in a document called
lang.js.this is `lang.js`:
export default { name: 'lang', title: 'Langue', type: 'document', fields: [ { name: 'name', title: 'Name', type: 'string', }, { name: 'title', title: 'Title', type: 'string', }, { name: 'isDefault', title: 'IsDefault', type: 'boolean', }, ], }
*[_type == 'lang' ]{name, title, isDefault}
"result":[3 items 0:{3 items "isDefault":false "name":"ja" "title":"日本語" } 1:{3 items "isDefault":true "name":"fr" "title":"Français" } 2:{3 items "isDefault":false "name":"en" "title":"English"
const query = '*[_type == "bike" && seats >= $minSeats] {name, seats}' const params = {minSeats: 2} client.fetch(query, params).then(bikes => { console.log('Bikes with more than one seat:') bikes.forEach(bike => { console.log(`${bike.name} (${bike.seats} seats)`) }) })
localeString.jsdifferent ways but I am not able so far to find how to insert that into
fieldsso it fits correctly in:
import client from 'part:@sanity/base/client' import groq from "groq" const query = groq `*[_type == 'lang']{ name, title, isDefault }` const params = {} export default { name: 'localeString', title: 'LocaleString', type: 'object', fieldsets: [ { title: 'Translations', name: 'translations', }, ], fields: [ { client.fetch(query, params).then(langs => { langs.forEach(lang => ({ name: lang.name, title: lang.title, type: 'text', fieldset: lang.isDefault ? null : 'translations', })) }) } ] }
Apr 27, 2020, 3:29 PM
M
Hi User, you’re pretty close already I believe 🙂 What’s the error you’re getting at the moment? Could you add
console.log(lang)to the
forEachloop to see if that output matches what you expect?
Apr 27, 2020, 4:02 PM
H
yes of course but I don't know how to look at console.log(lang).
Apr 27, 2020, 4:03 PM
M
What browser are you using?
Apr 27, 2020, 4:04 PM
H
firefox, chrome as you like. Right now firefox.
Apr 27, 2020, 4:04 PM
H
But before console.log() I have some errors displayed.
Apr 27, 2020, 4:05 PM
M
In Chrome, go to View > Developer > JavaScript console, or if you’re on a Mac, you can use CMD+ALT+J (not sure what the Windows shortcut is).
Apr 27, 2020, 4:08 PM
M
And feel free to paste those errors here 😉
Apr 27, 2020, 4:09 PM
H
Yes but where would you like the console.log(lang) to be placed?
Apr 27, 2020, 4:09 PM
H
From localeString, I query lang.js to get the references from lang.js for the languages
Apr 27, 2020, 4:10 PM
H
User, could you place the console.log(lang) in there please:
export default { name: 'localeString', title: 'LocaleString', type: 'object', fieldsets: [ { title: 'Translations', name: 'translations', }, ], fields: [ { client.fetch(query, params).then(langs => { langs.forEach(lang => ({ name: lang.name, title: lang.title, type: 'string', fieldset: lang.isDefault ? null : 'translations', })) }) } ] }
Apr 27, 2020, 4:12 PM
H
Please forgive me of being so clumsy.I did this:
and I got that:
Nothing fits.
import client from 'part:@sanity/base/client' import groq from "groq" const query = groq `*[_type == 'lang']{ name, title, isDefault }` const params = {} export default { name: 'localeString', title: 'LocaleString', type: 'object', fieldsets: [ { title: 'Translations', name: 'translations', }, ], fields: [ { console.log(lang), client.fetch(query, params).then(langs => { langs.forEach(lang => ({ name: lang.name, title: lang.title, type: 'string', fieldset: lang.isDefault ? null : 'translations', })) }) } ] }
ERROR in ./schemas/localeString.js Module build failed: SyntaxError: C:\xampp\htdocs\<http://francois-vidit-2.com|francois-vidit-2.com>\studio\schemas\localeString.js: Unexpected token, expected "," (46:13) 44 | fields: [ 45 | { > 46 | console.log(lang), | ^ 47 | client.fetch(query, params).then(langs => { 48 | langs.forEach(lang => ({ 49 | name: lang.name,
Apr 27, 2020, 4:20 PM
M
If I understand correctly, you want to load your languages dynamically from your
Have you tried something like this?
langdocument type instead of using
const supportedLanguages.
Have you tried something like this?
import client from 'part:@sanity/base/client' import groq from "groq" const query = groq `*[_type == 'lang']{ name, title, isDefault }` const params = {} export default { name: 'localeString', title: 'LocaleString', type: 'object', fieldsets: [ { title: 'Translations', name: 'translations', }, ], fields: client.fetch(query, params).then(langs => { langs.map(lang => ({ name: lang.name, title: lang.title, type: 'string', fieldset: lang.isDefault ? null : 'translations', })) }) }
Apr 27, 2020, 4:28 PM
H
yes completelythis is the error I get doing so:
The "fields" property must be an array of fields. Instead saw "object
Apr 27, 2020, 4:30 PM
H
you understand correctly.
Apr 27, 2020, 4:33 PM
M
Hi again. Actually, it’s not as straightforward as it seems. There’s nothing wrong with your approach per se, and it should actually return an array of language-specific fields, but it might be that Promises are not supported in type definitions. I’m checking this internally.
Apr 27, 2020, 5:39 PM
H
Thank you User.
Apr 27, 2020, 5:40 PM
H
Do you need more information?
Apr 27, 2020, 5:40 PM
H
I focusing on that point because my idea using Sanity is to avoid redondance of data: I would like all my localeSomething to point a single source of truth.
Apr 27, 2020, 5:42 PM
H
I feel better to realise that my question is been object of attention: I am a little bit more confident now.
Apr 27, 2020, 5:44 PM
H
Also I would like to link other field later on the same way.
Apr 27, 2020, 5:45 PM
H
We went on using the fetch method from that example.But on the Youtube video with User on initialValue, he is using async await.
I don't really understand the difference, I tried also that side.... miserabily!
I don't really understand the difference, I tried also that side.... miserabily!
Apr 27, 2020, 5:48 PM
M
It’s a perfectly valid approach - just not in type definitions perhaps if they don’t support Promises 🙂 I’ll let you know if there’s a workaround.
Apr 27, 2020, 6:02 PM
H
Yes 🌻 please!!!There must be one
👻
👻
Apr 27, 2020, 6:05 PM
P
I’m afraid I have to confirm that async schemas are currently not supported, so you’ll have to go the traditional route with this for now. Sorry about the time you lost researching this issue but hopefully you still learned a few things to use elsewhere? 🙂
Apr 27, 2020, 6:35 PM
F
what do you mean by the traditional way?
Apr 27, 2020, 6:36 PM
F
Ah by
const supportedLanguages?
Apr 27, 2020, 6:37 PM
F
I have already found a solution by having a central const
supportedLanguagesin a data folder and
importit, but it is not really SANITY!!
Apr 27, 2020, 6:38 PM
F
I am glad to have an answer at least, it is now clear.
Apr 27, 2020, 6:39 PM
P
Indeed, that way 🙂 I’m glad you have a solution at least (and it’s a single source) 👍 Hopefully future versions will give you a way to make the languages load dynamically.
Apr 27, 2020, 6:40 PM
F
you mean that the team at Sanity consider this as sufficiently important to consider working on it?
Apr 27, 2020, 6:41 PM
F
In terms of principles, It cannot be denied... It would push the concept of Sanity to a accomplishment... I am surprised that you seem to be surprised!!
Apr 27, 2020, 6:43 PM
F
I would love to be able to do that in a near future... 🌜
Apr 27, 2020, 6:45 PM
F
If I may ask another question:in the Docs there is a piece of code:
Am I getting it right if I say that this function has to be placed not in Sanity but where the localized data arrives to be rendered (whatever the javascript system) (for instance, for me, Gatsby)?
function localize(value, languages) { if (Array.isArray(value)) { return value.map(v => localize(v, languages)) } else if (typeof value == 'object') { if (/^locale[A-Z]/.test(value._type)) { const language = languages.find(lang => value[lang]) return value[language] } return Object.keys(value).reduce((result, key) => { result[key] = localize(value[key], languages) return result }, {}) } return value }
Apr 27, 2020, 6:49 PM
F
It is not precise where this should be, what role it plays and it is not obvious to me...
Apr 27, 2020, 6:50 PM
Sanity– build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.