Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
277 lines
16 KiB
Plaintext
277 lines
16 KiB
Plaintext
import { fieldAffectsData, fieldShouldBeLocalized, tabHasName } from '../fields/config/types.js';
|
|
/**
|
|
* Merges data from dataWithLocales onto docWithLocales for specified locales.
|
|
* For localized fields, merges only the specified locales while preserving others.
|
|
* For non-localized fields, keeps existing values from docWithLocales unchanged.
|
|
* Returns a new object without mutating the original.
|
|
*/ export function mergeLocalizedData({ configBlockReferences, dataWithLocales, docWithLocales, fields, parentIsLocalized = false, selectedLocales }) {
|
|
if (!docWithLocales || typeof docWithLocales !== 'object') {
|
|
return dataWithLocales || docWithLocales;
|
|
}
|
|
const result = {
|
|
...docWithLocales
|
|
};
|
|
for (const field of fields){
|
|
if (fieldAffectsData(field)) {
|
|
// If the parent is localized, all children are inherently "localized"
|
|
if (parentIsLocalized && dataWithLocales[field.name]) {
|
|
result[field.name] = dataWithLocales[field.name];
|
|
continue;
|
|
}
|
|
const fieldIsLocalized = fieldShouldBeLocalized({
|
|
field,
|
|
parentIsLocalized
|
|
});
|
|
switch(field.type){
|
|
case 'array':
|
|
{
|
|
if (field.name in dataWithLocales) {
|
|
const newValue = dataWithLocales[field.name];
|
|
const existingValue = docWithLocales[field.name];
|
|
if (fieldIsLocalized) {
|
|
// If localized, handle locale keys
|
|
if (newValue && typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
const updatedArray = {
|
|
...existingValue || {}
|
|
};
|
|
for (const locale of selectedLocales){
|
|
if (locale in newValue) {
|
|
updatedArray[locale] = newValue[locale];
|
|
}
|
|
}
|
|
result[field.name] = updatedArray;
|
|
} else {
|
|
// Preserve existing value if new value is not a valid object
|
|
result[field.name] = existingValue;
|
|
}
|
|
} else if (Array.isArray(newValue)) {
|
|
// Non-localized array - still process children for any localized fields
|
|
result[field.name] = newValue.map((newItem, index)=>{
|
|
const existingItem = existingValue?.[index] || {};
|
|
return mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales: newItem,
|
|
docWithLocales: existingItem,
|
|
fields: field.fields,
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'blocks':
|
|
{
|
|
if (field.name in dataWithLocales) {
|
|
const newValue = dataWithLocales[field.name];
|
|
const existingValue = docWithLocales[field.name];
|
|
if (fieldIsLocalized) {
|
|
// If localized, handle locale keys
|
|
if (newValue && typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
const updatedData = {
|
|
...existingValue || {}
|
|
};
|
|
for (const locale of selectedLocales){
|
|
if (locale in newValue) {
|
|
updatedData[locale] = newValue[locale];
|
|
}
|
|
}
|
|
result[field.name] = updatedData;
|
|
} else {
|
|
// Preserve existing value if new value is not a valid object
|
|
result[field.name] = existingValue;
|
|
}
|
|
} else if (Array.isArray(newValue)) {
|
|
// Non-localized blocks - still process children for any localized fields
|
|
result[field.name] = newValue.map((newBlockData, index)=>{
|
|
let block;
|
|
if (configBlockReferences && field.blockReferences) {
|
|
for (const blockOrReference of field.blockReferences){
|
|
if (typeof blockOrReference === 'string') {
|
|
block = configBlockReferences.find((b)=>b.slug === newBlockData.blockType);
|
|
} else {
|
|
block = blockOrReference;
|
|
}
|
|
}
|
|
} else if (field.blocks) {
|
|
block = field.blocks.find((b)=>b.slug === newBlockData.blockType);
|
|
}
|
|
if (block) {
|
|
const blockData = Array.isArray(existingValue) && existingValue[index] ? existingValue[index] : {};
|
|
return mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales: newBlockData,
|
|
docWithLocales: blockData,
|
|
fields: block?.fields || [],
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
}
|
|
return newBlockData;
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'group':
|
|
{
|
|
if (fieldAffectsData(field) && field.name) {
|
|
// Named groups create a nested data structure
|
|
if (field.name in dataWithLocales) {
|
|
const newValue = dataWithLocales[field.name];
|
|
const existingValue = docWithLocales[field.name];
|
|
if (fieldIsLocalized) {
|
|
if (newValue && typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
const groupData = {
|
|
...existingValue || {}
|
|
};
|
|
for (const locale of selectedLocales){
|
|
if (locale in newValue && typeof newValue[locale] === 'object') {
|
|
groupData[locale] = newValue[locale];
|
|
}
|
|
}
|
|
result[field.name] = groupData;
|
|
} else {
|
|
// Preserve existing value if new value is not a valid object
|
|
result[field.name] = existingValue;
|
|
}
|
|
} else if (typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
// Non-localized group - still process children for any localized fields
|
|
result[field.name] = mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales: newValue,
|
|
docWithLocales: existingValue || {},
|
|
fields: field.fields,
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
// Unnamed groups pass through the same data level
|
|
const merged = mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales,
|
|
docWithLocales: result,
|
|
fields: field.fields,
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
Object.assign(result, merged);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
// For all other data-affecting fields (text, number, select, etc.)
|
|
if (fieldIsLocalized) {
|
|
if (field.name in dataWithLocales) {
|
|
const newValue = dataWithLocales[field.name];
|
|
const existingValue = docWithLocales[field.name] || {};
|
|
// If localized, handle locale keys
|
|
if (newValue && typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
const merged = {
|
|
...existingValue
|
|
};
|
|
for (const locale of selectedLocales){
|
|
if (locale in newValue) {
|
|
merged[locale] = newValue[locale];
|
|
}
|
|
}
|
|
result[field.name] = merged;
|
|
} else if (parentIsLocalized) {
|
|
// Child of localized parent - replace with new value
|
|
result[field.name] = newValue;
|
|
} else {
|
|
// Preserve existing value if new value is not a valid object
|
|
result[field.name] = existingValue;
|
|
}
|
|
}
|
|
} else if (parentIsLocalized) {
|
|
result[field.name] = dataWithLocales[field.name];
|
|
} else {
|
|
result[field.name] = field.name in dataWithLocales ? dataWithLocales[field.name] : docWithLocales[field.name];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// Layout-only fields that don't affect data structure
|
|
switch(field.type){
|
|
case 'collapsible':
|
|
case 'row':
|
|
{
|
|
// These pass through the same data level
|
|
const merged = mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales,
|
|
docWithLocales: result,
|
|
fields: field.fields,
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
Object.assign(result, merged);
|
|
break;
|
|
}
|
|
case 'tabs':
|
|
{
|
|
for (const tab of field.tabs){
|
|
if (tabHasName(tab)) {
|
|
// Named tabs create a nested data structure and can be localized
|
|
const tabIsLocalized = fieldShouldBeLocalized({
|
|
field: tab,
|
|
parentIsLocalized
|
|
});
|
|
if (tab.name in dataWithLocales) {
|
|
const newValue = dataWithLocales[tab.name];
|
|
const existingValue = docWithLocales[tab.name];
|
|
if (tabIsLocalized) {
|
|
if (newValue && typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
const merged = {
|
|
...existingValue || {}
|
|
};
|
|
for (const locale of selectedLocales){
|
|
if (locale in newValue && typeof newValue[locale] === 'object') {
|
|
merged[locale] = newValue[locale];
|
|
}
|
|
}
|
|
result[tab.name] = merged;
|
|
} else {
|
|
// Preserve existing value if new value is not a valid object
|
|
result[tab.name] = existingValue;
|
|
}
|
|
} else if (typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
// Non-localized tab - still process children for any localized fields
|
|
result[tab.name] = mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales: newValue,
|
|
docWithLocales: existingValue || {},
|
|
fields: tab.fields,
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
// Unnamed tabs pass through the same data level
|
|
const merged = mergeLocalizedData({
|
|
configBlockReferences,
|
|
dataWithLocales,
|
|
docWithLocales: result,
|
|
fields: tab.fields,
|
|
parentIsLocalized,
|
|
selectedLocales
|
|
});
|
|
Object.assign(result, merged);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//# sourceMappingURL=mergeLocalizedData.js.map |