refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
< ? php
return [
'title' => 'Posts' ,
2026-03-31 00:18:07 +00:00
'search' => 'Buscar posts...' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'all_posts' => 'Todos los posts' ,
'new_post' => 'Nuevo post' ,
'no_posts' => 'No se encontraron posts' ,
2026-05-02 15:22:42 +00:00
'no_search_results' => 'Ningún post coincide con tu búsqueda' ,
'try_different_search' => 'Prueba otra palabra clave o limpia la búsqueda.' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'start_creating' => 'Empieza creando tu primer post.' ,
feat(posts): multi-select label filter on the posts list
Adds a combobox-style filter to the posts index toolbar so users can
narrow All / Scheduled / Posted / Drafts views by one or more labels.
- `PostController::index` accepts `?labels[]=<id>` and applies
`whereHas('labels', whereIn(...))` (OR semantics across selected labels).
Workspace labels are exposed to the page (sorted by name) and the
selected set comes back under `filters.labels`.
- New `LabelFilter.vue` component reuses the existing Popover + Command
pattern (matching `FontPicker` in the Brand settings page). Trigger
renders the selected `LabelBadge`s inline (mirroring how each post row
already displays its labels): 1-3 shown directly, 4+ shown as the
first three plus a "+N" overflow indicator. Clear button has a
tooltip and `cursor-pointer`, and stops `click`/`pointerdown`/
`mousedown` so it doesn't reopen the Popover.
- Existing search debounce is shared with the new label watcher via a
single `buildFilterUrl` helper. URL is updated with `preserveState +
replace` so the back stack stays clean.
- i18n in en / pt-BR / es: `filter_by_label`, `label_search_placeholder`,
`no_labels`, `clear_label_filter`.
Tests: 4 new index tests covering the labels prop exposure, single-label
filter, multi-label OR filter, and blank-id sanitization. Full suite:
1509 passed, 2 skipped, 0 failed.
2026-05-14 12:57:55 +00:00
'filter_by_label' => 'Filtrar por etiqueta' ,
'label_search_placeholder' => 'Buscar etiquetas...' ,
'no_labels' => 'No se encontraron etiquetas.' ,
'clear_label_filter' => 'Limpiar filtro de etiquetas' ,
2026-05-02 15:22:42 +00:00
'table' => [
2026-05-06 17:26:18 +00:00
'post' => 'Post' ,
2026-05-02 15:22:42 +00:00
'status' => 'Estado' ,
'content' => 'Contenido' ,
'platforms' => 'Plataformas' ,
'labels' => 'Etiquetas' ,
'scheduled_at' => 'Fecha' ,
'actions' => '' ,
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'manage_posts' => 'Administra todos tus posts' ,
'delete_confirm' => '¿Estás seguro de que deseas eliminar este post?' ,
'by' => 'por' ,
'actions' => [
'view' => 'Ver post' ,
2026-05-04 01:37:51 +00:00
'delete' => 'Eliminar' ,
'duplicate' => 'Duplicar' ,
'copy_id' => 'Copiar ID' ,
'copied' => 'ID copiado al portapapeles' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'form' => [
'post_type' => 'Tipo de post' ,
'board' => 'Tablero' ,
'select_board' => 'Seleccionar tablero' ,
'search_board' => 'Buscar tablero...' ,
'no_board_found' => 'No se encontró tablero' ,
'media' => 'Multimedia' ,
'min' => 'Min' ,
'uploading' => 'Subiendo...' ,
'drop_to_upload' => 'Suelta para subir' ,
'drag_and_drop' => 'Arrastra y suelta o haz clic para subir' ,
'photos_and_videos' => 'Fotos y videos' ,
'photos_only' => 'Solo fotos' ,
'videos_only' => 'Solo videos' ,
'drag_to_reorder' => 'Arrastra para reordenar' ,
'caption' => 'Descripción' ,
'write_caption' => 'Escribe tu descripción...' ,
2026-05-11 22:39:41 +00:00
'content_exceeds_platform' => ':platform: demasiado largo por :over caracteres (máx :limit).' ,
2026-04-02 20:57:06 +00:00
'tiktok' => [
'settings' => 'Configuración de TikTok' ,
feat(tiktok): photo carousel support + UX Content Sharing API compliance
## Photo carousel support
- Adds `ContentType::TikTokPhoto` enum case (max 35 photos, 1:1 aspect,
supportsImage true, supportsVideo false) and JS mirror in content-type.ts.
- Variant pill picker (Video / Photo carousel) at the top of TikTokSettings,
mirroring the Instagram pattern. Wired through ScheduleTab to the parent
editor's existing update:platformContentType emit.
- i18n keys for variant_label / variant.video / variant.photo in en/pt-BR/es.
- Publisher: split buildPostInfo into buildVideoPostInfo (uses `title`,
TikTok cap 2200 chars) and buildPhotoPostInfo (uses `description`, cap
4000 chars; omits Duet/Stitch/AIGC since they don't apply). Removed the
no-longer-needed queryCreatorInfo() call from publishVideo/publishPhotos
— its only previous consumer (silent privacy_level fallback) is gone.
## UX Content Sharing API compliance
Per TikTok review feedback citing
https://developers.tiktok.com/doc/content-sharing-guidelines#required_ux_implementation_in_your_app
Point 1 — already satisfied (creator_info fetch + nickname display).
Point 2/4 — Music Usage Confirmation declaration is now always visible
in TikTokSettings; text changes between "Music Usage Confirmation" and
"Branded Content Policy and Music Usage Confirmation" based on toggle
state. Previously the entire `<p>` block was conditional on a brand
toggle being selected, hiding the baseline declaration.
Point 2b — privacy_level may not have a default. UI was already correct;
backend hardened: UpdatePostRequest now requires meta.privacy_level for
tiktok platforms when status is publishing/scheduled (via withValidator);
TikTokPublisher::resolveRequiredPrivacyLevel throws TikTokPublishException
(ContentPolicy category) when missing instead of silently falling back to
the creator's preferred level.
Point 2c — interaction settings now condition on content type:
- Photo posts hide Duet/Stitch (they don't apply per TikTok docs).
- Photo posts hide AIGC (also video-only).
- Video posts hide Auto Add Music (photos-only feature).
- Max-duration warning hidden when not a video post.
Source of truth is the user-selected contentType prop, not inferred
from media — ensures the UI reacts immediately to the variant pill.
Point 3a — publish button stays disabled when Disclose toggle is on
without a sub-selection (already the case via tiktokComplianceValid).
The disabled tooltip now uses the verbatim TikTok-required text "You
need to indicate if your content promotes yourself, a third party, or
both." instead of the generic "Some platform settings are incomplete..."
when the only blocker is TikTok disclosure incompleteness.
Point 3b — SELF_ONLY (Only me) privacy option is no longer filtered out
when Branded Content is checked. It is rendered disabled with a hover
tooltip "Branded content visibility cannot be set to private." plus a
persistent amber warning paragraph below the dropdown. When the user
toggles Branded Content while privacy is SELF_ONLY, the privacy clears
and a vue-sonner warning toast surfaces the change.
## Cross-cutting
- New `resources/js/enums/platform.ts` mirrors the PHP Platform enum,
used in Edit.vue (tiktokComplianceValid + tiktokDisclosureIncomplete)
and ScheduleTab.vue (all selected*Platforms computeds) to replace
string literal comparisons against `'tiktok'` / `'facebook'` / etc.
- PostPlatformFactory tiktok() state defaults meta.privacy_level to
SELF_ONLY so existing test fixtures keep passing under the new
publisher/FormRequest requirements.
## Tests
- New tests/Unit/Enums/PostPlatform/TikTokPhotoContentTypeTest.php
covering the new enum case (4 tests).
- TikTokPublisherTest: added "video uses title not description" and
"throws when meta.privacy_level missing" regression tests; renamed
two existing tests that depended on the removed silent fallback.
- New tests/Feature/UpdatePostRequestTest.php with 3 tests covering
the FormRequest's privacy_level enforcement (publish-rejected,
publish-passes, draft-allowed).
Full Pest suite: 1490 passed, 2 skipped (pre-existing).
2026-05-09 15:47:49 +00:00
'variant_label' => 'Tipo de publicación' ,
'variant' => [
'video' => 'Video' ,
'photo' => 'Carrusel de fotos' ,
],
2026-04-23 16:23:24 +00:00
'posting_to' => 'Publicando en' ,
2026-04-02 20:57:06 +00:00
'privacy_level' => '¿Quién puede ver este video?' ,
2026-05-29 13:16:04 +00:00
'privacy_placeholder' => 'Selecciona quién puede ver esta publicación' ,
2026-04-02 20:57:06 +00:00
'privacy' => [
'public' => 'Público para todos' ,
'friends' => 'Amigos mutuos' ,
'followers' => 'Seguidores' ,
'private' => 'Solo yo' ,
feat(tiktok): photo carousel support + UX Content Sharing API compliance
## Photo carousel support
- Adds `ContentType::TikTokPhoto` enum case (max 35 photos, 1:1 aspect,
supportsImage true, supportsVideo false) and JS mirror in content-type.ts.
- Variant pill picker (Video / Photo carousel) at the top of TikTokSettings,
mirroring the Instagram pattern. Wired through ScheduleTab to the parent
editor's existing update:platformContentType emit.
- i18n keys for variant_label / variant.video / variant.photo in en/pt-BR/es.
- Publisher: split buildPostInfo into buildVideoPostInfo (uses `title`,
TikTok cap 2200 chars) and buildPhotoPostInfo (uses `description`, cap
4000 chars; omits Duet/Stitch/AIGC since they don't apply). Removed the
no-longer-needed queryCreatorInfo() call from publishVideo/publishPhotos
— its only previous consumer (silent privacy_level fallback) is gone.
## UX Content Sharing API compliance
Per TikTok review feedback citing
https://developers.tiktok.com/doc/content-sharing-guidelines#required_ux_implementation_in_your_app
Point 1 — already satisfied (creator_info fetch + nickname display).
Point 2/4 — Music Usage Confirmation declaration is now always visible
in TikTokSettings; text changes between "Music Usage Confirmation" and
"Branded Content Policy and Music Usage Confirmation" based on toggle
state. Previously the entire `<p>` block was conditional on a brand
toggle being selected, hiding the baseline declaration.
Point 2b — privacy_level may not have a default. UI was already correct;
backend hardened: UpdatePostRequest now requires meta.privacy_level for
tiktok platforms when status is publishing/scheduled (via withValidator);
TikTokPublisher::resolveRequiredPrivacyLevel throws TikTokPublishException
(ContentPolicy category) when missing instead of silently falling back to
the creator's preferred level.
Point 2c — interaction settings now condition on content type:
- Photo posts hide Duet/Stitch (they don't apply per TikTok docs).
- Photo posts hide AIGC (also video-only).
- Video posts hide Auto Add Music (photos-only feature).
- Max-duration warning hidden when not a video post.
Source of truth is the user-selected contentType prop, not inferred
from media — ensures the UI reacts immediately to the variant pill.
Point 3a — publish button stays disabled when Disclose toggle is on
without a sub-selection (already the case via tiktokComplianceValid).
The disabled tooltip now uses the verbatim TikTok-required text "You
need to indicate if your content promotes yourself, a third party, or
both." instead of the generic "Some platform settings are incomplete..."
when the only blocker is TikTok disclosure incompleteness.
Point 3b — SELF_ONLY (Only me) privacy option is no longer filtered out
when Branded Content is checked. It is rendered disabled with a hover
tooltip "Branded content visibility cannot be set to private." plus a
persistent amber warning paragraph below the dropdown. When the user
toggles Branded Content while privacy is SELF_ONLY, the privacy clears
and a vue-sonner warning toast surfaces the change.
## Cross-cutting
- New `resources/js/enums/platform.ts` mirrors the PHP Platform enum,
used in Edit.vue (tiktokComplianceValid + tiktokDisclosureIncomplete)
and ScheduleTab.vue (all selected*Platforms computeds) to replace
string literal comparisons against `'tiktok'` / `'facebook'` / etc.
- PostPlatformFactory tiktok() state defaults meta.privacy_level to
SELF_ONLY so existing test fixtures keep passing under the new
publisher/FormRequest requirements.
## Tests
- New tests/Unit/Enums/PostPlatform/TikTokPhotoContentTypeTest.php
covering the new enum case (4 tests).
- TikTokPublisherTest: added "video uses title not description" and
"throws when meta.privacy_level missing" regression tests; renamed
two existing tests that depended on the removed silent fallback.
- New tests/Feature/UpdatePostRequestTest.php with 3 tests covering
the FormRequest's privacy_level enforcement (publish-rejected,
publish-passes, draft-allowed).
Full Pest suite: 1490 passed, 2 skipped (pre-existing).
2026-05-09 15:47:49 +00:00
'private_disabled_branded' => 'El contenido de marca no puede ser privado.' ,
2026-04-02 20:57:06 +00:00
],
'privacy_hint' => 'Las opciones disponibles dependen de la configuración de tu cuenta de TikTok.' ,
'auto_add_music' => 'Agregar música automáticamente' ,
'auto_add_music_hint' => 'Disponible solo para fotos. Agrega una música predeterminada que puedes cambiar después.' ,
'yes' => 'Sí' ,
'no' => 'No' ,
'allow_users' => 'Permitir a los usuarios:' ,
'comments' => 'Comentar' ,
'duet' => 'Dueto' ,
'stitch' => 'Stitch' ,
'is_aigc' => 'Video hecho con IA' ,
2026-04-23 16:23:24 +00:00
'disclose' => 'Divulgar contenido del video' ,
'disclose_hint' => 'Activa para divulgar que este video promueve bienes o servicios a cambio de algo de valor. Tu video puede promocionarte a ti, a un tercero o ambos.' ,
'promotional_organic_title' => 'Tu foto/video será etiquetado como "Contenido Promocional".' ,
'promotional_paid_title' => 'Tu foto/video será etiquetado como "Asociación pagada".' ,
'promotional_description' => 'Esto no se puede cambiar una vez publicado el video.' ,
'compliance_incomplete' => 'Debes indicar si tu contenido promociona a ti mismo, a un tercero o a ambos.' ,
2026-05-09 16:56:00 +00:00
'privacy_required' => 'La visibilidad de TikTok es obligatoria al publicar.' ,
feat(tiktok): photo carousel support + UX Content Sharing API compliance
## Photo carousel support
- Adds `ContentType::TikTokPhoto` enum case (max 35 photos, 1:1 aspect,
supportsImage true, supportsVideo false) and JS mirror in content-type.ts.
- Variant pill picker (Video / Photo carousel) at the top of TikTokSettings,
mirroring the Instagram pattern. Wired through ScheduleTab to the parent
editor's existing update:platformContentType emit.
- i18n keys for variant_label / variant.video / variant.photo in en/pt-BR/es.
- Publisher: split buildPostInfo into buildVideoPostInfo (uses `title`,
TikTok cap 2200 chars) and buildPhotoPostInfo (uses `description`, cap
4000 chars; omits Duet/Stitch/AIGC since they don't apply). Removed the
no-longer-needed queryCreatorInfo() call from publishVideo/publishPhotos
— its only previous consumer (silent privacy_level fallback) is gone.
## UX Content Sharing API compliance
Per TikTok review feedback citing
https://developers.tiktok.com/doc/content-sharing-guidelines#required_ux_implementation_in_your_app
Point 1 — already satisfied (creator_info fetch + nickname display).
Point 2/4 — Music Usage Confirmation declaration is now always visible
in TikTokSettings; text changes between "Music Usage Confirmation" and
"Branded Content Policy and Music Usage Confirmation" based on toggle
state. Previously the entire `<p>` block was conditional on a brand
toggle being selected, hiding the baseline declaration.
Point 2b — privacy_level may not have a default. UI was already correct;
backend hardened: UpdatePostRequest now requires meta.privacy_level for
tiktok platforms when status is publishing/scheduled (via withValidator);
TikTokPublisher::resolveRequiredPrivacyLevel throws TikTokPublishException
(ContentPolicy category) when missing instead of silently falling back to
the creator's preferred level.
Point 2c — interaction settings now condition on content type:
- Photo posts hide Duet/Stitch (they don't apply per TikTok docs).
- Photo posts hide AIGC (also video-only).
- Video posts hide Auto Add Music (photos-only feature).
- Max-duration warning hidden when not a video post.
Source of truth is the user-selected contentType prop, not inferred
from media — ensures the UI reacts immediately to the variant pill.
Point 3a — publish button stays disabled when Disclose toggle is on
without a sub-selection (already the case via tiktokComplianceValid).
The disabled tooltip now uses the verbatim TikTok-required text "You
need to indicate if your content promotes yourself, a third party, or
both." instead of the generic "Some platform settings are incomplete..."
when the only blocker is TikTok disclosure incompleteness.
Point 3b — SELF_ONLY (Only me) privacy option is no longer filtered out
when Branded Content is checked. It is rendered disabled with a hover
tooltip "Branded content visibility cannot be set to private." plus a
persistent amber warning paragraph below the dropdown. When the user
toggles Branded Content while privacy is SELF_ONLY, the privacy clears
and a vue-sonner warning toast surfaces the change.
## Cross-cutting
- New `resources/js/enums/platform.ts` mirrors the PHP Platform enum,
used in Edit.vue (tiktokComplianceValid + tiktokDisclosureIncomplete)
and ScheduleTab.vue (all selected*Platforms computeds) to replace
string literal comparisons against `'tiktok'` / `'facebook'` / etc.
- PostPlatformFactory tiktok() state defaults meta.privacy_level to
SELF_ONLY so existing test fixtures keep passing under the new
publisher/FormRequest requirements.
## Tests
- New tests/Unit/Enums/PostPlatform/TikTokPhotoContentTypeTest.php
covering the new enum case (4 tests).
- TikTokPublisherTest: added "video uses title not description" and
"throws when meta.privacy_level missing" regression tests; renamed
two existing tests that depended on the removed silent fallback.
- New tests/Feature/UpdatePostRequestTest.php with 3 tests covering
the FormRequest's privacy_level enforcement (publish-rejected,
publish-passes, draft-allowed).
Full Pest suite: 1490 passed, 2 skipped (pre-existing).
2026-05-09 15:47:49 +00:00
'branded_cleared_private' => 'La visibilidad se borró porque el contenido de marca no puede ser privado.' ,
2026-05-29 13:16:04 +00:00
'interaction_disabled_by_creator' => 'Desactivado en la configuración de tu cuenta TikTok' ,
2026-04-23 16:23:24 +00:00
'max_duration_exceeded' => 'El video dura :duration s pero esta cuenta solo permite videos de hasta :max s.' ,
'processing_hint' => 'Después de publicar, puede tardar unos minutos en procesarse y aparecer en tu perfil de TikTok.' ,
'brand_organic' => 'Tu marca' ,
'brand_organic_hint' => 'Estás promocionándote a ti mismo o a tu propia marca. Este video será clasificado como Brand Organic.' ,
'brand_content' => 'Contenido patrocinado' ,
'brand_content_hint' => 'Estás promocionando otra marca o a un tercero. Este video será clasificado como Branded Content.' ,
'compliance' => [
'agree' => 'Al publicar, aceptas la' ,
'music_usage' => 'Confirmación de Uso de Música' ,
'and' => 'y la' ,
'branded_policy' => 'Política de Contenido Patrocinado' ,
],
2026-04-02 20:57:06 +00:00
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'instagram' => [
'settings' => 'Configuración de Instagram' ,
'posting_to' => 'Publicando en' ,
'variant_label' => 'Tipo de publicación' ,
'variant' => [
'feed' => 'Publicación' ,
'reel' => 'Reel' ,
'story' => 'Historia' ,
],
2026-05-02 15:22:42 +00:00
'aspect_label' => 'Proporción' ,
'aspect' => [
'square' => 'Cuadrado (1:1)' ,
'portrait' => 'Vertical (4:5)' ,
'landscape' => 'Horizontal (16:9)' ,
'original' => 'Original' ,
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
],
'facebook' => [
'settings' => 'Configuración de Facebook' ,
'posting_to' => 'Publicando en' ,
'variant_label' => 'Tipo de publicación' ,
'variant' => [
'post' => 'Publicación' ,
'reel' => 'Reel' ,
'story' => 'Historia' ,
],
2026-06-05 21:01:45 +00:00
'aspect_label' => 'Proporción' ,
'aspect' => [
'square' => 'Cuadrado (1:1)' ,
'portrait' => 'Vertical (4:5)' ,
'landscape' => 'Horizontal (16:9)' ,
'original' => 'Original' ,
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
],
2026-05-02 17:50:36 +00:00
'linkedin' => [
'settings' => 'Configuración de LinkedIn' ,
'settings_page' => 'Configuración de la Página de LinkedIn' ,
'posting_to' => 'Publicando en' ,
2026-06-25 00:05:09 +00:00
'document_title' => 'Título del documento' ,
'document_title_placeholder' => 'Se muestra en tu publicación de documento PDF' ,
2026-05-02 17:50:36 +00:00
],
'pinterest' => [
'settings' => 'Configuración de Pinterest' ,
'posting_to' => 'Publicando en' ,
'variant_label' => 'Tipo de pin' ,
'variant' => [
'pin' => 'Pin' ,
'video_pin' => 'Video Pin' ,
'carousel' => 'Carrusel' ,
],
2026-05-15 14:51:20 +00:00
'board' => 'Tablero' ,
'select_board' => 'Selecciona un tablero' ,
'no_boards' => 'No se encontraron tableros de Pinterest. Crea uno en tu cuenta de Pinterest primero.' ,
2026-07-25 02:02:40 +00:00
'boards_truncated' => 'No se pudieron cargar algunos tableros. Si falta el tuyo, abre Pinterest e inténtalo de nuevo.' ,
2026-05-15 14:51:20 +00:00
'search_board' => 'Buscar tableros...' ,
'no_board_found' => 'Ningún tablero coincide con tu búsqueda.' ,
'board_required' => 'Selecciona un tablero de Pinterest para publicar este post.' ,
Add optional Pinterest pin title and destination link (#232)
* Add optional Pinterest pin title, description, and link.
Expose title/description/link across web, API, and MCP; seed description from caption into meta on save, and publish description only from meta.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Expand Pinterest title/description/link test coverage.
Cover web draft persistence and validation bounds, API/MCP update merge and seed, and publisher payload fields on video and carousel pins.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Simplify Pinterest: description is post content again.
Keep optional title and link in meta/settings only. Remove the separate description textarea, seed logic, and meta.description path so Pinterest follows the shared caption pattern.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Refactor Pinterest meta handling and validation.
- Update CreatePost and UpdatePost actions to filter out null values from meta fields.
- Introduce a new method in PinterestPublisher to resolve board IDs, ensuring required fields are validated.
- Enhance PinterestSettings component to manage title and link inputs, including validation for HTTP URLs.
- Update PostPlatformMetaRules to enforce URL validation for Pinterest links.
- Add tests for clearing Pinterest title and link, and for rejecting invalid links during scheduling.
This refactor improves the handling of Pinterest metadata and enhances user experience by ensuring proper validation and error handling.
* Add validation messages and attributes for Pinterest meta fields
- Introduced custom validation messages and friendly attribute names for Pinterest link and title fields in PostPlatformMetaRules.
- Updated StorePostRequest, UpdatePostRequest, and related tools to utilize these new messages and attributes.
- Enhanced tests to assert correct error messages for invalid Pinterest links and title length constraints.
This update improves user feedback during post creation and editing, ensuring clarity in validation errors.
* Remove click.prevent directive from Pinterest link in PinterestPreview component.
This change simplifies the link behavior, allowing default click actions to occur, which may enhance user interaction with the Pinterest link.
* Update validation error messages for Pinterest meta fields in tests
- Refined the assertions in PostApiPlatformMetaTest to include localized validation messages for Pinterest title and link fields.
- Ensured that error messages reflect the updated validation rules, enhancing clarity for users during post creation and editing.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 21:15:50 +00:00
'title' => 'Título' ,
'title_placeholder' => 'Título opcional del pin' ,
'link' => 'Enlace de destino' ,
'link_placeholder' => 'https://ejemplo.com' ,
'link_invalid' => 'Introduce un enlace de destino válido (http o https).' ,
'title_max' => 'El título no puede tener más de 100 caracteres.' ,
'link_max' => 'El enlace de destino no puede tener más de 2048 caracteres.' ,
2026-05-02 17:50:36 +00:00
],
feat(channels): add Discord as a social channel
Connect a Discord server via OAuth (bot authorization) and schedule/publish
messages to its channels, with mentions and rich embeds.
- Connect: custom Socialite Discord provider (bot scope) maps the authorized
guild to a SocialAccount; throws if no server was authorized.
- Publish: DiscordPublisher posts via the global bot token, validates the chosen
channel belongs to the connected guild (anti cross-guild), optimizes media,
builds allowed_mentions only from explicit mention chips (no accidental pings),
and renders rich embeds.
- Compose: per-post channel picker (live lookup), mention autocomplete and an
embed editor, gated by a required-channel compliance rule; Discord post preview.
- Enum/config/content-type wiring, ConnectionVerifier health check, throttled
lookup endpoints, i18n (en/es/pt-BR), and tests.
Operators must create a Discord application and set DISCORD_CLIENT_ID,
DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN and DISCORD_CLIENT_REDIRECT.
2026-06-16 17:44:00 +00:00
'discord' => [
'settings' => 'Configuración de Discord' ,
'posting_to' => 'Publicando en' ,
'channel' => 'Canal' ,
'select_channel' => 'Selecciona un canal' ,
'loading_channels' => 'Cargando canales…' ,
2026-06-16 18:53:20 +00:00
'search_channel' => 'Buscar canales…' ,
'no_channels' => 'No se encontraron canales.' ,
feat(channels): add Discord as a social channel
Connect a Discord server via OAuth (bot authorization) and schedule/publish
messages to its channels, with mentions and rich embeds.
- Connect: custom Socialite Discord provider (bot scope) maps the authorized
guild to a SocialAccount; throws if no server was authorized.
- Publish: DiscordPublisher posts via the global bot token, validates the chosen
channel belongs to the connected guild (anti cross-guild), optimizes media,
builds allowed_mentions only from explicit mention chips (no accidental pings),
and renders rich embeds.
- Compose: per-post channel picker (live lookup), mention autocomplete and an
embed editor, gated by a required-channel compliance rule; Discord post preview.
- Enum/config/content-type wiring, ConnectionVerifier health check, throttled
lookup endpoints, i18n (en/es/pt-BR), and tests.
Operators must create a Discord application and set DISCORD_CLIENT_ID,
DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN and DISCORD_CLIENT_REDIRECT.
2026-06-16 17:44:00 +00:00
'channel_required' => 'Selecciona un canal de Discord para publicar este post.' ,
'mentions' => 'Menciones' ,
'search_mention' => 'Menciona un rol o miembro…' ,
'embeds' => 'Embeds' ,
'embed' => 'Embed' ,
'add_embed' => 'Añadir embed' ,
'embed_title' => 'Título del embed' ,
'embed_description' => 'Descripción del embed' ,
'embed_url' => 'URL del embed' ,
'embed_image' => 'URL de la imagen' ,
'embed_color' => 'Color' ,
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'warnings' => [
'no_variant' => 'Elige un tipo de publicación para continuar.' ,
'requires_media' => 'Este tipo requiere al menos una imagen o video.' ,
'max_files_exceeded' => 'Este tipo acepta hasta :max archivos (tienes :current).' ,
'min_files_required' => 'Este tipo requiere al menos :min archivos (tienes :current).' ,
'no_video_allowed' => 'Este tipo no acepta videos.' ,
'no_image_allowed' => 'Este tipo acepta solo videos.' ,
feat(linkedin): support PDF document (carousel) posts
Add LinkedIn document posts — the swipeable PDF carousel — for both personal profiles and company pages. This is the format every major competitor exposes via native PDF upload, and the reason a trial user churned.
- New 'document' media type (application/pdf) across the upload pipeline (Type enum, HasMedia, FormRequests incl. chunked, Platform media types)
- New LinkedInDocument / LinkedInPageDocument content types: PDF-only, single-file, with a supportsDocument() flag
- Publisher flow: documents initializeUpload -> PUT -> poll AVAILABLE -> post with content.media.{id,title}; optional document_title meta (falls back to file name)
- PDF is mutually exclusive with image/video, enforced in ContentTypeCompatibleWithMedia
- Frontend: 'Document (PDF)' variant, media rules (100MB cap), composer/gallery/detail PDF cards, real PDF embed in the LinkedIn editor preview, i18n in en/es/pt-BR
- Tests: publishers (personal + page, incl. processing-failure path), enums, compatibility rule, chunked PDF upload, API + MCP document_title round-trip
LinkedIn caps documents at 100MB / 300 pages (Documents API). The page limit is enforced by LinkedIn at publish, not validated client-side.
2026-06-24 19:32:27 +00:00
'no_document_allowed' => 'Este tipo no acepta documentos PDF.' ,
2026-06-25 00:05:09 +00:00
'no_mixed_media' => 'No se pueden combinar imágenes y un video en la misma publicación.' ,
2026-06-25 12:45:15 +00:00
'document_not_alone' => 'Un PDF debe publicarse solo, sin otras imágenes ni videos.' ,
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'gif_not_allowed' => 'Esta red no acepta GIF. Elimínalo o selecciona otra red.' ,
'image_too_large' => 'La imagen supera el límite de :max (la tuya es :current).' ,
'video_too_large' => 'El video supera el límite de :max (el tuyo es :current).' ,
feat(linkedin): support PDF document (carousel) posts
Add LinkedIn document posts — the swipeable PDF carousel — for both personal profiles and company pages. This is the format every major competitor exposes via native PDF upload, and the reason a trial user churned.
- New 'document' media type (application/pdf) across the upload pipeline (Type enum, HasMedia, FormRequests incl. chunked, Platform media types)
- New LinkedInDocument / LinkedInPageDocument content types: PDF-only, single-file, with a supportsDocument() flag
- Publisher flow: documents initializeUpload -> PUT -> poll AVAILABLE -> post with content.media.{id,title}; optional document_title meta (falls back to file name)
- PDF is mutually exclusive with image/video, enforced in ContentTypeCompatibleWithMedia
- Frontend: 'Document (PDF)' variant, media rules (100MB cap), composer/gallery/detail PDF cards, real PDF embed in the LinkedIn editor preview, i18n in en/es/pt-BR
- Tests: publishers (personal + page, incl. processing-failure path), enums, compatibility rule, chunked PDF upload, API + MCP document_title round-trip
LinkedIn caps documents at 100MB / 300 pages (Documents API). The page limit is enforced by LinkedIn at publish, not validated client-side.
2026-06-24 19:32:27 +00:00
'document_too_large' => 'El PDF supera el límite de :max (el tuyo es :current).' ,
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'video_too_long' => 'El video dura :current, pero este tipo permite hasta :max.' ,
'aspect_ratio_too_narrow' => 'La proporción :current es demasiado alta (mínimo :min).' ,
'aspect_ratio_too_wide' => 'La proporción :current es demasiado ancha (máximo :max).' ,
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'status' => [
2026-03-30 19:55:14 +00:00
'pending' => 'Pendiente' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'draft' => 'Borrador' ,
'scheduled' => 'Programado' ,
'publishing' => 'Publicando' ,
2026-05-19 13:03:30 +00:00
'retrying' => 'Reintentando' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'published' => 'Publicado' ,
'partially_published' => 'Parcialmente publicado' ,
'failed' => 'Fallido' ,
],
'descriptions' => [
'draft' => 'Posts esperando ser programados' ,
'scheduled' => 'Posts programados para publicar' ,
'published' => 'Posts ya publicados' ,
],
2026-05-03 12:36:50 +00:00
'ai' => [
'generate' => [
'button_tooltip' => 'Generar con IA' ,
'title' => 'Generar post con IA' ,
'description' => 'Describe sobre qué debe ser el post. La IA usará el contexto de tu marca para escribirlo.' ,
'prompt_label' => '¿De qué trata este post?' ,
'prompt_placeholder' => 'ej: anunciar nuestra nueva función de generación de imágenes para carruseles' ,
'preview_label' => 'Vista previa' ,
'start' => 'Generar' ,
'apply' => 'Usar este contenido' ,
'retry' => 'Intentar de nuevo' ,
'cancel' => 'Cancelar' ,
],
'review' => [
'button_tooltip' => 'Revisar con IA' ,
'title' => 'Revisar post con IA' ,
2026-05-03 16:44:13 +00:00
'description' => 'La IA analiza gramática, ortografía y claridad. Aplica las sugerencias con las que estés de acuerdo.' ,
2026-05-03 12:36:50 +00:00
'loading' => 'Revisando tu texto...' ,
'no_issues' => 'No se encontraron problemas. Todo bien.' ,
'original' => 'Original' ,
'suggestion' => 'Sugerencia' ,
'apply' => 'Aplicar' ,
2026-05-03 16:44:13 +00:00
'apply_all' => 'Aplicar todas' ,
'applied' => 'Aplicada' ,
'cancel' => 'Cancelar' ,
2026-05-03 12:36:50 +00:00
],
2026-05-21 19:27:55 +00:00
'image_regenerate' => [
'button' => 'Ajustar' ,
'title' => 'Ajustar imagen con IA' ,
'description' => 'Describe la corrección. La nueva imagen reemplaza la actual y mantiene su posición en el carrusel.' ,
'instruction_label' => 'Instrucción' ,
'instruction_placeholder' => 'ej: Corregir el error en el titular y aclarar el fondo.' ,
'processing' => 'Regenerando imagen... esto puede tardar unos segundos.' ,
'submit' => 'Regenerar imagen' ,
'cancel' => 'Cancelar' ,
'success' => 'Imagen actualizada. La nueva versión reemplazó la anterior en la publicación.' ,
'fallback_title' => 'Mejorar este texto de imagen' ,
'errors' => [
'required' => 'La instrucción es obligatoria.' ,
'start_failed' => 'No se pudo iniciar la regeneración.' ,
'unavailable' => 'No se pudo regenerar esta imagen en este momento.' ,
'timeout' => 'La regeneración está tardando más de lo esperado. Inténtalo de nuevo en un momento.' ,
'media_not_found' => 'No se encontró el archivo multimedia.' ,
'not_ai_media' => 'Solo se puede regenerar contenido generado por IA.' ,
],
],
2026-06-17 20:37:51 +00:00
'templates' => [
'image_card' => [
'name' => 'Publicación con imagen' ,
'description' => 'Imagen con IA, titular y descripción.' ,
],
'carousel' => [
'name' => 'Carrusel' ,
'description' => 'Carrusel de varias diapositivas con descripción.' ,
],
'tweet_card' => [
'name' => 'Tarjeta de tweet' ,
'description' => 'Tu publicación con estilo de post de X/Twitter.' ,
],
2026-06-17 22:43:21 +00:00
'tweet_card_image' => [
'name' => 'Tarjeta de tweet con foto' ,
'description' => 'Tu publicación como tarjeta de X/Twitter sobre una foto difuminada.' ,
],
2026-06-17 20:37:51 +00:00
],
2026-05-03 12:36:50 +00:00
],
2026-05-02 15:22:42 +00:00
'show' => [
'title' => 'Detalles del post' ,
'edit' => 'Editar' ,
refactor: in-page page headers, indies tabs, and post details polish
- Replace global AppHeader slots with in-page headers on Calendar, Edit,
and Show pages — full-width canvas with the page-specific controls
living in their own ink-bordered bar.
- Remove sidebar collapse mechanism: drop Cmd+B keyboard shortcut, force
defaultOpen=true (ignore persisted cookie), make toggleSidebar a no-op
on desktop. Sidebar is permanent on desktop, sheet behavior preserved
on mobile.
- Redesign Tabs to match the design system: each TabsTrigger renders as
a standalone sticker button (border-2 + rounded-md + shadow-xs), with
amber-200 active state mirroring the "POST" badge from post-templates.
- Show page layout: cap preview Card to max-w-xl, preserve natural
aspect for single-image posts (object-contain, max-h-[480px]), drop
redundant stats grid, swap header sides (Back button left, status +
date right with date first).
- Assets: bump GalleryBrowser search inputs to h-12 for comfortable
browsing across uploads, Unsplash, and Giphy tabs.
- Fix PostPlatformMetrics loading-forever bug: hoist useHttp out of the
onMounted callback into setup, and read the response array directly
(backend returns the array at root, not under .data).
- i18n: rename posts.show.back_to_posts → posts.show.back; remove unused
posts.show.summary.* keys.
2026-05-06 19:22:55 +00:00
'back' => 'Volver' ,
2026-05-02 15:22:42 +00:00
'no_content' => 'Sin texto' ,
'platforms' => 'Plataformas' ,
'no_platforms' => 'Ninguna plataforma seleccionada.' ,
'view_on_platform' => 'Ver en la plataforma' ,
'published_on' => 'Publicado el :date' ,
'scheduled_for' => 'Programado para el :date' ,
'draft' => 'Borrador' ,
'status_pending' => 'Pendiente' ,
'metrics' => 'Métricas' ,
'metrics_loading' => 'Cargando métricas…' ,
'metrics_unavailable' => 'Métricas aún no disponibles para esta plataforma.' ,
'metrics_empty' => 'No se devolvieron métricas.' ,
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'edit' => [
'title' => 'Editar post' ,
'view_title' => 'Ver post' ,
'labels' => 'Etiquetas' ,
2026-05-03 18:23:30 +00:00
'signatures' => 'Firmas' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'schedule' => 'Programar' ,
'delete' => 'Eliminar' ,
'schedule_for' => 'Programar para' ,
2026-05-06 17:26:18 +00:00
'unschedule' => 'Desprogramar' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'saving' => 'Guardando...' ,
'saved' => 'Guardado' ,
2026-04-17 02:05:51 +00:00
'draft' => 'Borrador' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'media' => 'Multimedia' ,
2026-04-17 02:05:51 +00:00
'add_media' => 'Añadir media' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'caption' => 'Descripción' ,
2026-04-17 02:05:51 +00:00
'caption_placeholder' => 'Escribe tu descripción...' ,
'compose_title' => 'Crear un post' ,
'compose_subtitle' => 'Compón tu mensaje y agrega media' ,
2026-05-02 17:50:36 +00:00
'preview_empty' => [
'title' => 'Ninguna plataforma seleccionada' ,
'description' => 'Selecciona una plataforma para publicar y ver la vista previa.' ,
],
2026-05-02 18:32:55 +00:00
'drop_zone_title' => 'Añadir media' ,
'drop_zone_subtitle' => 'Arrastra archivos o haz clic para seleccionar' ,
'add' => 'Añadir' ,
2026-04-17 02:05:51 +00:00
'publish_to' => 'Publicar en' ,
'organize' => 'Organizar' ,
'no_labels' => 'Todavía no hay etiquetas creadas' ,
'pick_time' => 'Elegir hora' ,
2026-05-19 19:26:40 +00:00
'pick_time_past' => 'Elige una fecha y hora en el futuro.' ,
2026-04-17 02:05:51 +00:00
'post_now' => 'Publicar ahora' ,
'time' => 'Hora' ,
'cancel' => 'Cancelar' ,
'schedule_date' => 'Fecha de programación' ,
'view_on_platform' => 'Ver en la plataforma' ,
'platform_status' => 'Estado de la plataforma' ,
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'compliance_incomplete' => 'Algunas configuraciones de plataforma están incompletas o son incompatibles con los medios adjuntos.' ,
2026-05-02 15:22:42 +00:00
'compliance' => [
2026-05-19 17:18:13 +00:00
'requires_content_or_media' => 'Agrega texto o multimedia para publicar.' ,
2026-05-02 15:22:42 +00:00
'requires_media' => 'Agrega una imagen o video para publicar aquí.' ,
'too_many_files' => 'Solo se permiten :max archivo(s) en este formato.' ,
'too_few_files' => 'Agrega al menos :min archivos para este formato.' ,
'no_videos' => 'Solo se permiten imágenes en este formato.' ,
'no_images' => 'Solo se permiten videos en este formato.' ,
2026-06-23 17:30:38 +00:00
'no_mixed_media' => 'No se pueden combinar imágenes y videos en la misma publicación.' ,
2026-05-02 15:22:42 +00:00
'no_gifs' => 'Los GIFs no son compatibles aquí.' ,
2026-06-24 20:36:39 +00:00
'no_documents' => 'Los documentos PDF no son compatibles con este formato.' ,
2026-06-25 12:45:15 +00:00
'document_not_alone' => 'Un PDF debe publicarse solo, sin otras imágenes ni videos.' ,
2026-05-02 15:22:42 +00:00
'video_too_large' => 'El video supera el límite de tamaño de esta plataforma.' ,
'video_too_long' => 'El video debe durar menos de :seconds segundos en este formato.' ,
'image_too_large' => 'La imagen supera el límite de tamaño de esta plataforma.' ,
2026-06-24 20:36:39 +00:00
'document_too_large' => 'El PDF supera el límite de tamaño de esta plataforma.' ,
2026-05-02 15:22:42 +00:00
'aspect_ratio_invalid' => 'La proporción de aspecto no es compatible con este formato.' ,
'no_content_type' => 'Elige un tipo de contenido para esta plataforma.' ,
2026-06-25 22:59:51 +00:00
'requires_text' => 'Agrega texto — este formato necesita un título.' ,
2026-05-02 15:22:42 +00:00
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'publishing' => 'Publicando...' ,
'publishing_overlay_title' => 'Tu publicación se está enviando' ,
'publishing_overlay_subtitle' => 'Esto puede tardar unos momentos. Puedes salir de esta página sin problemas.' ,
2026-05-11 23:47:53 +00:00
'scheduled_overlay_title' => 'Esta publicación está programada' ,
'scheduled_overlay_subtitle' => 'Programada para :date. Cancela la programación para hacer cambios.' ,
'unschedule_cta' => 'Cancelar para editar' ,
2026-04-17 02:05:51 +00:00
'tabs' => [
2026-07-17 21:38:20 +00:00
'compose' => 'Redactar' ,
2026-04-17 02:05:51 +00:00
'preview' => 'Vista previa' ,
2026-06-10 19:06:02 +00:00
'channels' => 'Canales' ,
2026-04-17 02:05:51 +00:00
'comments' => 'Comentarios' ,
'comments_empty' => 'Todavía no hay comentarios.' ,
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'media_picker' => [
'title' => 'Elegir de la galería' ,
'search' => 'Buscar media...' ,
'empty' => 'Aún no hay archivos en tu galería' ,
'cancel' => 'Cancelar' ,
'add' => 'Agregar' ,
'add_count' => 'Agregar :count' ,
],
2026-07-11 12:45:52 +00:00
'alt_text' => [
'label' => 'Texto alternativo' ,
'edit' => 'Editar texto alternativo' ,
'placeholder' => 'Describe esta imagen para las personas que usan lectores de pantalla' ,
'hint' => 'Se publica en las plataformas que admiten descripciones de imágenes.' ,
'save' => 'Guardar' ,
],
feat: media gallery picker, custom emoji picker, preview tabs, real platform logos
- gallery: extract /assets tabs (uploads, Unsplash, Giphy) into shared
GalleryBrowser used by both /assets and a new MediaPickerDialog inside the
post editor; add JSON search endpoint for workspace assets with tests
- emoji: replace broken emoji-picker-element web component with a custom
EmojiPicker (full Unicode set, search, categories, recently-used,
light/dark, i18n)
- preview tab: platform selector pills, variant tabs (data-driven from
content_types map) so the user can switch Feed/Reel/Story etc. and have
it autosave through the same handler ScheduleTab uses
- platform logos: shared usePlatformLogo composable (logo + label + content
types); replaces inline maps across 5 components, fixes
instagram-facebook falling back to default.png
- tooltips: hover details (display_name · @username + platform label) on
platform avatars across editor, posts list and calendar
- settings cards: show ` · @username` in the title bar so multiple accounts
on the same network are distinguishable
- routes: drop the throttle:6,1 group middleware on social connect routes
(was 429ing legitimate OAuth retries) and rely on the default limiter
2026-05-01 17:53:49 +00:00
'emoji_picker' => [
'search' => 'Buscar emoji' ,
'empty' => 'No se encontraron emojis' ,
'recent' => 'Usados con frecuencia' ,
'smileys' => 'Caritas y emociones' ,
'people' => 'Personas y cuerpo' ,
'nature' => 'Animales y naturaleza' ,
'food' => 'Comida y bebida' ,
'activities' => 'Actividades' ,
'travel' => 'Viajes y lugares' ,
'objects' => 'Objetos' ,
'symbols' => 'Símbolos' ,
'flags' => 'Banderas' ,
],
2026-04-17 02:05:51 +00:00
'status' => [
2026-06-22 19:47:27 +00:00
'pending' => 'Pendiente' ,
2026-05-06 17:26:18 +00:00
'scheduled' => 'Programado' ,
2026-04-17 02:05:51 +00:00
'published' => 'Publicado' ,
'publishing' => 'Publicando...' ,
2026-05-19 13:03:30 +00:00
'retrying' => 'Reintentando...' ,
2026-04-17 02:05:51 +00:00
'failed' => 'Fallido' ,
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'delete_modal' => [
'title' => 'Eliminar post' ,
'description' => '¿Estás seguro de que deseas eliminar este post? Esta acción no se puede deshacer.' ,
'action' => 'Eliminar' ,
'cancel' => 'Cancelar' ,
],
'sync_enable' => [
'title' => '¿Activar sincronización?' ,
'description' => 'Todas las plataformas compartirán el mismo contenido. Las ediciones personalizadas realizadas en plataformas individuales serán reemplazadas con el contenido actual.' ,
'cancel' => 'Cancelar' ,
'action' => 'Activar sincronización' ,
],
'sync_disable' => [
'title' => '¿Desactivar sincronización?' ,
'description' => 'Cada plataforma mantendrá su contenido actual, pero las ediciones futuras solo se aplicarán a la plataforma que estés editando.' ,
'customize_note' => 'Podrás personalizar el contenido de cada plataforma individualmente.' ,
'cancel' => 'Cancelar' ,
'action' => 'Desactivar sincronización' ,
],
'platforms_dialog' => [
'title' => 'Seleccionar plataformas' ,
'description' => 'Elige en qué plataformas publicar este post.' ,
],
2026-05-03 18:23:30 +00:00
'signatures_modal' => [
'search' => 'Buscar firmas...' ,
'no_results' => 'No se encontraron firmas.' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'validation' => [
'select_board' => 'Selecciona un tablero' ,
'images_not_supported' => 'Imágenes no soportadas' ,
'videos_not_supported' => 'Videos no soportados' ,
'max_images' => 'Máximo :count imágenes' ,
'requires_media' => 'Requiere multimedia' ,
2026-04-01 18:12:56 +00:00
'requires_content' => 'Se requiere texto' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'exceeded' => ':count excedido' ,
'does_not_support_images' => ':platform no soporta imágenes' ,
'supports_up_to_images' => ':platform soporta hasta :count imágenes' ,
'does_not_support_videos' => ':platform no soporta videos' ,
],
],
'content_types' => [
'instagram_feed' => [
'label' => 'Post del feed' ,
'description' => 'Aparece en tu feed y perfil' ,
],
'instagram_reel' => [
'label' => 'Reel' ,
2026-07-25 00:21:39 +00:00
'description' => 'Video corto de hasta 15 minutos' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'instagram_story' => [
'label' => 'Historia' ,
'description' => 'Desaparece después de 24 horas' ,
],
'linkedin_post' => [
'label' => 'Post' ,
2026-06-25 00:05:09 +00:00
'description' => 'Post estándar — imagen, varias imágenes, video o PDF' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'linkedin_page_post' => [
'label' => 'Post' ,
2026-06-25 00:05:09 +00:00
'description' => 'Post estándar — imagen, varias imágenes, video o PDF' ,
feat(linkedin): support PDF document (carousel) posts
Add LinkedIn document posts — the swipeable PDF carousel — for both personal profiles and company pages. This is the format every major competitor exposes via native PDF upload, and the reason a trial user churned.
- New 'document' media type (application/pdf) across the upload pipeline (Type enum, HasMedia, FormRequests incl. chunked, Platform media types)
- New LinkedInDocument / LinkedInPageDocument content types: PDF-only, single-file, with a supportsDocument() flag
- Publisher flow: documents initializeUpload -> PUT -> poll AVAILABLE -> post with content.media.{id,title}; optional document_title meta (falls back to file name)
- PDF is mutually exclusive with image/video, enforced in ContentTypeCompatibleWithMedia
- Frontend: 'Document (PDF)' variant, media rules (100MB cap), composer/gallery/detail PDF cards, real PDF embed in the LinkedIn editor preview, i18n in en/es/pt-BR
- Tests: publishers (personal + page, incl. processing-failure path), enums, compatibility rule, chunked PDF upload, API + MCP document_title round-trip
LinkedIn caps documents at 100MB / 300 pages (Documents API). The page limit is enforced by LinkedIn at publish, not validated client-side.
2026-06-24 19:32:27 +00:00
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'facebook_post' => [
'label' => 'Post' ,
'description' => 'Post estándar en tu página' ,
],
'facebook_reel' => [
'label' => 'Reel' ,
'description' => 'Video corto de hasta 90 segundos' ,
],
'facebook_story' => [
'label' => 'Historia' ,
2026-05-22 00:21:11 +00:00
'description' => 'Historia en video vertical, hasta 60 segundos' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'tiktok_video' => [
'label' => 'Video' ,
'description' => 'Contenido de video corto' ,
],
2026-05-09 16:56:00 +00:00
'tiktok_photo' => [
'label' => 'Carrusel de fotos' ,
'description' => 'Hasta 35 fotos en un carrusel deslizable' ,
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'youtube_short' => [
'label' => 'Short' ,
2026-07-23 15:06:15 +00:00
'description' => 'Video vertical de hasta 3 minutos' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'x_post' => [
'label' => 'Post' ,
'description' => 'Tweet con texto y multimedia' ,
],
'threads_post' => [
'label' => 'Post' ,
'description' => 'Post de texto con multimedia opcional' ,
],
'pinterest_pin' => [
'label' => 'Pin' ,
2026-05-09 16:56:00 +00:00
'description' => 'Pin de imagen estándar' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'pinterest_video_pin' => [
'label' => 'Pin de video' ,
2026-05-09 16:56:00 +00:00
'description' => 'Pin de video (4s - 15min)' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'pinterest_carousel' => [
'label' => 'Carrusel' ,
2026-05-09 16:56:00 +00:00
'description' => 'Carrusel multi-imagen (2-5 imágenes)' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'bluesky_post' => [
'label' => 'Post' ,
'description' => 'Post de texto con imágenes opcionales' ,
],
'mastodon_post' => [
'label' => 'Post' ,
'description' => 'Post de texto con multimedia opcional' ,
],
2026-06-14 01:10:12 +00:00
'telegram_post' => [
'label' => 'Post' ,
'description' => 'Post de texto con multimedia opcional' ,
],
feat(channels): add Discord as a social channel
Connect a Discord server via OAuth (bot authorization) and schedule/publish
messages to its channels, with mentions and rich embeds.
- Connect: custom Socialite Discord provider (bot scope) maps the authorized
guild to a SocialAccount; throws if no server was authorized.
- Publish: DiscordPublisher posts via the global bot token, validates the chosen
channel belongs to the connected guild (anti cross-guild), optimizes media,
builds allowed_mentions only from explicit mention chips (no accidental pings),
and renders rich embeds.
- Compose: per-post channel picker (live lookup), mention autocomplete and an
embed editor, gated by a required-channel compliance rule; Discord post preview.
- Enum/config/content-type wiring, ConnectionVerifier health check, throttled
lookup endpoints, i18n (en/es/pt-BR), and tests.
Operators must create a Discord application and set DISCORD_CLIENT_ID,
DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN and DISCORD_CLIENT_REDIRECT.
2026-06-16 17:44:00 +00:00
'discord_message' => [
'label' => 'Mensaje' ,
'description' => 'Mensaje a un canal de Discord con multimedia y embeds opcionales' ,
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
'platforms' => [
'linkedin' => 'LinkedIn' ,
'linkedin-page' => 'Página de LinkedIn' ,
'x' => 'X' ,
'tiktok' => 'TikTok' ,
'youtube' => 'YouTube Shorts' ,
'facebook' => 'Página de Facebook' ,
'instagram' => 'Instagram' ,
'threads' => 'Threads' ,
'pinterest' => 'Pinterest' ,
'bluesky' => 'Bluesky' ,
'mastodon' => 'Mastodon' ,
],
'flash' => [
'scheduled' => '¡Post programado correctamente!' ,
'deleted' => '¡Post eliminado correctamente!' ,
2026-05-04 01:37:51 +00:00
'duplicated' => 'Post duplicado como borrador.' ,
fix(facebook): empty-message rejection + state consistency + no re-publish on terminal
Production incident: a customer's Facebook Page post failed with 'The post
is empty. Please enter a message to share.' (error code 197) and ended up
with a contradictory DB state (status=published + error_message=set).
Three independent bugs were uncovered:
A. FacebookPublisher sends 'message'/'description' as null when the user
posts media without text. Graph API requires the key be omitted, not
null. Fixed in publishSingleImagePost, publishMultiImagePost,
publishVideoPost, publishReel.
B. markAsPublished/markAsFailed leak stale fields across transitions
(a published row could retain error_message from a prior failure,
vice-versa). Both transitions now explicitly clear the opposite
side's fields.
C. status='failed' was editable in the UI and the backend, so users
were re-clicking Publish, generating duplicate failure emails and
the contradictory state from bug B. The frontend isReadOnly check
and the UpdatePost backend guard now treat Published/PartiallyPublished/
Failed/Publishing as terminal. To retry, the user duplicates the post.
11 new tests guarantee these can't regress silently: FB payload shape
per content type, PostPlatform field-clearing on transitions, and the
terminal-status block at the controller level.
2026-05-15 16:01:49 +00:00
'cannot_edit_finalized' => 'Este post ya fue procesado y no puede republicarse. Duplícalo para intentar de nuevo.' ,
2026-05-02 15:22:42 +00:00
'cannot_delete_published' => 'Los posts publicados no se pueden eliminar.' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
'connect_first' => 'Conecta al menos una red social antes de crear un post.' ,
],
'errors' => [
'account_disconnected' => 'Cuenta social desconectada' ,
2026-03-31 00:18:07 +00:00
'account_inactive' => 'Cuenta social desactivada' ,
2026-05-12 21:46:06 +00:00
'account_token_expired' => 'Sesión de la cuenta social expirada — reconecta la cuenta' ,
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
],
2026-05-03 12:36:50 +00:00
2026-05-03 13:17:01 +00:00
'delete' => [
'title' => '¿Eliminar post?' ,
'description' => 'Esta acción no se puede deshacer. El post y todos sus archivos multimedia se eliminarán de forma permanente.' ,
'confirm' => 'Sí, eliminar' ,
'cancel' => 'Cancelar' ,
],
2026-05-03 12:36:50 +00:00
'create' => [
'title' => 'Crear nuevo post' ,
'description' => 'Elige cómo quieres empezar.' ,
'scratch_title' => 'Empezar desde cero' ,
'scratch_description' => 'Abre un post en blanco para escribirlo todo.' ,
'ai_title' => 'Generar con IA' ,
'ai_description' => 'Describe lo que quieres y la IA genera el contenido por ti.' ,
'ai_configure_description' => 'Elige un formato y describe el post que quieres crear.' ,
2026-06-17 20:42:23 +00:00
'ai_pick_template_description' => 'Elige un estilo para tu post generado por IA.' ,
2026-05-03 12:36:50 +00:00
'template_title' => 'Usar una plantilla' ,
'template_description' => 'Elige una de nuestras plantillas y personalízala.' ,
2026-05-03 13:06:02 +00:00
'preview' => [
'image_title' => 'Título de la imagen' ,
'image_body' => 'Texto de la imagen' ,
],
2026-05-03 12:36:50 +00:00
'coming_soon' => 'Próximamente' ,
'steps' => [
2026-06-17 20:42:23 +00:00
'template_picker_title' => 'Elige un estilo' ,
2026-05-03 12:36:50 +00:00
'format_title' => 'Elige un formato' ,
'format_description' => 'Selecciona el tipo de post que quieres crear.' ,
'account_title' => 'Elige una cuenta' ,
'account_description' => 'Selecciona la cuenta social donde publicar.' ,
'media_title' => 'Opciones de medios' ,
'media_carousel' => '¿Cuántas diapositivas?' ,
'media_optional' => '¿Incluir imágenes?' ,
'media_optional_label' => '¿Cuántas imágenes?' ,
'media_none' => 'Ninguna' ,
'media_count_label' => 'Número de imágenes' ,
2026-07-18 18:12:26 +00:00
'brand_colors_label' => 'Colores de marca' ,
'brand_colors_description' => 'Aplica la paleta de tu marca a las imágenes generadas. Desactívalo para que la IA elija los colores que mejor encajen con el contenido.' ,
2026-05-03 12:36:50 +00:00
'prompt_title' => 'Describe tu post' ,
'prompt_label' => '¿De qué trata este post?' ,
'prompt_placeholder' => 'Ej. Anuncia nuestra nueva función de carrusel para Instagram' ,
'preview_error' => 'Algo salió mal. Por favor, inténtalo de nuevo.' ,
2026-05-08 21:30:11 +00:00
'loading_page_title' => 'Generando tu publicación' ,
'loading_eta' => 'Tiempo estimado: cerca de :minutes.' ,
'loading_eta_minute_one' => '1 minuto' ,
'loading_eta_minute_other' => ':count minutos' ,
'loading_leave_title' => 'Puedes seguir trabajando.' ,
'loading_leave_body' => 'Te avisamos cuando la publicación esté lista.' ,
'loading_leave_cta' => 'Ir al calendario' ,
'loading_create_another_cta' => 'Crear otra publicación' ,
'loading_tip_credits' => 'Cada imagen IA usa unos 15 créditos.' ,
'loading_tip_edit' => 'Podrás editar todo cuando la publicación esté lista.' ,
'loading_tip_draft' => 'Las publicaciones generadas van directo a tus borradores.' ,
'loading_tip_brand' => 'Ajusta tu marca para influir en las próximas publicaciones.' ,
'loading_tip_carousel' => 'Los carruseles generan una diapositiva por imagen solicitada.' ,
'loading_tip_quality' => 'La calidad balancea velocidad y costo.' ,
2026-05-03 12:36:50 +00:00
'create' => 'Crear post' ,
'back' => 'Atrás' ,
'next' => 'Continuar' ,
'cancel' => 'Cancelar' ,
'discard' => 'Descartar' ,
'retry' => 'Intentar de nuevo' ,
'no_platforms' => 'Sin cuentas conectadas' ,
'connect_first' => 'Conecta al menos una cuenta social para usar la generación con IA.' ,
2026-06-17 21:09:02 +00:00
'no_account_for_template' => 'Conecta una cuenta compatible para usar esta plantilla.' ,
2026-05-03 12:36:50 +00:00
'format' => [
'instagram_feed' => 'Post de Feed de Instagram' ,
'instagram_carousel' => 'Carrusel de Instagram' ,
'linkedin_post' => 'Post de LinkedIn' ,
'linkedin_page_post' => 'Post de Página de LinkedIn' ,
'x_post' => 'Post en X' ,
'bluesky_post' => 'Post en Bluesky' ,
'threads_post' => 'Post en Threads' ,
'mastodon_post' => 'Post en Mastodon' ,
2026-06-14 01:10:12 +00:00
'telegram_post' => 'Post en Telegram' ,
feat(channels): add Discord as a social channel
Connect a Discord server via OAuth (bot authorization) and schedule/publish
messages to its channels, with mentions and rich embeds.
- Connect: custom Socialite Discord provider (bot scope) maps the authorized
guild to a SocialAccount; throws if no server was authorized.
- Publish: DiscordPublisher posts via the global bot token, validates the chosen
channel belongs to the connected guild (anti cross-guild), optimizes media,
builds allowed_mentions only from explicit mention chips (no accidental pings),
and renders rich embeds.
- Compose: per-post channel picker (live lookup), mention autocomplete and an
embed editor, gated by a required-channel compliance rule; Discord post preview.
- Enum/config/content-type wiring, ConnectionVerifier health check, throttled
lookup endpoints, i18n (en/es/pt-BR), and tests.
Operators must create a Discord application and set DISCORD_CLIENT_ID,
DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN and DISCORD_CLIENT_REDIRECT.
2026-06-16 17:44:00 +00:00
'discord_message' => 'Mensaje de Discord' ,
2026-05-03 12:36:50 +00:00
'facebook_post' => 'Post en Facebook' ,
'pinterest_pin' => 'Pin de Pinterest' ,
'instagram_story' => 'Story de Instagram' ,
'facebook_story' => 'Story de Facebook' ,
],
],
],
'templates' => [
'browser_title' => 'Elige una plantilla' ,
'browser_description' => 'Comienza con una plantilla curada y adáptala.' ,
'search_placeholder' => 'Buscar plantillas…' ,
'no_search_results' => 'Ninguna plantilla coincide con tu búsqueda' ,
'try_different_search' => 'Prueba otra palabra clave o limpia la búsqueda.' ,
'slides_count' => '{count} slide|{count} slides' ,
'all_platforms' => 'Todas las plataformas' ,
2026-05-06 17:26:18 +00:00
'platform_search_placeholder' => 'Buscar plataforma…' ,
'no_platform_match' => 'Ninguna plataforma coincide.' ,
2026-05-03 12:36:50 +00:00
'use_this' => 'Usar esta plantilla' ,
'no_templates' => 'No hay plantillas disponibles.' ,
'applying' => 'Aplicando plantilla…' ,
'category' => [
'product_launch' => 'Lanzamiento de producto' ,
'promotion' => 'Promoción' ,
'educational' => 'Educativo' ,
'behind_the_scenes' => 'Detrás de cámaras' ,
'testimonial' => 'Testimonio' ,
'industry_tip' => 'Consejo del sector' ,
'event' => 'Evento' ,
'engagement' => 'Interacción' ,
],
],
refactor: settings redesign, Spanish translations, language system, strict_types
Settings pages:
- Redesign layout to match Sendkit (max-w-4xl, space-y-12, Separator sections)
- Merge Members page into Workspace settings with Table, invite Dialog, ConfirmDeleteModal
- Add workspace logo upload/delete routes and controller methods
- Translate all hardcoded strings in Workspace.vue modals
Language system:
- Drop languages table, replace language_id FK with locale string column on users
- Create config/languages.php for available languages and default locale
- Add Spanish (es) translations (13 files)
- Simplify HandleInertiaRequests, ProfileController, RegisteredUserController
Code quality:
- Add declare(strict_types=1) to all PHP files
- Fix MastodonPublisher using wrong attribute (filename -> original_filename)
- Fix HasMediaTest for new has_photo/photo_url accessors
- Fix PublishToSocialPlatformTest type error revealed by strict_types
- Remove orphaned Language model from AppServiceProvider morph map
- Update User TypeScript interface (has_photo, photo_url, locale)
- Eager load media relation on workspaces to prevent N+1
- Add 8 new tests for workspace logo upload/delete
- Update workspace settings test to assert members/invitations props
All 710 tests passing.
2026-03-30 03:20:43 +00:00
];