From f3f72afecd4c54d8f06ed6bad7ecdc765f19b055 Mon Sep 17 00:00:00 2001
From: Paulo Castellano
- 📚 Documentation • + 📚 Documentation • 🗺️ Roadmap • 💬 Community
@@ -30,23 +30,23 @@ ## 🤔 Why TryPost? Tired of paying expensive monthly fees for social media scheduling tools? Want full control over your data? TryPost is the solution. -| | | -|---|---| -| 🔓 **100% Open Source** | Inspect the code, contribute, make it yours | -| 🏠 **Self-Hosted** | Your data stays on your servers | -| ♾️ **No Limits** | Schedule unlimited posts, connect unlimited accounts | -| 🔒 **Privacy First** | No tracking, no analytics, no data selling | +| | | +| ----------------------- | ---------------------------------------------------- | +| 🔓 **100% Open Source** | Inspect the code, contribute, make it yours | +| 🏠 **Self-Hosted** | Your data stays on your servers | +| ♾️ **No Limits** | Schedule unlimited posts, connect unlimited accounts | +| 🔒 **Privacy First** | No tracking, no analytics, no data selling | ## ✨ Features -| | | -|---|---| -| 📅 **Visual Calendar** | Drag and drop posts across your content calendar | -| ✍️ **Post Composer** | Create and preview posts for multiple platforms at once | -| 🖼️ **Media Library** | Upload images and videos with automatic optimization | -| 👥 **Team Collaboration** | Invite team members with role-based permissions | -| 🏢 **Workspaces** | Manage multiple brands or clients separately | -| 👀 **Multi-Platform Preview** | See exactly how your post will look on each platform | +| | | +| ----------------------------- | ------------------------------------------------------- | +| 📅 **Visual Calendar** | Drag and drop posts across your content calendar | +| ✍️ **Post Composer** | Create and preview posts for multiple platforms at once | +| 🖼️ **Media Library** | Upload images and videos with automatic optimization | +| 👥 **Team Collaboration** | Invite team members with role-based permissions | +| 🏢 **Workspaces** | Manage multiple brands or clients separately | +| 👀 **Multi-Platform Preview** | See exactly how your post will look on each platform | ## 🌐 Supported Platforms @@ -71,12 +71,12 @@ ## 🚀 Getting Started Get TryPost running in minutes: -| | | -|---|---| -| 📖 [Installation Guide](https://docs.trypost.it/getting-started/installation) | Step-by-step setup | -| 🐳 [Docker Setup](https://docs.trypost.it/self-hosting/docker) | Run with Laravel Sail | -| ⚙️ [Configuration](https://docs.trypost.it/getting-started/configuration) | Environment setup | -| 🔗 [Platform Setup](https://docs.trypost.it/platforms/) | Connect your social accounts | +| | | +| ----------------------------------------------------------------------------- | ---------------------------- | +| 📖 [Installation Guide](https://trypost.it/docs/getting-started/installation) | Step-by-step setup | +| 🐳 [Docker Setup](https://trypost.it/docs/self-hosting/docker) | Run with Laravel Sail | +| ⚙️ [Configuration](https://trypost.it/docs/getting-started/configuration) | Environment setup | +| 🔗 [Platform Setup](https://trypost.it/docs/platforms/) | Connect your social accounts | ## 🤝 Contributing diff --git a/app/Helpers/Asset.php b/app/Helpers/Asset.php new file mode 100644 index 00000000..12bafc08 --- /dev/null +++ b/app/Helpers/Asset.php @@ -0,0 +1,13 @@ +enforceStep($request->user(), Setup::Role); + if ($redirect) { + return $redirect; + } + return Inertia::render('onboarding/Step1', [ 'personas' => Persona::toSelectArray(), ]); @@ -34,11 +40,16 @@ public function storeStep1(Request $request): RedirectResponse 'setup' => Setup::Connections, ]); - return redirect()->route('app.onboarding.step2'); + return redirect()->route('app.onboarding.connect'); } - public function step2(Request $request): Response + public function step2(Request $request): Response|RedirectResponse { + $redirect = $this->enforceStep($request->user(), Setup::Connections); + if ($redirect) { + return $redirect; + } + $user = $request->user(); $workspace = $user->currentWorkspace; @@ -88,7 +99,7 @@ public function storeStep2(Request $request): SymfonyResponse|RedirectResponse $checkoutSession = $subscription->checkout([ 'success_url' => route('app.onboarding.complete').'?session_id={CHECKOUT_SESSION_ID}', - 'cancel_url' => route('app.onboarding.step2'), + 'cancel_url' => route('app.onboarding.connect'), ]); return Inertia::location($checkoutSession->url); @@ -107,4 +118,22 @@ public function complete(Request $request): RedirectResponse return redirect()->route('app.calendar'); } + + private function enforceStep(User $user, Setup $expectedStep): ?RedirectResponse + { + if ($user->setup === $expectedStep) { + return null; + } + + if ($user->setup === Setup::Completed) { + return redirect()->route('app.calendar'); + } + + return match ($user->setup) { + Setup::Role => redirect()->route('app.onboarding.role'), + Setup::Connections => redirect()->route('app.onboarding.connect'), + Setup::Subscription => redirect()->route('app.subscribe'), + default => redirect()->route('app.onboarding.role'), + }; + } } diff --git a/app/Http/Controllers/App/Settings/ProfileController.php b/app/Http/Controllers/App/Settings/ProfileController.php index 30ad8594..ef0cd314 100644 --- a/app/Http/Controllers/App/Settings/ProfileController.php +++ b/app/Http/Controllers/App/Settings/ProfileController.php @@ -77,14 +77,12 @@ public function updateLanguage(Request $request): RedirectResponse 'locale' => ['required', 'string', 'in:'.implode(',', array_keys(config('languages.available')))], ]); - $request->user()->update([ - 'locale' => $request->locale, - ]); - session()->flash('flash.banner', __('settings.flash.language_updated')); session()->flash('flash.bannerStyle', 'success'); - return back(); + return back()->withCookie( + cookie()->forever('locale', $request->locale, '/', config('session.domain')) + ); } public function destroy(ProfileDeleteRequest $request): RedirectResponse diff --git a/app/Http/Controllers/App/WorkspaceController.php b/app/Http/Controllers/App/WorkspaceController.php index 72f645e7..0e3cebf8 100644 --- a/app/Http/Controllers/App/WorkspaceController.php +++ b/app/Http/Controllers/App/WorkspaceController.php @@ -21,6 +21,7 @@ public function index(Request $request): Response $user = $request->user(); $workspaces = $user->workspaces() + ->with('media') ->withCount(['socialAccounts', 'posts']) ->latest() ->get(); diff --git a/app/Http/Controllers/App/WorkspaceInviteController.php b/app/Http/Controllers/App/WorkspaceInviteController.php index 39068f01..969ccf67 100644 --- a/app/Http/Controllers/App/WorkspaceInviteController.php +++ b/app/Http/Controllers/App/WorkspaceInviteController.php @@ -12,6 +12,7 @@ use App\Models\WorkspaceInvite; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Validation\Rule; use Inertia\Inertia; use Inertia\Response; @@ -133,4 +134,32 @@ public function removeMember(Request $request, string $userId): RedirectResponse return back(); } + + public function updateRole(Request $request, string $userId): RedirectResponse + { + $workspace = $request->user()->currentWorkspace; + + if (! $workspace) { + return redirect()->route('app.workspaces.create'); + } + + $this->authorize('manageTeam', $workspace); + + if ($workspace->user_id === $userId) { + return back()->withErrors(['role' => 'Cannot change the workspace owner role.']); + } + + $validated = $request->validate([ + 'role' => ['required', Rule::enum(WorkspaceRole::class)], + ]); + + $workspace->members()->updateExistingPivot($userId, [ + 'role' => data_get($validated, 'role'), + ]); + + session()->flash('flash.banner', __('settings.members.flash.role_updated')); + session()->flash('flash.bannerStyle', 'success'); + + return back(); + } } diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php index 9edaccb4..83a6d034 100644 --- a/app/Http/Controllers/Auth/RegisteredUserController.php +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -52,7 +52,6 @@ public function store(Request $request): RedirectResponse 'email' => $request->email, 'password' => $request->password, 'setup' => $isInviteRegistration ? Setup::Completed : Setup::Role, - 'locale' => config('languages.default'), 'email_verified_at' => $isInviteRegistration ? now() : null, ]); @@ -81,6 +80,6 @@ public function store(Request $request): RedirectResponse return redirect($redirect); } - return redirect()->route('app.onboarding.step1'); + return redirect()->route('app.onboarding.role'); } } diff --git a/app/Http/Controllers/Auth/SocialController.php b/app/Http/Controllers/Auth/SocialController.php index 5ed0e076..88005eeb 100644 --- a/app/Http/Controllers/Auth/SocialController.php +++ b/app/Http/Controllers/Auth/SocialController.php @@ -179,7 +179,7 @@ protected function forgetSocialConnectSession(): void protected function getRedirectRoute(): string { - return session('social_connect_onboarding', false) ? 'onboarding.step2' : 'accounts'; + return session('social_connect_onboarding', false) ? 'onboarding.connect' : 'accounts'; } /** diff --git a/app/Http/Middleware/App/EnsureUserSetupIsComplete.php b/app/Http/Middleware/App/EnsureUserSetupIsComplete.php index 37c279a2..caffd2b7 100644 --- a/app/Http/Middleware/App/EnsureUserSetupIsComplete.php +++ b/app/Http/Middleware/App/EnsureUserSetupIsComplete.php @@ -31,10 +31,10 @@ public function handle(Request $request, Closure $next): Response // Map setup status to allowed routes $allowedRoutes = match ($user->setup) { - Setup::Role => ['onboarding.step1', 'onboarding.step1.store'], - Setup::Connections => ['onboarding.step2', 'onboarding.step2.store', 'social.*'], - Setup::Subscription => ['onboarding.complete', 'onboarding.step2'], - default => ['onboarding.step1', 'onboarding.step1.store'], + Setup::Role => ['onboarding.role', 'onboarding.role.store'], + Setup::Connections => ['onboarding.connect', 'onboarding.connect.store', 'social.*'], + Setup::Subscription => ['onboarding.complete', 'onboarding.connect'], + default => ['onboarding.role', 'onboarding.role.store'], }; $currentRoute = $request->route()?->getName(); @@ -48,10 +48,10 @@ public function handle(Request $request, Closure $next): Response // Redirect to appropriate step return match ($user->setup) { - Setup::Role => redirect()->route('app.onboarding.step1'), - Setup::Connections => redirect()->route('app.onboarding.step2'), - Setup::Subscription => redirect()->route('app.onboarding.step2'), - default => redirect()->route('app.onboarding.step1'), + Setup::Role => redirect()->route('app.onboarding.role'), + Setup::Connections => redirect()->route('app.onboarding.connect'), + Setup::Subscription => redirect()->route('app.onboarding.connect'), + default => redirect()->route('app.onboarding.role'), }; } } diff --git a/app/Http/Middleware/App/HandleInertiaRequests.php b/app/Http/Middleware/App/HandleInertiaRequests.php index 29d1097e..dab26efc 100644 --- a/app/Http/Middleware/App/HandleInertiaRequests.php +++ b/app/Http/Middleware/App/HandleInertiaRequests.php @@ -7,7 +7,6 @@ use App\Http\Resources\App\HandleInertiaRequests\AuthUserResource; use App\Http\Resources\App\HandleInertiaRequests\AuthWorkspaceResource; use Illuminate\Http\Request; -use Illuminate\Support\Facades\App; use Inertia\Middleware; class HandleInertiaRequests extends Middleware @@ -26,10 +25,6 @@ public function share(Request $request): array { $user = $request->user(); - if ($user?->locale) { - App::setLocale($user->locale); - } - $currentWorkspace = $user?->currentWorkspace?->load('media'); return [ diff --git a/app/Http/Middleware/App/SetLocale.php b/app/Http/Middleware/App/SetLocale.php new file mode 100644 index 00000000..fecf0fe0 --- /dev/null +++ b/app/Http/Middleware/App/SetLocale.php @@ -0,0 +1,35 @@ +cookie('locale'); + $isValid = $locale && array_key_exists($locale, $available); + + App::setLocale($isValid ? $locale : config('languages.default')); + + $response = $next($request); + + if (! $isValid) { + $response->withCookie( + cookie()->forever('locale', config('languages.default'), '/', config('session.domain')), + ); + } + + return $response; + } +} diff --git a/app/Http/Resources/App/HandleInertiaRequests/AuthUserResource.php b/app/Http/Resources/App/HandleInertiaRequests/AuthUserResource.php index a75ecf22..ca20b7d9 100644 --- a/app/Http/Resources/App/HandleInertiaRequests/AuthUserResource.php +++ b/app/Http/Resources/App/HandleInertiaRequests/AuthUserResource.php @@ -21,7 +21,6 @@ public static function make(User $user): array 'photo_url' => $user->photo_url, 'email_verified_at' => $user->email_verified_at?->toIso8601String(), 'current_workspace_id' => $user->current_workspace_id, - 'locale' => $user->locale, 'created_at' => $user->created_at->toIso8601String(), 'updated_at' => $user->updated_at->toIso8601String(), ]; diff --git a/app/Mail/WorkspaceConnectionsDisconnected.php b/app/Mail/WorkspaceConnectionsDisconnected.php index 65808cdb..ebc88985 100644 --- a/app/Mail/WorkspaceConnectionsDisconnected.php +++ b/app/Mail/WorkspaceConnectionsDisconnected.php @@ -25,7 +25,7 @@ public function __construct( public Workspace $workspace, public Collection $disconnectedAccounts ) { - $this->locale = $this->workspace->owner?->locale ?? 'en'; + $this->locale = config('app.locale'); } public function envelope(): Envelope diff --git a/app/Models/User.php b/app/Models/User.php index 7eaa0a74..60d27ce7 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -33,7 +33,6 @@ class User extends Authenticatable implements MustVerifyEmail 'setup', 'persona', 'current_workspace_id', - 'locale', 'email_verified_at', ]; @@ -80,14 +79,6 @@ protected function casts(): array ]; } - /** - * Get the user's locale code (e.g. 'en', 'es', 'pt-br'). - */ - public function getLocaleCode(): string - { - return $this->locale ?? 'en'; - } - /** * Check if user has an active subscription. * In self-hosted mode, always returns true (no subscription required). diff --git a/bootstrap/app.php b/bootstrap/app.php index e8b623e8..62d1c155 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -4,6 +4,7 @@ use App\Http\Middleware\App\EnsureSubscribed; use App\Http\Middleware\App\HandleAppearance; use App\Http\Middleware\App\HandleInertiaRequests; +use App\Http\Middleware\App\SetLocale; use App\Http\Middleware\Mcp\AuthenticateMcpToken; use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; @@ -25,9 +26,10 @@ ->withMiddleware(function (Middleware $middleware): void { $middleware->trustProxies(at: '*'); - $middleware->encryptCookies(except: ['appearance', 'sidebar_state']); + $middleware->encryptCookies(except: ['appearance', 'sidebar_state', 'locale']); $middleware->web(append: [ + SetLocale::class, HandleAppearance::class, HandleInertiaRequests::class, AddLinkHeadersForPreloadedAssets::class, diff --git a/composer.json b/composer.json index 42398170..2ad891be 100644 --- a/composer.json +++ b/composer.json @@ -70,7 +70,8 @@ }, "autoload": { "files": [ - "app/Helpers/upload.php" + "app/Helpers/Upload.php", + "app/Helpers/Asset.php" ], "psr-4": { "App\\": "app/", diff --git a/config/app.php b/config/app.php index 7d48fac7..a28266cd 100644 --- a/config/app.php +++ b/config/app.php @@ -56,6 +56,8 @@ 'url' => env('APP_URL', 'http://localhost'), + 'email_asset_url' => env('EMAIL_ASSET_URL', 'https://app.trypost.it'), + /* |-------------------------------------------------------------------------- | Application Timezone diff --git a/config/languages.php b/config/languages.php index e3c9168f..16fb788a 100644 --- a/config/languages.php +++ b/config/languages.php @@ -18,7 +18,7 @@ 'available' => [ 'en' => 'English', 'es' => 'Español', - 'pt-br' => 'Português', + 'pt-BR' => 'Português', ], /* diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 3f35050a..7c5fff22 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -33,7 +33,6 @@ public function definition(): array 'password' => static::$password ??= Hash::make('password'), 'remember_token' => Str::random(10), 'current_workspace_id' => null, - 'locale' => 'en', 'stripe_id' => null, 'pm_type' => null, 'pm_last_four' => null, diff --git a/database/migrations/2026_03_30_115716_drop_locale_from_users.php b/database/migrations/2026_03_30_115716_drop_locale_from_users.php new file mode 100644 index 00000000..29542842 --- /dev/null +++ b/database/migrations/2026_03_30_115716_drop_locale_from_users.php @@ -0,0 +1,24 @@ +dropColumn('locale'); + }); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->string('locale', 10)->default('en')->after('current_workspace_id'); + }); + } +}; diff --git a/lang/en/auth.php b/lang/en/auth.php index be4ac939..e2af5863 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -22,6 +22,35 @@ 'welcome_trial' => 'Welcome to TryPost! Your trial has started.', ], + 'legal' => 'By continuing, you agree to our Terms of Service and Privacy Policy.', + + 'slides' => [ + 'calendar' => [ + 'title' => 'Visual Calendar', + 'description' => 'Plan and schedule your content with an intuitive drag-and-drop calendar across all your social accounts.', + ], + 'scheduling' => [ + 'title' => 'Smart Scheduling', + 'description' => 'Schedule posts across LinkedIn, X, Instagram, TikTok, YouTube, and more — all from one place.', + ], + 'media' => [ + 'title' => 'Rich Media', + 'description' => 'Publish images, carousels, stories, and reels. Each platform gets the right format automatically.', + ], + 'video' => [ + 'title' => 'Video Publishing', + 'description' => 'Upload videos once and publish to TikTok, YouTube Shorts, Instagram Reels, and Facebook Reels.', + ], + 'team' => [ + 'title' => 'Team Workspaces', + 'description' => 'Invite your team, assign roles, and manage multiple brands from separate workspaces.', + ], + 'hashtags' => [ + 'title' => 'Hashtag Groups', + 'description' => 'Save hashtag collections and add them to posts with one click. Organize with labels and filters.', + ], + ], + 'login' => [ 'title' => 'Log in to your account', 'description' => 'Enter your email and password below to log in', @@ -43,6 +72,8 @@ 'name_placeholder' => 'Full name', 'email' => 'Email address', 'password' => 'Password', + 'show_password' => 'Show password', + 'hide_password' => 'Hide password', 'submit' => 'Create account', 'has_account' => 'Already have an account?', 'log_in' => 'Log in', diff --git a/lang/en/billing.php b/lang/en/billing.php index 33448842..30f02399 100644 --- a/lang/en/billing.php +++ b/lang/en/billing.php @@ -4,6 +4,23 @@ 'title' => 'Subscription', 'description' => 'Manage your subscription and payment method', + 'subscribe' => [ + 'page_title' => 'Start your free trial', + 'title' => 'Start your free trial', + 'description' => ':days days free. No credit card required to start.', + 'start_trial' => 'Start :days-day free trial', + 'cancel_anytime' => 'Cancel anytime. No questions asked.', + 'switch_workspace' => 'Switch workspace', + 'features' => [ + 'calendar' => 'Visual drag-and-drop calendar', + 'scheduling' => 'Unlimited post scheduling', + 'media' => 'Images, carousels & stories', + 'video' => 'Video publishing across platforms', + 'team' => 'Team collaboration & workspaces', + 'hashtags' => 'Hashtag groups & labels', + ], + ], + 'trial' => [ 'title' => 'Trial period active', 'description' => 'Your trial ends on :date. After that, your subscription will be charged automatically.', diff --git a/lang/en/common.php b/lang/en/common.php new file mode 100644 index 00000000..7044de87 --- /dev/null +++ b/lang/en/common.php @@ -0,0 +1,12 @@ + [ + 'cannot_be_undone' => 'This cannot be undone.', + 'type' => 'Type', + 'to_confirm' => 'to confirm.', + 'copy_to_clipboard' => 'Copy to clipboard', + ], +]; diff --git a/lang/en/settings.php b/lang/en/settings.php index 76973cee..f7876819 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -77,6 +77,8 @@ 'cancel' => 'Cancel', 'remove' => 'Remove', + 'make_admin' => 'Make admin', + 'make_member' => 'Make member', 'invite' => [ 'title' => 'Invite Member', @@ -122,6 +124,7 @@ 'invite_sent' => 'Invite sent successfully!', 'invite_deleted' => 'Invite deleted.', 'member_removed' => 'Member removed successfully.', + 'role_updated' => 'Member role updated.', '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.', diff --git a/lang/es/auth.php b/lang/es/auth.php index ba016ab9..011a6122 100644 --- a/lang/es/auth.php +++ b/lang/es/auth.php @@ -10,6 +10,35 @@ 'welcome_trial' => '¡Bienvenido a TryPost! Tu prueba ha comenzado.', ], + 'legal' => 'Al continuar, aceptas nuestros Términos de Servicio y Política de Privacidad.', + + 'slides' => [ + 'calendar' => [ + 'title' => 'Calendario Visual', + 'description' => 'Planifica y programa tu contenido con un calendario intuitivo de arrastrar y soltar en todas tus cuentas sociales.', + ], + 'scheduling' => [ + 'title' => 'Programación Inteligente', + 'description' => 'Programa posts en LinkedIn, X, Instagram, TikTok, YouTube y más — todo desde un solo lugar.', + ], + 'media' => [ + 'title' => 'Contenido Multimedia', + 'description' => 'Publica imágenes, carruseles, historias y reels. Cada plataforma recibe el formato correcto automáticamente.', + ], + 'video' => [ + 'title' => 'Publicación de Video', + 'description' => 'Sube videos una vez y publícalos en TikTok, YouTube Shorts, Instagram Reels y Facebook Reels.', + ], + 'team' => [ + 'title' => 'Workspaces en Equipo', + 'description' => 'Invita a tu equipo, asigna roles y gestiona múltiples marcas en workspaces separados.', + ], + 'hashtags' => [ + 'title' => 'Grupos de Hashtags', + 'description' => 'Guarda colecciones de hashtags y agrégalos a tus posts con un clic. Organiza con etiquetas y filtros.', + ], + ], + 'login' => [ 'title' => 'Inicia sesión en tu cuenta', 'description' => 'Introduce tu correo y contraseña para iniciar sesión', @@ -31,6 +60,8 @@ 'name_placeholder' => 'Nombre completo', 'email' => 'Correo electrónico', 'password' => 'Contraseña', + 'show_password' => 'Mostrar contraseña', + 'hide_password' => 'Ocultar contraseña', 'submit' => 'Crear cuenta', 'has_account' => '¿Ya tienes una cuenta?', 'log_in' => 'Iniciar sesión', diff --git a/lang/es/billing.php b/lang/es/billing.php index 0d54e732..fd620b0d 100644 --- a/lang/es/billing.php +++ b/lang/es/billing.php @@ -4,6 +4,23 @@ 'title' => 'Suscripción', 'description' => 'Administra tu suscripción y método de pago', + 'subscribe' => [ + 'page_title' => 'Comienza tu prueba gratuita', + 'title' => 'Comienza tu prueba gratuita', + 'description' => ':days días gratis. Sin tarjeta de crédito para empezar.', + 'start_trial' => 'Comenzar prueba de :days días', + 'cancel_anytime' => 'Cancela en cualquier momento. Sin preguntas.', + 'switch_workspace' => 'Cambiar workspace', + 'features' => [ + 'calendar' => 'Calendario visual con arrastrar y soltar', + 'scheduling' => 'Programación ilimitada de posts', + 'media' => 'Imágenes, carruseles e historias', + 'video' => 'Publicación de videos en todas las plataformas', + 'team' => 'Colaboración en equipo y workspaces', + 'hashtags' => 'Grupos de hashtags y etiquetas', + ], + ], + 'trial' => [ 'title' => 'Periodo de prueba activo', 'description' => 'Tu prueba termina el :date. Después, tu suscripción se cobrará automáticamente.', diff --git a/lang/es/common.php b/lang/es/common.php new file mode 100644 index 00000000..1b36b723 --- /dev/null +++ b/lang/es/common.php @@ -0,0 +1,12 @@ + [ + 'cannot_be_undone' => 'Esta acción no se puede deshacer.', + 'type' => 'Escribe', + 'to_confirm' => 'para confirmar.', + 'copy_to_clipboard' => 'Copiar al portapapeles', + ], +]; diff --git a/lang/es/settings.php b/lang/es/settings.php index 24eb7a73..b5e3cef0 100644 --- a/lang/es/settings.php +++ b/lang/es/settings.php @@ -77,6 +77,8 @@ 'cancel' => 'Cancelar', 'remove' => 'Eliminar', + 'make_admin' => 'Hacer administrador', + 'make_member' => 'Hacer miembro', 'invite' => [ 'title' => 'Invitar miembro', @@ -122,6 +124,7 @@ 'invite_sent' => '¡Invitación enviada correctamente!', 'invite_deleted' => 'Invitación eliminada.', 'member_removed' => '¡Miembro eliminado correctamente!', + 'role_updated' => 'Rol del miembro actualizado.', 'wrong_email' => 'Esta invitación es para otro correo electrónico.', 'already_member' => 'Ya eres miembro de este workspace.', 'invite_accepted' => '¡Bienvenido! Ahora eres miembro del workspace.', diff --git a/lang/php_en.json b/lang/php_en.json new file mode 100644 index 00000000..b1dba844 --- /dev/null +++ b/lang/php_en.json @@ -0,0 +1 @@ +{"auth.failed":"These credentials do not match our records.","auth.password":"The provided password is incorrect.","auth.throttle":"Too many login attempts. Please try again in :seconds seconds.","pagination.previous":"« Previous","pagination.next":"Next »","passwords.reset":"Your password has been reset.","passwords.sent":"We have emailed your password reset link.","passwords.throttled":"Please wait before retrying.","passwords.token":"This password reset token is invalid.","passwords.user":"We can't find a user with that email address.","validation.accepted":"The :attribute field must be accepted.","validation.accepted_if":"The :attribute field must be accepted when :other is :value.","validation.active_url":"The :attribute field must be a valid URL.","validation.after":"The :attribute field must be a date after :date.","validation.after_or_equal":"The :attribute field must be a date after or equal to :date.","validation.alpha":"The :attribute field must only contain letters.","validation.alpha_dash":"The :attribute field must only contain letters, numbers, dashes, and underscores.","validation.alpha_num":"The :attribute field must only contain letters and numbers.","validation.any_of":"The :attribute field is invalid.","validation.array":"The :attribute field must be an array.","validation.ascii":"The :attribute field must only contain single-byte alphanumeric characters and symbols.","validation.before":"The :attribute field must be a date before :date.","validation.before_or_equal":"The :attribute field must be a date before or equal to :date.","validation.between.array":"The :attribute field must have between :min and :max items.","validation.between.file":"The :attribute field must be between :min and :max kilobytes.","validation.between.numeric":"The :attribute field must be between :min and :max.","validation.between.string":"The :attribute field must be between :min and :max characters.","validation.boolean":"The :attribute field must be true or false.","validation.can":"The :attribute field contains an unauthorized value.","validation.confirmed":"The :attribute field confirmation does not match.","validation.contains":"The :attribute field is missing a required value.","validation.current_password":"The password is incorrect.","validation.date":"The :attribute field must be a valid date.","validation.date_equals":"The :attribute field must be a date equal to :date.","validation.date_format":"The :attribute field must match the format :format.","validation.decimal":"The :attribute field must have :decimal decimal places.","validation.declined":"The :attribute field must be declined.","validation.declined_if":"The :attribute field must be declined when :other is :value.","validation.different":"The :attribute field and :other must be different.","validation.digits":"The :attribute field must be :digits digits.","validation.digits_between":"The :attribute field must be between :min and :max digits.","validation.dimensions":"The :attribute field has invalid image dimensions.","validation.distinct":"The :attribute field has a duplicate value.","validation.doesnt_contain":"The :attribute field must not contain any of the following: :values.","validation.doesnt_end_with":"The :attribute field must not end with one of the following: :values.","validation.doesnt_start_with":"The :attribute field must not start with one of the following: :values.","validation.email":"The :attribute field must be a valid email address.","validation.encoding":"The :attribute field must be encoded in :encoding.","validation.ends_with":"The :attribute field must end with one of the following: :values.","validation.enum":"The selected :attribute is invalid.","validation.exists":"The selected :attribute is invalid.","validation.extensions":"The :attribute field must have one of the following extensions: :values.","validation.file":"The :attribute field must be a file.","validation.filled":"The :attribute field must have a value.","validation.gt.array":"The :attribute field must have more than :value items.","validation.gt.file":"The :attribute field must be greater than :value kilobytes.","validation.gt.numeric":"The :attribute field must be greater than :value.","validation.gt.string":"The :attribute field must be greater than :value characters.","validation.gte.array":"The :attribute field must have :value items or more.","validation.gte.file":"The :attribute field must be greater than or equal to :value kilobytes.","validation.gte.numeric":"The :attribute field must be greater than or equal to :value.","validation.gte.string":"The :attribute field must be greater than or equal to :value characters.","validation.hex_color":"The :attribute field must be a valid hexadecimal color.","validation.image":"The :attribute field must be an image.","validation.in":"The selected :attribute is invalid.","validation.in_array":"The :attribute field must exist in :other.","validation.in_array_keys":"The :attribute field must contain at least one of the following keys: :values.","validation.integer":"The :attribute field must be an integer.","validation.ip":"The :attribute field must be a valid IP address.","validation.ipv4":"The :attribute field must be a valid IPv4 address.","validation.ipv6":"The :attribute field must be a valid IPv6 address.","validation.json":"The :attribute field must be a valid JSON string.","validation.list":"The :attribute field must be a list.","validation.lowercase":"The :attribute field must be lowercase.","validation.lt.array":"The :attribute field must have less than :value items.","validation.lt.file":"The :attribute field must be less than :value kilobytes.","validation.lt.numeric":"The :attribute field must be less than :value.","validation.lt.string":"The :attribute field must be less than :value characters.","validation.lte.array":"The :attribute field must not have more than :value items.","validation.lte.file":"The :attribute field must be less than or equal to :value kilobytes.","validation.lte.numeric":"The :attribute field must be less than or equal to :value.","validation.lte.string":"The :attribute field must be less than or equal to :value characters.","validation.mac_address":"The :attribute field must be a valid MAC address.","validation.max.array":"The :attribute field must not have more than :max items.","validation.max.file":"The :attribute field must not be greater than :max kilobytes.","validation.max.numeric":"The :attribute field must not be greater than :max.","validation.max.string":"The :attribute field must not be greater than :max characters.","validation.max_digits":"The :attribute field must not have more than :max digits.","validation.mimes":"The :attribute field must be a file of type: :values.","validation.mimetypes":"The :attribute field must be a file of type: :values.","validation.min.array":"The :attribute field must have at least :min items.","validation.min.file":"The :attribute field must be at least :min kilobytes.","validation.min.numeric":"The :attribute field must be at least :min.","validation.min.string":"The :attribute field must be at least :min characters.","validation.min_digits":"The :attribute field must have at least :min digits.","validation.missing":"The :attribute field must be missing.","validation.missing_if":"The :attribute field must be missing when :other is :value.","validation.missing_unless":"The :attribute field must be missing unless :other is :value.","validation.missing_with":"The :attribute field must be missing when :values is present.","validation.missing_with_all":"The :attribute field must be missing when :values are present.","validation.multiple_of":"The :attribute field must be a multiple of :value.","validation.not_in":"The selected :attribute is invalid.","validation.not_regex":"The :attribute field format is invalid.","validation.numeric":"The :attribute field must be a number.","validation.password.letters":"The :attribute field must contain at least one letter.","validation.password.mixed":"The :attribute field must contain at least one uppercase and one lowercase letter.","validation.password.numbers":"The :attribute field must contain at least one number.","validation.password.symbols":"The :attribute field must contain at least one symbol.","validation.password.uncompromised":"The given :attribute has appeared in a data leak. Please choose a different :attribute.","validation.present":"The :attribute field must be present.","validation.present_if":"The :attribute field must be present when :other is :value.","validation.present_unless":"The :attribute field must be present unless :other is :value.","validation.present_with":"The :attribute field must be present when :values is present.","validation.present_with_all":"The :attribute field must be present when :values are present.","validation.prohibited":"The :attribute field is prohibited.","validation.prohibited_if":"The :attribute field is prohibited when :other is :value.","validation.prohibited_if_accepted":"The :attribute field is prohibited when :other is accepted.","validation.prohibited_if_declined":"The :attribute field is prohibited when :other is declined.","validation.prohibited_unless":"The :attribute field is prohibited unless :other is in :values.","validation.prohibits":"The :attribute field prohibits :other from being present.","validation.regex":"The :attribute field format is invalid.","validation.required":"The :attribute field is required.","validation.required_array_keys":"The :attribute field must contain entries for: :values.","validation.required_if":"The :attribute field is required when :other is :value.","validation.required_if_accepted":"The :attribute field is required when :other is accepted.","validation.required_if_declined":"The :attribute field is required when :other is declined.","validation.required_unless":"The :attribute field is required unless :other is in :values.","validation.required_with":"The :attribute field is required when :values is present.","validation.required_with_all":"The :attribute field is required when :values are present.","validation.required_without":"The :attribute field is required when :values is not present.","validation.required_without_all":"The :attribute field is required when none of :values are present.","validation.same":"The :attribute field must match :other.","validation.size.array":"The :attribute field must contain :size items.","validation.size.file":"The :attribute field must be :size kilobytes.","validation.size.numeric":"The :attribute field must be :size.","validation.size.string":"The :attribute field must be :size characters.","validation.starts_with":"The :attribute field must start with one of the following: :values.","validation.string":"The :attribute field must be a string.","validation.timezone":"The :attribute field must be a valid timezone.","validation.unique":"The :attribute has already been taken.","validation.uploaded":"The :attribute failed to upload.","validation.uppercase":"The :attribute field must be uppercase.","validation.url":"The :attribute field must be a valid URL.","validation.ulid":"The :attribute field must be a valid ULID.","validation.uuid":"The :attribute field must be a valid UUID.","validation.custom.attribute-name.rule-name":"custom-message","accounts.title":"Connections","accounts.page_title":"Connected Accounts","accounts.description":"Connect your social networks to schedule and publish posts","accounts.not_connected":"Not connected","accounts.connect":"Connect","accounts.connection_lost":"Connection lost","accounts.reconnect_account":"Reconnect account","accounts.view_profile":"View profile","accounts.disconnect":"Disconnect","accounts.disconnect_modal.title":"Disconnect Account","accounts.disconnect_modal.description":"Are you sure you want to disconnect this account? You can reconnect it at any time.","accounts.disconnect_modal.confirm":"Disconnect","accounts.disconnect_modal.cancel":"Cancel","accounts.bluesky.title":"Connect Bluesky","accounts.bluesky.description":"Enter your credentials to connect","accounts.bluesky.email":"Email","accounts.bluesky.email_placeholder":"yourhandle.bsky.social","accounts.bluesky.app_password":"App Password","accounts.bluesky.app_password_placeholder":"xxxx-xxxx-xxxx-xxxx","accounts.bluesky.app_password_hint":"Use an App Password for security. Create one at bsky.app/settings.","accounts.bluesky.submit":"Connect Bluesky","accounts.bluesky.submitting":"Connecting...","accounts.mastodon.title":"Connect Mastodon","accounts.mastodon.description":"Enter your Mastodon instance","accounts.mastodon.instance_url":"Instance URL","accounts.mastodon.instance_placeholder":"https://mastodon.social","accounts.mastodon.instance_hint":"Enter your Mastodon instance URL (e.g., mastodon.social, techhub.social)","accounts.mastodon.submit":"Continue with Mastodon","accounts.mastodon.submitting":"Connecting...","accounts.facebook.title":"Select Facebook Page","accounts.facebook.description":"Choose which page you want to connect","accounts.facebook.no_pages":"No pages found","accounts.facebook.no_pages_description":"You are not an admin of any Facebook page.","accounts.facebook.page_label":"Facebook Page","accounts.linkedin.title":"Select LinkedIn Page","accounts.linkedin.description":"Choose which page you want to connect","accounts.linkedin.no_pages":"No pages found","accounts.linkedin.no_pages_description":"You are not an administrator of any LinkedIn page.","accounts.linkedin.page_label":"LinkedIn Page","accounts.flash.disconnected":"Account disconnected successfully!","accounts.flash.connected":"Account connected successfully!","accounts.flash.session_expired":"Session expired. Please try again.","accounts.flash.workspace_not_found":"Workspace not found.","accounts.flash.already_connected":"This platform is already connected.","accounts.flash.no_youtube_channels":"No YouTube channels found. Please create a channel first.","auth.flash.welcome":"Welcome to TryPost!","auth.flash.welcome_trial":"Welcome to TryPost! Your trial has started.","auth.legal":"By continuing, you agree to our Terms of Service and Privacy Policy.","auth.slides.calendar.title":"Visual Calendar","auth.slides.calendar.description":"Plan and schedule your content with an intuitive drag-and-drop calendar across all your social accounts.","auth.slides.scheduling.title":"Smart Scheduling","auth.slides.scheduling.description":"Schedule posts across LinkedIn, X, Instagram, TikTok, YouTube, and more — all from one place.","auth.slides.media.title":"Rich Media","auth.slides.media.description":"Publish images, carousels, stories, and reels. Each platform gets the right format automatically.","auth.slides.video.title":"Video Publishing","auth.slides.video.description":"Upload videos once and publish to TikTok, YouTube Shorts, Instagram Reels, and Facebook Reels.","auth.slides.team.title":"Team Workspaces","auth.slides.team.description":"Invite your team, assign roles, and manage multiple brands from separate workspaces.","auth.slides.hashtags.title":"Hashtag Groups","auth.slides.hashtags.description":"Save hashtag collections and add them to posts with one click. Organize with labels and filters.","auth.login.title":"Log in to your account","auth.login.description":"Enter your email and password below to log in","auth.login.page_title":"Log in","auth.login.email":"Email address","auth.login.password":"Password","auth.login.forgot_password":"Forgot password?","auth.login.remember_me":"Remember me","auth.login.submit":"Log in","auth.login.no_account":"Don't have an account?","auth.login.sign_up":"Sign up","auth.register.title":"Create an account","auth.register.description":"Enter your details below to create your account","auth.register.page_title":"Register","auth.register.name":"Name","auth.register.name_placeholder":"Full name","auth.register.email":"Email address","auth.register.password":"Password","auth.register.show_password":"Show password","auth.register.hide_password":"Hide password","auth.register.submit":"Create account","auth.register.has_account":"Already have an account?","auth.register.log_in":"Log in","auth.forgot_password.title":"Forgot password","auth.forgot_password.description":"Enter your email to receive a password reset link","auth.forgot_password.page_title":"Forgot password","auth.forgot_password.email":"Email address","auth.forgot_password.submit":"Email password reset link","auth.forgot_password.return_to":"Or, return to","auth.forgot_password.log_in":"log in","auth.reset_password.title":"Reset password","auth.reset_password.description":"Please enter your new password below","auth.reset_password.page_title":"Reset password","auth.reset_password.email":"Email","auth.reset_password.password":"Password","auth.reset_password.confirm_password":"Confirm Password","auth.reset_password.confirm_placeholder":"Confirm password","auth.reset_password.submit":"Reset password","auth.verify_email.title":"Verify email","auth.verify_email.description":"Please verify your email address by clicking on the link we just emailed to you.","auth.verify_email.page_title":"Email verification","auth.verify_email.link_sent":"A new verification link has been sent to the email address you provided during registration.","auth.verify_email.resend":"Resend verification email","auth.verify_email.log_out":"Log out","auth.accept_invite.page_title":"Accept Invite","auth.accept_invite.title":"You've been invited!","auth.accept_invite.description":"You've been invited to join the :workspace workspace.","auth.accept_invite.workspace":"Workspace","auth.accept_invite.your_role":"Your role","auth.accept_invite.email":"Email","auth.accept_invite.accept":"Accept Invite","auth.accept_invite.decline":"Decline Invite","auth.accept_invite.login_prompt":"Log in or create an account to accept this invite.","auth.accept_invite.log_in":"Log in","auth.accept_invite.create_account":"Create Account","billing.title":"Subscription","billing.description":"Manage your subscription and payment method","billing.subscribe.page_title":"Start your free trial","billing.subscribe.title":"Start your free trial","billing.subscribe.description":":days days free. No credit card required to start.","billing.subscribe.start_trial":"Start :days-day free trial","billing.subscribe.cancel_anytime":"Cancel anytime. No questions asked.","billing.subscribe.switch_workspace":"Switch workspace","billing.subscribe.features.calendar":"Visual drag-and-drop calendar","billing.subscribe.features.scheduling":"Unlimited post scheduling","billing.subscribe.features.media":"Images, carousels & stories","billing.subscribe.features.video":"Video publishing across platforms","billing.subscribe.features.team":"Team collaboration & workspaces","billing.subscribe.features.hashtags":"Hashtag groups & labels","billing.trial.title":"Trial period active","billing.trial.description":"Your trial ends on :date. After that, your subscription will be charged automatically.","billing.subscription.title":"Your Subscription","billing.subscription.workspaces":"Workspaces","billing.subscription.quantity":"Subscription quantity","billing.subscription.expires":"Expires :date","billing.subscription.canceled_on":"Your subscription will be canceled on :date","billing.subscription.manage":"Manage on Stripe","billing.invoices.title":"Invoices","billing.invoices.description":"Payment history","billing.invoices.empty":"No invoices found","billing.invoices.paid":"Paid","billing.status.active":"Active","billing.status.canceled":"Canceled","billing.status.incomplete":"Incomplete","billing.status.incomplete_expired":"Expired","billing.status.past_due":"Past due","billing.status.trialing":"Trial","billing.status.unpaid":"Unpaid","calendar.title":"Calendar","calendar.today":"Today","calendar.day":"Day","calendar.week":"Week","calendar.month":"Month","calendar.new_post":"New Post","calendar.no_content":"No content","calendar.more":"+:count more","common.confirm_modal.cannot_be_undone":"This cannot be undone.","common.confirm_modal.type":"Type","common.confirm_modal.to_confirm":"to confirm.","common.confirm_modal.copy_to_clipboard":"Copy to clipboard","hashtags.title":"Hashtags","hashtags.description":"Create hashtag groups to quickly add to your posts","hashtags.new_group":"New Group","hashtags.no_groups_yet":"No hashtag groups yet","hashtags.no_groups_description":"Create hashtag groups to quickly add popular hashtags to your posts","hashtags.create_first_group":"Create your first group","hashtags.hashtags_count":":count hashtags","hashtags.create.title":"Create Hashtag Group","hashtags.create.description":"Give your group a name and add hashtags separated by spaces or commas","hashtags.create.name":"Group Name","hashtags.create.name_placeholder":"e.g. Marketing, Travel, Food","hashtags.create.hashtags":"Hashtags","hashtags.create.hashtags_placeholder":"#marketing #socialmedia #business #growth","hashtags.create.hashtags_hint":"Enter hashtags separated by spaces or commas. Include the # symbol.","hashtags.create.submit":"Create Group","hashtags.create.submitting":"Creating...","hashtags.edit.title":"Edit Hashtag Group","hashtags.edit.description":"Update the name and hashtags for this group","hashtags.edit.name":"Group Name","hashtags.edit.name_placeholder":"e.g. Marketing, Travel, Food","hashtags.edit.hashtags":"Hashtags","hashtags.edit.hashtags_placeholder":"#marketing #socialmedia #business #growth","hashtags.edit.hashtags_hint":"Enter hashtags separated by spaces or commas. Include the # symbol.","hashtags.edit.submit":"Save Changes","hashtags.edit.submitting":"Saving...","hashtags.delete.title":"Delete Hashtag Group","hashtags.delete.description":"Are you sure you want to delete this hashtag group? This action cannot be undone.","hashtags.delete.confirm":"Delete","hashtags.delete.cancel":"Cancel","hashtags.flash.created":"Hashtag group created successfully!","hashtags.flash.updated":"Hashtag group updated successfully!","hashtags.flash.deleted":"Hashtag group deleted successfully!","labels.title":"Labels","labels.description":"Create labels to organize and categorize your posts","labels.new_label":"New Label","labels.no_labels_yet":"No labels yet","labels.create_first_label":"Create your first label","labels.create.title":"Create Label","labels.create.description":"Give your label a name and pick a color","labels.create.name":"Name","labels.create.name_placeholder":"Enter label name...","labels.create.color":"Color","labels.create.submit":"Create Label","labels.create.submitting":"Creating...","labels.edit.title":"Edit Label","labels.edit.description":"Update the name and color for this label","labels.edit.name":"Name","labels.edit.name_placeholder":"Enter label name...","labels.edit.color":"Color","labels.edit.submit":"Save Changes","labels.edit.submitting":"Saving...","labels.delete.title":"Delete Label","labels.delete.description":"Are you sure you want to delete this label? This action cannot be undone.","labels.delete.confirm":"Delete","labels.delete.cancel":"Cancel","labels.flash.created":"Label created successfully!","labels.flash.updated":"Label updated successfully!","labels.flash.deleted":"Label deleted successfully!","mail.workspace_connections_disconnected.subject":"{1} :count account needs to be reconnected in :workspace|[2,*] :count accounts need to be reconnected in :workspace","mail.workspace_connections_disconnected.title":"Accounts Need Reconnection","mail.workspace_connections_disconnected.intro":"The following social accounts in your :workspace workspace have been disconnected and need to be reconnected:","mail.workspace_connections_disconnected.reasons_title":"This may have happened because:","mail.workspace_connections_disconnected.reason_expired":"Access tokens expired","mail.workspace_connections_disconnected.reason_revoked":"You revoked access to TryPost on the platform","mail.workspace_connections_disconnected.reason_changed":"The platform changed their authentication requirements","mail.workspace_connections_disconnected.reconnect_cta":"Please reconnect these accounts to continue scheduling and publishing posts.","mail.workspace_connections_disconnected.button":"Reconnect Accounts","posts.title":"Posts","posts.all_posts":"All Posts","posts.new_post":"New Post","posts.no_posts":"No posts found","posts.start_creating":"Start by creating your first post.","posts.manage_posts":"Manage all your posts","posts.delete_confirm":"Are you sure you want to delete this post?","posts.by":"by","posts.actions.view":"View post","posts.actions.delete":"Delete post","posts.form.post_type":"Post Type","posts.form.board":"Board","posts.form.select_board":"Select a board","posts.form.search_board":"Search board...","posts.form.no_board_found":"No board found","posts.form.media":"Media","posts.form.min":"Min","posts.form.uploading":"Uploading...","posts.form.drop_to_upload":"Drop to upload","posts.form.drag_and_drop":"Drag & drop or click to upload","posts.form.photos_and_videos":"Photos and videos","posts.form.photos_only":"Photos only","posts.form.videos_only":"Videos only","posts.form.drag_to_reorder":"Drag to reorder","posts.form.caption":"Caption","posts.form.write_caption":"Write your caption...","posts.status.draft":"Draft","posts.status.scheduled":"Scheduled","posts.status.publishing":"Publishing","posts.status.published":"Published","posts.status.partially_published":"Partially Published","posts.status.failed":"Failed","posts.descriptions.draft":"Posts waiting to be scheduled","posts.descriptions.scheduled":"Posts scheduled for publishing","posts.descriptions.published":"Posts already published","posts.edit.title":"Edit Post","posts.edit.view_title":"View Post","posts.edit.manage_platforms":"Manage platforms","posts.edit.sync":"Sync","posts.edit.labels":"Labels","posts.edit.hashtags":"Hashtags","posts.edit.schedule":"Schedule","posts.edit.publish":"Publish","posts.edit.delete":"Delete","posts.edit.settings":"Settings","posts.edit.schedule_for":"Schedule for","posts.edit.saving":"Saving...","posts.edit.saved":"Saved","posts.edit.scheduled_at":"Scheduled:","posts.edit.published_at":"Published:","posts.edit.media":"Media","posts.edit.caption":"Caption","posts.edit.no_caption":"No caption","posts.edit.no_content":"No content","posts.edit.empty_state.title":"No platforms selected","posts.edit.empty_state.description":"Select at least one platform to create your post","posts.edit.delete_modal.title":"Delete Post","posts.edit.delete_modal.description":"Are you sure you want to delete this post? This action cannot be undone.","posts.edit.delete_modal.action":"Delete","posts.edit.delete_modal.cancel":"Cancel","posts.edit.sync_enable.title":"Enable sync?","posts.edit.sync_enable.description":"All platforms will share the same content. Any custom edits made to individual platforms will be replaced with the current content.","posts.edit.sync_enable.cancel":"Cancel","posts.edit.sync_enable.action":"Enable sync","posts.edit.sync_disable.title":"Disable sync?","posts.edit.sync_disable.description":"Each platform will keep its current content, but future edits will only apply to the platform you're editing.","posts.edit.sync_disable.customize_note":"You'll be able to customize the content for each platform individually.","posts.edit.sync_disable.cancel":"Cancel","posts.edit.sync_disable.action":"Disable sync","posts.edit.platforms_dialog.title":"Select Platforms","posts.edit.platforms_dialog.description":"Choose which platforms to publish this post to.","posts.edit.hashtags_modal.search":"Search hashtags...","posts.edit.hashtags_modal.no_results":"No hashtags found.","posts.edit.validation.select_board":"Select a board","posts.edit.validation.images_not_supported":"Images not supported","posts.edit.validation.videos_not_supported":"Videos not supported","posts.edit.validation.max_images":"Max :count images","posts.edit.validation.requires_media":"Requires media","posts.edit.validation.exceeded":":count exceeded","posts.edit.validation.does_not_support_images":":platform does not support images","posts.edit.validation.supports_up_to_images":":platform supports up to :count images","posts.edit.validation.does_not_support_videos":":platform does not support videos","posts.content_types.instagram_feed.label":"Feed Post","posts.content_types.instagram_feed.description":"Appears in your feed and profile","posts.content_types.instagram_reel.label":"Reel","posts.content_types.instagram_reel.description":"Short video up to 90 seconds","posts.content_types.instagram_story.label":"Story","posts.content_types.instagram_story.description":"Disappears after 24 hours","posts.content_types.linkedin_post.label":"Post","posts.content_types.linkedin_post.description":"Standard post with text and media","posts.content_types.linkedin_carousel.label":"Carousel","posts.content_types.linkedin_carousel.description":"Swipeable images","posts.content_types.linkedin_page_post.label":"Post","posts.content_types.linkedin_page_post.description":"Standard post with text and media","posts.content_types.linkedin_page_carousel.label":"Carousel","posts.content_types.linkedin_page_carousel.description":"Swipeable images","posts.content_types.facebook_post.label":"Post","posts.content_types.facebook_post.description":"Standard post on your page","posts.content_types.facebook_reel.label":"Reel","posts.content_types.facebook_reel.description":"Short video up to 90 seconds","posts.content_types.facebook_story.label":"Story","posts.content_types.facebook_story.description":"Disappears after 24 hours","posts.content_types.tiktok_video.label":"Video","posts.content_types.tiktok_video.description":"Short-form video content","posts.content_types.youtube_short.label":"Short","posts.content_types.youtube_short.description":"Vertical video up to 60 seconds","posts.content_types.x_post.label":"Post","posts.content_types.x_post.description":"Tweet with text and media","posts.content_types.threads_post.label":"Post","posts.content_types.threads_post.description":"Text post with optional media","posts.content_types.pinterest_pin.label":"Pin","posts.content_types.pinterest_pin.description":"Image pin with link","posts.content_types.pinterest_video_pin.label":"Video Pin","posts.content_types.pinterest_video_pin.description":"Video content","posts.content_types.pinterest_carousel.label":"Carousel","posts.content_types.pinterest_carousel.description":"2-5 images","posts.content_types.bluesky_post.label":"Post","posts.content_types.bluesky_post.description":"Text post with optional images","posts.content_types.mastodon_post.label":"Post","posts.content_types.mastodon_post.description":"Text post with optional media","posts.platforms.linkedin":"LinkedIn","posts.platforms.linkedin-page":"LinkedIn Page","posts.platforms.x":"X","posts.platforms.tiktok":"TikTok","posts.platforms.youtube":"YouTube Shorts","posts.platforms.facebook":"Facebook Page","posts.platforms.instagram":"Instagram","posts.platforms.threads":"Threads","posts.platforms.pinterest":"Pinterest","posts.platforms.bluesky":"Bluesky","posts.platforms.mastodon":"Mastodon","posts.flash.scheduled":"Post scheduled successfully!","posts.flash.publishing":"Post is being published!","posts.flash.deleted":"Post deleted successfully!","posts.flash.cannot_edit_published":"Published posts cannot be edited.","posts.flash.connect_first":"Connect at least one social network before creating a post.","posts.errors.account_disconnected":"Social account is disconnected","settings.title":"Settings","settings.description":"Manage your profile and account settings","settings.nav.profile":"Profile","settings.nav.password":"Password","settings.nav.workspace":"Workspace","settings.nav.members":"Members","settings.nav.billing":"Billing","settings.profile.title":"Profile settings","settings.profile.photo_heading":"Profile photo","settings.profile.photo_description":"Upload a profile photo","settings.profile.heading":"Profile information","settings.profile.description":"Update your name and email address","settings.profile.avatar":"Avatar","settings.profile.name":"Name","settings.profile.name_placeholder":"Full name","settings.profile.email":"Email address","settings.profile.email_placeholder":"Email address","settings.profile.email_unverified":"Your email address is unverified.","settings.profile.resend_verification":"Click here to resend the verification email.","settings.profile.verification_sent":"A new verification link has been sent to your email address.","settings.profile.save":"Save","settings.password.title":"Password settings","settings.password.heading":"Update password","settings.password.description":"Ensure your account is using a long, random password to stay secure","settings.password.current_password":"Current password","settings.password.current_password_placeholder":"Current password","settings.password.new_password":"New password","settings.password.new_password_placeholder":"New password","settings.password.confirm_password":"Confirm password","settings.password.confirm_password_placeholder":"Confirm password","settings.password.save":"Save password","settings.delete_account.heading":"Delete account","settings.delete_account.description":"Delete your account and all of its resources","settings.delete_account.warning":"Warning","settings.delete_account.warning_message":"Please proceed with caution, this cannot be undone.","settings.delete_account.button":"Delete account","settings.delete_account.modal_title":"Are you sure you want to delete your account?","settings.delete_account.modal_description":"Once your account is deleted, all of its resources and data will also be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.","settings.delete_account.password":"Password","settings.delete_account.password_placeholder":"Password","settings.delete_account.cancel":"Cancel","settings.delete_account.confirm":"Delete account","settings.workspace.title":"Workspace settings","settings.workspace.logo_heading":"Workspace logo","settings.workspace.logo_description":"Upload a logo for your workspace","settings.workspace.heading":"Workspace name","settings.workspace.description":"Update your workspace name and timezone","settings.workspace.members_heading":"Members","settings.workspace.members_description":"Manage workspace members and invitations","settings.workspace.name":"Name","settings.workspace.name_placeholder":"My Workspace","settings.workspace.timezone":"Timezone","settings.workspace.save":"Save","settings.members.title":"Members","settings.members.heading":"Team members","settings.members.description":"Manage members and invites for this workspace","settings.members.cancel":"Cancel","settings.members.remove":"Remove","settings.members.make_admin":"Make admin","settings.members.make_member":"Make member","settings.members.invite.title":"Invite Member","settings.members.invite.description":"Send an email invite to add collaborators","settings.members.invite.email":"Email","settings.members.invite.email_placeholder":"collaborator@email.com","settings.members.invite.role":"Role","settings.members.invite.role_placeholder":"Select a role","settings.members.invite.submit":"Send Invite","settings.members.pending.title":"Pending Invites","settings.members.pending.description":"Invites awaiting acceptance","settings.members.pending.empty":"No pending invites","settings.members.list.title":"Members","settings.members.list.description":"People with access to this workspace","settings.members.list.empty":"No members besides the owner","settings.members.remove_modal.title":"Remove member","settings.members.remove_modal.description":"Are you sure you want to remove this member from the workspace? They will lose access to all workspace resources.","settings.members.remove_modal.action":"Remove member","settings.members.cancel_invite_modal.title":"Cancel invitation","settings.members.cancel_invite_modal.description":"Are you sure you want to cancel this invitation?","settings.members.cancel_invite_modal.action":"Cancel invitation","settings.members.roles.owner":"Owner","settings.members.roles.admin":"Admin","settings.members.roles.member":"Member","settings.members.flash.invite_sent":"Invite sent successfully!","settings.members.flash.invite_deleted":"Invite deleted.","settings.members.flash.member_removed":"Member removed successfully.","settings.members.flash.role_updated":"Member role updated.","settings.members.flash.wrong_email":"This invite is for a different email address.","settings.members.flash.already_member":"You are already a member of this workspace.","settings.members.flash.invite_accepted":"Welcome! You are now a member of the workspace.","settings.members.flash.invite_declined":"Invite declined.","settings.flash.profile_updated":"Profile updated successfully!","settings.flash.language_updated":"Language updated successfully!","settings.flash.password_updated":"Password updated successfully!","settings.flash.workspace_updated":"Settings updated successfully!","settings.flash.photo_updated":"Photo updated successfully!","settings.flash.photo_deleted":"Photo removed successfully!","settings.flash.logo_updated":"Logo uploaded successfully!","settings.flash.logo_deleted":"Logo removed successfully!","sidebar.workspaces":"Workspaces","sidebar.select_workspace":"Select workspace","sidebar.create_workspace":"Create workspace","sidebar.create_post":"Create post","sidebar.profile":"Profile","sidebar.log_out":"Log out","sidebar.workspace":"Workspace: :name","sidebar.workspace_select":"Workspace: Select","sidebar.theme":"Theme: :name","sidebar.theme_light":"Light","sidebar.theme_dark":"Dark","sidebar.theme_system":"System","sidebar.language":"Language: :name","sidebar.language_select":"Language: Select","sidebar.groups.posts":"Posts","sidebar.groups.configuration":"Configurations","sidebar.groups.support":"Support","sidebar.posts.calendar":"Calendar","sidebar.posts.all":"All","sidebar.posts.scheduled":"Scheduled","sidebar.posts.posted":"Posted","sidebar.posts.drafts":"Drafts","sidebar.config.connections":"Connections","sidebar.config.hashtags":"Hashtags","sidebar.config.labels":"Labels","sidebar.config.settings":"Settings","sidebar.support.discord":"Discord","sidebar.support.share_feedback":"Share feedback","sidebar.support.last_updates":"Last Updates","sidebar.support.docs":"Docs"} \ No newline at end of file diff --git a/lang/php_es.json b/lang/php_es.json new file mode 100644 index 00000000..c33358b2 --- /dev/null +++ b/lang/php_es.json @@ -0,0 +1 @@ +{"accounts.title":"Conexiones","accounts.page_title":"Cuentas conectadas","accounts.description":"Conecta tus redes sociales para programar y publicar posts","accounts.not_connected":"No conectado","accounts.connect":"Conectar","accounts.connection_lost":"Conexión perdida","accounts.reconnect_account":"Reconectar cuenta","accounts.view_profile":"Ver perfil","accounts.disconnect":"Desconectar","accounts.disconnect_modal.title":"Desconectar cuenta","accounts.disconnect_modal.description":"¿Estás seguro de que deseas desconectar esta cuenta? Puedes volver a conectarla en cualquier momento.","accounts.disconnect_modal.confirm":"Desconectar","accounts.disconnect_modal.cancel":"Cancelar","accounts.bluesky.title":"Conectar Bluesky","accounts.bluesky.description":"Introduce tus credenciales para conectar","accounts.bluesky.email":"Correo electrónico","accounts.bluesky.email_placeholder":"tuusuario.bsky.social","accounts.bluesky.app_password":"Contraseña de app","accounts.bluesky.app_password_placeholder":"xxxx-xxxx-xxxx-xxxx","accounts.bluesky.app_password_hint":"Usa una Contraseña de App por seguridad. Crea una en bsky.app/settings.","accounts.bluesky.submit":"Conectar Bluesky","accounts.bluesky.submitting":"Conectando...","accounts.mastodon.title":"Conectar Mastodon","accounts.mastodon.description":"Introduce tu instancia de Mastodon","accounts.mastodon.instance_url":"URL de la instancia","accounts.mastodon.instance_placeholder":"https://mastodon.social","accounts.mastodon.instance_hint":"Introduce la URL de tu instancia de Mastodon (ej: mastodon.social, techhub.social)","accounts.mastodon.submit":"Continuar con Mastodon","accounts.mastodon.submitting":"Conectando...","accounts.facebook.title":"Seleccionar página de Facebook","accounts.facebook.description":"Elige qué página deseas conectar","accounts.facebook.no_pages":"No se encontraron páginas","accounts.facebook.no_pages_description":"No eres administrador de ninguna página de Facebook.","accounts.facebook.page_label":"Página de Facebook","accounts.linkedin.title":"Seleccionar página de LinkedIn","accounts.linkedin.description":"Elige qué página deseas conectar","accounts.linkedin.no_pages":"No se encontraron páginas","accounts.linkedin.no_pages_description":"No eres administrador de ninguna página de LinkedIn.","accounts.linkedin.page_label":"Página de LinkedIn","accounts.flash.disconnected":"¡Cuenta desconectada correctamente!","accounts.flash.connected":"¡Cuenta conectada correctamente!","accounts.flash.session_expired":"Sesión expirada. Inténtalo de nuevo.","accounts.flash.workspace_not_found":"Workspace no encontrado.","accounts.flash.already_connected":"Esta plataforma ya está conectada.","accounts.flash.no_youtube_channels":"No se encontraron canales de YouTube. Crea un canal primero.","auth.failed":"Estas credenciales no coinciden con nuestros registros.","auth.password":"La contraseña proporcionada es incorrecta.","auth.throttle":"Demasiados intentos de inicio de sesión. Inténtalo de nuevo en :seconds segundos.","auth.flash.welcome":"¡Bienvenido a TryPost!","auth.flash.welcome_trial":"¡Bienvenido a TryPost! Tu prueba ha comenzado.","auth.legal":"Al continuar, aceptas nuestros Términos de Servicio y Política de Privacidad.","auth.slides.calendar.title":"Calendario Visual","auth.slides.calendar.description":"Planifica y programa tu contenido con un calendario intuitivo de arrastrar y soltar en todas tus cuentas sociales.","auth.slides.scheduling.title":"Programación Inteligente","auth.slides.scheduling.description":"Programa posts en LinkedIn, X, Instagram, TikTok, YouTube y más — todo desde un solo lugar.","auth.slides.media.title":"Contenido Multimedia","auth.slides.media.description":"Publica imágenes, carruseles, historias y reels. Cada plataforma recibe el formato correcto automáticamente.","auth.slides.video.title":"Publicación de Video","auth.slides.video.description":"Sube videos una vez y publícalos en TikTok, YouTube Shorts, Instagram Reels y Facebook Reels.","auth.slides.team.title":"Workspaces en Equipo","auth.slides.team.description":"Invita a tu equipo, asigna roles y gestiona múltiples marcas en workspaces separados.","auth.slides.hashtags.title":"Grupos de Hashtags","auth.slides.hashtags.description":"Guarda colecciones de hashtags y agrégalos a tus posts con un clic. Organiza con etiquetas y filtros.","auth.login.title":"Inicia sesión en tu cuenta","auth.login.description":"Introduce tu correo y contraseña para iniciar sesión","auth.login.page_title":"Iniciar sesión","auth.login.email":"Correo electrónico","auth.login.password":"Contraseña","auth.login.forgot_password":"¿Olvidaste tu contraseña?","auth.login.remember_me":"Recuérdame","auth.login.submit":"Iniciar sesión","auth.login.no_account":"¿No tienes una cuenta?","auth.login.sign_up":"Regístrate","auth.register.title":"Crear una cuenta","auth.register.description":"Introduce tus datos para crear tu cuenta","auth.register.page_title":"Registro","auth.register.name":"Nombre","auth.register.name_placeholder":"Nombre completo","auth.register.email":"Correo electrónico","auth.register.password":"Contraseña","auth.register.show_password":"Mostrar contraseña","auth.register.hide_password":"Ocultar contraseña","auth.register.submit":"Crear cuenta","auth.register.has_account":"¿Ya tienes una cuenta?","auth.register.log_in":"Iniciar sesión","auth.forgot_password.title":"Olvidé mi contraseña","auth.forgot_password.description":"Introduce tu correo para recibir un enlace de restablecimiento","auth.forgot_password.page_title":"Olvidé mi contraseña","auth.forgot_password.email":"Correo electrónico","auth.forgot_password.submit":"Enviar enlace de restablecimiento","auth.forgot_password.return_to":"O vuelve a","auth.forgot_password.log_in":"iniciar sesión","auth.reset_password.title":"Restablecer contraseña","auth.reset_password.description":"Introduce tu nueva contraseña","auth.reset_password.page_title":"Restablecer contraseña","auth.reset_password.email":"Correo electrónico","auth.reset_password.password":"Contraseña","auth.reset_password.confirm_password":"Confirmar contraseña","auth.reset_password.confirm_placeholder":"Confirmar contraseña","auth.reset_password.submit":"Restablecer contraseña","auth.verify_email.title":"Verificar correo","auth.verify_email.description":"Verifica tu correo electrónico haciendo clic en el enlace que acabamos de enviarte.","auth.verify_email.page_title":"Verificación de correo","auth.verify_email.link_sent":"Se ha enviado un nuevo enlace de verificación al correo electrónico proporcionado durante el registro.","auth.verify_email.resend":"Reenviar correo de verificación","auth.verify_email.log_out":"Cerrar sesión","auth.accept_invite.page_title":"Aceptar invitación","auth.accept_invite.title":"¡Has sido invitado!","auth.accept_invite.description":"Has sido invitado a unirte al workspace :workspace.","auth.accept_invite.workspace":"Workspace","auth.accept_invite.your_role":"Tu rol","auth.accept_invite.email":"Correo electrónico","auth.accept_invite.accept":"Aceptar invitación","auth.accept_invite.decline":"Rechazar invitación","auth.accept_invite.login_prompt":"Inicia sesión o crea una cuenta para aceptar esta invitación.","auth.accept_invite.log_in":"Iniciar sesión","auth.accept_invite.create_account":"Crear cuenta","billing.title":"Suscripción","billing.description":"Administra tu suscripción y método de pago","billing.subscribe.page_title":"Comienza tu prueba gratuita","billing.subscribe.title":"Comienza tu prueba gratuita","billing.subscribe.description":":days días gratis. Sin tarjeta de crédito para empezar.","billing.subscribe.start_trial":"Comenzar prueba de :days días","billing.subscribe.cancel_anytime":"Cancela en cualquier momento. Sin preguntas.","billing.subscribe.switch_workspace":"Cambiar workspace","billing.subscribe.features.calendar":"Calendario visual con arrastrar y soltar","billing.subscribe.features.scheduling":"Programación ilimitada de posts","billing.subscribe.features.media":"Imágenes, carruseles e historias","billing.subscribe.features.video":"Publicación de videos en todas las plataformas","billing.subscribe.features.team":"Colaboración en equipo y workspaces","billing.subscribe.features.hashtags":"Grupos de hashtags y etiquetas","billing.trial.title":"Periodo de prueba activo","billing.trial.description":"Tu prueba termina el :date. Después, tu suscripción se cobrará automáticamente.","billing.subscription.title":"Tu suscripción","billing.subscription.workspaces":"Workspaces","billing.subscription.quantity":"Cantidad de suscripción","billing.subscription.expires":"Expira :date","billing.subscription.canceled_on":"Tu suscripción se cancelará el :date","billing.subscription.manage":"Administrar en Stripe","billing.invoices.title":"Facturas","billing.invoices.description":"Historial de pagos","billing.invoices.empty":"No se encontraron facturas","billing.invoices.paid":"Pagado","billing.status.active":"Activa","billing.status.canceled":"Cancelada","billing.status.incomplete":"Incompleta","billing.status.incomplete_expired":"Expirada","billing.status.past_due":"Vencida","billing.status.trialing":"Prueba","billing.status.unpaid":"Sin pagar","calendar.title":"Calendario","calendar.today":"Hoy","calendar.day":"Día","calendar.week":"Semana","calendar.month":"Mes","calendar.new_post":"Nuevo post","calendar.no_content":"Sin contenido","calendar.more":"+:count más","common.confirm_modal.cannot_be_undone":"Esta acción no se puede deshacer.","common.confirm_modal.type":"Escribe","common.confirm_modal.to_confirm":"para confirmar.","common.confirm_modal.copy_to_clipboard":"Copiar al portapapeles","hashtags.title":"Hashtags","hashtags.description":"Crea grupos de hashtags para agregarlos rápidamente a tus posts","hashtags.new_group":"Nuevo grupo","hashtags.no_groups_yet":"Aún no hay grupos de hashtags","hashtags.no_groups_description":"Crea grupos de hashtags para agregar rápidamente hashtags populares a tus posts","hashtags.create_first_group":"Crea tu primer grupo","hashtags.hashtags_count":":count hashtags","hashtags.create.title":"Crear grupo de hashtags","hashtags.create.description":"Dale un nombre a tu grupo y agrega hashtags separados por espacios o comas","hashtags.create.name":"Nombre del grupo","hashtags.create.name_placeholder":"ej: Marketing, Viajes, Comida","hashtags.create.hashtags":"Hashtags","hashtags.create.hashtags_placeholder":"#marketing #redessociales #negocios #crecimiento","hashtags.create.hashtags_hint":"Ingresa hashtags separados por espacios o comas. Incluye el símbolo #.","hashtags.create.submit":"Crear grupo","hashtags.create.submitting":"Creando...","hashtags.edit.title":"Editar grupo de hashtags","hashtags.edit.description":"Actualiza el nombre y los hashtags de este grupo","hashtags.edit.name":"Nombre del grupo","hashtags.edit.name_placeholder":"ej: Marketing, Viajes, Comida","hashtags.edit.hashtags":"Hashtags","hashtags.edit.hashtags_placeholder":"#marketing #redessociales #negocios #crecimiento","hashtags.edit.hashtags_hint":"Ingresa hashtags separados por espacios o comas. Incluye el símbolo #.","hashtags.edit.submit":"Guardar cambios","hashtags.edit.submitting":"Guardando...","hashtags.delete.title":"Eliminar grupo de hashtags","hashtags.delete.description":"¿Estás seguro de que deseas eliminar este grupo de hashtags? Esta acción no se puede deshacer.","hashtags.delete.confirm":"Eliminar","hashtags.delete.cancel":"Cancelar","hashtags.flash.created":"¡Grupo de hashtags creado correctamente!","hashtags.flash.updated":"¡Grupo de hashtags actualizado correctamente!","hashtags.flash.deleted":"¡Grupo de hashtags eliminado correctamente!","labels.title":"Etiquetas","labels.description":"Crea etiquetas para organizar y categorizar tus posts","labels.new_label":"Nueva etiqueta","labels.no_labels_yet":"Aún no hay etiquetas","labels.create_first_label":"Crea tu primera etiqueta","labels.create.title":"Crear etiqueta","labels.create.description":"Dale un nombre y elige un color para tu etiqueta","labels.create.name":"Nombre","labels.create.name_placeholder":"Nombre de la etiqueta...","labels.create.color":"Color","labels.create.submit":"Crear etiqueta","labels.create.submitting":"Creando...","labels.edit.title":"Editar etiqueta","labels.edit.description":"Actualiza el nombre y el color de esta etiqueta","labels.edit.name":"Nombre","labels.edit.name_placeholder":"Nombre de la etiqueta...","labels.edit.color":"Color","labels.edit.submit":"Guardar cambios","labels.edit.submitting":"Guardando...","labels.delete.title":"Eliminar etiqueta","labels.delete.description":"¿Estás seguro de que deseas eliminar esta etiqueta? Esta acción no se puede deshacer.","labels.delete.confirm":"Eliminar","labels.delete.cancel":"Cancelar","labels.flash.created":"¡Etiqueta creada correctamente!","labels.flash.updated":"¡Etiqueta actualizada correctamente!","labels.flash.deleted":"¡Etiqueta eliminada correctamente!","mail.workspace_connections_disconnected.subject":"{1} :count cuenta necesita ser reconectada en :workspace|[2,*] :count cuentas necesitan ser reconectadas en :workspace","mail.workspace_connections_disconnected.title":"Cuentas necesitan reconexión","mail.workspace_connections_disconnected.intro":"Las siguientes cuentas sociales en tu workspace :workspace se han desconectado y necesitan ser reconectadas:","mail.workspace_connections_disconnected.reasons_title":"Esto puede haber ocurrido porque:","mail.workspace_connections_disconnected.reason_expired":"Los tokens de acceso expiraron","mail.workspace_connections_disconnected.reason_revoked":"Revocaste el acceso a TryPost en la plataforma","mail.workspace_connections_disconnected.reason_changed":"La plataforma cambió sus requisitos de autenticación","mail.workspace_connections_disconnected.reconnect_cta":"Reconecta estas cuentas para seguir programando y publicando posts.","mail.workspace_connections_disconnected.button":"Reconectar cuentas","pagination.previous":"« Anterior","pagination.next":"Siguiente »","passwords.reset":"Tu contraseña ha sido restablecida.","passwords.sent":"Te hemos enviado un enlace para restablecer tu contraseña.","passwords.throttled":"Espera antes de intentarlo de nuevo.","passwords.token":"Este token de restablecimiento de contraseña no es válido.","passwords.user":"No encontramos un usuario con ese correo electrónico.","posts.title":"Posts","posts.all_posts":"Todos los posts","posts.new_post":"Nuevo post","posts.no_posts":"No se encontraron posts","posts.start_creating":"Empieza creando tu primer post.","posts.manage_posts":"Administra todos tus posts","posts.delete_confirm":"¿Estás seguro de que deseas eliminar este post?","posts.by":"por","posts.actions.view":"Ver post","posts.actions.delete":"Eliminar post","posts.form.post_type":"Tipo de post","posts.form.board":"Tablero","posts.form.select_board":"Seleccionar tablero","posts.form.search_board":"Buscar tablero...","posts.form.no_board_found":"No se encontró tablero","posts.form.media":"Multimedia","posts.form.min":"Min","posts.form.uploading":"Subiendo...","posts.form.drop_to_upload":"Suelta para subir","posts.form.drag_and_drop":"Arrastra y suelta o haz clic para subir","posts.form.photos_and_videos":"Fotos y videos","posts.form.photos_only":"Solo fotos","posts.form.videos_only":"Solo videos","posts.form.drag_to_reorder":"Arrastra para reordenar","posts.form.caption":"Descripción","posts.form.write_caption":"Escribe tu descripción...","posts.status.draft":"Borrador","posts.status.scheduled":"Programado","posts.status.publishing":"Publicando","posts.status.published":"Publicado","posts.status.partially_published":"Parcialmente publicado","posts.status.failed":"Fallido","posts.descriptions.draft":"Posts esperando ser programados","posts.descriptions.scheduled":"Posts programados para publicar","posts.descriptions.published":"Posts ya publicados","posts.edit.title":"Editar post","posts.edit.view_title":"Ver post","posts.edit.manage_platforms":"Administrar plataformas","posts.edit.sync":"Sincronizar","posts.edit.labels":"Etiquetas","posts.edit.hashtags":"Hashtags","posts.edit.schedule":"Programar","posts.edit.publish":"Publicar","posts.edit.delete":"Eliminar","posts.edit.settings":"Configuración","posts.edit.schedule_for":"Programar para","posts.edit.saving":"Guardando...","posts.edit.saved":"Guardado","posts.edit.scheduled_at":"Programado:","posts.edit.published_at":"Publicado:","posts.edit.media":"Multimedia","posts.edit.caption":"Descripción","posts.edit.no_caption":"Sin descripción","posts.edit.no_content":"Sin contenido","posts.edit.empty_state.title":"No hay plataformas seleccionadas","posts.edit.empty_state.description":"Selecciona al menos una plataforma para crear tu post","posts.edit.delete_modal.title":"Eliminar post","posts.edit.delete_modal.description":"¿Estás seguro de que deseas eliminar este post? Esta acción no se puede deshacer.","posts.edit.delete_modal.action":"Eliminar","posts.edit.delete_modal.cancel":"Cancelar","posts.edit.sync_enable.title":"¿Activar sincronización?","posts.edit.sync_enable.description":"Todas las plataformas compartirán el mismo contenido. Las ediciones personalizadas realizadas en plataformas individuales serán reemplazadas con el contenido actual.","posts.edit.sync_enable.cancel":"Cancelar","posts.edit.sync_enable.action":"Activar sincronización","posts.edit.sync_disable.title":"¿Desactivar sincronización?","posts.edit.sync_disable.description":"Cada plataforma mantendrá su contenido actual, pero las ediciones futuras solo se aplicarán a la plataforma que estés editando.","posts.edit.sync_disable.customize_note":"Podrás personalizar el contenido de cada plataforma individualmente.","posts.edit.sync_disable.cancel":"Cancelar","posts.edit.sync_disable.action":"Desactivar sincronización","posts.edit.platforms_dialog.title":"Seleccionar plataformas","posts.edit.platforms_dialog.description":"Elige en qué plataformas publicar este post.","posts.edit.hashtags_modal.search":"Buscar hashtags...","posts.edit.hashtags_modal.no_results":"No se encontraron hashtags.","posts.edit.validation.select_board":"Selecciona un tablero","posts.edit.validation.images_not_supported":"Imágenes no soportadas","posts.edit.validation.videos_not_supported":"Videos no soportados","posts.edit.validation.max_images":"Máximo :count imágenes","posts.edit.validation.requires_media":"Requiere multimedia","posts.edit.validation.exceeded":":count excedido","posts.edit.validation.does_not_support_images":":platform no soporta imágenes","posts.edit.validation.supports_up_to_images":":platform soporta hasta :count imágenes","posts.edit.validation.does_not_support_videos":":platform no soporta videos","posts.content_types.instagram_feed.label":"Post del feed","posts.content_types.instagram_feed.description":"Aparece en tu feed y perfil","posts.content_types.instagram_reel.label":"Reel","posts.content_types.instagram_reel.description":"Video corto de hasta 90 segundos","posts.content_types.instagram_story.label":"Historia","posts.content_types.instagram_story.description":"Desaparece después de 24 horas","posts.content_types.linkedin_post.label":"Post","posts.content_types.linkedin_post.description":"Post estándar con texto y multimedia","posts.content_types.linkedin_carousel.label":"Carrusel","posts.content_types.linkedin_carousel.description":"Imágenes deslizables","posts.content_types.linkedin_page_post.label":"Post","posts.content_types.linkedin_page_post.description":"Post estándar con texto y multimedia","posts.content_types.linkedin_page_carousel.label":"Carrusel","posts.content_types.linkedin_page_carousel.description":"Imágenes deslizables","posts.content_types.facebook_post.label":"Post","posts.content_types.facebook_post.description":"Post estándar en tu página","posts.content_types.facebook_reel.label":"Reel","posts.content_types.facebook_reel.description":"Video corto de hasta 90 segundos","posts.content_types.facebook_story.label":"Historia","posts.content_types.facebook_story.description":"Desaparece después de 24 horas","posts.content_types.tiktok_video.label":"Video","posts.content_types.tiktok_video.description":"Contenido de video corto","posts.content_types.youtube_short.label":"Short","posts.content_types.youtube_short.description":"Video vertical de hasta 60 segundos","posts.content_types.x_post.label":"Post","posts.content_types.x_post.description":"Tweet con texto y multimedia","posts.content_types.threads_post.label":"Post","posts.content_types.threads_post.description":"Post de texto con multimedia opcional","posts.content_types.pinterest_pin.label":"Pin","posts.content_types.pinterest_pin.description":"Pin de imagen con enlace","posts.content_types.pinterest_video_pin.label":"Pin de video","posts.content_types.pinterest_video_pin.description":"Contenido de video","posts.content_types.pinterest_carousel.label":"Carrusel","posts.content_types.pinterest_carousel.description":"2-5 imágenes","posts.content_types.bluesky_post.label":"Post","posts.content_types.bluesky_post.description":"Post de texto con imágenes opcionales","posts.content_types.mastodon_post.label":"Post","posts.content_types.mastodon_post.description":"Post de texto con multimedia opcional","posts.platforms.linkedin":"LinkedIn","posts.platforms.linkedin-page":"Página de LinkedIn","posts.platforms.x":"X","posts.platforms.tiktok":"TikTok","posts.platforms.youtube":"YouTube Shorts","posts.platforms.facebook":"Página de Facebook","posts.platforms.instagram":"Instagram","posts.platforms.threads":"Threads","posts.platforms.pinterest":"Pinterest","posts.platforms.bluesky":"Bluesky","posts.platforms.mastodon":"Mastodon","posts.flash.scheduled":"¡Post programado correctamente!","posts.flash.publishing":"¡El post se está publicando!","posts.flash.deleted":"¡Post eliminado correctamente!","posts.flash.cannot_edit_published":"Los posts publicados no se pueden editar.","posts.flash.connect_first":"Conecta al menos una red social antes de crear un post.","posts.errors.account_disconnected":"Cuenta social desconectada","settings.title":"Configuración","settings.description":"Administra tu perfil y configuración de la cuenta","settings.nav.profile":"Perfil","settings.nav.password":"Contraseña","settings.nav.workspace":"Workspace","settings.nav.members":"Miembros","settings.nav.billing":"Facturación","settings.profile.title":"Configuración del perfil","settings.profile.photo_heading":"Foto de perfil","settings.profile.photo_description":"Sube una foto de perfil","settings.profile.heading":"Información del perfil","settings.profile.description":"Actualiza tu nombre y correo electrónico","settings.profile.avatar":"Avatar","settings.profile.name":"Nombre","settings.profile.name_placeholder":"Nombre completo","settings.profile.email":"Correo electrónico","settings.profile.email_placeholder":"Correo electrónico","settings.profile.email_unverified":"Tu correo electrónico no ha sido verificado.","settings.profile.resend_verification":"Haz clic aquí para reenviar el correo de verificación.","settings.profile.verification_sent":"Se ha enviado un nuevo enlace de verificación a tu correo electrónico.","settings.profile.save":"Guardar","settings.password.title":"Configuración de contraseña","settings.password.heading":"Actualizar contraseña","settings.password.description":"Asegúrate de que tu cuenta use una contraseña larga y aleatoria para mantenerte seguro","settings.password.current_password":"Contraseña actual","settings.password.current_password_placeholder":"Contraseña actual","settings.password.new_password":"Nueva contraseña","settings.password.new_password_placeholder":"Nueva contraseña","settings.password.confirm_password":"Confirmar contraseña","settings.password.confirm_password_placeholder":"Confirmar contraseña","settings.password.save":"Guardar contraseña","settings.delete_account.heading":"Eliminar cuenta","settings.delete_account.description":"Elimina tu cuenta y todos sus recursos","settings.delete_account.warning":"Advertencia","settings.delete_account.warning_message":"Procede con precaución, esta acción no se puede deshacer.","settings.delete_account.button":"Eliminar cuenta","settings.delete_account.modal_title":"¿Estás seguro de que deseas eliminar tu cuenta?","settings.delete_account.modal_description":"Una vez eliminada tu cuenta, todos sus recursos y datos también se eliminarán permanentemente. Introduce tu contraseña para confirmar que deseas eliminar permanentemente tu cuenta.","settings.delete_account.password":"Contraseña","settings.delete_account.password_placeholder":"Contraseña","settings.delete_account.cancel":"Cancelar","settings.delete_account.confirm":"Eliminar cuenta","settings.workspace.title":"Configuración del workspace","settings.workspace.logo_heading":"Logo del workspace","settings.workspace.logo_description":"Sube un logo para tu workspace","settings.workspace.heading":"Nombre del workspace","settings.workspace.description":"Actualiza el nombre y zona horaria del workspace","settings.workspace.members_heading":"Miembros","settings.workspace.members_description":"Administra miembros e invitaciones del workspace","settings.workspace.name":"Nombre","settings.workspace.name_placeholder":"Mi Workspace","settings.workspace.timezone":"Zona horaria","settings.workspace.save":"Guardar","settings.members.title":"Miembros","settings.members.heading":"Miembros del equipo","settings.members.description":"Administra miembros e invitaciones de este workspace","settings.members.cancel":"Cancelar","settings.members.remove":"Eliminar","settings.members.make_admin":"Hacer administrador","settings.members.make_member":"Hacer miembro","settings.members.invite.title":"Invitar miembro","settings.members.invite.description":"Envía una invitación por correo para agregar colaboradores","settings.members.invite.email":"Correo electrónico","settings.members.invite.email_placeholder":"colaborador@email.com","settings.members.invite.role":"Rol","settings.members.invite.role_placeholder":"Selecciona un rol","settings.members.invite.submit":"Enviar invitación","settings.members.pending.title":"Invitaciones pendientes","settings.members.pending.description":"Invitaciones en espera de aceptación","settings.members.pending.empty":"No hay invitaciones pendientes","settings.members.list.title":"Miembros","settings.members.list.description":"Personas con acceso a este workspace","settings.members.list.empty":"No hay miembros además del propietario","settings.members.remove_modal.title":"Eliminar miembro","settings.members.remove_modal.description":"¿Estás seguro de que deseas eliminar a este miembro del workspace? Perderá acceso a todos los recursos del workspace.","settings.members.remove_modal.action":"Eliminar miembro","settings.members.cancel_invite_modal.title":"Cancelar invitación","settings.members.cancel_invite_modal.description":"¿Estás seguro de que deseas cancelar esta invitación?","settings.members.cancel_invite_modal.action":"Cancelar invitación","settings.members.roles.owner":"Propietario","settings.members.roles.admin":"Administrador","settings.members.roles.member":"Miembro","settings.members.flash.invite_sent":"¡Invitación enviada correctamente!","settings.members.flash.invite_deleted":"Invitación eliminada.","settings.members.flash.member_removed":"¡Miembro eliminado correctamente!","settings.members.flash.role_updated":"Rol del miembro actualizado.","settings.members.flash.wrong_email":"Esta invitación es para otro correo electrónico.","settings.members.flash.already_member":"Ya eres miembro de este workspace.","settings.members.flash.invite_accepted":"¡Bienvenido! Ahora eres miembro del workspace.","settings.members.flash.invite_declined":"Invitación rechazada.","settings.flash.profile_updated":"¡Perfil actualizado correctamente!","settings.flash.language_updated":"¡Idioma actualizado correctamente!","settings.flash.password_updated":"¡Contraseña actualizada correctamente!","settings.flash.workspace_updated":"¡Configuración actualizada correctamente!","settings.flash.photo_updated":"¡Foto actualizada correctamente!","settings.flash.photo_deleted":"¡Foto eliminada correctamente!","settings.flash.logo_updated":"¡Logo subido correctamente!","settings.flash.logo_deleted":"¡Logo eliminado correctamente!","sidebar.workspaces":"Workspaces","sidebar.select_workspace":"Seleccionar workspace","sidebar.create_workspace":"Crear workspace","sidebar.create_post":"Crear post","sidebar.profile":"Perfil","sidebar.log_out":"Cerrar sesión","sidebar.workspace":"Workspace: :name","sidebar.workspace_select":"Workspace: Seleccionar","sidebar.theme":"Tema: :name","sidebar.theme_light":"Claro","sidebar.theme_dark":"Oscuro","sidebar.theme_system":"Sistema","sidebar.language":"Idioma: :name","sidebar.language_select":"Idioma: Seleccionar","sidebar.groups.posts":"Posts","sidebar.groups.configuration":"Configuración","sidebar.groups.support":"Soporte","sidebar.posts.calendar":"Calendario","sidebar.posts.all":"Todos","sidebar.posts.scheduled":"Programados","sidebar.posts.posted":"Publicados","sidebar.posts.drafts":"Borradores","sidebar.config.connections":"Conexiones","sidebar.config.hashtags":"Hashtags","sidebar.config.labels":"Etiquetas","sidebar.config.settings":"Configuración","sidebar.support.discord":"Discord","sidebar.support.share_feedback":"Dar feedback","sidebar.support.last_updates":"Últimas actualizaciones","sidebar.support.docs":"Documentación","validation.accepted":"El campo :attribute debe ser aceptado.","validation.accepted_if":"El campo :attribute debe ser aceptado cuando :other es :value.","validation.active_url":"El campo :attribute debe ser una URL válida.","validation.after":"El campo :attribute debe ser una fecha posterior a :date.","validation.after_or_equal":"El campo :attribute debe ser una fecha posterior o igual a :date.","validation.alpha":"El campo :attribute solo puede contener letras.","validation.alpha_dash":"El campo :attribute solo puede contener letras, números, guiones y guiones bajos.","validation.alpha_num":"El campo :attribute solo puede contener letras y números.","validation.any_of":"El campo :attribute no es válido.","validation.array":"El campo :attribute debe ser un arreglo.","validation.ascii":"El campo :attribute solo puede contener caracteres alfanuméricos de un byte y símbolos.","validation.before":"El campo :attribute debe ser una fecha anterior a :date.","validation.before_or_equal":"El campo :attribute debe ser una fecha anterior o igual a :date.","validation.between.array":"El campo :attribute debe tener entre :min y :max elementos.","validation.between.file":"El campo :attribute debe pesar entre :min y :max kilobytes.","validation.between.numeric":"El campo :attribute debe estar entre :min y :max.","validation.between.string":"El campo :attribute debe tener entre :min y :max caracteres.","validation.boolean":"El campo :attribute debe ser verdadero o falso.","validation.can":"El campo :attribute contiene un valor no autorizado.","validation.confirmed":"La confirmación del campo :attribute no coincide.","validation.contains":"Al campo :attribute le falta un valor requerido.","validation.current_password":"La contraseña es incorrecta.","validation.date":"El campo :attribute debe ser una fecha válida.","validation.date_equals":"El campo :attribute debe ser una fecha igual a :date.","validation.date_format":"El campo :attribute debe coincidir con el formato :format.","validation.decimal":"El campo :attribute debe tener :decimal decimales.","validation.declined":"El campo :attribute debe ser rechazado.","validation.declined_if":"El campo :attribute debe ser rechazado cuando :other es :value.","validation.different":"El campo :attribute y :other deben ser diferentes.","validation.digits":"El campo :attribute debe tener :digits dígitos.","validation.digits_between":"El campo :attribute debe tener entre :min y :max dígitos.","validation.dimensions":"El campo :attribute tiene dimensiones de imagen no válidas.","validation.distinct":"El campo :attribute tiene un valor duplicado.","validation.doesnt_contain":"El campo :attribute no debe contener ninguno de los siguientes: :values.","validation.doesnt_end_with":"El campo :attribute no debe terminar con uno de los siguientes: :values.","validation.doesnt_start_with":"El campo :attribute no debe comenzar con uno de los siguientes: :values.","validation.email":"El campo :attribute debe ser un correo electrónico válido.","validation.encoding":"El campo :attribute debe estar codificado en :encoding.","validation.ends_with":"El campo :attribute debe terminar con uno de los siguientes: :values.","validation.enum":"El :attribute seleccionado no es válido.","validation.exists":"El :attribute seleccionado no es válido.","validation.extensions":"El campo :attribute debe tener una de las siguientes extensiones: :values.","validation.file":"El campo :attribute debe ser un archivo.","validation.filled":"El campo :attribute debe tener un valor.","validation.gt.array":"El campo :attribute debe tener más de :value elementos.","validation.gt.file":"El campo :attribute debe pesar más de :value kilobytes.","validation.gt.numeric":"El campo :attribute debe ser mayor que :value.","validation.gt.string":"El campo :attribute debe tener más de :value caracteres.","validation.gte.array":"El campo :attribute debe tener :value elementos o más.","validation.gte.file":"El campo :attribute debe pesar :value kilobytes o más.","validation.gte.numeric":"El campo :attribute debe ser mayor o igual a :value.","validation.gte.string":"El campo :attribute debe tener :value caracteres o más.","validation.hex_color":"El campo :attribute debe ser un color hexadecimal válido.","validation.image":"El campo :attribute debe ser una imagen.","validation.in":"El :attribute seleccionado no es válido.","validation.in_array":"El campo :attribute debe existir en :other.","validation.in_array_keys":"El campo :attribute debe contener al menos una de las siguientes claves: :values.","validation.integer":"El campo :attribute debe ser un número entero.","validation.ip":"El campo :attribute debe ser una dirección IP válida.","validation.ipv4":"El campo :attribute debe ser una dirección IPv4 válida.","validation.ipv6":"El campo :attribute debe ser una dirección IPv6 válida.","validation.json":"El campo :attribute debe ser una cadena JSON válida.","validation.list":"El campo :attribute debe ser una lista.","validation.lowercase":"El campo :attribute debe estar en minúsculas.","validation.lt.array":"El campo :attribute debe tener menos de :value elementos.","validation.lt.file":"El campo :attribute debe pesar menos de :value kilobytes.","validation.lt.numeric":"El campo :attribute debe ser menor que :value.","validation.lt.string":"El campo :attribute debe tener menos de :value caracteres.","validation.lte.array":"El campo :attribute no debe tener más de :value elementos.","validation.lte.file":"El campo :attribute debe pesar :value kilobytes o menos.","validation.lte.numeric":"El campo :attribute debe ser menor o igual a :value.","validation.lte.string":"El campo :attribute debe tener :value caracteres o menos.","validation.mac_address":"El campo :attribute debe ser una dirección MAC válida.","validation.max.array":"El campo :attribute no debe tener más de :max elementos.","validation.max.file":"El campo :attribute no debe pesar más de :max kilobytes.","validation.max.numeric":"El campo :attribute no debe ser mayor que :max.","validation.max.string":"El campo :attribute no debe tener más de :max caracteres.","validation.max_digits":"El campo :attribute no debe tener más de :max dígitos.","validation.mimes":"El campo :attribute debe ser un archivo de tipo: :values.","validation.mimetypes":"El campo :attribute debe ser un archivo de tipo: :values.","validation.min.array":"El campo :attribute debe tener al menos :min elementos.","validation.min.file":"El campo :attribute debe pesar al menos :min kilobytes.","validation.min.numeric":"El campo :attribute debe ser al menos :min.","validation.min.string":"El campo :attribute debe tener al menos :min caracteres.","validation.min_digits":"El campo :attribute debe tener al menos :min dígitos.","validation.missing":"El campo :attribute debe estar ausente.","validation.missing_if":"El campo :attribute debe estar ausente cuando :other es :value.","validation.missing_unless":"El campo :attribute debe estar ausente a menos que :other sea :value.","validation.missing_with":"El campo :attribute debe estar ausente cuando :values está presente.","validation.missing_with_all":"El campo :attribute debe estar ausente cuando :values están presentes.","validation.multiple_of":"El campo :attribute debe ser múltiplo de :value.","validation.not_in":"El :attribute seleccionado no es válido.","validation.not_regex":"El formato del campo :attribute no es válido.","validation.numeric":"El campo :attribute debe ser un número.","validation.password.letters":"El campo :attribute debe contener al menos una letra.","validation.password.mixed":"El campo :attribute debe contener al menos una letra mayúscula y una minúscula.","validation.password.numbers":"El campo :attribute debe contener al menos un número.","validation.password.symbols":"El campo :attribute debe contener al menos un símbolo.","validation.password.uncompromised":"El :attribute proporcionado ha aparecido en una filtración de datos. Elige un :attribute diferente.","validation.present":"El campo :attribute debe estar presente.","validation.present_if":"El campo :attribute debe estar presente cuando :other es :value.","validation.present_unless":"El campo :attribute debe estar presente a menos que :other sea :value.","validation.present_with":"El campo :attribute debe estar presente cuando :values está presente.","validation.present_with_all":"El campo :attribute debe estar presente cuando :values están presentes.","validation.prohibited":"El campo :attribute está prohibido.","validation.prohibited_if":"El campo :attribute está prohibido cuando :other es :value.","validation.prohibited_if_accepted":"El campo :attribute está prohibido cuando :other es aceptado.","validation.prohibited_if_declined":"El campo :attribute está prohibido cuando :other es rechazado.","validation.prohibited_unless":"El campo :attribute está prohibido a menos que :other esté en :values.","validation.prohibits":"El campo :attribute prohíbe que :other esté presente.","validation.regex":"El formato del campo :attribute no es válido.","validation.required":"El campo :attribute es obligatorio.","validation.required_array_keys":"El campo :attribute debe contener entradas para: :values.","validation.required_if":"El campo :attribute es obligatorio cuando :other es :value.","validation.required_if_accepted":"El campo :attribute es obligatorio cuando :other es aceptado.","validation.required_if_declined":"El campo :attribute es obligatorio cuando :other es rechazado.","validation.required_unless":"El campo :attribute es obligatorio a menos que :other esté en :values.","validation.required_with":"El campo :attribute es obligatorio cuando :values está presente.","validation.required_with_all":"El campo :attribute es obligatorio cuando :values están presentes.","validation.required_without":"El campo :attribute es obligatorio cuando :values no está presente.","validation.required_without_all":"El campo :attribute es obligatorio cuando ninguno de :values está presente.","validation.same":"El campo :attribute debe coincidir con :other.","validation.size.array":"El campo :attribute debe contener :size elementos.","validation.size.file":"El campo :attribute debe pesar :size kilobytes.","validation.size.numeric":"El campo :attribute debe ser :size.","validation.size.string":"El campo :attribute debe tener :size caracteres.","validation.starts_with":"El campo :attribute debe comenzar con uno de los siguientes: :values.","validation.string":"El campo :attribute debe ser una cadena de texto.","validation.timezone":"El campo :attribute debe ser una zona horaria válida.","validation.unique":"El :attribute ya ha sido registrado.","validation.uploaded":"El :attribute no se pudo subir.","validation.uppercase":"El campo :attribute debe estar en mayúsculas.","validation.url":"El campo :attribute debe ser una URL válida.","validation.ulid":"El campo :attribute debe ser un ULID válido.","validation.uuid":"El campo :attribute debe ser un UUID válido.","validation.custom.attribute-name.rule-name":"custom-message"} \ No newline at end of file diff --git a/lang/php_pt-BR.json b/lang/php_pt-BR.json new file mode 100644 index 00000000..3d9a5e7a --- /dev/null +++ b/lang/php_pt-BR.json @@ -0,0 +1 @@ +{"accounts.title":"Conexões","accounts.page_title":"Contas Conectadas","accounts.description":"Conecte suas redes sociais para agendar e publicar posts","accounts.not_connected":"Não conectado","accounts.connect":"Conectar","accounts.connection_lost":"Conexão perdida","accounts.reconnect_account":"Reconectar conta","accounts.view_profile":"Ver perfil","accounts.disconnect":"Desconectar","accounts.disconnect_modal.title":"Desconectar Conta","accounts.disconnect_modal.description":"Tem certeza que deseja desconectar esta conta? Você pode reconectá-la a qualquer momento.","accounts.disconnect_modal.confirm":"Desconectar","accounts.disconnect_modal.cancel":"Cancelar","accounts.bluesky.title":"Conectar Bluesky","accounts.bluesky.description":"Digite suas credenciais para conectar","accounts.bluesky.email":"E-mail","accounts.bluesky.email_placeholder":"seuhandle.bsky.social","accounts.bluesky.app_password":"Senha do App","accounts.bluesky.app_password_placeholder":"xxxx-xxxx-xxxx-xxxx","accounts.bluesky.app_password_hint":"Use uma Senha do App por segurança. Crie uma em bsky.app/settings.","accounts.bluesky.submit":"Conectar Bluesky","accounts.bluesky.submitting":"Conectando...","accounts.mastodon.title":"Conectar Mastodon","accounts.mastodon.description":"Digite a instância do seu Mastodon","accounts.mastodon.instance_url":"URL da Instância","accounts.mastodon.instance_placeholder":"https://mastodon.social","accounts.mastodon.instance_hint":"Digite a URL da sua instância Mastodon (ex: mastodon.social, techhub.social)","accounts.mastodon.submit":"Continuar com Mastodon","accounts.mastodon.submitting":"Conectando...","accounts.facebook.title":"Selecionar Página do Facebook","accounts.facebook.description":"Escolha qual página você deseja conectar","accounts.facebook.no_pages":"Nenhuma página encontrada","accounts.facebook.no_pages_description":"Você não é administrador de nenhuma página do Facebook.","accounts.facebook.page_label":"Página do Facebook","accounts.linkedin.title":"Selecionar Página do LinkedIn","accounts.linkedin.description":"Escolha qual página você deseja conectar","accounts.linkedin.no_pages":"Nenhuma página encontrada","accounts.linkedin.no_pages_description":"Você não é administrador de nenhuma página do LinkedIn.","accounts.linkedin.page_label":"Página do LinkedIn","accounts.flash.disconnected":"Conta desconectada com sucesso!","accounts.flash.connected":"Conta conectada com sucesso!","accounts.flash.session_expired":"Sessão expirada. Por favor, tente novamente.","accounts.flash.workspace_not_found":"Workspace não encontrado.","accounts.flash.already_connected":"Esta plataforma já está conectada.","accounts.flash.no_youtube_channels":"Nenhum canal do YouTube encontrado. Por favor, crie um canal primeiro.","auth.failed":"Essas credenciais não correspondem aos nossos registros.","auth.password":"A senha fornecida está incorreta.","auth.throttle":"Muitas tentativas de login. Por favor, tente novamente em :seconds segundos.","auth.flash.welcome":"Bem-vindo ao TryPost!","auth.flash.welcome_trial":"Bem-vindo ao TryPost! Seu período de teste começou.","auth.legal":"Ao continuar, você concorda com nossos Termos de Serviço e Política de Privacidade.","auth.slides.calendar.title":"Calendário Visual","auth.slides.calendar.description":"Planeje e agende seu conteúdo com um calendário intuitivo de arrastar e soltar em todas as suas contas sociais.","auth.slides.scheduling.title":"Agendamento Inteligente","auth.slides.scheduling.description":"Agende posts no LinkedIn, X, Instagram, TikTok, YouTube e mais — tudo em um só lugar.","auth.slides.media.title":"Mídia Rica","auth.slides.media.description":"Publique imagens, carrosséis, stories e reels. Cada plataforma recebe o formato correto automaticamente.","auth.slides.video.title":"Publicação de Vídeo","auth.slides.video.description":"Envie vídeos uma vez e publique no TikTok, YouTube Shorts, Instagram Reels e Facebook Reels.","auth.slides.team.title":"Workspaces em Equipe","auth.slides.team.description":"Convide sua equipe, atribua funções e gerencie múltiplas marcas em workspaces separados.","auth.slides.hashtags.title":"Grupos de Hashtags","auth.slides.hashtags.description":"Salve coleções de hashtags e adicione aos posts com um clique. Organize com etiquetas e filtros.","auth.login.title":"Entrar na sua conta","auth.login.description":"Digite seu email e senha abaixo para entrar","auth.login.page_title":"Entrar","auth.login.email":"Endereço de email","auth.login.password":"Senha","auth.login.forgot_password":"Esqueceu a senha?","auth.login.remember_me":"Lembrar de mim","auth.login.submit":"Entrar","auth.login.no_account":"Não tem uma conta?","auth.login.sign_up":"Cadastre-se","auth.register.title":"Criar uma conta","auth.register.description":"Digite seus dados abaixo para criar sua conta","auth.register.page_title":"Cadastro","auth.register.name":"Nome","auth.register.name_placeholder":"Nome completo","auth.register.email":"Endereço de email","auth.register.password":"Senha","auth.register.show_password":"Mostrar senha","auth.register.hide_password":"Esconder senha","auth.register.submit":"Criar conta","auth.register.has_account":"Já tem uma conta?","auth.register.log_in":"Entrar","auth.forgot_password.title":"Esqueceu a senha","auth.forgot_password.description":"Digite seu email para receber um link de redefinição de senha","auth.forgot_password.page_title":"Esqueceu a senha","auth.forgot_password.email":"Endereço de email","auth.forgot_password.submit":"Enviar link de redefinição","auth.forgot_password.return_to":"Ou, volte para","auth.forgot_password.log_in":"entrar","auth.reset_password.title":"Redefinir senha","auth.reset_password.description":"Por favor, digite sua nova senha abaixo","auth.reset_password.page_title":"Redefinir senha","auth.reset_password.email":"Email","auth.reset_password.password":"Senha","auth.reset_password.confirm_password":"Confirmar Senha","auth.reset_password.confirm_placeholder":"Confirmar senha","auth.reset_password.submit":"Redefinir senha","auth.verify_email.title":"Verificar email","auth.verify_email.description":"Por favor, verifique seu endereço de email clicando no link que acabamos de enviar.","auth.verify_email.page_title":"Verificação de email","auth.verify_email.link_sent":"Um novo link de verificação foi enviado para o endereço de email que você forneceu durante o cadastro.","auth.verify_email.resend":"Reenviar email de verificação","auth.verify_email.log_out":"Sair","auth.accept_invite.page_title":"Aceitar Convite","auth.accept_invite.title":"Você foi convidado!","auth.accept_invite.description":"Você foi convidado para participar do workspace :workspace.","auth.accept_invite.workspace":"Workspace","auth.accept_invite.your_role":"Seu cargo","auth.accept_invite.email":"Email","auth.accept_invite.accept":"Aceitar Convite","auth.accept_invite.decline":"Recusar Convite","auth.accept_invite.login_prompt":"Entre ou crie uma conta para aceitar este convite.","auth.accept_invite.log_in":"Entrar","auth.accept_invite.create_account":"Criar Conta","billing.title":"Assinatura","billing.description":"Gerencie sua assinatura e método de pagamento","billing.subscribe.page_title":"Comece seu teste gratuito","billing.subscribe.title":"Comece seu teste gratuito","billing.subscribe.description":":days dias grátis. Sem cartão de crédito para começar.","billing.subscribe.start_trial":"Começar teste de :days dias","billing.subscribe.cancel_anytime":"Cancele a qualquer momento. Sem perguntas.","billing.subscribe.switch_workspace":"Trocar workspace","billing.subscribe.features.calendar":"Calendário visual com arrastar e soltar","billing.subscribe.features.scheduling":"Agendamento ilimitado de posts","billing.subscribe.features.media":"Imagens, carrosséis e stories","billing.subscribe.features.video":"Publicação de vídeos em todas as plataformas","billing.subscribe.features.team":"Colaboração em equipe e workspaces","billing.subscribe.features.hashtags":"Grupos de hashtags e etiquetas","billing.trial.title":"Período de teste ativo","billing.trial.description":"Seu período de teste termina em :date. Após isso, sua assinatura será cobrada automaticamente.","billing.subscription.title":"Sua Assinatura","billing.subscription.workspaces":"Workspaces","billing.subscription.quantity":"Quantidade da assinatura","billing.subscription.expires":"Expira em :date","billing.subscription.canceled_on":"Sua assinatura será cancelada em :date","billing.subscription.manage":"Gerenciar no Stripe","billing.invoices.title":"Faturas","billing.invoices.description":"Histórico de pagamentos","billing.invoices.empty":"Nenhuma fatura encontrada","billing.invoices.paid":"Pago","billing.status.active":"Ativo","billing.status.canceled":"Cancelado","billing.status.incomplete":"Incompleto","billing.status.incomplete_expired":"Expirado","billing.status.past_due":"Vencido","billing.status.trialing":"Teste","billing.status.unpaid":"Não pago","calendar.title":"Calendário","calendar.today":"Hoje","calendar.day":"Dia","calendar.week":"Semana","calendar.month":"Mês","calendar.new_post":"Novo Post","calendar.no_content":"Sem conteúdo","calendar.more":"+:count mais","common.confirm_modal.cannot_be_undone":"Esta ação não pode ser desfeita.","common.confirm_modal.type":"Digite","common.confirm_modal.to_confirm":"para confirmar.","common.confirm_modal.copy_to_clipboard":"Copiar para a área de transferência","hashtags.title":"Hashtags","hashtags.description":"Crie grupos de hashtags para adicionar rapidamente aos seus posts","hashtags.new_group":"Novo Grupo","hashtags.no_groups_yet":"Nenhum grupo de hashtags ainda","hashtags.no_groups_description":"Crie grupos de hashtags para adicionar rapidamente hashtags populares aos seus posts","hashtags.create_first_group":"Crie seu primeiro grupo","hashtags.hashtags_count":":count hashtags","hashtags.create.title":"Criar Grupo de Hashtags","hashtags.create.description":"Dê um nome ao grupo e adicione hashtags separadas por espaços ou vírgulas","hashtags.create.name":"Nome do Grupo","hashtags.create.name_placeholder":"ex: Marketing, Viagem, Comida","hashtags.create.hashtags":"Hashtags","hashtags.create.hashtags_placeholder":"#marketing #redessociais #negocios #crescimento","hashtags.create.hashtags_hint":"Digite as hashtags separadas por espaços ou vírgulas. Inclua o símbolo #.","hashtags.create.submit":"Criar Grupo","hashtags.create.submitting":"Criando...","hashtags.edit.title":"Editar Grupo de Hashtags","hashtags.edit.description":"Atualize o nome e as hashtags deste grupo","hashtags.edit.name":"Nome do Grupo","hashtags.edit.name_placeholder":"ex: Marketing, Viagem, Comida","hashtags.edit.hashtags":"Hashtags","hashtags.edit.hashtags_placeholder":"#marketing #redessociais #negocios #crescimento","hashtags.edit.hashtags_hint":"Digite as hashtags separadas por espaços ou vírgulas. Inclua o símbolo #.","hashtags.edit.submit":"Salvar Alterações","hashtags.edit.submitting":"Salvando...","hashtags.delete.title":"Excluir Grupo de Hashtags","hashtags.delete.description":"Tem certeza que deseja excluir este grupo de hashtags? Esta ação não pode ser desfeita.","hashtags.delete.confirm":"Excluir","hashtags.delete.cancel":"Cancelar","hashtags.flash.created":"Grupo de hashtags criado com sucesso!","hashtags.flash.updated":"Grupo de hashtags atualizado com sucesso!","hashtags.flash.deleted":"Grupo de hashtags excluído com sucesso!","labels.title":"Etiquetas","labels.description":"Crie etiquetas para organizar e categorizar seus posts","labels.new_label":"Nova Etiqueta","labels.no_labels_yet":"Nenhuma etiqueta ainda","labels.create_first_label":"Crie sua primeira etiqueta","labels.create.title":"Criar Etiqueta","labels.create.description":"Dê um nome e escolha uma cor para sua etiqueta","labels.create.name":"Nome","labels.create.name_placeholder":"Digite o nome da etiqueta...","labels.create.color":"Cor","labels.create.submit":"Criar Etiqueta","labels.create.submitting":"Criando...","labels.edit.title":"Editar Etiqueta","labels.edit.description":"Atualize o nome e a cor desta etiqueta","labels.edit.name":"Nome","labels.edit.name_placeholder":"Digite o nome da etiqueta...","labels.edit.color":"Cor","labels.edit.submit":"Salvar Alterações","labels.edit.submitting":"Salvando...","labels.delete.title":"Excluir Etiqueta","labels.delete.description":"Tem certeza que deseja excluir esta etiqueta? Esta ação não pode ser desfeita.","labels.delete.confirm":"Excluir","labels.delete.cancel":"Cancelar","labels.flash.created":"Etiqueta criada com sucesso!","labels.flash.updated":"Etiqueta atualizada com sucesso!","labels.flash.deleted":"Etiqueta excluída com sucesso!","mail.workspace_connections_disconnected.subject":"{1} :count conta precisa ser reconectada em :workspace|[2,*] :count contas precisam ser reconectadas em :workspace","mail.workspace_connections_disconnected.title":"Contas Precisam ser Reconectadas","mail.workspace_connections_disconnected.intro":"As seguintes contas de redes sociais no seu workspace :workspace foram desconectadas e precisam ser reconectadas:","mail.workspace_connections_disconnected.reasons_title":"Isso pode ter acontecido porque:","mail.workspace_connections_disconnected.reason_expired":"Os tokens de acesso expiraram","mail.workspace_connections_disconnected.reason_revoked":"Você revogou o acesso ao TryPost na plataforma","mail.workspace_connections_disconnected.reason_changed":"A plataforma mudou os requisitos de autenticação","mail.workspace_connections_disconnected.reconnect_cta":"Por favor, reconecte essas contas para continuar agendando e publicando posts.","mail.workspace_connections_disconnected.button":"Reconectar Contas","pagination.previous":"« Anterior","pagination.next":"Próximo »","passwords.reset":"Sua senha foi redefinida.","passwords.sent":"Enviamos o link de redefinição de senha por e-mail.","passwords.throttled":"Por favor, aguarde antes de tentar novamente.","passwords.token":"Este token de redefinição de senha é inválido.","passwords.user":"Não conseguimos encontrar um usuário com esse endereço de e-mail.","posts.title":"Posts","posts.all_posts":"Todos os Posts","posts.new_post":"Novo Post","posts.no_posts":"Nenhum post encontrado","posts.start_creating":"Comece criando seu primeiro post.","posts.manage_posts":"Gerencie todos os seus posts","posts.delete_confirm":"Tem certeza que deseja excluir este post?","posts.by":"por","posts.actions.view":"Ver post","posts.actions.delete":"Excluir post","posts.form.post_type":"Tipo de Post","posts.form.board":"Pasta","posts.form.select_board":"Selecione uma pasta","posts.form.search_board":"Buscar pasta...","posts.form.no_board_found":"Nenhuma pasta encontrada","posts.form.media":"Mídia","posts.form.min":"Mín","posts.form.uploading":"Enviando...","posts.form.drop_to_upload":"Solte para enviar","posts.form.drag_and_drop":"Arraste e solte ou clique para enviar","posts.form.photos_and_videos":"Fotos e vídeos","posts.form.photos_only":"Apenas fotos","posts.form.videos_only":"Apenas vídeos","posts.form.drag_to_reorder":"Arraste para reordenar","posts.form.caption":"Legenda","posts.form.write_caption":"Escreva sua legenda...","posts.status.draft":"Rascunho","posts.status.scheduled":"Agendado","posts.status.publishing":"Publicando","posts.status.published":"Publicado","posts.status.partially_published":"Parcialmente Publicado","posts.status.failed":"Falhou","posts.descriptions.draft":"Posts aguardando agendamento","posts.descriptions.scheduled":"Posts agendados para publicação","posts.descriptions.published":"Posts já publicados","posts.edit.title":"Editar Post","posts.edit.view_title":"Visualizar Post","posts.edit.manage_platforms":"Gerenciar plataformas","posts.edit.sync":"Sincronizar","posts.edit.labels":"Etiquetas","posts.edit.hashtags":"Hashtags","posts.edit.schedule":"Agendar","posts.edit.publish":"Publicar","posts.edit.delete":"Excluir","posts.edit.settings":"Configurações","posts.edit.schedule_for":"Agendar para","posts.edit.saving":"Salvando...","posts.edit.saved":"Salvo","posts.edit.scheduled_at":"Agendado:","posts.edit.published_at":"Publicado:","posts.edit.media":"Mídia","posts.edit.caption":"Legenda","posts.edit.no_caption":"Sem legenda","posts.edit.no_content":"Sem conteúdo","posts.edit.empty_state.title":"Nenhuma plataforma selecionada","posts.edit.empty_state.description":"Selecione pelo menos uma plataforma para criar seu post","posts.edit.delete_modal.title":"Excluir Post","posts.edit.delete_modal.description":"Tem certeza que deseja excluir este post? Esta ação não pode ser desfeita.","posts.edit.delete_modal.action":"Excluir","posts.edit.delete_modal.cancel":"Cancelar","posts.edit.sync_enable.title":"Ativar sincronização?","posts.edit.sync_enable.description":"Todas as plataformas compartilharão o mesmo conteúdo. Qualquer edição personalizada feita em plataformas individuais será substituída pelo conteúdo atual.","posts.edit.sync_enable.cancel":"Cancelar","posts.edit.sync_enable.action":"Ativar sincronização","posts.edit.sync_disable.title":"Desativar sincronização?","posts.edit.sync_disable.description":"Cada plataforma manterá seu conteúdo atual, mas edições futuras serão aplicadas apenas à plataforma que você estiver editando.","posts.edit.sync_disable.customize_note":"Você poderá personalizar o conteúdo para cada plataforma individualmente.","posts.edit.sync_disable.cancel":"Cancelar","posts.edit.sync_disable.action":"Desativar sincronização","posts.edit.platforms_dialog.title":"Selecionar Plataformas","posts.edit.platforms_dialog.description":"Escolha em quais plataformas publicar este post.","posts.edit.hashtags_modal.search":"Buscar hashtags...","posts.edit.hashtags_modal.no_results":"Nenhuma hashtag encontrada.","posts.edit.validation.select_board":"Selecione uma pasta","posts.edit.validation.images_not_supported":"Imagens não suportadas","posts.edit.validation.videos_not_supported":"Vídeos não suportados","posts.edit.validation.max_images":"Máx :count imagens","posts.edit.validation.requires_media":"Requer mídia","posts.edit.validation.exceeded":":count excedido","posts.edit.validation.does_not_support_images":":platform não suporta imagens","posts.edit.validation.supports_up_to_images":":platform suporta até :count imagens","posts.edit.validation.does_not_support_videos":":platform não suporta vídeos","posts.content_types.instagram_feed.label":"Post do Feed","posts.content_types.instagram_feed.description":"Aparece no seu feed e perfil","posts.content_types.instagram_reel.label":"Reels","posts.content_types.instagram_reel.description":"Vídeo curto de até 90 segundos","posts.content_types.instagram_story.label":"Story","posts.content_types.instagram_story.description":"Desaparece após 24 horas","posts.content_types.linkedin_post.label":"Post","posts.content_types.linkedin_post.description":"Post padrão com texto e mídia","posts.content_types.linkedin_carousel.label":"Carrossel","posts.content_types.linkedin_carousel.description":"Imagens deslizáveis","posts.content_types.linkedin_page_post.label":"Post","posts.content_types.linkedin_page_post.description":"Post padrão com texto e mídia","posts.content_types.linkedin_page_carousel.label":"Carrossel","posts.content_types.linkedin_page_carousel.description":"Imagens deslizáveis","posts.content_types.facebook_post.label":"Post","posts.content_types.facebook_post.description":"Post padrão na sua página","posts.content_types.facebook_reel.label":"Reels","posts.content_types.facebook_reel.description":"Vídeo curto de até 90 segundos","posts.content_types.facebook_story.label":"Story","posts.content_types.facebook_story.description":"Desaparece após 24 horas","posts.content_types.tiktok_video.label":"Vídeo","posts.content_types.tiktok_video.description":"Conteúdo de vídeo curto","posts.content_types.youtube_short.label":"Short","posts.content_types.youtube_short.description":"Vídeo vertical de até 60 segundos","posts.content_types.x_post.label":"Post","posts.content_types.x_post.description":"Tweet com texto e mídia","posts.content_types.threads_post.label":"Post","posts.content_types.threads_post.description":"Post de texto com mídia opcional","posts.content_types.pinterest_pin.label":"Pin","posts.content_types.pinterest_pin.description":"Pin de imagem com link","posts.content_types.pinterest_video_pin.label":"Pin de Vídeo","posts.content_types.pinterest_video_pin.description":"Conteúdo em vídeo","posts.content_types.pinterest_carousel.label":"Carrossel","posts.content_types.pinterest_carousel.description":"2-5 imagens","posts.content_types.bluesky_post.label":"Post","posts.content_types.bluesky_post.description":"Post de texto com imagens opcionais","posts.content_types.mastodon_post.label":"Post","posts.content_types.mastodon_post.description":"Post de texto com mídia opcional","posts.platforms.linkedin":"LinkedIn","posts.platforms.linkedin-page":"Página do LinkedIn","posts.platforms.x":"X","posts.platforms.tiktok":"TikTok","posts.platforms.youtube":"YouTube Shorts","posts.platforms.facebook":"Página do Facebook","posts.platforms.instagram":"Instagram","posts.platforms.threads":"Threads","posts.platforms.pinterest":"Pinterest","posts.platforms.bluesky":"Bluesky","posts.platforms.mastodon":"Mastodon","posts.flash.scheduled":"Post agendado com sucesso!","posts.flash.publishing":"Post está sendo publicado!","posts.flash.deleted":"Post excluído com sucesso!","posts.flash.cannot_edit_published":"Posts publicados não podem ser editados.","posts.flash.connect_first":"Conecte pelo menos uma rede social antes de criar um post.","posts.errors.account_disconnected":"Conta social está desconectada","settings.title":"Configurações","settings.description":"Gerencie seu perfil e configurações da conta","settings.nav.profile":"Perfil","settings.nav.password":"Senha","settings.nav.workspace":"Workspace","settings.nav.members":"Membros","settings.nav.billing":"Faturamento","settings.profile.title":"Configurações do perfil","settings.profile.photo_heading":"Foto do perfil","settings.profile.photo_description":"Envie uma foto de perfil","settings.profile.heading":"Informações do perfil","settings.profile.description":"Atualize seu nome e endereço de e-mail","settings.profile.avatar":"Avatar","settings.profile.name":"Nome","settings.profile.name_placeholder":"Nome completo","settings.profile.email":"Endereço de e-mail","settings.profile.email_placeholder":"Endereço de e-mail","settings.profile.email_unverified":"Seu endereço de e-mail não foi verificado.","settings.profile.resend_verification":"Clique aqui para reenviar o e-mail de verificação.","settings.profile.verification_sent":"Um novo link de verificação foi enviado para seu endereço de e-mail.","settings.profile.save":"Salvar","settings.password.title":"Configurações de senha","settings.password.heading":"Atualizar senha","settings.password.description":"Certifique-se de que sua conta esteja usando uma senha longa e aleatória para se manter seguro","settings.password.current_password":"Senha atual","settings.password.current_password_placeholder":"Senha atual","settings.password.new_password":"Nova senha","settings.password.new_password_placeholder":"Nova senha","settings.password.confirm_password":"Confirmar senha","settings.password.confirm_password_placeholder":"Confirmar senha","settings.password.save":"Salvar senha","settings.delete_account.heading":"Excluir conta","settings.delete_account.description":"Exclua sua conta e todos os seus recursos","settings.delete_account.warning":"Atenção","settings.delete_account.warning_message":"Por favor, prossiga com cuidado, isso não pode ser desfeito.","settings.delete_account.button":"Excluir conta","settings.delete_account.modal_title":"Tem certeza que deseja excluir sua conta?","settings.delete_account.modal_description":"Uma vez que sua conta for excluída, todos os seus recursos e dados também serão permanentemente excluídos. Por favor, digite sua senha para confirmar que deseja excluir permanentemente sua conta.","settings.delete_account.password":"Senha","settings.delete_account.password_placeholder":"Senha","settings.delete_account.cancel":"Cancelar","settings.delete_account.confirm":"Excluir conta","settings.workspace.title":"Configurações do workspace","settings.workspace.logo_heading":"Logo do workspace","settings.workspace.logo_description":"Envie um logo para o workspace","settings.workspace.heading":"Nome do workspace","settings.workspace.description":"Atualize o nome e fuso horário do workspace","settings.workspace.members_heading":"Membros","settings.workspace.members_description":"Gerencie membros e convites do workspace","settings.workspace.name":"Nome","settings.workspace.name_placeholder":"Meu Workspace","settings.workspace.timezone":"Fuso horário","settings.workspace.save":"Salvar","settings.members.title":"Membros","settings.members.heading":"Membros da equipe","settings.members.description":"Gerencie membros e convites deste workspace","settings.members.cancel":"Cancelar","settings.members.remove":"Remover","settings.members.make_admin":"Tornar administrador","settings.members.make_member":"Tornar membro","settings.members.invite.title":"Convidar Membro","settings.members.invite.description":"Envie um convite por e-mail para adicionar colaboradores","settings.members.invite.email":"E-mail","settings.members.invite.email_placeholder":"colaborador@email.com","settings.members.invite.role":"Função","settings.members.invite.role_placeholder":"Selecione uma função","settings.members.invite.submit":"Enviar Convite","settings.members.pending.title":"Convites Pendentes","settings.members.pending.description":"Convites aguardando aceitação","settings.members.pending.empty":"Nenhum convite pendente","settings.members.list.title":"Membros","settings.members.list.description":"Pessoas com acesso a este workspace","settings.members.list.empty":"Nenhum membro além do proprietário","settings.members.remove_modal.title":"Remover membro","settings.members.remove_modal.description":"Tem certeza que deseja remover este membro do workspace? Ele perderá acesso a todos os recursos do workspace.","settings.members.remove_modal.action":"Remover membro","settings.members.cancel_invite_modal.title":"Cancelar convite","settings.members.cancel_invite_modal.description":"Tem certeza que deseja cancelar este convite?","settings.members.cancel_invite_modal.action":"Cancelar convite","settings.members.roles.owner":"Proprietário","settings.members.roles.admin":"Administrador","settings.members.roles.member":"Membro","settings.members.flash.invite_sent":"Convite enviado com sucesso!","settings.members.flash.invite_deleted":"Convite excluído.","settings.members.flash.member_removed":"Membro removido com sucesso.","settings.members.flash.role_updated":"Função do membro atualizada.","settings.members.flash.wrong_email":"Este convite é para um endereço de e-mail diferente.","settings.members.flash.already_member":"Você já é membro deste workspace.","settings.members.flash.invite_accepted":"Bem-vindo! Você agora é membro do workspace.","settings.members.flash.invite_declined":"Convite recusado.","settings.flash.profile_updated":"Perfil atualizado com sucesso!","settings.flash.language_updated":"Idioma atualizado com sucesso!","settings.flash.password_updated":"Senha atualizada com sucesso!","settings.flash.workspace_updated":"Configurações atualizadas com sucesso!","settings.flash.photo_updated":"Foto atualizada com sucesso!","settings.flash.photo_deleted":"Foto removida com sucesso!","settings.flash.logo_updated":"Logo enviado com sucesso!","settings.flash.logo_deleted":"Logo removido com sucesso!","sidebar.select_workspace":"Selecionar workspace","sidebar.create_workspace":"Criar workspace","sidebar.create_post":"Novo post","sidebar.profile":"Perfil","sidebar.log_out":"Sair","sidebar.workspace":"Workspace: :name","sidebar.workspace_select":"Workspace: Selecionar","sidebar.theme":"Tema: :name","sidebar.theme_light":"Claro","sidebar.theme_dark":"Escuro","sidebar.theme_system":"Sistema","sidebar.language":"Idioma: :name","sidebar.language_select":"Idioma: Selecionar","sidebar.groups.posts":"Posts","sidebar.groups.configuration":"Configurações","sidebar.groups.support":"Suporte","sidebar.posts.calendar":"Calendário","sidebar.posts.all":"Todos","sidebar.posts.scheduled":"Agendados","sidebar.posts.posted":"Publicados","sidebar.posts.drafts":"Rascunhos","sidebar.config.connections":"Conexões","sidebar.config.hashtags":"Hashtags","sidebar.config.labels":"Etiquetas","sidebar.config.settings":"Configurações","sidebar.support.discord":"Discord","sidebar.support.share_feedback":"Enviar feedback","sidebar.support.last_updates":"Últimas Atualizações","sidebar.support.docs":"Documentação","validation.accepted":"O campo :attribute deve ser aceito.","validation.accepted_if":"O campo :attribute deve ser aceito quando :other for :value.","validation.active_url":"O campo :attribute deve ser uma URL válida.","validation.after":"O campo :attribute deve ser uma data posterior a :date.","validation.after_or_equal":"O campo :attribute deve ser uma data posterior ou igual a :date.","validation.alpha":"O campo :attribute deve conter apenas letras.","validation.alpha_dash":"O campo :attribute deve conter apenas letras, números, hifens e underscores.","validation.alpha_num":"O campo :attribute deve conter apenas letras e números.","validation.any_of":"O campo :attribute é inválido.","validation.array":"O campo :attribute deve ser um array.","validation.ascii":"O campo :attribute deve conter apenas caracteres alfanuméricos e símbolos de um byte.","validation.before":"O campo :attribute deve ser uma data anterior a :date.","validation.before_or_equal":"O campo :attribute deve ser uma data anterior ou igual a :date.","validation.between.array":"O campo :attribute deve ter entre :min e :max itens.","validation.between.file":"O campo :attribute deve estar entre :min e :max kilobytes.","validation.between.numeric":"O campo :attribute deve estar entre :min e :max.","validation.between.string":"O campo :attribute deve estar entre :min e :max caracteres.","validation.boolean":"O campo :attribute deve ser verdadeiro ou falso.","validation.can":"O campo :attribute contém um valor não autorizado.","validation.confirmed":"A confirmação do campo :attribute não corresponde.","validation.contains":"O campo :attribute está faltando um valor obrigatório.","validation.current_password":"A senha está incorreta.","validation.date":"O campo :attribute deve ser uma data válida.","validation.date_equals":"O campo :attribute deve ser uma data igual a :date.","validation.date_format":"O campo :attribute deve corresponder ao formato :format.","validation.decimal":"O campo :attribute deve ter :decimal casas decimais.","validation.declined":"O campo :attribute deve ser recusado.","validation.declined_if":"O campo :attribute deve ser recusado quando :other for :value.","validation.different":"O campo :attribute e :other devem ser diferentes.","validation.digits":"O campo :attribute deve ter :digits dígitos.","validation.digits_between":"O campo :attribute deve ter entre :min e :max dígitos.","validation.dimensions":"O campo :attribute deve ter dimensões de imagem válidas.","validation.distinct":"O campo :attribute tem um valor duplicado.","validation.doesnt_contain":"O campo :attribute não deve conter nenhum dos seguintes: :values.","validation.doesnt_end_with":"O campo :attribute não deve terminar com nenhum dos seguintes: :values.","validation.doesnt_start_with":"O campo :attribute não deve começar com nenhum dos seguintes: :values.","validation.email":"O campo :attribute deve ser um endereço de e-mail válido.","validation.encoding":"O campo :attribute deve ser codificado em :encoding.","validation.ends_with":"O campo :attribute deve terminar com um dos seguintes: :values.","validation.enum":"O :attribute selecionado é inválido.","validation.exists":"O :attribute selecionado é inválido.","validation.extensions":"O campo :attribute deve ter uma das seguintes extensões: :values.","validation.file":"O campo :attribute deve ser um arquivo.","validation.filled":"O campo :attribute deve ter um valor.","validation.gt.array":"O campo :attribute deve ter mais de :value itens.","validation.gt.file":"O campo :attribute deve ser maior que :value kilobytes.","validation.gt.numeric":"O campo :attribute deve ser maior que :value.","validation.gt.string":"O campo :attribute deve ser maior que :value caracteres.","validation.gte.array":"O campo :attribute deve ter :value itens ou mais.","validation.gte.file":"O campo :attribute deve ser maior ou igual a :value kilobytes.","validation.gte.numeric":"O campo :attribute deve ser maior ou igual a :value.","validation.gte.string":"O campo :attribute deve ser maior ou igual a :value caracteres.","validation.hex_color":"O campo :attribute deve ser uma cor hexadecimal válida.","validation.image":"O campo :attribute deve ser uma imagem.","validation.in":"O :attribute selecionado é inválido.","validation.in_array":"O campo :attribute deve existir em :other.","validation.in_array_keys":"O campo :attribute deve conter pelo menos uma das seguintes chaves: :values.","validation.integer":"O campo :attribute deve ser um inteiro.","validation.ip":"O campo :attribute deve ser um endereço IP válido.","validation.ipv4":"O campo :attribute deve ser um endereço IPv4 válido.","validation.ipv6":"O campo :attribute deve ser um endereço IPv6 válido.","validation.json":"O campo :attribute deve ser uma string JSON válida.","validation.list":"O campo :attribute deve ser uma lista.","validation.lowercase":"O campo :attribute deve estar em minúsculas.","validation.lt.array":"O campo :attribute deve ter menos de :value itens.","validation.lt.file":"O campo :attribute deve ser menor que :value kilobytes.","validation.lt.numeric":"O campo :attribute deve ser menor que :value.","validation.lt.string":"O campo :attribute deve ser menor que :value caracteres.","validation.lte.array":"O campo :attribute deve ter :value itens ou menos.","validation.lte.file":"O campo :attribute deve ser menor ou igual a :value kilobytes.","validation.lte.numeric":"O campo :attribute deve ser menor ou igual a :value.","validation.lte.string":"O campo :attribute deve ser menor ou igual a :value caracteres.","validation.mac_address":"O campo :attribute deve ser um endereço MAC válido.","validation.max.array":"O campo :attribute deve ter no máximo :max itens.","validation.max.file":"O campo :attribute deve ter no máximo :max kilobytes.","validation.max.numeric":"O campo :attribute deve ter no máximo :max.","validation.max.string":"O campo :attribute deve ter no máximo :max caracteres.","validation.max_digits":"O campo :attribute não deve ter mais que :max dígitos.","validation.mimes":"O campo :attribute deve ser um arquivo do tipo: :values.","validation.mimetypes":"O campo :attribute deve ser um arquivo do tipo: :values.","validation.min.array":"O campo :attribute deve ter pelo menos :min itens.","validation.min.file":"O campo :attribute deve ter pelo menos :min kilobytes.","validation.min.numeric":"O campo :attribute deve ter pelo menos :min.","validation.min.string":"O campo :attribute deve ter pelo menos :min caracteres.","validation.min_digits":"O campo :attribute deve ter pelo menos :min dígitos.","validation.missing":"O campo :attribute deve estar ausente.","validation.missing_if":"O campo :attribute deve estar ausente quando :other for :value.","validation.missing_unless":"O campo :attribute deve estar ausente a menos que :other seja :value.","validation.missing_with":"O campo :attribute deve estar ausente quando :values estiver presente.","validation.missing_with_all":"O campo :attribute deve estar ausente quando :values estiverem presentes.","validation.multiple_of":"O campo :attribute deve ser um múltiplo de :value.","validation.not_in":"O :attribute selecionado é inválido.","validation.not_regex":"O formato do campo :attribute é inválido.","validation.numeric":"O campo :attribute deve ser um número.","validation.password.letters":"O campo :attribute deve conter pelo menos uma letra.","validation.password.mixed":"O campo :attribute deve conter pelo menos uma letra maiúscula e uma minúscula.","validation.password.numbers":"O campo :attribute deve conter pelo menos um número.","validation.password.symbols":"O campo :attribute deve conter pelo menos um símbolo.","validation.password.uncompromised":"O :attribute fornecido apareceu em um vazamento de dados. Por favor, escolha um :attribute diferente.","validation.present":"O campo :attribute deve estar presente.","validation.present_if":"O campo :attribute deve estar presente quando :other for :value.","validation.present_unless":"O campo :attribute deve estar presente a menos que :other seja :value.","validation.present_with":"O campo :attribute deve estar presente quando :values estiver presente.","validation.present_with_all":"O campo :attribute deve estar presente quando :values estiverem presentes.","validation.prohibited":"O campo :attribute é proibido.","validation.prohibited_if":"O campo :attribute é proibido quando :other for :value.","validation.prohibited_if_accepted":"O campo :attribute é proibido quando :other for aceito.","validation.prohibited_if_declined":"O campo :attribute é proibido quando :other for recusado.","validation.prohibited_unless":"O campo :attribute é proibido a menos que :other esteja em :values.","validation.prohibits":"O campo :attribute proíbe :other de estar presente.","validation.regex":"O formato do campo :attribute é inválido.","validation.required":"O campo :attribute é obrigatório.","validation.required_array_keys":"O campo :attribute deve conter entradas para: :values.","validation.required_if":"O campo :attribute é obrigatório quando :other for :value.","validation.required_if_accepted":"O campo :attribute é obrigatório quando :other for aceito.","validation.required_if_declined":"O campo :attribute é obrigatório quando :other for recusado.","validation.required_unless":"O campo :attribute é obrigatório a menos que :other esteja em :values.","validation.required_with":"O campo :attribute é obrigatório quando :values estiver presente.","validation.required_with_all":"O campo :attribute é obrigatório quando :values estiverem presentes.","validation.required_without":"O campo :attribute é obrigatório quando :values não estiver presente.","validation.required_without_all":"O campo :attribute é obrigatório quando nenhum dos :values estiver presente.","validation.same":"O campo :attribute deve ser igual a :other.","validation.size.array":"O campo :attribute deve conter :size itens.","validation.size.file":"O campo :attribute deve ter :size kilobytes.","validation.size.numeric":"O campo :attribute deve ser :size.","validation.size.string":"O campo :attribute deve ter :size caracteres.","validation.starts_with":"O campo :attribute deve começar com um dos seguintes: :values.","validation.string":"O campo :attribute deve ser uma string.","validation.timezone":"O campo :attribute deve ser um fuso horário válido.","validation.unique":"O :attribute já foi utilizado.","validation.uploaded":"O :attribute falhou ao ser enviado.","validation.uppercase":"O campo :attribute deve estar em maiúsculo.","validation.url":"O campo :attribute deve ser uma URL válida.","validation.ulid":"O campo :attribute deve ser um ULID válido.","validation.uuid":"O campo :attribute deve ser um UUID válido.","validation.custom.attribute-name.rule-name":"custom-message"} \ No newline at end of file diff --git a/lang/pt-br/auth.php b/lang/pt-br/auth.php index 1333a3a5..b04e5b7b 100644 --- a/lang/pt-br/auth.php +++ b/lang/pt-br/auth.php @@ -22,6 +22,35 @@ 'welcome_trial' => 'Bem-vindo ao TryPost! Seu período de teste começou.', ], + 'legal' => 'Ao continuar, você concorda com nossos Termos de Serviço e Política de Privacidade.', + + 'slides' => [ + 'calendar' => [ + 'title' => 'Calendário Visual', + 'description' => 'Planeje e agende seu conteúdo com um calendário intuitivo de arrastar e soltar em todas as suas contas sociais.', + ], + 'scheduling' => [ + 'title' => 'Agendamento Inteligente', + 'description' => 'Agende posts no LinkedIn, X, Instagram, TikTok, YouTube e mais — tudo em um só lugar.', + ], + 'media' => [ + 'title' => 'Mídia Rica', + 'description' => 'Publique imagens, carrosséis, stories e reels. Cada plataforma recebe o formato correto automaticamente.', + ], + 'video' => [ + 'title' => 'Publicação de Vídeo', + 'description' => 'Envie vídeos uma vez e publique no TikTok, YouTube Shorts, Instagram Reels e Facebook Reels.', + ], + 'team' => [ + 'title' => 'Workspaces em Equipe', + 'description' => 'Convide sua equipe, atribua funções e gerencie múltiplas marcas em workspaces separados.', + ], + 'hashtags' => [ + 'title' => 'Grupos de Hashtags', + 'description' => 'Salve coleções de hashtags e adicione aos posts com um clique. Organize com etiquetas e filtros.', + ], + ], + 'login' => [ 'title' => 'Entrar na sua conta', 'description' => 'Digite seu email e senha abaixo para entrar', @@ -43,6 +72,8 @@ 'name_placeholder' => 'Nome completo', 'email' => 'Endereço de email', 'password' => 'Senha', + 'show_password' => 'Mostrar senha', + 'hide_password' => 'Esconder senha', 'submit' => 'Criar conta', 'has_account' => 'Já tem uma conta?', 'log_in' => 'Entrar', diff --git a/lang/pt-br/billing.php b/lang/pt-br/billing.php index 943b13f9..ebef44dc 100644 --- a/lang/pt-br/billing.php +++ b/lang/pt-br/billing.php @@ -4,6 +4,23 @@ 'title' => 'Assinatura', 'description' => 'Gerencie sua assinatura e método de pagamento', + 'subscribe' => [ + 'page_title' => 'Comece seu teste gratuito', + 'title' => 'Comece seu teste gratuito', + 'description' => ':days dias grátis. Sem cartão de crédito para começar.', + 'start_trial' => 'Começar teste de :days dias', + 'cancel_anytime' => 'Cancele a qualquer momento. Sem perguntas.', + 'switch_workspace' => 'Trocar workspace', + 'features' => [ + 'calendar' => 'Calendário visual com arrastar e soltar', + 'scheduling' => 'Agendamento ilimitado de posts', + 'media' => 'Imagens, carrosséis e stories', + 'video' => 'Publicação de vídeos em todas as plataformas', + 'team' => 'Colaboração em equipe e workspaces', + 'hashtags' => 'Grupos de hashtags e etiquetas', + ], + ], + 'trial' => [ 'title' => 'Período de teste ativo', 'description' => 'Seu período de teste termina em :date. Após isso, sua assinatura será cobrada automaticamente.', diff --git a/lang/pt-br/common.php b/lang/pt-br/common.php new file mode 100644 index 00000000..7efd7966 --- /dev/null +++ b/lang/pt-br/common.php @@ -0,0 +1,12 @@ + [ + 'cannot_be_undone' => 'Esta ação não pode ser desfeita.', + 'type' => 'Digite', + 'to_confirm' => 'para confirmar.', + 'copy_to_clipboard' => 'Copiar para a área de transferência', + ], +]; diff --git a/lang/pt-br/settings.php b/lang/pt-br/settings.php index 51ed7e98..44233b07 100644 --- a/lang/pt-br/settings.php +++ b/lang/pt-br/settings.php @@ -77,6 +77,8 @@ 'cancel' => 'Cancelar', 'remove' => 'Remover', + 'make_admin' => 'Tornar administrador', + 'make_member' => 'Tornar membro', 'invite' => [ 'title' => 'Convidar Membro', @@ -122,6 +124,7 @@ 'invite_sent' => 'Convite enviado com sucesso!', 'invite_deleted' => 'Convite excluído.', 'member_removed' => 'Membro removido com sucesso.', + 'role_updated' => 'Função do membro atualizada.', 'wrong_email' => 'Este convite é para um endereço de e-mail diferente.', 'already_member' => 'Você já é membro deste workspace.', 'invite_accepted' => 'Bem-vindo! Você agora é membro do workspace.', diff --git a/maizzle/components/header.html b/maizzle/components/header.html index 7803f18d..894443cd 100644 --- a/maizzle/components/header.html +++ b/maizzle/components/header.html @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index 6b413c3f..58c102c7 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -2,7 +2,6 @@ import { Link, router, usePage } from '@inertiajs/vue3'; import { IconAffiliate, - IconBook, IconBrandDiscord, IconCalendar, IconChevronRight, @@ -10,7 +9,6 @@ import { IconFileCheck, IconFileText, IconHash, - IconKey, IconLifebuoy, IconMessageCircle, IconPencil, @@ -46,7 +44,6 @@ import { useSidebar, } from '@/components/ui/sidebar'; import { accounts, calendar } from '@/routes/app'; -import { index as apiKeysIndex } from '@/routes/app/api-keys'; import { index as hashtags } from '@/routes/app/hashtags'; import { index as labels } from '@/routes/app/labels'; import { edit as editProfile } from '@/routes/app/profile'; @@ -77,6 +74,7 @@ const postsNavItems = computed{{ description }}
+
+
+ + {{ description }} +
+{{ showPassword ? $t('auth.register.hide_password') : $t('auth.register.show_password') }}
+- Start your free {{ trialDays }}-day trial and take control of your social media -
+
+
+ {{ trans('billing.subscribe.description', { days: displayDays }) }} +
++ {{ $t('billing.subscribe.cancel_anytime') }} +
+ + {{ $t('billing.subscribe.switch_workspace') }} + +- Create an API key to access your workspace programmatically. + +
+ Your new API key has been created. Copy it now — you won't be able to see it again.
-{{ token.name }}
-- {{ token.key_hint }} -
-
+ {{ newToken }}
+
+
- Gerencie seus workspaces e redes sociais
+ {{ workspace.name }}
+ {{ workspace.social_accounts_count }} connections · {{ workspace.posts_count }} posts
- Crie seu primeiro workspace para começar a agendar posts.
- Nenhum workspace
-
diff --git a/resources/views/mail/email-verification.blade.php b/resources/views/mail/email-verification.blade.php
index 5f9d0cfd..e2ea57dc 100644
--- a/resources/views/mail/email-verification.blade.php
+++ b/resources/views/mail/email-verification.blade.php
@@ -59,7 +59,7 @@
diff --git a/resources/views/mail/password-reset.blade.php b/resources/views/mail/password-reset.blade.php
index 4901dab4..6fa05966 100644
--- a/resources/views/mail/password-reset.blade.php
+++ b/resources/views/mail/password-reset.blade.php
@@ -59,7 +59,7 @@
diff --git a/resources/views/mail/workspace-connections-disconnected.blade.php b/resources/views/mail/workspace-connections-disconnected.blade.php
index db518221..5f775b04 100644
--- a/resources/views/mail/workspace-connections-disconnected.blade.php
+++ b/resources/views/mail/workspace-connections-disconnected.blade.php
@@ -62,7 +62,7 @@
diff --git a/resources/views/mail/workspace-invite.blade.php b/resources/views/mail/workspace-invite.blade.php
index 2de10741..34f7fdac 100644
--- a/resources/views/mail/workspace-invite.blade.php
+++ b/resources/views/mail/workspace-invite.blade.php
@@ -62,7 +62,7 @@
diff --git a/routes/app.php b/routes/app.php
index a1799a6e..07ea5098 100644
--- a/routes/app.php
+++ b/routes/app.php
@@ -47,10 +47,11 @@ function () {
// Onboarding routes
Route::middleware(['auth', 'verified'])->prefix('onboarding')->group(function () {
- Route::get('step1', [OnboardingController::class, 'step1'])->name('app.onboarding.step1');
- Route::post('step1', [OnboardingController::class, 'storeStep1'])->name('app.onboarding.step1.store');
- Route::get('step2', [OnboardingController::class, 'step2'])->name('app.onboarding.step2');
- Route::post('step2', [OnboardingController::class, 'storeStep2'])->name('app.onboarding.step2.store');
+ Route::get('/', fn () => redirect()->route('app.onboarding.role'));
+ Route::get('role', [OnboardingController::class, 'step1'])->name('app.onboarding.role');
+ Route::post('role', [OnboardingController::class, 'storeStep1'])->name('app.onboarding.role.store');
+ Route::get('connect', [OnboardingController::class, 'step2'])->name('app.onboarding.connect');
+ Route::post('connect', [OnboardingController::class, 'storeStep2'])->name('app.onboarding.connect.store');
Route::get('complete', [OnboardingController::class, 'complete'])->name('app.onboarding.complete');
});
@@ -140,6 +141,7 @@ function () {
Route::post('settings/members/invites', [WorkspaceInviteController::class, 'store'])->name('app.invites.store');
Route::delete('settings/members/invites/{invite}', [WorkspaceInviteController::class, 'destroy'])->name('app.invites.destroy');
Route::delete('settings/members/{user}', [WorkspaceInviteController::class, 'removeMember'])->name('app.members.remove');
+ Route::put('settings/members/{user}/role', [WorkspaceInviteController::class, 'updateRole'])->name('app.members.update-role');
// Hashtags
Route::get('hashtags', [WorkspaceHashtagController::class, 'index'])->name('app.hashtags.index');
diff --git a/tests/Feature/Auth/RegistrationTest.php b/tests/Feature/Auth/RegistrationTest.php
index 3afb0a1d..39719fa8 100644
--- a/tests/Feature/Auth/RegistrationTest.php
+++ b/tests/Feature/Auth/RegistrationTest.php
@@ -19,7 +19,7 @@
$response->assertSessionHasNoErrors();
$this->assertAuthenticated();
- $response->assertRedirect(route('app.onboarding.step1', absolute: false));
+ $response->assertRedirect(route('app.onboarding.role', absolute: false));
});
test('new users get a default workspace on registration', function () {
diff --git a/tests/Feature/Middleware/EnsureUserSetupIsCompleteTest.php b/tests/Feature/Middleware/EnsureUserSetupIsCompleteTest.php
index 4a6376be..dd358e6e 100644
--- a/tests/Feature/Middleware/EnsureUserSetupIsCompleteTest.php
+++ b/tests/Feature/Middleware/EnsureUserSetupIsCompleteTest.php
@@ -29,7 +29,7 @@
$this->actingAs($user)
->get(route('app.calendar'))
- ->assertRedirect(route('app.onboarding.step1'));
+ ->assertRedirect(route('app.onboarding.role'));
});
test('user on connections step is redirected to onboarding step 2', function () {
@@ -42,7 +42,7 @@
$this->actingAs($user)
->get(route('app.calendar'))
- ->assertRedirect(route('app.onboarding.step2'));
+ ->assertRedirect(route('app.onboarding.connect'));
});
test('user on subscription step is redirected to onboarding step 2', function () {
@@ -55,14 +55,14 @@
$this->actingAs($user)
->get(route('app.calendar'))
- ->assertRedirect(route('app.onboarding.step2'));
+ ->assertRedirect(route('app.onboarding.connect'));
});
test('user on role step can access onboarding step 1', function () {
$user = User::factory()->create(['setup' => Setup::Role]);
$this->actingAs($user)
- ->get(route('app.onboarding.step1'))
+ ->get(route('app.onboarding.role'))
->assertOk();
});
@@ -70,7 +70,7 @@
$user = User::factory()->create(['setup' => Setup::Connections]);
$this->actingAs($user)
- ->get(route('app.onboarding.step2'))
+ ->get(route('app.onboarding.connect'))
->assertOk();
});
diff --git a/tests/Feature/OnboardingControllerTest.php b/tests/Feature/OnboardingControllerTest.php
index aaea875a..3f67a9cc 100644
--- a/tests/Feature/OnboardingControllerTest.php
+++ b/tests/Feature/OnboardingControllerTest.php
@@ -15,13 +15,13 @@
// Step 1 tests
test('step1 requires authentication', function () {
- $response = $this->get(route('app.onboarding.step1'));
+ $response = $this->get(route('app.onboarding.role'));
$response->assertRedirect(route('login'));
});
test('step1 shows persona selection', function () {
- $response = $this->actingAs($this->user)->get(route('app.onboarding.step1'));
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.role'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
@@ -32,7 +32,7 @@
// Store Step 1 tests
test('store step1 requires authentication', function () {
- $response = $this->post(route('app.onboarding.step1.store'), [
+ $response = $this->post(route('app.onboarding.role.store'), [
'persona' => Persona::Founder->value,
]);
@@ -40,11 +40,11 @@
});
test('store step1 saves persona and redirects to step2', function () {
- $response = $this->actingAs($this->user)->post(route('app.onboarding.step1.store'), [
+ $response = $this->actingAs($this->user)->post(route('app.onboarding.role.store'), [
'persona' => Persona::Founder->value,
]);
- $response->assertRedirect(route('app.onboarding.step2'));
+ $response->assertRedirect(route('app.onboarding.connect'));
$this->user->refresh();
expect($this->user->persona)->toBe(Persona::Founder);
@@ -52,7 +52,7 @@
});
test('store step1 validates persona is required', function () {
- $response = $this->actingAs($this->user)->post(route('app.onboarding.step1.store'), [
+ $response = $this->actingAs($this->user)->post(route('app.onboarding.role.store'), [
'persona' => '',
]);
@@ -60,7 +60,7 @@
});
test('store step1 validates persona is valid enum', function () {
- $response = $this->actingAs($this->user)->post(route('app.onboarding.step1.store'), [
+ $response = $this->actingAs($this->user)->post(route('app.onboarding.role.store'), [
'persona' => 'invalid',
]);
@@ -69,7 +69,7 @@
// Step 2 tests
test('step2 requires authentication', function () {
- $response = $this->get(route('app.onboarding.step2'));
+ $response = $this->get(route('app.onboarding.connect'));
$response->assertRedirect(route('login'));
});
@@ -77,7 +77,7 @@
test('step2 shows social accounts connection', function () {
$this->user->update(['setup' => Setup::Connections]);
- $response = $this->actingAs($this->user)->get(route('app.onboarding.step2'));
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.connect'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
@@ -97,7 +97,7 @@
'platform' => Platform::LinkedIn,
]);
- $response = $this->actingAs($this->user)->get(route('app.onboarding.step2'));
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.connect'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
@@ -107,7 +107,7 @@
// Store Step 2 tests
test('store step2 requires authentication', function () {
- $response = $this->post(route('app.onboarding.step2.store'));
+ $response = $this->post(route('app.onboarding.connect.store'));
$response->assertRedirect(route('login'));
});
@@ -116,7 +116,7 @@
config(['trypost.self_hosted' => true]);
$this->user->update(['setup' => Setup::Connections]);
- $response = $this->actingAs($this->user)->post(route('app.onboarding.step2.store'));
+ $response = $this->actingAs($this->user)->post(route('app.onboarding.connect.store'));
$response->assertRedirect(route('app.calendar'));
@@ -141,3 +141,68 @@
$this->user->refresh();
expect($this->user->setup)->toBe(Setup::Completed);
});
+
+// Step enforcement tests
+test('step1 redirects to connect when user already completed role step', function () {
+ $this->user->update(['setup' => Setup::Connections]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.role'));
+
+ $response->assertRedirect(route('app.onboarding.connect'));
+});
+
+test('step1 redirects to subscribe when user is on subscription step', function () {
+ $this->user->update(['setup' => Setup::Subscription]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.role'));
+
+ $response->assertRedirect(route('app.subscribe'));
+});
+
+test('step1 redirects to calendar when setup is completed', function () {
+ $this->user->update(['setup' => Setup::Completed]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.role'));
+
+ $response->assertRedirect(route('app.calendar'));
+});
+
+test('step2 redirects to role when user has not completed role step', function () {
+ $this->user->update(['setup' => Setup::Role]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.connect'));
+
+ $response->assertRedirect(route('app.onboarding.role'));
+});
+
+test('step2 redirects to subscribe when user is on subscription step', function () {
+ $this->user->update(['setup' => Setup::Subscription]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.connect'));
+
+ $response->assertRedirect(route('app.subscribe'));
+});
+
+test('step2 redirects to calendar when setup is completed', function () {
+ $this->user->update(['setup' => Setup::Completed]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.connect'));
+
+ $response->assertRedirect(route('app.calendar'));
+});
+
+test('user on role step can access role page', function () {
+ $this->user->update(['setup' => Setup::Role]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.role'));
+
+ $response->assertOk();
+});
+
+test('user on connections step can access connect page', function () {
+ $this->user->update(['setup' => Setup::Connections]);
+
+ $response = $this->actingAs($this->user)->get(route('app.onboarding.connect'));
+
+ $response->assertOk();
+});
diff --git a/tests/Feature/Settings/ProfileUpdateTest.php b/tests/Feature/Settings/ProfileUpdateTest.php
index cb97cd9a..d04e1c04 100644
--- a/tests/Feature/Settings/ProfileUpdateTest.php
+++ b/tests/Feature/Settings/ProfileUpdateTest.php
@@ -54,7 +54,7 @@
expect($user->refresh()->email_verified_at)->not->toBeNull();
});
-test('user can update their locale', function () {
+test('user can update their locale via cookie', function () {
$user = User::factory()->create();
$response = $this
@@ -68,7 +68,7 @@
->assertSessionHasNoErrors()
->assertRedirect(route('app.posts.index'));
- expect($user->refresh()->locale)->toBe('es');
+ $response->assertCookieNotExpired('locale');
});
test('user cannot update locale with invalid code', function () {
diff --git a/tests/Feature/WorkspaceInviteControllerTest.php b/tests/Feature/WorkspaceInviteControllerTest.php
index 9c6abbfd..556f9b26 100644
--- a/tests/Feature/WorkspaceInviteControllerTest.php
+++ b/tests/Feature/WorkspaceInviteControllerTest.php
@@ -157,3 +157,73 @@
$response->assertSessionHasErrors('member');
});
+
+// Update role tests
+test('update role requires authentication', function () {
+ $member = User::factory()->create(['setup' => Setup::Completed]);
+ $this->workspace->members()->attach($member->id, ['role' => WorkspaceRole::Member->value]);
+
+ $response = $this->put(route('app.members.update-role', $member), [
+ 'role' => WorkspaceRole::Admin->value,
+ ]);
+
+ $response->assertRedirect(route('login'));
+});
+
+test('update role changes member to admin', function () {
+ $member = User::factory()->create(['setup' => Setup::Completed]);
+ $this->workspace->members()->attach($member->id, ['role' => WorkspaceRole::Member->value]);
+
+ $response = $this->actingAs($this->user)->put(route('app.members.update-role', $member), [
+ 'role' => WorkspaceRole::Admin->value,
+ ]);
+
+ $response->assertRedirect();
+ expect($this->workspace->members()->where('user_id', $member->id)->first()->pivot->role)->toBe(WorkspaceRole::Admin->value);
+});
+
+test('update role changes admin to member', function () {
+ $member = User::factory()->create(['setup' => Setup::Completed]);
+ $this->workspace->members()->attach($member->id, ['role' => WorkspaceRole::Admin->value]);
+
+ $response = $this->actingAs($this->user)->put(route('app.members.update-role', $member), [
+ 'role' => WorkspaceRole::Member->value,
+ ]);
+
+ $response->assertRedirect();
+ expect($this->workspace->members()->where('user_id', $member->id)->first()->pivot->role)->toBe(WorkspaceRole::Member->value);
+});
+
+test('update role fails for workspace owner', function () {
+ $response = $this->actingAs($this->user)->put(route('app.members.update-role', $this->user), [
+ 'role' => WorkspaceRole::Member->value,
+ ]);
+
+ $response->assertSessionHasErrors('role');
+});
+
+test('update role fails with invalid role', function () {
+ $member = User::factory()->create(['setup' => Setup::Completed]);
+ $this->workspace->members()->attach($member->id, ['role' => WorkspaceRole::Member->value]);
+
+ $response = $this->actingAs($this->user)->put(route('app.members.update-role', $member), [
+ 'role' => 'invalid',
+ ]);
+
+ $response->assertSessionHasErrors('role');
+});
+
+test('update role requires authorization', function () {
+ $member = User::factory()->create(['setup' => Setup::Completed]);
+ $this->workspace->members()->attach($member->id, ['role' => WorkspaceRole::Member->value]);
+
+ $nonAdmin = User::factory()->create(['setup' => Setup::Completed]);
+ $this->workspace->members()->attach($nonAdmin->id, ['role' => WorkspaceRole::Member->value]);
+ $nonAdmin->update(['current_workspace_id' => $this->workspace->id]);
+
+ $response = $this->actingAs($nonAdmin)->put(route('app.members.update-role', $member), [
+ 'role' => WorkspaceRole::Admin->value,
+ ]);
+
+ $response->assertForbidden();
+});