-
Notifications
You must be signed in to change notification settings - Fork 54
Localization support #18
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we’re there yet with the frontend? I wonder if we should add some sort of locale selector as well. Doesn't need to be fancy, a <select><option>
in the main nav would suffice.
I also added dedicated localized example content to this branch.
import {generateLocaleType, getLocaleTypeName, supportedLanguages} from './localize' | ||
|
||
const localizedTypes = ['string', 'text', 'slug', 'portableText', 'simplePortableText'] | ||
|
||
const localizeField = (field, traceModified) => { | ||
if (!localizedTypes.includes(field.type)) return field | ||
|
||
const localizedField = { | ||
...field, | ||
type: getLocaleTypeName(field.type) | ||
} | ||
|
||
if (traceModified) { | ||
traceModified.push(localizedField) | ||
} | ||
|
||
return localizedField | ||
} | ||
|
||
const inModified = name => field => field.name === name | ||
|
||
export const localizeSupportedTypes = typeDef => { | ||
const fieldsModified = [] | ||
const localizedDef = {...typeDef} | ||
|
||
// Localize fields | ||
if (localizedDef.fields) { | ||
localizedDef.fields = localizedDef.fields.map(field => { | ||
if (field.type === 'array') { | ||
return { | ||
...field, | ||
of: field.of.map(localizeField) | ||
} | ||
} | ||
|
||
return localizeField(field, fieldsModified) | ||
}) | ||
} | ||
|
||
// Localize any previews to first language | ||
if (localizedDef.preview && localizedDef.preview.select && fieldsModified.length > 0) { | ||
localizedDef.preview = { | ||
...localizedDef.preview, | ||
select: Object.keys(localizedDef.preview.select).reduce((select, key) => { | ||
// Find any fields that have been modified and change name | ||
let baseKey | ||
const selectorToChange = localizedDef.preview.select[key] | ||
if (selectorToChange.includes('.')) { | ||
baseKey = selectorToChange.substring(0, selectorToChange.indexOf('.')) | ||
} else { | ||
baseKey = selectorToChange | ||
} | ||
|
||
if (!fieldsModified.find(inModified(baseKey))) { | ||
select[key] = localizedDef.preview.select[key] | ||
} else { | ||
let prefix = selectorToChange | ||
let suffix = '' | ||
if (selectorToChange.includes('.')) { | ||
prefix = selectorToChange.substring(0, selectorToChange.indexOf('.')) | ||
suffix = selectorToChange.substring(selectorToChange.indexOf('.')) | ||
} | ||
select[key] = `${prefix}.${supportedLanguages[0].id}${suffix}` | ||
} | ||
return select | ||
}, {}) | ||
} | ||
} | ||
|
||
return localizedDef | ||
} | ||
|
||
export default localizedTypes.map(generateLocaleType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty clever, but I have a hard time deciding if it’s a bit too clever?
-
If we are going with it, we should add comments to make it easier to parse what’s happening (it’s not that hard to guess from the code, but we need to keep in mind that we have many who are beginners).
-
Although it’s nifty that you just add this to localize fields without having to actually change types in the other schema-fields, it also makes it a bit ”magic”. I didn't get what was happening at first. It’s also often the case that you don't want to localize all string fields. So we need to make it more obvious in the
schema
field, how you can add non-localized fields as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments to hopefully make it clearer what this function is doing
template/studio/schemas/schema.js
Outdated
siteConfig, | ||
textSection, | ||
] | ||
.map(localizeSupportedTypes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make it easy™ to opt a field type out if the localization?
template/web/next.config.js
Outdated
|
||
// Generate a page for each language | ||
Object.keys(slug).forEach(lang => { | ||
if (lang === '_type') return | ||
|
||
const path = slug[lang].current === '/' ? `/${lang}` : `/${lang}/${slug[lang].current}` | ||
obj[path] = { | ||
query: { | ||
slug: slug[lang].current, | ||
lang: lang | ||
}, | ||
includeInSitemap, | ||
disallowRobot, | ||
_createdAt, | ||
_updatedAt, | ||
page: '/LandingPage' | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get this to work, e.g. http://localhost:3000/en/about
Btw, you can test this branch here: https://www.sanity.io/create?template=sanity-io%2Fsanity-template-nextjs-landing-pages&ref=localization-support |
Co-authored-by: Knut Melvær <[email protected]>
…mplate-nextjs-landing-pages into localization-support
also updated data
Adds support for localization in both the studio and web app.
Default supported languages are: English, Spanish, Norwegian