trypost/lang/en/settings.php

364 lines
15 KiB
PHP
Raw Normal View History

2026-01-21 23:50:57 +00:00
<?php
return [
'title' => 'Settings',
'description' => 'Manage your profile and account settings',
'hub' => [
'title' => 'Settings',
'description' => 'Choose what you want to manage.',
'profile' => [
'title' => 'Profile',
'description' => 'Update your personal info, password, and notification preferences.',
],
'workspace' => [
'title' => 'Workspace',
'description' => 'Configure your workspace, brand, members, and API keys.',
],
'account' => [
'title' => 'Account',
'description' => 'Manage your account info, usage, and billing.',
],
],
2026-01-21 23:50:57 +00:00
'nav' => [
'profile' => 'Profile',
'authentication' => 'Authentication',
2026-01-21 23:50:57 +00:00
'workspace' => 'Workspace',
'members' => 'Members',
refactor: notification preferences, header slots, calendar layout, UI polish Notification preferences: - Create notification_preferences table (post_published, post_failed, account_disconnected booleans per user) - NotificationPreferenceController with firstOrCreate on first visit - SendNotification job respects email preferences before sending - Settings page with toggle switches, i18n in 3 languages - 8 new tests for preferences (controller + wantsEmailFor + job integration) Post published notification: - PostPublished mail + maizzle template - Notify owner on successful publish via SendNotification job - PostPublished type added to notification enum Header & Layout: - Rename AppSidebarHeader to AppHeader with left/center/right slots - showSidebarTrigger prop to hide sidebar toggle - Calendar: controls in header (left: nav, center: date, right: tabs + new post) - Fixed header with scrollable content (flex h-screen pattern) - fullWidth pages use overflow-y-auto (fixes month view scroll) UI improvements: - Action buttons moved to header-right: posts, hashtags, labels - Settings breadcrumbs: "Settings > Profile" pattern - Calendar: remove duplicate New Post button from day view - Remove size="sm" from Schedule/Publish buttons - Remove bg-background from header (inherits from SidebarInset) - Add Cancel button to labels and hashtags create/edit dialogs - Add common.cancel i18n key - Clean up orphaned Calendar breadcrumbs - Fix SocialAccountsGrid buttons to use shadcn Button ghost All 753 tests passing.
2026-03-30 21:18:17 +00:00
'notifications' => 'Notifications',
2026-01-21 23:50:57 +00:00
'billing' => 'Billing',
],
refactor: notification preferences, header slots, calendar layout, UI polish Notification preferences: - Create notification_preferences table (post_published, post_failed, account_disconnected booleans per user) - NotificationPreferenceController with firstOrCreate on first visit - SendNotification job respects email preferences before sending - Settings page with toggle switches, i18n in 3 languages - 8 new tests for preferences (controller + wantsEmailFor + job integration) Post published notification: - PostPublished mail + maizzle template - Notify owner on successful publish via SendNotification job - PostPublished type added to notification enum Header & Layout: - Rename AppSidebarHeader to AppHeader with left/center/right slots - showSidebarTrigger prop to hide sidebar toggle - Calendar: controls in header (left: nav, center: date, right: tabs + new post) - Fixed header with scrollable content (flex h-screen pattern) - fullWidth pages use overflow-y-auto (fixes month view scroll) UI improvements: - Action buttons moved to header-right: posts, hashtags, labels - Settings breadcrumbs: "Settings > Profile" pattern - Calendar: remove duplicate New Post button from day view - Remove size="sm" from Schedule/Publish buttons - Remove bg-background from header (inherits from SidebarInset) - Add Cancel button to labels and hashtags create/edit dialogs - Add common.cancel i18n key - Clean up orphaned Calendar breadcrumbs - Fix SocialAccountsGrid buttons to use shadcn Button ghost All 753 tests passing.
2026-03-30 21:18:17 +00:00
'notifications' => [
'title' => 'Notification preferences',
'heading' => 'Email notifications',
'description' => 'Choose which email notifications you want to receive',
'post_published' => 'Post published',
'post_published_description' => 'Receive an email when your post is published successfully',
'post_failed' => 'Post failed',
'post_failed_description' => 'Receive an email when your post fails to publish',
'account_disconnected' => 'Account disconnected',
'account_disconnected_description' => 'Receive an email when a social account is disconnected',
'save' => 'Save preferences',
],
2026-01-21 23:50:57 +00:00
'profile' => [
'title' => 'Profile settings',
'photo_heading' => 'Profile photo',
'photo_description' => 'Upload a profile photo',
2026-01-21 23:50:57 +00:00
'heading' => 'Profile information',
'description' => 'Update your name and email address',
'avatar' => 'Avatar',
'name' => 'Name',
'name_placeholder' => 'Full name',
'email' => 'Email address',
'email_placeholder' => 'Email address',
'email_unverified' => 'Your email address is unverified.',
'resend_verification' => 'Click here to resend the verification email.',
'verification_sent' => 'A new verification link has been sent to your email address.',
'save' => 'Save',
],
'authentication' => [
'title' => 'Authentication',
'page_title' => 'Authentication settings',
'sessions' => [
'title' => 'Active sessions',
'description' => 'If you notice anything suspicious, sign out of other devices.',
'unknown_browser' => 'Unknown browser',
'unknown_ip' => 'Unknown IP',
'on' => 'on',
'active_now' => 'Active now',
'log_out_others' => 'Log out other devices',
'modal_title' => 'Log out other devices',
'modal_description_password' => 'Enter your current password to confirm you want to log out other browser sessions.',
'modal_description_email' => 'Type your email address to confirm you want to log out other browser sessions.',
'password_placeholder' => 'Current password',
'email_placeholder' => 'Your account email',
'cancel' => 'Cancel',
'submit' => 'Log out other devices',
'email_mismatch' => 'The email address does not match your account.',
'flash_logged_out' => 'You have been logged out from other devices.',
],
'password' => [
'update_title' => 'Update password',
'set_title' => 'Set a password',
'update_description' => 'Ensure your account is using a long, random password to stay secure.',
'set_description' => 'Add a password so you can sign in without a connected provider.',
'current_password' => 'Current password',
'new_password' => 'New password',
'confirm_password' => 'Confirm password',
'save' => 'Save password',
'set' => 'Set password',
],
'providers' => [
'title' => 'Connected accounts',
'description' => 'Sign in faster with these connected providers.',
'connected' => 'Connected',
'not_connected' => 'Not connected',
'connect' => 'Connect',
'disconnect' => 'Disconnect',
'flash_disconnected' => ':provider disconnected successfully.',
'flash_connected' => ':provider connected successfully.',
'flash_already_linked' => 'That :provider account is already linked to another user.',
'flash_cannot_disconnect' => 'You cannot disconnect your only sign-in method. Set a password or connect another provider first.',
],
2026-01-21 23:50:57 +00:00
],
'delete_account' => [
'heading' => 'Delete account',
'description' => 'Delete your account and all of its resources',
'warning' => 'Warning',
'warning_message' => 'Please proceed with caution, this cannot be undone.',
'button' => 'Delete account',
'modal_title' => 'Are you sure you want to delete your account?',
'modal_description_password' => 'Once your account is deleted, all of its resources and data will also be permanently deleted. Please enter your password to confirm.',
'modal_description_email' => 'Once your account is deleted, all of its resources and data will also be permanently deleted. Please type your email address :email to confirm.',
2026-01-21 23:50:57 +00:00
'password' => 'Password',
'password_placeholder' => 'Password',
'email_placeholder' => 'Your account email',
'email_mismatch' => 'The email address does not match your account.',
2026-01-21 23:50:57 +00:00
'cancel' => 'Cancel',
'confirm' => 'Delete account',
],
'workspace' => [
feat: @mentions in comments, AI Action layer + MCP tools, settings tabs Mentions in post comments - @mention autocomplete (workspace members, current user excluded) with marker syntax @[uuid] persisted, display names rendered via CommentBody chips; live edit replaces markers with names and converts back on save. - NotifyMentions action with workspace-scoped membership check, dedupes same user, only newly-added mentions on update. - Email + in-app via SendNotification job, respecting per-user notification_preferences.mentioned_in_comment. - Heartbeat-based presence (Cache, 60s TTL, 30s ping) so online recipients get only the in-app notification — no email noise. - Real-time bell on workspace.{id}.user.{id} private channel (NotificationCreated event), scoped channel name avoids client-side filtering and lays out a convention for future workspace channels. - Mailable localized via lang/{en,es,pt-BR}/mail.php; Maizzle source template for the email is committed and built into resources/views/mail. AI generation refactor (Action layer + MCP) - Extracted Actions/Ai/Generate{Image,Video} with QuotaExhaustedException so agent tools and MCP tools share a single domain entry point. - Mcp/Tools/Ai/Generate{Image,Video}Tool registered in TryPostServer; both return MediaResource payloads. - Orientation::imageApiSize maps non-OpenAI ratios to 1:1/2:3/3:2. - config/ai.php is now the single source of truth driven by env, removing the trypost.ai shim. Default text/image providers flipped to OpenAI. Settings/UX - /settings/workspace split into shadcn Tabs (Workspace / Brand / Users) with three components. - /assets and the in-editor MediaPicker open the ImagePreviewDialog lightbox on image click while preserving action button behaviour. - Comments tab landed via ?tab=comments&comment=<id> from notification click (scroll-to + temporary highlight). - Mention autocomplete popover flips above when near the viewport bottom. - Real social platform PNGs replace Tabler brand glyphs in schedule pills and post list, with hover tooltip carrying display_name + handle. Bug fixes - AcceptInvite: controller now passes workspace + role payload that the Vue page expects; login/register CTAs preselect the invite email. - WorkspaceInvite mailable: stopped referencing nonexistent $invite->workspace and $invite->role; column added to the migration, Invite model casts role to WorkspaceRole, CreateInvite persists it. - PostCommentCreated: added broadcastAs so .PostCommentCreated actually matches the Echo listener; payload now includes mentioned_users so receivers render the chip correctly without a refetch. - Preview components for X/Pinterest/Threads/Bluesky/LinkedIn/Mastodon/ TikTok/YouTube switched from item.type === 'image' to !isVideoMedia(item) so media without a persisted type still renders. - UpdatePostRequest now accepts media.*.{type,mime_type,size,...} so the posts.media JSON keeps the metadata that the previews need. - Removed throttle:6,1 from social connect routes (was 429ing legitimate OAuth retries). - Used MediaType enum cases instead of literal 'image'/'video' strings when creating media rows. Tests - MentionParser unit tests, NotifyMentions feature tests including online/offline channel selection and preference gating, MCP AI tool happy paths, MentionedInComment mailable rendering, AcceptInvite + search-members + index mentioned_users path. 1229 passing.
2026-05-01 23:59:03 +00:00
'tabs' => [
'workspace' => 'Workspace',
'brand' => 'Brand',
'users' => 'Members',
'api_keys' => 'API Keys',
feat: @mentions in comments, AI Action layer + MCP tools, settings tabs Mentions in post comments - @mention autocomplete (workspace members, current user excluded) with marker syntax @[uuid] persisted, display names rendered via CommentBody chips; live edit replaces markers with names and converts back on save. - NotifyMentions action with workspace-scoped membership check, dedupes same user, only newly-added mentions on update. - Email + in-app via SendNotification job, respecting per-user notification_preferences.mentioned_in_comment. - Heartbeat-based presence (Cache, 60s TTL, 30s ping) so online recipients get only the in-app notification — no email noise. - Real-time bell on workspace.{id}.user.{id} private channel (NotificationCreated event), scoped channel name avoids client-side filtering and lays out a convention for future workspace channels. - Mailable localized via lang/{en,es,pt-BR}/mail.php; Maizzle source template for the email is committed and built into resources/views/mail. AI generation refactor (Action layer + MCP) - Extracted Actions/Ai/Generate{Image,Video} with QuotaExhaustedException so agent tools and MCP tools share a single domain entry point. - Mcp/Tools/Ai/Generate{Image,Video}Tool registered in TryPostServer; both return MediaResource payloads. - Orientation::imageApiSize maps non-OpenAI ratios to 1:1/2:3/3:2. - config/ai.php is now the single source of truth driven by env, removing the trypost.ai shim. Default text/image providers flipped to OpenAI. Settings/UX - /settings/workspace split into shadcn Tabs (Workspace / Brand / Users) with three components. - /assets and the in-editor MediaPicker open the ImagePreviewDialog lightbox on image click while preserving action button behaviour. - Comments tab landed via ?tab=comments&comment=<id> from notification click (scroll-to + temporary highlight). - Mention autocomplete popover flips above when near the viewport bottom. - Real social platform PNGs replace Tabler brand glyphs in schedule pills and post list, with hover tooltip carrying display_name + handle. Bug fixes - AcceptInvite: controller now passes workspace + role payload that the Vue page expects; login/register CTAs preselect the invite email. - WorkspaceInvite mailable: stopped referencing nonexistent $invite->workspace and $invite->role; column added to the migration, Invite model casts role to WorkspaceRole, CreateInvite persists it. - PostCommentCreated: added broadcastAs so .PostCommentCreated actually matches the Echo listener; payload now includes mentioned_users so receivers render the chip correctly without a refetch. - Preview components for X/Pinterest/Threads/Bluesky/LinkedIn/Mastodon/ TikTok/YouTube switched from item.type === 'image' to !isVideoMedia(item) so media without a persisted type still renders. - UpdatePostRequest now accepts media.*.{type,mime_type,size,...} so the posts.media JSON keeps the metadata that the previews need. - Removed throttle:6,1 from social connect routes (was 429ing legitimate OAuth retries). - Used MediaType enum cases instead of literal 'image'/'video' strings when creating media rows. Tests - MentionParser unit tests, NotifyMentions feature tests including online/offline channel selection and preference gating, MCP AI tool happy paths, MentionedInComment mailable rendering, AcceptInvite + search-members + index mentioned_users path. 1229 passing.
2026-05-01 23:59:03 +00:00
],
2026-01-21 23:50:57 +00:00
'title' => 'Workspace settings',
'logo_heading' => 'Workspace logo',
'logo_description' => 'Upload a logo for your workspace',
'heading' => 'Workspace name',
'description' => 'Update your workspace name',
'members_heading' => 'Members',
'members_description' => 'Manage workspace members and invitations',
2026-01-21 23:50:57 +00:00
'name' => 'Name',
'name_placeholder' => 'My Workspace',
'save' => 'Save',
],
'brand' => [
'title' => 'Brand',
'description' => 'Configure your brand identity for AI-generated content.',
feat: AI image generation pipeline and post creation overhaul Core changes: - Replace Unsplash slide pipeline with gpt-image-2 via Laravel AI SDK. New AiImageClient builds prompts from a Blade template seeded by the workspace's ImageStyle enum, content language, brand color (mapped to a human-readable name via HexColorName helper) and brand description. - Drop Template B from TemplateImageGenerator: every slide now renders as Template A (full-bleed photo + bottom gradient + white/grey overlay). Removes renderTemplateB, roundCorners, blendHex, ensureContrast and the closing-slide pipeline. - StreamPostCreation creates the Post directly and dispatches PostCreationReady with post_id; the wizard kills its preview step and redirects straight to the post editor on completion. Finalize endpoint removed. - New Workspace.image_style enum field with an 8-option visual picker shared by /workspaces/create and /settings/workspace/brand via a single BrandForm component (autofill is a prop). 8 sample webp thumbs ship under public/images/branding/image-styles/. - Media items gain optional source ('ai'|'unsplash'|'giphy') and source_meta (recipe needed to regenerate AI images later); the gallery picker tags Unsplash/Giphy attachments. - Brand-color autofill: new CssColorFrequencyExtractor parses every hex/rgb/hsl value in the homepage CSS, clusters perceptually similar shades in CIE LAB (Delta E 76 < 12), filters neutrals and returns the most frequent cluster. Solves Tailwind/utility-CSS sites where no semantic --primary variable is exposed. - Credits: gpt-image-2 metered at 15 credits/image (low quality default). - Layout: AuthSplitLayout right column is sticky/h-svh so the form textarea growth no longer stretches the marketing slider. - i18n cleanup: localized labels follow the no-em-dash convention.
2026-05-08 16:38:30 +00:00
'name' => 'Workspace name',
'name_placeholder' => 'My brand',
'website' => 'Website',
'website_placeholder' => 'https://yourbrand.com',
'brand_description' => 'Description',
'brand_description_placeholder' => 'Tell us about your brand, what you do, and who your audience is...',
'voice' => 'Brand voice',
'voice_description' => 'Pick the traits that define how your content sounds.',
'voice_group' => [
'pov' => 'Point of view',
'formality' => 'Formality',
'energy' => 'Energy',
'humor' => 'Humor',
'attitude' => 'Attitude',
'warmth' => 'Warmth',
'confidence' => 'Confidence',
'style' => 'Style',
],
'voice_trait' => [
'first_person' => 'First person',
'second_person' => 'Second person (you)',
'third_person' => 'Third person',
'formal' => 'Formal',
'balanced' => 'Balanced',
'casual' => 'Casual',
'calm' => 'Calm',
'moderate' => 'Moderate',
'enthusiastic' => 'Enthusiastic',
'vibrant' => 'Vibrant',
'serious' => 'Serious',
'dry' => 'Dry / subtle',
'witty' => 'Witty',
'playful' => 'Playful',
'respectful' => 'Respectful',
'even_handed' => 'Even-handed',
'bold' => 'Bold',
'provocative' => 'Provocative',
'neutral' => 'Neutral',
'friendly' => 'Friendly',
'empathetic' => 'Empathetic',
'humble' => 'Humble',
'confident' => 'Confident',
'assertive' => 'Assertive',
'direct' => 'Direct',
'concise' => 'Concise',
'transparent' => 'Transparent',
'no_hype' => 'No hype',
'practical' => 'Practical',
'data_driven' => 'Data-driven',
'storytelling' => 'Storytelling',
'inspirational' => 'Inspirational',
'educational' => 'Educational',
'technical' => 'Technical',
'minimalist' => 'Few emojis',
],
'brand_color' => 'Brand color',
'background_color' => 'Background color',
'text_color' => 'Text color',
'font' => 'Font',
feat: AI image generation pipeline and post creation overhaul Core changes: - Replace Unsplash slide pipeline with gpt-image-2 via Laravel AI SDK. New AiImageClient builds prompts from a Blade template seeded by the workspace's ImageStyle enum, content language, brand color (mapped to a human-readable name via HexColorName helper) and brand description. - Drop Template B from TemplateImageGenerator: every slide now renders as Template A (full-bleed photo + bottom gradient + white/grey overlay). Removes renderTemplateB, roundCorners, blendHex, ensureContrast and the closing-slide pipeline. - StreamPostCreation creates the Post directly and dispatches PostCreationReady with post_id; the wizard kills its preview step and redirects straight to the post editor on completion. Finalize endpoint removed. - New Workspace.image_style enum field with an 8-option visual picker shared by /workspaces/create and /settings/workspace/brand via a single BrandForm component (autofill is a prop). 8 sample webp thumbs ship under public/images/branding/image-styles/. - Media items gain optional source ('ai'|'unsplash'|'giphy') and source_meta (recipe needed to regenerate AI images later); the gallery picker tags Unsplash/Giphy attachments. - Brand-color autofill: new CssColorFrequencyExtractor parses every hex/rgb/hsl value in the homepage CSS, clusters perceptually similar shades in CIE LAB (Delta E 76 < 12), filters neutrals and returns the most frequent cluster. Solves Tailwind/utility-CSS sites where no semantic --primary variable is exposed. - Credits: gpt-image-2 metered at 15 credits/image (low quality default). - Layout: AuthSplitLayout right column is sticky/h-svh so the form textarea growth no longer stretches the marketing slider. - i18n cleanup: localized labels follow the no-em-dash convention.
2026-05-08 16:38:30 +00:00
'image_style' => 'Image style',
'image_style_description' => 'Visual style applied when generating slide and cover images for AI posts.',
'image_style_cinematic' => 'Cinematic',
'image_style_illustration' => 'Illustration',
'image_style_isometric_3d' => 'Isometric',
'image_style_cartoon' => 'Cartoon',
'image_style_typographic' => 'Typographic',
'image_style_infographic' => 'Infographic',
'image_style_minimalist' => 'Minimalist',
'image_style_mockup' => 'Mockup',
feat: add workspace content_language setting for AI generation Users can now pick the language AI uses for captions, hashtags, descriptions, AND on-image / on-screen text — independent of the app UI locale. A user with pt-BR UI who writes for an English audience gets English content, and vice versa. - New content_language column on workspaces (added to the existing create_workspaces_table migration since we're pre-production), defaulting to 'en'. Fillable on the model. - Dropdown in Settings → Workspace → Brand, side-by-side with Tone. Options: English, Português (Brasil), Español. Short helper copy explains what the setting controls. - Validation: sometimes|string|in:en,pt-BR,es — optional on update so existing callers that don't post the field keep the current value (DB default handles fresh workspaces). - System prompt now uses $content_language (sourced from the workspace) instead of app()->getLocale(). The rule was also strengthened: the AI must always write in this language regardless of what language the user types instructions in, and must instruct image/video tools to render on-media text in this language too. - Image and video Blade prompts received a new line forcing any text rendered inside the generated media to use $content_language. - GenerateImage tool and VideoGenerationService pass the workspace's content_language into their respective prompt templates. Previously the caption would be in Portuguese (since it followed the user's input language) but the image could render with English text because there was no explicit constraint. Now the whole pipeline is aligned to one per-workspace language.
2026-04-16 13:37:03 +00:00
'content_language' => 'Content language',
'content_language_description' => 'Language used for AI-generated captions, hashtags, and any text inside generated images or videos.',
'font_placeholder' => 'Select a font…',
'font_search' => 'Search font…',
'font_empty' => 'No fonts match.',
'language_placeholder' => 'Select a language…',
'language_search' => 'Search language…',
'language_empty' => 'No language found.',
],
2026-01-21 23:50:57 +00:00
'members' => [
'title' => 'Members',
'heading' => 'Team members',
'description' => 'Manage members and invites for this workspace',
'cancel' => 'Cancel',
'remove' => 'Remove',
'make_role' => 'Make :role',
2026-01-21 23:50:57 +00:00
'invite' => [
'title' => 'Invite Member',
'description' => 'Send an email invite to add collaborators',
'email' => 'Email',
'email_placeholder' => 'collaborator@email.com',
'role' => 'Role',
'role_placeholder' => 'Select a role',
'submit' => 'Send Invite',
],
'pending' => [
'title' => 'Pending Invites',
'description' => 'Invites awaiting acceptance',
'empty' => 'No pending invites',
],
'list' => [
'title' => 'Members',
'description' => 'People with access to this workspace',
'empty' => 'No members besides the owner',
],
'remove_modal' => [
'title' => 'Remove member',
'description' => 'Are you sure you want to remove this member from the workspace? They will lose access to all workspace resources.',
'action' => 'Remove member',
],
'cancel_invite_modal' => [
'title' => 'Cancel invitation',
'description' => 'Are you sure you want to cancel this invitation?',
'action' => 'Cancel invitation',
2026-01-21 23:50:57 +00:00
],
'roles' => [
'owner' => 'Owner',
'admin' => 'Admin',
'member' => 'Member',
feat: @mentions in comments, AI Action layer + MCP tools, settings tabs Mentions in post comments - @mention autocomplete (workspace members, current user excluded) with marker syntax @[uuid] persisted, display names rendered via CommentBody chips; live edit replaces markers with names and converts back on save. - NotifyMentions action with workspace-scoped membership check, dedupes same user, only newly-added mentions on update. - Email + in-app via SendNotification job, respecting per-user notification_preferences.mentioned_in_comment. - Heartbeat-based presence (Cache, 60s TTL, 30s ping) so online recipients get only the in-app notification — no email noise. - Real-time bell on workspace.{id}.user.{id} private channel (NotificationCreated event), scoped channel name avoids client-side filtering and lays out a convention for future workspace channels. - Mailable localized via lang/{en,es,pt-BR}/mail.php; Maizzle source template for the email is committed and built into resources/views/mail. AI generation refactor (Action layer + MCP) - Extracted Actions/Ai/Generate{Image,Video} with QuotaExhaustedException so agent tools and MCP tools share a single domain entry point. - Mcp/Tools/Ai/Generate{Image,Video}Tool registered in TryPostServer; both return MediaResource payloads. - Orientation::imageApiSize maps non-OpenAI ratios to 1:1/2:3/3:2. - config/ai.php is now the single source of truth driven by env, removing the trypost.ai shim. Default text/image providers flipped to OpenAI. Settings/UX - /settings/workspace split into shadcn Tabs (Workspace / Brand / Users) with three components. - /assets and the in-editor MediaPicker open the ImagePreviewDialog lightbox on image click while preserving action button behaviour. - Comments tab landed via ?tab=comments&comment=<id> from notification click (scroll-to + temporary highlight). - Mention autocomplete popover flips above when near the viewport bottom. - Real social platform PNGs replace Tabler brand glyphs in schedule pills and post list, with hover tooltip carrying display_name + handle. Bug fixes - AcceptInvite: controller now passes workspace + role payload that the Vue page expects; login/register CTAs preselect the invite email. - WorkspaceInvite mailable: stopped referencing nonexistent $invite->workspace and $invite->role; column added to the migration, Invite model casts role to WorkspaceRole, CreateInvite persists it. - PostCommentCreated: added broadcastAs so .PostCommentCreated actually matches the Echo listener; payload now includes mentioned_users so receivers render the chip correctly without a refetch. - Preview components for X/Pinterest/Threads/Bluesky/LinkedIn/Mastodon/ TikTok/YouTube switched from item.type === 'image' to !isVideoMedia(item) so media without a persisted type still renders. - UpdatePostRequest now accepts media.*.{type,mime_type,size,...} so the posts.media JSON keeps the metadata that the previews need. - Removed throttle:6,1 from social connect routes (was 429ing legitimate OAuth retries). - Used MediaType enum cases instead of literal 'image'/'video' strings when creating media rows. Tests - MentionParser unit tests, NotifyMentions feature tests including online/offline channel selection and preference gating, MCP AI tool happy paths, MentionedInComment mailable rendering, AcceptInvite + search-members + index mentioned_users path. 1229 passing.
2026-05-01 23:59:03 +00:00
'viewer' => 'Viewer',
2026-01-21 23:50:57 +00:00
],
2026-01-22 01:08:18 +00:00
'flash' => [
'invite_sent' => 'Invite sent successfully!',
'invite_deleted' => 'Invite deleted.',
'member_removed' => 'Member removed successfully.',
refactor: auth split layout, subscribe redesign, onboarding, i18n, cookie locale Auth pages: - Create AuthSplitLayout with animated feature slides (6 slides, 3 languages) - All auth pages use split layout (form left, visual right) - Add show/hide password toggle with tooltip on Register - Legal footer only shown on Register via showLegal prop Subscribe page: - Redesign to match auth card pattern (centered, clean) - Platform icons, feature checklist, dynamic trial days (trialDays - 1) - Add "Switch workspace" link - Full i18n (en, es, pt-BR) Onboarding: - Rename URLs: step1 -> role, step2 -> connect - Add enforceStep() to prevent skipping/going back steps - Redirect /onboarding to /onboarding/role - Redesign Step2 with AuthSplitLayout and compact platform list - 21 tests covering all step enforcement scenarios Workspaces page: - Redesign with AuthSplitLayout (list with avatars, current badge) Language system: - Move locale from DB to cookie (forever, unencrypted, session.domain) - Create SetLocale middleware (sets cookie if missing, validates against config) - Rename lang/pt-br to lang/pt-BR - Add dayjs es locale Other: - Copy utils.ts from sendkit (formatNumber, formatMoney, copyToClipboard) - ConfirmDeleteModal with text confirmation (sendkit pattern) - i18n for ConfirmDeleteModal internal strings (common.php) - EmptyState component for posts index - Exact match for "All" posts in sidebar - Posts breadcrumbs show current status filter - DialogFooter buttons aligned left - API Keys page redesign with Table, DropdownMenu, EmptyState - Extract CreateApiKeyDialog and InviteMemberDialog to components - Remove API Keys from sidebar - DropdownMenuItem destructive variant for Remove action
2026-03-30 14:53:42 +00:00
'role_updated' => 'Member role updated.',
2026-01-22 01:08:18 +00:00
'wrong_email' => 'This invite is for a different email address.',
'already_member' => 'You are already a member of this workspace.',
'invite_accepted' => 'Welcome! You are now a member of the workspace.',
'invite_declined' => 'Invite declined.',
],
],
'account' => [
'tabs' => [
'account' => 'Account',
'usage' => 'Usage',
'billing' => 'Billing',
],
'title' => 'Account Settings',
'description' => 'Manage your account name and billing email',
'name' => 'Account Name',
'name_placeholder' => 'My Company',
'billing_email' => 'Billing Email',
'billing_email_placeholder' => 'billing@company.com',
'billing_email_hint' => 'This email will be used for invoices and billing communications from Stripe.',
'submit' => 'Save',
],
2026-01-22 01:08:18 +00:00
'flash' => [
'account_updated' => 'Account updated successfully!',
2026-01-22 01:08:18 +00:00
'profile_updated' => 'Profile updated successfully!',
'password_updated' => 'Password updated successfully!',
'workspace_updated' => 'Settings updated successfully!',
'photo_updated' => 'Photo updated successfully!',
'photo_deleted' => 'Photo removed successfully!',
'logo_updated' => 'Logo uploaded successfully!',
'logo_deleted' => 'Logo removed successfully!',
refactor: notification preferences, header slots, calendar layout, UI polish Notification preferences: - Create notification_preferences table (post_published, post_failed, account_disconnected booleans per user) - NotificationPreferenceController with firstOrCreate on first visit - SendNotification job respects email preferences before sending - Settings page with toggle switches, i18n in 3 languages - 8 new tests for preferences (controller + wantsEmailFor + job integration) Post published notification: - PostPublished mail + maizzle template - Notify owner on successful publish via SendNotification job - PostPublished type added to notification enum Header & Layout: - Rename AppSidebarHeader to AppHeader with left/center/right slots - showSidebarTrigger prop to hide sidebar toggle - Calendar: controls in header (left: nav, center: date, right: tabs + new post) - Fixed header with scrollable content (flex h-screen pattern) - fullWidth pages use overflow-y-auto (fixes month view scroll) UI improvements: - Action buttons moved to header-right: posts, hashtags, labels - Settings breadcrumbs: "Settings > Profile" pattern - Calendar: remove duplicate New Post button from day view - Remove size="sm" from Schedule/Publish buttons - Remove bg-background from header (inherits from SidebarInset) - Add Cancel button to labels and hashtags create/edit dialogs - Add common.cancel i18n key - Clean up orphaned Calendar breadcrumbs - Fix SocialAccountsGrid buttons to use shadcn Button ghost All 753 tests passing.
2026-03-30 21:18:17 +00:00
'notifications_updated' => 'Notification preferences updated!',
2026-01-21 23:50:57 +00:00
],
'api_keys' => [
'title' => 'API Keys',
'page_title' => 'API Keys',
'heading' => 'API Keys',
'description' => 'Manage API keys for programmatic access to your workspace.',
'create' => 'Create API Key',
'copy' => 'Copy',
'new_token_message' => 'Your new API key has been created. Copy it now — you won\'t be able to see it again.',
'table' => [
'name' => 'Name',
'key' => 'Key',
'status' => 'Status',
'expires' => 'Expires',
'last_used' => 'Last Used',
'never' => 'Never',
],
'actions' => [
'copy_id' => 'Copy API Key ID',
'copy_id_success' => 'API Key ID copied to clipboard',
'delete' => 'Delete',
],
'empty' => [
'title' => 'No API keys yet',
'description' => 'Create an API key to access your workspace programmatically.',
],
'delete_modal' => [
'title' => 'Delete API key',
'description' => 'Are you sure you want to delete this API key? Any applications using this key will lose access immediately.',
'action' => 'Delete API key',
],
'create_dialog' => [
'title' => 'Create API Key',
'description' => 'Create a new API key for programmatic access to your workspace.',
'name' => 'Name',
'name_placeholder' => 'e.g. Production API Key',
'expires' => 'Expiration date (optional)',
'expires_placeholder' => 'No expiration',
'submit' => 'Create',
'cancel' => 'Cancel',
],
'flash' => [
'created' => 'API key created successfully!',
'deleted' => 'API key deleted successfully!',
],
],
2026-01-21 23:50:57 +00:00
];