Translate node summary labels in the canvas

The Generate/Delay/Condition/Publish node summaries rendered English prose and
raw enum values (account/accounts, single, hours, contains, scheduled · +N min).
Route them through i18n: pluralize the account count, and reuse the existing
unit/operator/mode/format labels in all three locales. Drop the redundant
?? defaults where the node is always created with the value (unit, operator,
mode) and tighten those prop types to required.
This commit is contained in:
Paulo Castellano 2026-06-13 17:10:38 -03:00
parent 90e9e4bee6
commit 9b3e9e8307
7 changed files with 34 additions and 17 deletions

View file

@ -279,6 +279,11 @@
'use_brand_voice_hint' => 'Apply your brand description and voice. Turn off for faithful curation of third-party sources (news, RSS).',
'use_brand_visuals' => 'Use brand visuals',
'use_brand_visuals_hint' => 'Steer AI images with your brand colors and identity. Turn off for neutral imagery driven only by the post topic.',
'account_summary' => ':count account · :format|:count accounts · :format',
'formats' => [
'single' => 'single',
'carousel' => 'carousel',
],
],
'delay' => [
'duration' => 'Duration',
@ -311,6 +316,7 @@
'draft' => 'Save as draft',
],
'scheduled_offset' => 'Offset from trigger (minutes)',
'offset_summary' => ':mode · +:offset min',
],
'webhook' => [
'url' => 'URL',

View file

@ -279,6 +279,11 @@
'use_brand_voice_hint' => 'Aplica la descripción y la voz de tu marca. Desactiva para curaduría fiel de fuentes de terceros (noticias, RSS).',
'use_brand_visuals' => 'Usar visual de marca',
'use_brand_visuals_hint' => 'Guía las imágenes de IA con los colores e identidad de tu marca. Desactiva para imágenes neutrales, guiadas solo por el tema del post.',
'account_summary' => ':count cuenta · :format|:count cuentas · :format',
'formats' => [
'single' => 'único',
'carousel' => 'carrusel',
],
],
'delay' => [
'duration' => 'Duración',
@ -311,6 +316,7 @@
'draft' => 'Guardar como borrador',
],
'scheduled_offset' => 'Diferencia desde el disparador (minutos)',
'offset_summary' => ':mode · +:offset min',
],
'webhook' => [
'url' => 'URL',

View file

@ -279,6 +279,11 @@
'use_brand_voice_hint' => 'Aplica a descrição e a voz da sua marca. Desligue para curadoria fiel de fontes de terceiros (notícias, RSS).',
'use_brand_visuals' => 'Usar visual da marca',
'use_brand_visuals_hint' => 'Guia as imagens de IA com as cores e identidade da sua marca. Desligue para imagens neutras, guiadas só pelo tema do post.',
'account_summary' => ':count conta · :format|:count contas · :format',
'formats' => [
'single' => 'único',
'carousel' => 'carrossel',
],
],
'delay' => [
'duration' => 'Duração',
@ -311,6 +316,7 @@
'draft' => 'Salvar como rascunho',
],
'scheduled_offset' => 'Atraso a partir do trigger (minutos)',
'offset_summary' => ':mode · +:offset min',
],
'webhook' => [
'url' => 'URL',

View file

@ -1,15 +1,15 @@
<script setup lang="ts">
import { IconGitBranch } from '@tabler/icons-vue';
import { Handle, Position } from '@vue-flow/core';
import { trans } from 'laravel-vue-i18n';
import { computed } from 'vue';
import { ConditionHandle } from '@/types/automation/condition-handle';
import { ConditionOperator } from '@/types/automation/condition-operator';
const props = defineProps<{
data: {
field?: string;
operator?: string;
operator: string;
value?: string;
};
selected?: boolean;
@ -17,7 +17,7 @@ const props = defineProps<{
const summary = computed(() => {
const field = props.data.field || '…';
const operator = props.data.operator || ConditionOperator.Contains;
const operator = trans(`automations.config.condition.operators.${props.data.operator}`);
const value = props.data.value || '…';
return `${field} ${operator} ${value}`;
});

View file

@ -1,22 +1,20 @@
<script setup lang="ts">
import { IconClock } from '@tabler/icons-vue';
import { Handle, Position } from '@vue-flow/core';
import { trans } from 'laravel-vue-i18n';
import { computed } from 'vue';
import { DelayUnit } from '@/types/automation/delay-unit';
const props = defineProps<{
data: {
duration?: number;
unit?: string;
duration: number;
unit: string;
};
selected?: boolean;
}>();
const summary = computed(() => {
const duration = props.data.duration ?? 1;
const unit = props.data.unit ?? DelayUnit.Hours;
return `${duration} ${unit}`;
const unit = trans(`automations.config.delay.units.${props.data.unit}`);
return `${props.data.duration} ${unit}`;
});
</script>

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
import { IconSparkles } from '@tabler/icons-vue';
import { Handle, Position } from '@vue-flow/core';
import { trans, transChoice } from 'laravel-vue-i18n';
import { computed } from 'vue';
const props = defineProps<{
@ -14,9 +15,8 @@ const props = defineProps<{
const summary = computed(() => {
const count = props.data.accounts?.length ?? props.data.social_account_ids?.length ?? 0;
const format = props.data.format ?? 'single';
const accountLabel = count === 1 ? 'account' : 'accounts';
return `${count} ${accountLabel} · ${format}`;
const format = trans(`automations.config.generate.formats.${props.data.format ?? 'single'}`);
return transChoice('automations.config.generate.account_summary', count, { count: String(count), format });
});
</script>

View file

@ -1,22 +1,23 @@
<script setup lang="ts">
import { IconSend } from '@tabler/icons-vue';
import { Handle, Position } from '@vue-flow/core';
import { trans } from 'laravel-vue-i18n';
import { computed } from 'vue';
import { PublishMode } from '@/types/automation/publish-mode';
const props = defineProps<{
data: {
mode?: string;
mode: string;
scheduled_offset?: number;
};
selected?: boolean;
}>();
const summary = computed(() => {
const mode = props.data.mode ?? PublishMode.Now;
if (mode === PublishMode.Scheduled && props.data.scheduled_offset != null) {
return `scheduled · +${props.data.scheduled_offset} min`;
const mode = trans(`automations.config.publish.modes.${props.data.mode}`);
if (props.data.mode === PublishMode.Scheduled && props.data.scheduled_offset != null) {
return trans('automations.config.publish.offset_summary', { mode, offset: String(props.data.scheduled_offset) });
}
return mode;
});