Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/utils/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@builder.io/utils",
"version": "1.1.27",
"version": "1.1.29",
"description": "Utils for working with Builder.io content",
"main": "./dist/index.js",
"scripts": {
Expand Down
58 changes: 33 additions & 25 deletions packages/utils/src/__snapshots__/translation-helpers.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,31 @@ Object {
}
`;

exports[`getTranslateableFields from carousel content and custom component with subFields to match snapshot 1`] = `
Object {
"blocks.builder-06d3f6da74fb4054ad311afc1dda3675#text": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>I am slide second</p>",
},
"blocks.builder-0a10ae48b6314221bbb7d06d068d623d#text": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>I am slide 1</p>",
},
"blocks.builder-23e0618256ab40799ecf6504bc57fa1c#listItems.0.field1": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>text 1 value</p>",
},
"blocks.builder-23e0618256ab40799ecf6504bc57fa1c#listItems.1.field1": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>text 1.1 value</p>",
},
"blocks.builder-23e0618256ab40799ecf6504bc57fa1c#title.text": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>custom component subField input</p>",
},
}
`;

exports[`getTranslateableFields from content to match snapshot 1`] = `
Object {
"blocks.block-id#text": Object {
Expand Down Expand Up @@ -360,6 +385,14 @@ Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "en-us headings!",
},
"blocks.button-localized-text-id#text": Object {
"instructions": "Button with pre-localized text",
"value": "Click Me!",
},
"blocks.button-plain-text-id#text": Object {
"instructions": "Button with plain text",
"value": "Cute Baby",
},
"metadata.seo": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": Object {
Expand All @@ -386,28 +419,3 @@ Object {
},
}
`;

exports[`getTranslateableFields from carousel content and custom component with subFields to match snapshot 1`] = `
Object {
"blocks.builder-06d3f6da74fb4054ad311afc1dda3675#text": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>I am slide second</p>",
},
"blocks.builder-0a10ae48b6314221bbb7d06d068d623d#text": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>I am slide 1</p>",
},
"blocks.builder-23e0618256ab40799ecf6504bc57fa1c#listItems.0.field1": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>text 1 value</p>",
},
"blocks.builder-23e0618256ab40799ecf6504bc57fa1c#listItems.1.field1": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>text 1.1 value</p>",
},
"blocks.builder-23e0618256ab40799ecf6504bc57fa1c#title.text": Object {
"instructions": "Visit https://builder.io/fiddle/... for more details",
"value": "<p>custom component subField input</p>",
},
}
`;
54 changes: 46 additions & 8 deletions packages/utils/src/translation-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,27 @@ export function getTranslateableFields(

// blocks
if (blocks) {
// Track how many levels deep we are inside excluded blocks
let excludedDepth = 0;

traverse(blocks).forEach(function (el) {
if (this.key && el && el.meta?.localizedTextInputs) {
// Check if this element starts an exclusion zone
const startsExclusion = el && el.meta?.excludeFromTranslation;
if (startsExclusion) {
excludedDepth++;
}

// After processing children, decrement the counter if this element started an exclusion
this.after(function () {
if (startsExclusion) {
excludedDepth--;
}
});

// Skip translation if we're inside an excluded block (excludedDepth > 0)
const isExcluded = excludedDepth > 0;

if (this.key && el && el.meta?.localizedTextInputs && !isExcluded) {
const localizedTextInputs = el.meta.localizedTextInputs as string[];
if (localizedTextInputs && Array.isArray(localizedTextInputs)) {
localizedTextInputs
Expand All @@ -238,7 +257,7 @@ export function getTranslateableFields(
});
}
}
if (el && el.id && el.component?.name === 'Text' && !el.meta?.excludeFromTranslation) {
if (el && el.id && el.component?.name === 'Text' && !isExcluded) {
const componentText = el.component.options.text;
results[`blocks.${el.id}#text`] = {
value:
Expand All @@ -249,7 +268,7 @@ export function getTranslateableFields(
};
}

if (el && el.id && el.component?.name === 'Core:Button' && !el.meta?.excludeFromTranslation) {
if (el && el.id && el.component?.name === 'Core:Button' && !isExcluded) {
const componentText = el.component.options?.text;
if (componentText) {
const textValue = typeof componentText === 'string'
Expand All @@ -264,7 +283,7 @@ export function getTranslateableFields(
}
}

if (el && el.id && el.component?.name === 'Symbol') {
if (el && el.id && el.component?.name === 'Symbol'&& !isExcluded) {
const symbolInputs = Object.entries(el.component?.options?.symbol?.data) || [];
if (symbolInputs.length) {
const basePath = `blocks.${el.id}.symbolInput`;
Expand Down Expand Up @@ -316,8 +335,27 @@ export function applyTranslation(
}

if (blocks) {
// Track how many levels deep we are inside excluded blocks
let excludedDepth = 0;

traverse(blocks).forEach(function (el) {
if (el && el.id && el.component?.name === 'Symbol') {
// Check if this element starts an exclusion zone
const startsExclusion = el && el.meta?.excludeFromTranslation;
if (startsExclusion) {
excludedDepth++;
}

// After processing children, decrement the counter if this element started an exclusion
this.after(function () {
if (startsExclusion) {
excludedDepth--;
}
});

// Skip translation if we're inside an excluded block (excludedDepth > 0)
const isExcluded = excludedDepth > 0;

if (el && el.id && el.component?.name === 'Symbol' && !isExcluded) {
const symbolInputs = Object.entries(el.component?.options?.symbol?.data) || [];
if (symbolInputs.length) {
const transformedMeta = {};
Expand Down Expand Up @@ -368,7 +406,7 @@ export function applyTranslation(
el &&
el.id &&
el.component?.name === 'Text' &&
!el.meta?.excludeFromTranslation &&
!isExcluded &&
translation[`blocks.${el.id}#text`]
) {
const localizedValues =
Expand Down Expand Up @@ -405,7 +443,7 @@ export function applyTranslation(
el &&
el.id &&
el.component?.name === 'Core:Button' &&
!el.meta?.excludeFromTranslation &&
!isExcluded &&
translation[`blocks.${el.id}#text`]
) {
const localizedValues =
Expand Down Expand Up @@ -440,7 +478,7 @@ export function applyTranslation(
}

// custom components
if (el && el.id && el.meta?.localizedTextInputs) {
if (el && el.id && el.meta?.localizedTextInputs && !isExcluded) {
// there's a localized input
const keys = el.meta?.localizedTextInputs as string[];
let options = el.component.options;
Expand Down
18 changes: 9 additions & 9 deletions plugins/smartling/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions plugins/smartling/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@builder.io/plugin-smartling",
"version": "0.0.23-11",
"version": "0.0.23-13",
"description": "",
"keywords": [],
"main": "dist/plugin.system.js",
Expand Down Expand Up @@ -125,7 +125,7 @@
"typescript": "^3.0.3"
},
"dependencies": {
"@builder.io/utils": "1.1.26",
"@builder.io/utils": "1.1.29",
"fast-json-stable-stringify": "^2.1.0",
"lodash": "^4.17.21",
"object-hash": "^3.0.0",
Expand Down
84 changes: 82 additions & 2 deletions plugins/smartling/src/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ Builder.register('plugin', {
advanced: false,
requiredPermissions: ['admin'],
},
{
name: 'enableVisualContextCapture',
friendlyName: 'Enable Visual Context Capture',
type: 'boolean',
defaultValue: false,
helperText: 'Enable automatic visual context capture for translations',
requiredPermissions: ['admin'],
},
],
onSave: async actions => {
const pluginPrivateKey = await appState.globalState.getPluginPrivateKey(pkg.name);
Expand Down Expand Up @@ -460,7 +468,7 @@ const initializeSmartlingPlugin = async () => {
}
const element = selectedElements[0];
const isExcluded = element.meta?.get(transcludedMetaKey);
return element.component?.name === 'Text' && !isExcluded;
return !isExcluded;
},
onClick(elements) {
elements.forEach(el => el.meta.set('excludeFromTranslation', true));
Expand All @@ -476,13 +484,85 @@ const initializeSmartlingPlugin = async () => {
}
const element = selectedElements[0];
const isExcluded = element.meta?.get(transcludedMetaKey);
return element.component?.name === 'Text' && isExcluded;
return isExcluded;
},
onClick(elements) {
elements.forEach(el => el.meta.set('excludeFromTranslation', false));
},
});


registerContextMenuAction({
label: 'Add String Instructions',
showIf(selectedElements) {
if (selectedElements.length !== 1) {
// todo maybe apply for multiple
return false;
}
const element = selectedElements[0];
return element.meta?.get('instructions') === undefined;
},
async onClick(elements) {
if (elements.length !== 1) {
// todo maybe apply for multiple
return false;
}
const instructions = await appState.dialogs.prompt({
placeholderText: 'Enter string instructions for translation',
});
if (instructions) {
elements[0].meta.set('instructions', instructions);
appState.snackBar.show('String instructions added to content');
}
},
});

registerContextMenuAction({
label: 'Edit String Instructions',
showIf(selectedElements) {
if (selectedElements.length !== 1) {
// todo maybe apply for multiple
return false;
}
const element = selectedElements[0];
return element.meta?.get('instructions') !== undefined;
},
async onClick(elements) {
if (elements.length !== 1) {
// todo maybe apply for multiple
return false;
}
const element = elements[0];
const instructions = element.meta?.get('instructions');
if (instructions !== undefined) {
const newInstructions = await appState.dialogs.prompt({
placeholderText: 'Enter new string instructions for translation',
defaultValue: instructions,
});
if (newInstructions) {
element.meta.set('instructions', newInstructions);
appState.snackBar.show('String instructions updated');
}
}
},
});

registerContextMenuAction({
label: 'Delete String Instructions',
showIf(selectedElements) {
if (selectedElements.length !== 1) {
// todo maybe apply for multiple
return false;
}
const element = selectedElements[0];
return element.meta?.get('instructions') !== undefined;
},
onClick(elements) {
elements[0].meta.delete('instructions');
appState.snackBar.show('String instructions deleted');
},
});

registerContentAction({
label: 'Add to translation job',
showIf(content, model) {
Expand Down
Loading