From 831164f24c94d46bcc601e43b9a9b848d113961e Mon Sep 17 00:00:00 2001 From: Dave Earley Date: Sun, 16 Jun 2024 23:04:54 -0700 Subject: [PATCH] Internationalization (i18n) --- .../AttendeeDomainObjectAbstract.php | 14 + .../Generated/OrderDomainObjectAbstract.php | 14 + .../Generated/UserDomainObjectAbstract.php | 14 + .../Actions/Accounts/CreateAccountAction.php | 4 +- .../Orders/CreateOrderActionPublic.php | 3 + .../Orders/ResendOrderConfirmationAction.php | 15 +- backend/app/Http/Kernel.php | 2 + .../Middleware/SetUserLocaleMiddleware.php | 27 ++ backend/app/Locale.php | 23 ++ backend/app/Mail/Order/OrderCancelled.php | 2 +- backend/app/Mail/Order/OrderRefunded.php | 2 +- backend/app/Mail/Order/OrderSummary.php | 2 +- .../app/Mail/User/ConfirmEmailChangeMail.php | 2 +- backend/app/Mail/User/ForgotPassword.php | 2 +- .../app/Mail/User/ResetPasswordSuccess.php | 2 +- backend/app/Mail/User/UserInvited.php | 2 +- .../Application/Locale/LocaleService.php | 35 +++ .../Attendee/SendAttendeeTicketService.php | 21 +- .../Mail/SendEventEmailMessagesService.php | 2 +- .../Domain/Mail/SendOrderDetailsService.php | 28 +- .../Domain/Order/OrderCancelService.php | 13 +- .../Domain/Order/OrderManagementService.php | 2 + .../StripeRefundExpiredOrderService.php | 14 +- .../Domain/User/SendUserInvitationService.php | 13 +- .../Handlers/Attendee/EditAttendeeHandler.php | 6 +- .../Handlers/Auth/ForgotPasswordHandler.php | 14 +- .../Handlers/Auth/ResetPasswordHandler.php | 7 +- .../Handlers/Order/CompleteOrderHandler.php | 1 + .../Handlers/Order/CreateOrderHandler.php | 3 +- .../Order/DTO/CreateOrderPublicDTO.php | 1 + .../Payment/Stripe/RefundOrderHandler.php | 15 +- .../Handlers/User/UpdateMeHandler.php | 1 + backend/bootstrap/cache/packages.php | 7 + backend/bootstrap/cache/services.php | 54 ++-- backend/composer.json | 1 + backend/composer.lock | 130 ++++++++- .../2024_06_16_143927_add_locale_to_users.php | 22 ++ ...4_06_16_192150_add_locale_to_attendees.php | 21 ++ ...2024_06_16_192151_add_locale_to_orders.php | 21 ++ backend/lang/de.json | 263 ++++++++++++++++++ backend/lang/es.json | 263 ++++++++++++++++++ backend/lang/fr.json | 263 ++++++++++++++++++ backend/lang/pt-br.json | 263 ++++++++++++++++++ backend/lang/pt.json | 263 ++++++++++++++++++ backend/lang/ru.json | 263 ++++++++++++++++++ backend/lang/zh-cn.json | 263 ++++++++++++++++++ .../emails/auth/forgot-password.blade.php | 12 +- .../auth/reset-password-success.blade.php | 14 +- .../views/emails/event/message.blade.php | 11 +- .../emails/orders/attendee-ticket.blade.php | 12 +- .../emails/orders/order-cancelled.blade.php | 11 +- .../emails/orders/order-failed.blade.php | 13 +- .../emails/orders/order-refunded.blade.php | 7 +- .../organizer/summary-for-organizer.blade.php | 27 +- ...ayment-success-but-order-expired.blade.php | 15 +- .../views/emails/orders/summary.blade.php | 37 ++- .../user/confirm-email-address.blade.php | 2 +- .../user/confirm-email-change.blade.php | 11 +- .../views/emails/user/user-invited.blade.php | 10 +- frontend/src/App.tsx | 39 +-- .../common/QuestionsTable/index.tsx | 13 +- frontend/src/entry.client.tsx | 28 +- frontend/src/entry.server.tsx | 11 +- frontend/src/locales/de.js | 2 +- frontend/src/locales/de.po | 102 ++++--- frontend/src/locales/en.js | 2 +- frontend/src/locales/en.po | 104 ++++--- frontend/src/locales/es.js | 2 +- frontend/src/locales/es.po | 102 ++++--- frontend/src/locales/fr.js | 2 +- frontend/src/locales/fr.po | 102 ++++--- frontend/src/locales/pt-br.js | 2 +- frontend/src/locales/pt-br.po | 102 ++++--- frontend/src/locales/pt.js | 2 +- frontend/src/locales/pt.po | 102 ++++--- frontend/src/locales/ru.js | 2 +- frontend/src/locales/ru.po | 102 ++++--- frontend/src/locales/zh-cn.js | 2 +- frontend/src/locales/zh-cn.po | 102 ++++--- 79 files changed, 2942 insertions(+), 568 deletions(-) create mode 100644 backend/app/Http/Middleware/SetUserLocaleMiddleware.php create mode 100644 backend/app/Locale.php create mode 100644 backend/app/Services/Application/Locale/LocaleService.php create mode 100644 backend/database/migrations/2024_06_16_143927_add_locale_to_users.php create mode 100644 backend/database/migrations/2024_06_16_192150_add_locale_to_attendees.php create mode 100644 backend/database/migrations/2024_06_16_192151_add_locale_to_orders.php create mode 100644 backend/lang/de.json create mode 100644 backend/lang/es.json create mode 100644 backend/lang/fr.json create mode 100644 backend/lang/pt-br.json create mode 100644 backend/lang/pt.json create mode 100644 backend/lang/ru.json create mode 100644 backend/lang/zh-cn.json diff --git a/backend/app/DomainObjects/Generated/AttendeeDomainObjectAbstract.php b/backend/app/DomainObjects/Generated/AttendeeDomainObjectAbstract.php index 23f6f105..59b052de 100644 --- a/backend/app/DomainObjects/Generated/AttendeeDomainObjectAbstract.php +++ b/backend/app/DomainObjects/Generated/AttendeeDomainObjectAbstract.php @@ -27,6 +27,7 @@ abstract class AttendeeDomainObjectAbstract extends \HiEvents\DomainObjects\Abst final public const CREATED_AT = 'created_at'; final public const UPDATED_AT = 'updated_at'; final public const DELETED_AT = 'deleted_at'; + final public const LOCALE = 'locale'; protected int $id; protected int $order_id; @@ -45,6 +46,7 @@ abstract class AttendeeDomainObjectAbstract extends \HiEvents\DomainObjects\Abst protected string $created_at; protected string $updated_at; protected ?string $deleted_at = null; + protected string $locale = 'en'; public function toArray(): array { @@ -66,6 +68,7 @@ public function toArray(): array 'created_at' => $this->created_at ?? null, 'updated_at' => $this->updated_at ?? null, 'deleted_at' => $this->deleted_at ?? null, + 'locale' => $this->locale ?? null, ]; } @@ -255,4 +258,15 @@ public function getDeletedAt(): ?string { return $this->deleted_at; } + + public function setLocale(string $locale): self + { + $this->locale = $locale; + return $this; + } + + public function getLocale(): string + { + return $this->locale; + } } diff --git a/backend/app/DomainObjects/Generated/OrderDomainObjectAbstract.php b/backend/app/DomainObjects/Generated/OrderDomainObjectAbstract.php index 00c4f280..939ca2cd 100644 --- a/backend/app/DomainObjects/Generated/OrderDomainObjectAbstract.php +++ b/backend/app/DomainObjects/Generated/OrderDomainObjectAbstract.php @@ -38,6 +38,7 @@ abstract class OrderDomainObjectAbstract extends \HiEvents\DomainObjects\Abstrac final public const TAXES_AND_FEES_ROLLUP = 'taxes_and_fees_rollup'; final public const TOTAL_TAX = 'total_tax'; final public const TOTAL_FEE = 'total_fee'; + final public const LOCALE = 'locale'; protected int $id; protected int $event_id; @@ -67,6 +68,7 @@ abstract class OrderDomainObjectAbstract extends \HiEvents\DomainObjects\Abstrac protected array|string|null $taxes_and_fees_rollup = null; protected float $total_tax = 0.0; protected float $total_fee = 0.0; + protected string $locale = 'en'; public function toArray(): array { @@ -99,6 +101,7 @@ public function toArray(): array 'taxes_and_fees_rollup' => $this->taxes_and_fees_rollup ?? null, 'total_tax' => $this->total_tax ?? null, 'total_fee' => $this->total_fee ?? null, + 'locale' => $this->locale ?? null, ]; } @@ -409,4 +412,15 @@ public function getTotalFee(): float { return $this->total_fee; } + + public function setLocale(string $locale): self + { + $this->locale = $locale; + return $this; + } + + public function getLocale(): string + { + return $this->locale; + } } diff --git a/backend/app/DomainObjects/Generated/UserDomainObjectAbstract.php b/backend/app/DomainObjects/Generated/UserDomainObjectAbstract.php index fdedf0a6..4751d979 100644 --- a/backend/app/DomainObjects/Generated/UserDomainObjectAbstract.php +++ b/backend/app/DomainObjects/Generated/UserDomainObjectAbstract.php @@ -22,6 +22,7 @@ abstract class UserDomainObjectAbstract extends \HiEvents\DomainObjects\Abstract final public const LAST_NAME = 'last_name'; final public const PENDING_EMAIL = 'pending_email'; final public const TIMEZONE = 'timezone'; + final public const LOCALE = 'locale'; protected int $id; protected string $email; @@ -35,6 +36,7 @@ abstract class UserDomainObjectAbstract extends \HiEvents\DomainObjects\Abstract protected ?string $last_name = null; protected ?string $pending_email = null; protected string $timezone; + protected string $locale = 'en'; public function toArray(): array { @@ -51,6 +53,7 @@ public function toArray(): array 'last_name' => $this->last_name ?? null, 'pending_email' => $this->pending_email ?? null, 'timezone' => $this->timezone ?? null, + 'locale' => $this->locale ?? null, ]; } @@ -185,4 +188,15 @@ public function getTimezone(): string { return $this->timezone; } + + public function setLocale(string $locale): self + { + $this->locale = $locale; + return $this; + } + + public function getLocale(): string + { + return $this->locale; + } } diff --git a/backend/app/Http/Actions/Accounts/CreateAccountAction.php b/backend/app/Http/Actions/Accounts/CreateAccountAction.php index 54a868bd..97e60e91 100644 --- a/backend/app/Http/Actions/Accounts/CreateAccountAction.php +++ b/backend/app/Http/Actions/Accounts/CreateAccountAction.php @@ -10,6 +10,7 @@ use HiEvents\Http\Request\Account\CreateAccountRequest; use HiEvents\Http\ResponseCodes; use HiEvents\Resources\Account\AccountResource; +use HiEvents\Services\Application\Locale\LocaleService; use HiEvents\Services\Handlers\Account\CreateAccountHandler; use HiEvents\Services\Handlers\Account\DTO\CreateAccountDTO; use HiEvents\Services\Handlers\Account\Exceptions\AccountRegistrationDisabledException; @@ -24,6 +25,7 @@ class CreateAccountAction extends BaseAuthAction public function __construct( private readonly CreateAccountHandler $createAccountHandler, private readonly LoginHandler $loginHandler, + private readonly LocaleService $localeService, ) { } @@ -42,7 +44,7 @@ public function __invoke(CreateAccountRequest $request): JsonResponse 'password' => $request->validated('password'), 'timezone' => $request->validated('timezone'), 'currency_code' => $request->validated('currency_code'), - 'locale' => $request->getPreferredLanguage(), + 'locale' => $this->localeService->getLocaleOrDefault($request->getPreferredLanguage()), ])); } catch (EmailAlreadyExists $e) { throw ValidationException::withMessages([ diff --git a/backend/app/Http/Actions/Orders/CreateOrderActionPublic.php b/backend/app/Http/Actions/Orders/CreateOrderActionPublic.php index 61cdaaee..9c1ee8d7 100644 --- a/backend/app/Http/Actions/Orders/CreateOrderActionPublic.php +++ b/backend/app/Http/Actions/Orders/CreateOrderActionPublic.php @@ -8,6 +8,7 @@ use HiEvents\Http\Request\Order\CreateOrderRequest; use HiEvents\Http\ResponseCodes; use HiEvents\Resources\Order\OrderResourcePublic; +use HiEvents\Services\Application\Locale\LocaleService; use HiEvents\Services\Domain\Order\OrderCreateRequestValidationService; use HiEvents\Services\Handlers\Order\CreateOrderHandler; use HiEvents\Services\Handlers\Order\DTO\CreateOrderPublicDTO; @@ -22,6 +23,7 @@ public function __construct( private readonly CreateOrderHandler $orderHandler, private readonly OrderCreateRequestValidationService $orderCreateRequestValidationService, private readonly CheckoutSessionManagementService $sessionIdentifierService, + private readonly LocaleService $localeService, ) { @@ -41,6 +43,7 @@ public function __invoke(CreateOrderRequest $request, int $eventId): JsonRespons 'promo_code' => $request->input('promo_code'), 'tickets' => TicketOrderDetailsDTO::collectionFromArray($request->input('tickets')), 'session_identifier' => $this->sessionIdentifierService->getSessionId(), + 'order_locale' => $this->localeService->getLocaleOrDefault($request->getPreferredLanguage()), ]) ); diff --git a/backend/app/Http/Actions/Orders/ResendOrderConfirmationAction.php b/backend/app/Http/Actions/Orders/ResendOrderConfirmationAction.php index 5bb9da97..024aff0f 100644 --- a/backend/app/Http/Actions/Orders/ResendOrderConfirmationAction.php +++ b/backend/app/Http/Actions/Orders/ResendOrderConfirmationAction.php @@ -49,12 +49,15 @@ public function __invoke(int $eventId, int $orderId): Response ->loadRelation(new Relationship(EventSettingDomainObject::class)) ->findById($order->getEventId()); - $this->mailer->to($order->getEmail())->send(new OrderSummary( - order: $order, - event: $event, - organizer: $event->getOrganizer(), - eventSettings: $event->getEventSettings(), - )); + $this->mailer + ->to($order->getEmail()) + ->locale($order->getLocale()) + ->send(new OrderSummary( + order: $order, + event: $event, + organizer: $event->getOrganizer(), + eventSettings: $event->getEventSettings(), + )); } return $this->noContentResponse(); diff --git a/backend/app/Http/Kernel.php b/backend/app/Http/Kernel.php index 08df4113..50ae0df0 100644 --- a/backend/app/Http/Kernel.php +++ b/backend/app/Http/Kernel.php @@ -3,6 +3,7 @@ namespace HiEvents\Http; use HiEvents\Http\Middleware\SetAccountContext; +use HiEvents\Http\Middleware\SetUserLocaleMiddleware; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; use Illuminate\Auth\Middleware\Authorize; use Illuminate\Auth\Middleware\EnsureEmailIsVerified; @@ -65,6 +66,7 @@ class Kernel extends HttpKernel ThrottleRequests::class . ':api', SubstituteBindings::class, SetAccountContext::class, + SetUserLocaleMiddleware::class, ], ]; diff --git a/backend/app/Http/Middleware/SetUserLocaleMiddleware.php b/backend/app/Http/Middleware/SetUserLocaleMiddleware.php new file mode 100644 index 00000000..6e8f9dcc --- /dev/null +++ b/backend/app/Http/Middleware/SetUserLocaleMiddleware.php @@ -0,0 +1,27 @@ +getLocale()); + App::setFallbackLocale(config('app.locale')); + } elseif ($request->hasHeader('Accept-Language')) { + App::setLocale($request->header('Accept-Language')); + App::setFallbackLocale(config('app.locale')); + } + + return $next($request); + } +} diff --git a/backend/app/Locale.php b/backend/app/Locale.php new file mode 100644 index 00000000..fd0196a6 --- /dev/null +++ b/backend/app/Locale.php @@ -0,0 +1,23 @@ +eventSettings->getSupportEmail(), - subject: 'Your order has been cancelled', + subject: __('Your order has been cancelled'), ); } diff --git a/backend/app/Mail/Order/OrderRefunded.php b/backend/app/Mail/Order/OrderRefunded.php index f20b2570..411fe872 100644 --- a/backend/app/Mail/Order/OrderRefunded.php +++ b/backend/app/Mail/Order/OrderRefunded.php @@ -29,7 +29,7 @@ public function envelope(): Envelope { return new Envelope( replyTo: $this->eventSettings->getSupportEmail(), - subject: 'You\'ve received a refund', + subject: __('You\'ve received a refund'), ); } diff --git a/backend/app/Mail/Order/OrderSummary.php b/backend/app/Mail/Order/OrderSummary.php index 0052b5e3..c04bd78d 100644 --- a/backend/app/Mail/Order/OrderSummary.php +++ b/backend/app/Mail/Order/OrderSummary.php @@ -30,7 +30,7 @@ public function envelope(): Envelope { return new Envelope( replyTo: $this->eventSettings->getSupportEmail(), - subject: 'Your Order is Confirmed! 🎉', + subject: __('Your Order is Confirmed!') . ' 🎉', ); } diff --git a/backend/app/Mail/User/ConfirmEmailChangeMail.php b/backend/app/Mail/User/ConfirmEmailChangeMail.php index c73fa23d..5c6b8a90 100644 --- a/backend/app/Mail/User/ConfirmEmailChangeMail.php +++ b/backend/app/Mail/User/ConfirmEmailChangeMail.php @@ -28,7 +28,7 @@ public function __construct(UserDomainObject $user, string $token) public function envelope(): Envelope { return new Envelope( - subject: 'Confirm email change', + subject: __('Confirm email change'), ); } diff --git a/backend/app/Mail/User/ForgotPassword.php b/backend/app/Mail/User/ForgotPassword.php index 9c7a3201..db1a12b5 100644 --- a/backend/app/Mail/User/ForgotPassword.php +++ b/backend/app/Mail/User/ForgotPassword.php @@ -28,7 +28,7 @@ public function __construct(UserDomainObject $user, string $token) public function envelope(): Envelope { return new Envelope( - subject: 'Password reset', + subject: __('Password reset'), ); } diff --git a/backend/app/Mail/User/ResetPasswordSuccess.php b/backend/app/Mail/User/ResetPasswordSuccess.php index 5a7633e0..342d9fe6 100644 --- a/backend/app/Mail/User/ResetPasswordSuccess.php +++ b/backend/app/Mail/User/ResetPasswordSuccess.php @@ -14,7 +14,7 @@ class ResetPasswordSuccess extends BaseMail public function envelope(): Envelope { return new Envelope( - subject: 'Your password has been reset', + subject: __('Your password has been reset'), ); } diff --git a/backend/app/Mail/User/UserInvited.php b/backend/app/Mail/User/UserInvited.php index c5626928..20296f7f 100644 --- a/backend/app/Mail/User/UserInvited.php +++ b/backend/app/Mail/User/UserInvited.php @@ -34,7 +34,7 @@ public function __construct( public function envelope(): Envelope { return new Envelope( - subject: 'You\'ve been invited to join ' . $this->appName, + subject: __('You\'ve been invited to join :appName', ['appName' => $this->appName]), ); } diff --git a/backend/app/Services/Application/Locale/LocaleService.php b/backend/app/Services/Application/Locale/LocaleService.php new file mode 100644 index 00000000..1746ab03 --- /dev/null +++ b/backend/app/Services/Application/Locale/LocaleService.php @@ -0,0 +1,35 @@ +config->get('app.locale'); + } +} diff --git a/backend/app/Services/Domain/Attendee/SendAttendeeTicketService.php b/backend/app/Services/Domain/Attendee/SendAttendeeTicketService.php index 3fc48ca4..27da9f08 100644 --- a/backend/app/Services/Domain/Attendee/SendAttendeeTicketService.php +++ b/backend/app/Services/Domain/Attendee/SendAttendeeTicketService.php @@ -18,17 +18,20 @@ public function __construct( } public function send( - AttendeeDomainObject $attendee, - EventDomainObject $event, + AttendeeDomainObject $attendee, + EventDomainObject $event, EventSettingDomainObject $eventSettings, - OrganizerDomainObject $organizer, + OrganizerDomainObject $organizer, ): void { - $this->mailer->to($attendee->getEmail())->send(new AttendeeTicketMail( - attendee: $attendee, - event: $event, - eventSettings: $eventSettings, - organizer: $organizer, - )); + $this->mailer + ->to($attendee->getEmail()) + ->locale($attendee->getLocale()) + ->send(new AttendeeTicketMail( + attendee: $attendee, + event: $event, + eventSettings: $eventSettings, + organizer: $organizer, + )); } } diff --git a/backend/app/Services/Domain/Mail/SendEventEmailMessagesService.php b/backend/app/Services/Domain/Mail/SendEventEmailMessagesService.php index 60fc7763..f4a6b05c 100644 --- a/backend/app/Services/Domain/Mail/SendEventEmailMessagesService.php +++ b/backend/app/Services/Domain/Mail/SendEventEmailMessagesService.php @@ -203,7 +203,7 @@ private function sendMessage( string $emailAddress, string $fullName, SendMessageDTO $messageData, - EventDomainObject $event + EventDomainObject $event, ): void { $this->mailer->to( diff --git a/backend/app/Services/Domain/Mail/SendOrderDetailsService.php b/backend/app/Services/Domain/Mail/SendOrderDetailsService.php index 19a38fb7..62040573 100644 --- a/backend/app/Services/Domain/Mail/SendOrderDetailsService.php +++ b/backend/app/Services/Domain/Mail/SendOrderDetailsService.php @@ -46,11 +46,14 @@ public function sendOrderSummaryAndTicketEmails(OrderDomainObject $order): void } if ($order->isOrderFailed()) { - $this->mailer->to($order->getEmail())->send(new OrderFailed( - order: $order, - event: $event, - eventSettings: $event->getEventSettings(), - )); + $this->mailer + ->to($order->getEmail()) + ->locale($order->getLocale()) + ->send(new OrderFailed( + order: $order, + event: $event, + eventSettings: $event->getEventSettings(), + )); } } @@ -75,12 +78,15 @@ private function sendAttendeeTicketEmails(OrderDomainObject $order, EventDomainO private function sendOrderSummaryEmails(OrderDomainObject $order, EventDomainObject $event): void { - $this->mailer->to($order->getEmail())->send(new OrderSummary( - order: $order, - event: $event, - organizer: $event->getOrganizer(), - eventSettings: $event->getEventSettings(), - )); + $this->mailer + ->to($order->getEmail()) + ->locale($order->getLocale()) + ->send(new OrderSummary( + order: $order, + event: $event, + organizer: $event->getOrganizer(), + eventSettings: $event->getEventSettings(), + )); if ($order->getIsManuallyCreated() || !$event->getEventSettings()->getNotifyOrganizerOfNewOrders()) { return; diff --git a/backend/app/Services/Domain/Order/OrderCancelService.php b/backend/app/Services/Domain/Order/OrderCancelService.php index 55f3b84a..c9317a32 100644 --- a/backend/app/Services/Domain/Order/OrderCancelService.php +++ b/backend/app/Services/Domain/Order/OrderCancelService.php @@ -43,11 +43,14 @@ public function cancelOrder(OrderDomainObject $order): void ->loadRelation(EventSettingDomainObject::class) ->findById($order->getEventId()); - $this->mailer->to($order->getEmail())->send(new OrderCancelled( - order: $order, - event: $event, - eventSettings: $event->getEventSettings(), - )); + $this->mailer + ->to($order->getEmail()) + ->locale($order->getLocale()) + ->send(new OrderCancelled( + order: $order, + event: $event, + eventSettings: $event->getEventSettings(), + )); }); } diff --git a/backend/app/Services/Domain/Order/OrderManagementService.php b/backend/app/Services/Domain/Order/OrderManagementService.php index a3ea531e..998c110e 100644 --- a/backend/app/Services/Domain/Order/OrderManagementService.php +++ b/backend/app/Services/Domain/Order/OrderManagementService.php @@ -37,6 +37,7 @@ public function createNewOrder( int $eventId, EventDomainObject $event, int $timeOutMinutes, + string $locale, ?PromoCodeDomainObject $promoCode, string $sessionId = null, ): OrderDomainObject @@ -54,6 +55,7 @@ public function createNewOrder( 'public_id' => $publicId, 'promo_code_id' => $promoCode?->getId(), 'promo_code' => $promoCode?->getCode(), + 'locale' => $locale, ]); } diff --git a/backend/app/Services/Domain/Payment/Stripe/StripeRefundExpiredOrderService.php b/backend/app/Services/Domain/Payment/Stripe/StripeRefundExpiredOrderService.php index e16b150c..c5473ce8 100644 --- a/backend/app/Services/Domain/Payment/Stripe/StripeRefundExpiredOrderService.php +++ b/backend/app/Services/Domain/Payment/Stripe/StripeRefundExpiredOrderService.php @@ -54,11 +54,15 @@ public function refundExpiredOrder( $stripePayment, ); - $this->mailer->to($order->getEmail())->send(new PaymentSuccessButOrderExpiredMail( - order: $order, - event: $event, - - )); + $this->mailer + ->to($order->getEmail()) + ->locale($order->getLocale()) + ->send(new PaymentSuccessButOrderExpiredMail( + order: $order, + event: $event, + eventSettings: $event->getEventSettings(), + organizer: $event->getOrganizer(), + )); $this->logger->info('Refunded expired order', [ 'order_id' => $order->getId(), diff --git a/backend/app/Services/Domain/User/SendUserInvitationService.php b/backend/app/Services/Domain/User/SendUserInvitationService.php index e43f761c..b213292e 100644 --- a/backend/app/Services/Domain/User/SendUserInvitationService.php +++ b/backend/app/Services/Domain/User/SendUserInvitationService.php @@ -38,10 +38,13 @@ public function sendInvitation(UserDomainObject $invitedUser, int $accountId): v expiry: now()->addWeek(), ); - $this->mailer->to($invitedUser->getEmail())->send(new UserInvited( - invitedUser: $invitedUser, - appName: $this->config->get('app.name'), - inviteLink: sprintf(Url::getFrontEndUrlFromConfig(Url::ACCEPT_INVITATION), $invitedPayload), - )); + $this->mailer + ->to($invitedUser->getEmail()) + ->locale($invitedUser->getLocale()) + ->send(new UserInvited( + invitedUser: $invitedUser, + appName: $this->config->get('app.name'), + inviteLink: sprintf(Url::getFrontEndUrlFromConfig(Url::ACCEPT_INVITATION), $invitedPayload), + )); } } diff --git a/backend/app/Services/Handlers/Attendee/EditAttendeeHandler.php b/backend/app/Services/Handlers/Attendee/EditAttendeeHandler.php index 3baa3c51..ea11affd 100644 --- a/backend/app/Services/Handlers/Attendee/EditAttendeeHandler.php +++ b/backend/app/Services/Handlers/Attendee/EditAttendeeHandler.php @@ -102,9 +102,9 @@ private function validateTicketId(EditAttendeeDTO $editAttendeeDTO): void ); if ($availableQuantity <= 0) { - throw new NoTicketsAvailableException(__('There are no tickets available. ' . - 'If you would like to assign this ticket to this attendee,' . - ' please adjust the ticket\'s available quantity.')); + throw new NoTicketsAvailableException( + __('There are no tickets available. If you would like to assign this ticket to this attendee, please adjust the ticket\'s available quantity.') + ); } } diff --git a/backend/app/Services/Handlers/Auth/ForgotPasswordHandler.php b/backend/app/Services/Handlers/Auth/ForgotPasswordHandler.php index e7fd4ce7..6403bb91 100644 --- a/backend/app/Services/Handlers/Auth/ForgotPasswordHandler.php +++ b/backend/app/Services/Handlers/Auth/ForgotPasswordHandler.php @@ -2,6 +2,7 @@ namespace HiEvents\Services\Handlers\Auth; +use HiEvents\DomainObjects\UserDomainObject; use HiEvents\Mail\User\ForgotPassword; use HiEvents\Repository\Interfaces\PasswordResetTokenRepositoryInterface; use HiEvents\Repository\Interfaces\UserRepositoryInterface; @@ -66,17 +67,20 @@ private function generateAndSaveResetToken(string $email): string return $token; } - private function sendResetPasswordEmail($user, string $token): void + private function sendResetPasswordEmail(UserDomainObject $user, string $token): void { $this->logger->info('resetting password for user', [ 'user' => $user->getId(), 'email' => $user->getEmail(), ]); - $this->mailer->to($user->getEmail())->send(new ForgotPassword( - user: $user, - token: $token, - )); + $this->mailer + ->to($user->getEmail()) + ->locale($user->getLocale()) + ->send(new ForgotPassword( + user: $user, + token: $token, + )); } private function logUnrecognisedEmail(string $email): void diff --git a/backend/app/Services/Handlers/Auth/ResetPasswordHandler.php b/backend/app/Services/Handlers/Auth/ResetPasswordHandler.php index 0ae88d29..6462dc46 100644 --- a/backend/app/Services/Handlers/Auth/ResetPasswordHandler.php +++ b/backend/app/Services/Handlers/Auth/ResetPasswordHandler.php @@ -81,8 +81,11 @@ private function logResetPasswordSuccess($user): void ); } - private function sendResetPasswordEmail($user): void + private function sendResetPasswordEmail(UserDomainObject $user): void { - $this->mailer->to($user->getEmail())->send(new ResetPasswordSuccess()); + $this->mailer + ->to($user->getEmail()) + ->locale($user->getLocale()) + ->send(new ResetPasswordSuccess()); } } diff --git a/backend/app/Services/Handlers/Order/CompleteOrderHandler.php b/backend/app/Services/Handlers/Order/CompleteOrderHandler.php index 116fc380..d68363b5 100644 --- a/backend/app/Services/Handlers/Order/CompleteOrderHandler.php +++ b/backend/app/Services/Handlers/Order/CompleteOrderHandler.php @@ -114,6 +114,7 @@ private function createAttendees(Collection $attendees, OrderDomainObject $order AttendeeDomainObjectAbstract::ORDER_ID => $order->getId(), AttendeeDomainObjectAbstract::PUBLIC_ID => $order->getPublicId() . '-' . $publicIdIndex++, AttendeeDomainObjectAbstract::SHORT_ID => IdHelper::randomPrefixedId(IdHelper::ATTENDEE_PREFIX), + AttendeeDomainObjectAbstract::LOCALE => $order->getLocale(), ]; } diff --git a/backend/app/Services/Handlers/Order/CreateOrderHandler.php b/backend/app/Services/Handlers/Order/CreateOrderHandler.php index 13e9b3fc..e94c4f7a 100644 --- a/backend/app/Services/Handlers/Order/CreateOrderHandler.php +++ b/backend/app/Services/Handlers/Order/CreateOrderHandler.php @@ -61,8 +61,9 @@ public function handle( eventId: $eventId, event: $event, timeOutMinutes: $event->getEventSettings()?->getOrderTimeoutInMinutes(), + locale: $createOrderPublicDTO->order_locale, promoCode: $promoCode, - sessionId: $sessionId + sessionId: $sessionId, ); $orderItems = $this->orderItemProcessingService->process( diff --git a/backend/app/Services/Handlers/Order/DTO/CreateOrderPublicDTO.php b/backend/app/Services/Handlers/Order/DTO/CreateOrderPublicDTO.php index d6f61f54..f9a3abea 100644 --- a/backend/app/Services/Handlers/Order/DTO/CreateOrderPublicDTO.php +++ b/backend/app/Services/Handlers/Order/DTO/CreateOrderPublicDTO.php @@ -13,6 +13,7 @@ public function __construct( */ public readonly Collection $tickets, public readonly bool $is_user_authenticated, + public readonly ?string $order_locale = null, public readonly ?string $promo_code = null, public readonly ?string $session_identifier = null, ) diff --git a/backend/app/Services/Handlers/Order/Payment/Stripe/RefundOrderHandler.php b/backend/app/Services/Handlers/Order/Payment/Stripe/RefundOrderHandler.php index 76b2d107..5f6dfd35 100644 --- a/backend/app/Services/Handlers/Order/Payment/Stripe/RefundOrderHandler.php +++ b/backend/app/Services/Handlers/Order/Payment/Stripe/RefundOrderHandler.php @@ -82,12 +82,15 @@ private function validateRefundability(OrderDomainObject $order): void private function notifyBuyer(OrderDomainObject $order, EventDomainObject $event, MoneyValue $amount): void { - $this->mailer->to($order->getEmail())->send(new OrderRefunded( - order: $order, - event: $event, - eventSettings: $event->getEventSettings(), - refundAmount: $amount - )); + $this->mailer + ->to($order->getEmail()) + ->locale($order->getLocale()) + ->send(new OrderRefunded( + order: $order, + event: $event, + eventSettings: $event->getEventSettings(), + refundAmount: $amount + )); } private function markOrderRefundPending(OrderDomainObject $order): OrderDomainObject diff --git a/backend/app/Services/Handlers/User/UpdateMeHandler.php b/backend/app/Services/Handlers/User/UpdateMeHandler.php index 07c1f484..11e6e63f 100644 --- a/backend/app/Services/Handlers/User/UpdateMeHandler.php +++ b/backend/app/Services/Handlers/User/UpdateMeHandler.php @@ -96,6 +96,7 @@ private function sendEmailChangeConfirmation(UserDomainObject $existingUser): vo { $this->mailer ->to($existingUser->getEmail()) + ->locale($existingUser->getLocale()) ->send(new ConfirmEmailChangeMail($existingUser, $this->encryptedPayloadService->encryptPayload([ 'id' => $existingUser->getId(), ])) diff --git a/backend/bootstrap/cache/packages.php b/backend/bootstrap/cache/packages.php index 9eea52f1..206aa197 100755 --- a/backend/bootstrap/cache/packages.php +++ b/backend/bootstrap/cache/packages.php @@ -1,4 +1,11 @@ + array ( + 'providers' => + array ( + 0 => 'Druc\\Langscanner\\LangscannerServiceProvider', + ), + ), 'laravel/sail' => array ( 'providers' => diff --git a/backend/bootstrap/cache/services.php b/backend/bootstrap/cache/services.php index c59e4f97..80afc409 100755 --- a/backend/bootstrap/cache/services.php +++ b/backend/bootstrap/cache/services.php @@ -23,20 +23,21 @@ 19 => 'Illuminate\\Translation\\TranslationServiceProvider', 20 => 'Illuminate\\Validation\\ValidationServiceProvider', 21 => 'Illuminate\\View\\ViewServiceProvider', - 22 => 'Laravel\\Sail\\SailServiceProvider', - 23 => 'Laravel\\Sanctum\\SanctumServiceProvider', - 24 => 'Laravel\\Tinker\\TinkerServiceProvider', - 25 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 26 => 'Carbon\\Laravel\\ServiceProvider', - 27 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - 28 => 'Termwind\\Laravel\\TermwindServiceProvider', - 29 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider', - 30 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', - 31 => 'HiEvents\\Providers\\AppServiceProvider', - 32 => 'HiEvents\\Providers\\AuthServiceProvider', - 33 => 'HiEvents\\Providers\\EventServiceProvider', - 34 => 'HiEvents\\Providers\\RouteServiceProvider', - 35 => 'HiEvents\\Providers\\RepositoryServiceProvider', + 22 => 'Druc\\Langscanner\\LangscannerServiceProvider', + 23 => 'Laravel\\Sail\\SailServiceProvider', + 24 => 'Laravel\\Sanctum\\SanctumServiceProvider', + 25 => 'Laravel\\Tinker\\TinkerServiceProvider', + 26 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 27 => 'Carbon\\Laravel\\ServiceProvider', + 28 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + 29 => 'Termwind\\Laravel\\TermwindServiceProvider', + 30 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider', + 31 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', + 32 => 'HiEvents\\Providers\\AppServiceProvider', + 33 => 'HiEvents\\Providers\\AuthServiceProvider', + 34 => 'HiEvents\\Providers\\EventServiceProvider', + 35 => 'HiEvents\\Providers\\RouteServiceProvider', + 36 => 'HiEvents\\Providers\\RepositoryServiceProvider', ), 'eager' => array ( @@ -50,18 +51,19 @@ 7 => 'Illuminate\\Pagination\\PaginationServiceProvider', 8 => 'Illuminate\\Session\\SessionServiceProvider', 9 => 'Illuminate\\View\\ViewServiceProvider', - 10 => 'Laravel\\Sanctum\\SanctumServiceProvider', - 11 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 12 => 'Carbon\\Laravel\\ServiceProvider', - 13 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - 14 => 'Termwind\\Laravel\\TermwindServiceProvider', - 15 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider', - 16 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', - 17 => 'HiEvents\\Providers\\AppServiceProvider', - 18 => 'HiEvents\\Providers\\AuthServiceProvider', - 19 => 'HiEvents\\Providers\\EventServiceProvider', - 20 => 'HiEvents\\Providers\\RouteServiceProvider', - 21 => 'HiEvents\\Providers\\RepositoryServiceProvider', + 10 => 'Druc\\Langscanner\\LangscannerServiceProvider', + 11 => 'Laravel\\Sanctum\\SanctumServiceProvider', + 12 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 13 => 'Carbon\\Laravel\\ServiceProvider', + 14 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + 15 => 'Termwind\\Laravel\\TermwindServiceProvider', + 16 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider', + 17 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', + 18 => 'HiEvents\\Providers\\AppServiceProvider', + 19 => 'HiEvents\\Providers\\AuthServiceProvider', + 20 => 'HiEvents\\Providers\\EventServiceProvider', + 21 => 'HiEvents\\Providers\\RouteServiceProvider', + 22 => 'HiEvents\\Providers\\RepositoryServiceProvider', ), 'deferred' => array ( diff --git a/backend/composer.json b/backend/composer.json index 4b410491..a4cd71d9 100644 --- a/backend/composer.json +++ b/backend/composer.json @@ -10,6 +10,7 @@ "ext-intl": "*", "brick/money": "^0.8.0", "doctrine/dbal": "^3.6", + "druc/laravel-langscanner": "^2.2", "ezyang/htmlpurifier": "^4.17", "guzzlehttp/guzzle": "^7.2", "laravel/framework": "^11.0", diff --git a/backend/composer.lock b/backend/composer.lock index 06dfbfb9..731cf7d6 100644 --- a/backend/composer.lock +++ b/backend/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5f55a1a7adc1f649d32d094a084840d1", + "content-hash": "43724230ba59b855b143ce8ccfb1ab91", "packages": [ { "name": "aws/aws-crt-php", @@ -1066,6 +1066,74 @@ ], "time": "2023-08-10T19:36:49+00:00" }, + { + "name": "druc/laravel-langscanner", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/druc/laravel-langscanner.git", + "reference": "78b3d381d0c2a0cfc4ed4062a6f5bd8b72f7efa4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/druc/laravel-langscanner/zipball/78b3d381d0c2a0cfc4ed4062a6f5bd8b72f7efa4", + "reference": "78b3d381d0c2a0cfc4ed4062a6f5bd8b72f7efa4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/contracts": "^9.0|^10.0|^11.0", + "php": "^8.0", + "spatie/laravel-package-tools": "^1.11.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.3", + "nunomaduro/collision": "^6.2", + "orchestra/testbench": "^7.02|^9.0", + "phpunit/phpunit": "^9.5|^10.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Druc\\Langscanner\\LangscannerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Druc\\Langscanner\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Constantin Druc", + "email": "druc@pinsmile.com", + "role": "Developer" + } + ], + "description": "Scan missing language translations.", + "homepage": "https://github.com/druc/laravel-langscanner", + "keywords": [ + "druc", + "laravel-langscanner" + ], + "support": { + "issues": "https://github.com/druc/laravel-langscanner/issues", + "source": "https://github.com/druc/laravel-langscanner/tree/v2.2.0" + }, + "funding": [ + { + "url": "https://github.com/druc", + "type": "github" + } + ], + "time": "2024-03-25T20:09:17+00:00" + }, { "name": "egulias/email-validator", "version": "4.0.2", @@ -4931,6 +4999,66 @@ }, "time": "2024-05-16T15:11:32+00:00" }, + { + "name": "spatie/laravel-package-tools", + "version": "1.16.4", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-package-tools.git", + "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", + "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^9.28|^10.0|^11.0", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "orchestra/testbench": "^7.7|^8.0", + "pestphp/pest": "^1.22", + "phpunit/phpunit": "^9.5.24", + "spatie/pest-plugin-test-time": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\LaravelPackageTools\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Tools for creating Laravel packages", + "homepage": "https://github.com/spatie/laravel-package-tools", + "keywords": [ + "laravel-package-tools", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-package-tools/issues", + "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.4" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-03-20T07:29:11+00:00" + }, { "name": "stripe/stripe-php", "version": "v10.21.0", diff --git a/backend/database/migrations/2024_06_16_143927_add_locale_to_users.php b/backend/database/migrations/2024_06_16_143927_add_locale_to_users.php new file mode 100644 index 00000000..2187a0d6 --- /dev/null +++ b/backend/database/migrations/2024_06_16_143927_add_locale_to_users.php @@ -0,0 +1,22 @@ +string('locale', 20)->default(config('app.locale')); + }); + } + + public function down(): void + { + Schema::table('users', static function (Blueprint $table) { + $table->dropColumn('locale'); + }); + } +}; diff --git a/backend/database/migrations/2024_06_16_192150_add_locale_to_attendees.php b/backend/database/migrations/2024_06_16_192150_add_locale_to_attendees.php new file mode 100644 index 00000000..571584a9 --- /dev/null +++ b/backend/database/migrations/2024_06_16_192150_add_locale_to_attendees.php @@ -0,0 +1,21 @@ +string('locale', 20)->default(config('app.locale')); + }); + } + + public function down(): void + { + Schema::table('attendees', static function (Blueprint $table) { + $table->dropColumn('locale'); + }); + } +}; diff --git a/backend/database/migrations/2024_06_16_192151_add_locale_to_orders.php b/backend/database/migrations/2024_06_16_192151_add_locale_to_orders.php new file mode 100644 index 00000000..e1395801 --- /dev/null +++ b/backend/database/migrations/2024_06_16_192151_add_locale_to_orders.php @@ -0,0 +1,21 @@ +string('locale', 20)->default(config('app.locale')); + }); + } + + public function down(): void + { + Schema::table('orders', static function (Blueprint $table) { + $table->dropColumn('locale'); + }); + } +}; diff --git a/backend/lang/de.json b/backend/lang/de.json new file mode 100644 index 00000000..63217f53 --- /dev/null +++ b/backend/lang/de.json @@ -0,0 +1,263 @@ +{ + "Older First": "Älteste zuerst", + "Newer First": "Neueste zuerst", + "Recently Updated First": "Zuletzt aktualisiert zuerst", + "Recently Updated Last": "Zuletzt aktualisiert zuletzt", + "First Name A-Z": "Vorname A-Z", + "First Name Z-A": "Vorname Z-A", + "Last Name A-Z": "Nachname A-Z", + "Last Name Z-A": "Nachname Z-A", + "Status A-Z": "Status A-Z", + "Status Z-A": "Status Z-A", + "Closest start date": "Nächstes Startdatum", + "Furthest start date": "Weitestes Startdatum", + "Closest end date": "Nächstes Enddatum", + "Furthest end date": "Weitestes Enddatum", + "Newest first": "Neueste zuerst", + "Oldest first": "Älteste zuerst", + "Recently Updated": "Kürzlich aktualisiert", + "Least Recently Updated": "Am wenigsten kürzlich aktualisiert", + "Oldest First": "Älteste zuerst", + "Newest First": "Neueste zuerst", + "Buyer Name A-Z": "Käufername A-Z", + "Buyer Name Z-A": "Käufername Z-A", + "Amount Ascending": "Betrag aufsteigend", + "Amount Descending": "Betrag absteigend", + "Buyer Email A-Z": "Käufer-E-Mail A-Z", + "Buyer Email Z-A": "Käufer-E-Mail Z-A", + "Order # Ascending": "Bestellnummer aufsteigend", + "Order # Descending": "Bestellnummer absteigend", + "Code Name A-Z": "Codename A-Z", + "Code Name Z-A": "Codename Z-A", + "Usage Count Ascending": "Nutzungsanzahl aufsteigend", + "Usage Count Descending": "Nutzungsanzahl absteigend", + "Homepage order": "Homepage-Bestellung", + "Title A-Z": "Titel A-Z", + "Title Z-A": "Titel Z-A", + "Sale start date closest": "Nächstes Verkaufsstartdatum", + "Sale start date furthest": "Weitestes Verkaufsstartdatum", + "Sale end date closest": "Nächstes Verkaufsenddatum", + "Sale end date furthest": "Weitestes Verkaufsenddatum", + "Account registration is disabled": "Kontoregistrierung ist deaktiviert", + "The invitation has expired": "Die Einladung ist abgelaufen", + "The invitation is invalid": "Die Einladung ist ungültig", + "Invitation valid, but user not found": "Einladung gültig, aber Benutzer nicht gefunden", + "No user found for this invitation. The invitation may have been revoked.": "Kein Benutzer für diese Einladung gefunden. Die Einladung wurde möglicherweise widerrufen.", + "Logout Successful": "Abmeldung erfolgreich", + "Your password has been reset. Please login with your new password.": "Ihr Passwort wurde zurückgesetzt. Bitte melden Sie sich mit Ihrem neuen Passwort an.", + "No account ID found in token": "Keine Kontonummer im Token gefunden", + "Event with ID :eventId is not live and user is not authenticated": "Veranstaltung mit ID :eventId ist nicht live und Benutzer ist nicht authentifiziert", + "Sorry, we could not verify your session. Please restart your order.": "Entschuldigung, wir konnten Ihre Sitzung nicht überprüfen. Bitte starten Sie Ihre Bestellung neu.", + "The email confirmation link has expired. Please request a new one.": "Der E-Mail-Bestätigungslink ist abgelaufen. Bitte fordern Sie einen neuen an.", + "The email confirmation link is invalid.": "Der E-Mail-Bestätigungslink ist ungültig.", + "No invitation found for this user.": "Keine Einladung für diesen Benutzer gefunden.", + "User status is not Invited": "Benutzerstatus ist nicht eingeladen", + "Email is required": "E-Mail ist erforderlich", + "Email must be a valid email address": "E-Mail muss eine gültige E-Mail-Adresse sein", + "First name is required": "Vorname ist erforderlich", + "Last name is required": "Nachname ist erforderlich", + "Ticket is required": "Ticket ist erforderlich", + "Ticket price is required": "Ticketpreis ist erforderlich", + "Please enter a valid hex color code. In the format #000000 or #000.": "Bitte geben Sie einen gültigen Hex-Farbcode ein. Im Format #000000 oder #000.", + "The maximum timeout is 2 hours.": "Das maximale Timeout beträgt 2 Stunden.", + "The address line 1 field is required": "Das Feld Adresszeile 1 ist erforderlich", + "The city field is required": "Das Feld Stadt ist erforderlich", + "The zip or postal code field is required": "Das Feld Postleitzahl ist erforderlich", + "The country field is required": "Das Feld Land ist erforderlich", + "The country field should be a 2 character ISO 3166 code": "Das Feld Land sollte ein 2-stelliger ISO 3166-Code sein", + "Please select at least one ticket.": "Bitte wählen Sie mindestens ein Ticket aus.", + "The sale end date must be after the sale start date.": "Das Verkaufsenddatum muss nach dem Verkaufsstartdatum liegen.", + "The sale end date must be a valid date.": "Das Verkaufsenddatum muss ein gültiges Datum sein.", + "The sale start date must be after the ticket sale start date.": "Das Verkaufsstartdatum muss nach dem Ticketverkaufsstartdatum liegen.", + "Welcome to :app_name! Please confirm your email address": "Willkommen bei :app_name! Bitte bestätigen Sie Ihre E-Mail-Adresse", + "🎟️ Your Ticket for :event": "🎟️ Ihr Ticket für :event", + "Your order wasn't successful": "Ihre Bestellung war nicht erfolgreich", + "We were unable to process your order": "Wir konnten Ihre Bestellung nicht bearbeiten", + "New order for :amount for :event 🎉": "Neue Bestellung für :amount für :event 🎉", + "New order for :event 🎉": "Neue Bestellung für :event 🎉", + "Current account ID is not set": "Aktuelle Kontonummer ist nicht gesetzt", + "User not found in this account": "Benutzer in diesem Konto nicht gefunden", + "User not found": "Benutzer nicht gefunden", + "Username or Password are incorrect": "Benutzername oder Passwort sind falsch", + "Account not found": "Konto nicht gefunden", + "Attempt to log in to a non-active account": "Versuch, sich in ein nicht aktives Konto einzuloggen", + "User account is not active": "Benutzerkonto ist nicht aktiv", + "Invalid reset token": "Ungültiger Reset-Token", + "Reset token has expired": "Reset-Token ist abgelaufen", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "Tägliche Veranstaltungsstatistiken aktualisiert für Veranstaltung :event_id mit insgesamt erstatteten Betrag von :amount", + "Event statistics updated for event :event_id with total refunded amount of :amount": "Veranstaltungsstatistiken aktualisiert für Veranstaltung :event_id mit insgesamt erstatteten Betrag von :amount", + "This promo code is invalid": "Dieser Promo-Code ist ungültig", + "You haven't selected any tickets": "Sie haben keine Tickets ausgewählt", + "The maximum number of tickets available for :tickets is :max": "Die maximale Anzahl an verfügbaren Tickets für :tickets beträgt :max", + "You must order at least :min tickets for :ticket": "Sie müssen mindestens :min Tickets für :ticket bestellen", + "The minimum amount is :price": "Der Mindestbetrag ist :price", + "The ticket :ticket is sold out": "Das Ticket :ticket ist ausverkauft", + ":field must be specified": ":field muss angegeben werden", + "Invalid price ID": "Ungültige Preis-ID", + "The maximum number of tickets available for :ticket is :max": "Die maximale Anzahl an verfügbaren Tickets für :ticket beträgt :max", + "Ticket with id :id not found": "Ticket mit ID :id nicht gefunden", + "Failed to refund stripe charge": "Fehler bei der Rückerstattung der Stripe-Gebühr", + "Payment was successful, but order has expired. Order: :id": "Zahlung war erfolgreich, aber Bestellung ist abgelaufen. Bestellung: :id", + "Order is not awaiting payment. Order: :id": "Bestellung wartet nicht auf Zahlung. Bestellung: :id", + "There was an error communicating with the payment provider. Please try again later.": "Es gab einen Fehler bei der Kommunikation mit dem Zahlungsanbieter. Bitte versuchen Sie es später erneut.", + "Stripe Connect account not found for the event organizer": "Stripe Connect-Konto für den Veranstalter nicht gefunden", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "Kann nicht zurückerstatten: Stripe Connect-Konto nicht gefunden und saas_mode_enabled ist aktiviert", + "Invalid calculation type": "Ungültiger Berechnungstyp", + "One or more tax IDs are invalid": "Eine oder mehrere Steuer-IDs sind ungültig", + "Invalid ticket ids: :ids": "Ungültige Ticket-IDs: :ids", + "Order has no order items": "Bestellung hat keine Bestellpositionen", + "There is already an account associated with this email. Please log in instead.": "Es gibt bereits ein Konto, das mit dieser E-Mail-Adresse verknüpft ist. Bitte melden Sie sich stattdessen an.", + "Stripe Connect Account creation is only available in Saas Mode.": "Stripe Connect-Kontoerstellung ist nur im Saas-Modus verfügbar.", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "Es gibt Probleme beim Erstellen oder Abrufen des Stripe Connect-Kontos. Bitte versuchen Sie es erneut.", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "Es gibt Probleme beim Erstellen des Stripe Connect-Konto-Links. Bitte versuchen Sie es erneut.", + "Cannot check in attendee as they are not active.": "Teilnehmer kann nicht eingecheckt werden, da er nicht aktiv ist.", + "in": "in", + "out": "aus", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "Es sind keine Tickets verfügbar. ' .\n 'Wenn Sie diesem Teilnehmer ein Ticket zuweisen möchten,' .\n ' passen Sie bitte die verfügbare Menge des Tickets an.", + "The ticket price ID is invalid.": "Die Ticketpreis-ID ist ungültig.", + "Ticket ID is not valid": "Ticket-ID ist nicht gültig", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "Es sind keine Tickets verfügbar. ' .\n 'Wenn Sie dieses Ticket diesem Teilnehmer zuweisen möchten,' .\n ' passen Sie bitte die verfügbare Menge des Tickets an.", + "Attendee ID is not valid": "Teilnehmer-ID ist nicht gültig", + "The invitation does not exist": "Die Einladung existiert nicht", + "The invitation has already been accepted": "Die Einladung wurde bereits angenommen", + "Organizer :id not found": "Veranstalter :id nicht gefunden", + "Continue": "Fortsetzen", + "Event :id not found": "Veranstaltung :id nicht gefunden", + "You cannot change the currency of an event that has completed orders": "Sie können die Währung einer Veranstaltung mit abgeschlossenen Bestellungen nicht ändern", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "Sie müssen Ihr Konto überprüfen, bevor Sie den Status einer Veranstaltung aktualisieren können.\n Sie können die Bestätigung erneut senden, indem Sie Ihre Profilseite besuchen.", + "You cannot send messages until your account is verified.": "Sie können keine Nachrichten senden, bis Ihr Konto überprüft ist.", + "Order not found": "Bestellung nicht gefunden", + "Order already cancelled": "Bestellung bereits storniert", + "Failed to create attendee": "Erstellung des Teilnehmers fehlgeschlagen", + "This order is has already been processed": "Diese Bestellung wurde bereits bearbeitet", + "This order has expired": "Diese Bestellung ist abgelaufen", + "This order has already been processed": "Diese Bestellung wurde bereits bearbeitet", + "There is an unexpected ticket price ID in the order": "Es gibt eine unerwartete Ticketpreis-ID in der Bestellung", + "This event is not live.": "Diese Veranstaltung ist nicht live.", + "Sorry, we could not verify your session. Please create a new order.": "Entschuldigung, wir konnten Ihre Sitzung nicht überprüfen. Bitte erstellen Sie eine neue Bestellung.", + "There is no Stripe data associated with this order.": "Es sind keine Stripe-Daten mit dieser Bestellung verknüpft.", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "Es gibt bereits eine Rückerstattung für diese Bestellung. '\n . 'Bitte warten Sie, bis die Rückerstattung bearbeitet wurde, bevor Sie eine weitere anfordern.", + "Promo code :code already exists": "Promo-Code :code existiert bereits", + "The code :code is already in use for this event": "Der Code :code wird bereits für diese Veranstaltung verwendet", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "Sie können diese Frage nicht löschen, da Antworten damit verknüpft sind. Sie können die Frage stattdessen ausblenden.", + "One or more of the ordered question IDs do not exist for the event.": "Eine oder mehrere der bestellten Fragen-IDs existieren nicht für die Veranstaltung.", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "Sie können dieses Ticket nicht löschen, da es Bestellungen damit verknüpft sind. Sie können es stattdessen ausblenden.", + "Ticket type cannot be changed as tickets have been registered for this type": "Der Tickettyp kann nicht geändert werden, da Tickets für diesen Typ registriert wurden", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "Die bestellten Ticket-IDs müssen genau mit allen Tickets für die Veranstaltung übereinstimmen, ohne fehlende oder zusätzliche IDs.", + "No email change pending": "Keine E-Mail-Änderung ausstehend", + "The email :email already exists on this account": "Die E-Mail :email existiert bereits auf diesem Konto", + "You are not authorized to perform this action.": "Sie sind nicht berechtigt, diese Aktion durchzuführen.", + "Your account is not active.": "Ihr Konto ist nicht aktiv.", + "Payload has expired or is invalid.": "Payload ist abgelaufen oder ungültig.", + "Payload could not be decrypted.": "Payload konnte nicht entschlüsselt werden.", + "Could not upload image to :disk. Check :disk is configured correctly": "Bild konnte nicht auf :disk hochgeladen werden. Überprüfen Sie, ob :disk korrekt konfiguriert ist", + "Could not upload image": "Bild konnte nicht hochgeladen werden", + "Length must be a positive integer.": "Die Länge muss eine positive ganze Zahl sein.", + "Prefix length exceeds the total desired token length.": "Die Präfixlänge überschreitet die gewünschte Gesamtlänge des Tokens.", + "A valid email is required": "Eine gültige E-Mail ist erforderlich", + "The title field is required": "Das Titelfeld ist erforderlich", + "The attribute name is required": "Der Attributname ist erforderlich", + "The attribute value is required": "Der Attributwert ist erforderlich", + "The attribute is_public fields is required": "Das Attribut ist_public Felder ist erforderlich", + "Required questions have not been answered. You may need to reload the page.": "Erforderliche Fragen wurden nicht beantwortet. Möglicherweise müssen Sie die Seite neu laden.", + "This question is outdated. Please reload the page.": "Diese Frage ist veraltet. Bitte laden Sie die Seite neu.", + "Please select an option": "Bitte wählen Sie eine Option aus", + "This field is required.": "Dieses Feld ist erforderlich.", + "This field must be less than 255 characters.": "Dieses Feld muss weniger als 255 Zeichen enthalten.", + "This field must be at least 2 characters.": "Dieses Feld muss mindestens 2 Zeichen enthalten.", + "Hello": "Hallo", + "You have requested to reset your password for your account on :appName.": "Sie haben die Rücksetzung Ihres Passworts für Ihr Konto bei :appName angefordert.", + "Please click the link below to reset your password.": "Bitte klicken Sie auf den untenstehenden Link, um Ihr Passwort zurückzusetzen.", + "Reset Password": "Passwort zurücksetzen", + "If you did not request a password reset, please ignore this email or reply to let us know.": "Wenn Sie keine Passwortzurücksetzung angefordert haben, ignorieren Sie diese E-Mail bitte oder antworten Sie, um uns dies mitzuteilen.", + "Thank you": "Danke", + "Your password has been reset for your account on :appName.": "Ihr Passwort wurde für Ihr Konto bei :appName zurückgesetzt.", + "If you did not request a password reset, please immediately contact reset your password.": "Wenn Sie keine Passwortzurücksetzung angefordert haben, setzen Sie Ihr Passwort bitte umgehend zurück.", + "You are receiving this communication because you are registered as an attendee for the following event:": "Sie erhalten diese Nachricht, weil Sie als Teilnehmer für die folgende Veranstaltung registriert sind:", + "If you believe you have received this email in error,": "Wenn Sie glauben, diese E-Mail irrtümlich erhalten zu haben,", + "please contact the event organizer at": "bitte kontaktieren Sie den Veranstalter unter", + "If you believe this is spam, please report it to": "Wenn Sie glauben, dass dies Spam ist, melden Sie es bitte an", + "You're going to": "Sie gehen zu", + "Please find your ticket details below.": "Bitte finden Sie Ihre Ticketdetails unten.", + "View Ticket": "Ticket anzeigen", + "at": "unter", + "Best regards,": "Mit freundlichen Grüßen,", + "Your order for": "Ihre Bestellung für", + "has been cancelled.": "wurde storniert.", + "Order #:": "Bestellung #:", + "If you have any questions or need assistance, please respond to this email.": "Wenn Sie Fragen haben oder Unterstützung benötigen, antworten Sie bitte auf diese E-Mail.", + "Your recent order for": "Ihre kürzliche Bestellung für", + "was not successful.": "war nicht erfolgreich.", + "View Event Homepage": "Veranstaltungshomepage anzeigen", + "If you have any questions or need assistance, feel free to reach out to our support team": "Wenn Sie Fragen haben oder Unterstützung benötigen, können Sie sich gerne an unser Support-Team wenden", + "Best regards": "Mit freundlichen Grüßen", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "Sie haben eine Rückerstattung von :refundAmount für die folgende Veranstaltung erhalten: :eventTitle.", + "You've received a new order!": "Sie haben eine neue Bestellung erhalten!", + "Congratulations! You've received a new order for ": "Herzlichen Glückwunsch! Sie haben eine neue Bestellung für ", + "Please find the details below.": "Bitte finden Sie die Details unten.", + "Order Amount:": "Bestellbetrag:", + "Order ID:": "Bestell-ID:", + "View Order": "Bestellung anzeigen", + "Ticket": "Ticket", + "Price": "Preis", + "Total": "Gesamt", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "Ihre kürzliche Bestellung für :eventTitle war nicht erfolgreich. Die Bestellung ist abgelaufen, während Sie die Zahlung abgeschlossen haben. Wir haben eine Rückerstattung für die Bestellung ausgestellt.", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "Wir entschuldigen uns für die Unannehmlichkeiten. Wenn Sie Fragen haben oder Unterstützung benötigen, können Sie uns gerne unter erreichen", + "View Event Page": "Veranstaltungsseite anzeigen", + "Hi.Events": "Hi.Events", + "Your Order is Confirmed! ": "Ihre Bestellung ist bestätigt! ", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "Herzlichen Glückwunsch! Ihre Bestellung für :eventTitle am :eventDate um :eventTime war erfolgreich. Bitte finden Sie Ihre Bestelldetails unten.", + "Event Details": "Veranstaltungsdetails", + "Event Name:": "Veranstaltungsname:", + "Date & Time:": "Datum & Uhrzeit:", + "Order Summary": "Bestellübersicht", + "Order Number:": "Bestellnummer:", + "Total Amount:": "Gesamtbetrag:", + "View Order Summary & Tickets": "Bestellübersicht & Tickets anzeigen", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "Wenn Sie Fragen haben oder Unterstützung benötigen, können Sie sich gerne an unser freundliches Support-Team wenden unter", + "What's Next?": "Was kommt als nächstes?", + "Download Tickets:": "Tickets herunterladen:", + "Please download your tickets from the order summary page.": "Bitte laden Sie Ihre Tickets von der Bestellübersichtsseite herunter.", + "Prepare for the Event:": "Bereiten Sie sich auf die Veranstaltung vor:", + "Make sure to note the event date, time, and location.": "Stellen Sie sicher, dass Sie das Veranstaltungsdatum, die Uhrzeit und den Ort notieren.", + "Stay Updated:": "Bleiben Sie auf dem Laufenden:", + "Keep an eye on your email for any updates from the event organizer.": "Behalten Sie Ihre E-Mail im Auge für Updates vom Veranstalter.", + "Hi :name": "Hallo :name", + "Welcome to :appName! We're excited to have you aboard!": "Willkommen bei :appName! Wir freuen uns, Sie an Bord zu haben!", + "To get started and activate your account, please click the link below to confirm your email address:": "Um loszulegen und Ihr Konto zu aktivieren, klicken Sie bitte auf den untenstehenden Link, um Ihre E-Mail-Adresse zu bestätigen:", + "Confirm Your Email": "Bestätigen Sie Ihre E-Mail", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "Wenn Sie kein Konto bei uns erstellt haben, sind keine weiteren Maßnahmen erforderlich. Ihre E-Mail-Adresse wird ohne Bestätigung nicht verwendet.", + "Best Regards,": "Mit freundlichen Grüßen,", + "The :appName Team": "Das :appName-Team", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "Sie haben die Änderung Ihrer E-Mail-Adresse zu :pendingEmail angefordert. Bitte klicken Sie auf den untenstehenden Link, um diese Änderung zu bestätigen.", + "Confirm email change": "E-Mail-Änderung bestätigen", + "If you did not request this change, please immediately change your password.": "Wenn Sie diese Änderung nicht angefordert haben, ändern Sie bitte sofort Ihr Passwort.", + "Thanks,": "Danke,", + "You've been invited to join :appName.": "Sie wurden eingeladen, sich :appName anzuschließen.", + "To accept the invitation, please click the link below:": "Um die Einladung anzunehmen, klicken Sie bitte auf den untenstehenden Link:", + "Accept Invitation": "Einladung annehmen", + "All rights reserved.": "Alle Rechte vorbehalten.", + "Congratulations 🎉": "Herzlichen Glückwunsch 🎉", + "Your order has been cancelled": "Ihre Bestellung wurde storniert", + "You've received a refund": "Sie haben eine Rückerstattung erhalten", + "Your Order is Confirmed!": "Ihre Bestellung ist bestätigt!", + "Password reset": "Passwort zurücksetzen", + "Your password has been reset": "Ihr Passwort wurde zurückgesetzt", + "You've been invited to join :appName": "Sie wurden eingeladen, sich :appName anzuschließen", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "Es gibt bereits eine Rückerstattung für diese Bestellung.\n Bitte warten Sie, bis die Rückerstattung bearbeitet wurde, bevor Sie eine weitere anfordern.", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "Cannot delete ticket price with id :id because it has sales": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/lang/es.json b/backend/lang/es.json new file mode 100644 index 00000000..b0eb7d3f --- /dev/null +++ b/backend/lang/es.json @@ -0,0 +1,263 @@ +{ + "Older First": "", + "Newer First": "", + "Recently Updated First": "", + "Recently Updated Last": "", + "First Name A-Z": "", + "First Name Z-A": "", + "Last Name A-Z": "", + "Last Name Z-A": "", + "Status A-Z": "", + "Status Z-A": "", + "Closest start date": "", + "Furthest start date": "", + "Closest end date": "", + "Furthest end date": "", + "Newest first": "", + "Oldest first": "", + "Recently Updated": "", + "Least Recently Updated": "", + "Oldest First": "", + "Newest First": "", + "Buyer Name A-Z": "", + "Buyer Name Z-A": "", + "Amount Ascending": "", + "Amount Descending": "", + "Buyer Email A-Z": "", + "Buyer Email Z-A": "", + "Order # Ascending": "", + "Order # Descending": "", + "Code Name A-Z": "", + "Code Name Z-A": "", + "Usage Count Ascending": "", + "Usage Count Descending": "", + "Homepage order": "", + "Title A-Z": "", + "Title Z-A": "", + "Sale start date closest": "", + "Sale start date furthest": "", + "Sale end date closest": "", + "Sale end date furthest": "", + "Account registration is disabled": "", + "The invitation has expired": "", + "The invitation is invalid": "", + "Invitation valid, but user not found": "", + "No user found for this invitation. The invitation may have been revoked.": "", + "Logout Successful": "", + "Your password has been reset. Please login with your new password.": "", + "No account ID found in token": "", + "Event with ID :eventId is not live and user is not authenticated": "", + "Sorry, we could not verify your session. Please restart your order.": "", + "The email confirmation link has expired. Please request a new one.": "", + "The email confirmation link is invalid.": "", + "No invitation found for this user.": "", + "User status is not Invited": "", + "Email is required": "", + "Email must be a valid email address": "", + "First name is required": "", + "Last name is required": "", + "Ticket is required": "", + "Ticket price is required": "", + "Please enter a valid hex color code. In the format #000000 or #000.": "", + "The maximum timeout is 2 hours.": "", + "The address line 1 field is required": "", + "The city field is required": "", + "The zip or postal code field is required": "", + "The country field is required": "", + "The country field should be a 2 character ISO 3166 code": "", + "Please select at least one ticket.": "", + "The sale end date must be after the sale start date.": "", + "The sale end date must be a valid date.": "", + "The sale start date must be after the ticket sale start date.": "", + "Welcome to :app_name! Please confirm your email address": "", + "🎟️ Your Ticket for :event": "", + "Your order wasn't successful": "", + "We were unable to process your order": "", + "New order for :amount for :event 🎉": "", + "New order for :event 🎉": "", + "Current account ID is not set": "", + "User not found in this account": "", + "User not found": "", + "Username or Password are incorrect": "", + "Account not found": "", + "Attempt to log in to a non-active account": "", + "User account is not active": "", + "Invalid reset token": "", + "Reset token has expired": "", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "", + "Event statistics updated for event :event_id with total refunded amount of :amount": "", + "This promo code is invalid": "", + "You haven't selected any tickets": "", + "The maximum number of tickets available for :tickets is :max": "", + "You must order at least :min tickets for :ticket": "", + "The minimum amount is :price": "", + "The ticket :ticket is sold out": "", + ":field must be specified": "", + "Invalid price ID": "", + "The maximum number of tickets available for :ticket is :max": "", + "Ticket with id :id not found": "", + "Failed to refund stripe charge": "", + "Payment was successful, but order has expired. Order: :id": "", + "Order is not awaiting payment. Order: :id": "", + "There was an error communicating with the payment provider. Please try again later.": "", + "Stripe Connect account not found for the event organizer": "", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "", + "Invalid calculation type": "", + "One or more tax IDs are invalid": "", + "Invalid ticket ids: :ids": "", + "Cannot delete ticket price with id :id because it has sales": "", + "Order has no order items": "", + "There is already an account associated with this email. Please log in instead.": "", + "Stripe Connect Account creation is only available in Saas Mode.": "", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "", + "Cannot check in attendee as they are not active.": "", + "in": "", + "out": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "The ticket price ID is invalid.": "", + "Ticket ID is not valid": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "Attendee ID is not valid": "", + "The invitation does not exist": "", + "The invitation has already been accepted": "", + "Organizer :id not found": "", + "Continue": "", + "Event :id not found": "", + "You cannot change the currency of an event that has completed orders": "", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "", + "You cannot send messages until your account is verified.": "", + "Order not found": "", + "Order already cancelled": "", + "Failed to create attendee": "", + "This order is has already been processed": "", + "This order has expired": "", + "This order has already been processed": "", + "There is an unexpected ticket price ID in the order": "", + "This event is not live.": "", + "Sorry, we could not verify your session. Please create a new order.": "", + "There is no Stripe data associated with this order.": "", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "", + "Promo code :code already exists": "", + "The code :code is already in use for this event": "", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "", + "One or more of the ordered question IDs do not exist for the event.": "", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "", + "Ticket type cannot be changed as tickets have been registered for this type": "", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "", + "No email change pending": "", + "The email :email already exists on this account": "", + "You are not authorized to perform this action.": "", + "Your account is not active.": "", + "Payload has expired or is invalid.": "", + "Payload could not be decrypted.": "", + "Could not upload image to :disk. Check :disk is configured correctly": "", + "Could not upload image": "", + "Length must be a positive integer.": "", + "Prefix length exceeds the total desired token length.": "", + "A valid email is required": "", + "The title field is required": "", + "The attribute name is required": "", + "The attribute value is required": "", + "The attribute is_public fields is required": "", + "Required questions have not been answered. You may need to reload the page.": "", + "This question is outdated. Please reload the page.": "", + "Please select an option": "", + "This field is required.": "", + "This field must be less than 255 characters.": "", + "This field must be at least 2 characters.": "", + "Hello": "", + "You have requested to reset your password for your account on :appName.": "", + "Please click the link below to reset your password.": "", + "Reset Password": "", + "If you did not request a password reset, please ignore this email or reply to let us know.": "", + "Thank you": "", + "Your password has been reset for your account on :appName.": "", + "If you did not request a password reset, please immediately contact reset your password.": "", + "You are receiving this communication because you are registered as an attendee for the following event:": "", + "If you believe you have received this email in error,": "", + "please contact the event organizer at": "", + "If you believe this is spam, please report it to": "", + "You're going to": "", + "Please find your ticket details below.": "", + "View Ticket": "", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "", + "at": "", + "Best regards,": "", + "Your order for": "", + "has been cancelled.": "", + "Order #:": "", + "If you have any questions or need assistance, please respond to this email.": "", + "Your recent order for": "", + "was not successful.": "", + "View Event Homepage": "", + "If you have any questions or need assistance, feel free to reach out to our support team": "", + "Best regards": "", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "", + "You've received a new order!": "", + "Congratulations! You've received a new order for ": "", + "Please find the details below.": "", + "Order Amount:": "", + "Order ID:": "", + "View Order": "", + "Ticket": "", + "Price": "", + "Total": "", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "", + "View Event Page": "", + "Hi.Events": "", + "Your Order is Confirmed! ": "", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "", + "Event Details": "", + "Event Name:": "", + "Date & Time:": "", + "Order Summary": "", + "Order Number:": "", + "Total Amount:": "", + "View Order Summary & Tickets": "", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "", + "What's Next?": "", + "Download Tickets:": "", + "Please download your tickets from the order summary page.": "", + "Prepare for the Event:": "", + "Make sure to note the event date, time, and location.": "", + "Stay Updated:": "", + "Keep an eye on your email for any updates from the event organizer.": "", + "Hi :name": "", + "Welcome to :appName! We're excited to have you aboard!": "", + "To get started and activate your account, please click the link below to confirm your email address:": "", + "Confirm Your Email": "", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "", + "Best Regards,": "", + "The :appName Team": "", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "", + "Confirm email change": "", + "If you did not request this change, please immediately change your password.": "", + "Thanks,": "", + "You've been invited to join :appName.": "", + "To accept the invitation, please click the link below:": "", + "Accept Invitation": "", + "All rights reserved.": "", + "Congratulations 🎉": "", + "Your order has been cancelled": "", + "You've received a refund": "", + "Your Order is Confirmed!": "", + "Password reset": "", + "Your password has been reset": "", + "You've been invited to join :appName": "", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/lang/fr.json b/backend/lang/fr.json new file mode 100644 index 00000000..b595de9b --- /dev/null +++ b/backend/lang/fr.json @@ -0,0 +1,263 @@ +{ + "Older First": "Plus ancien en premier", + "Newer First": "Plus récent en premier", + "Recently Updated First": "Récemment mis à jour en premier", + "Recently Updated Last": "Récemment mis à jour en dernier", + "First Name A-Z": "Prénom A-Z", + "First Name Z-A": "Prénom Z-A", + "Last Name A-Z": "Nom A-Z", + "Last Name Z-A": "Nom Z-A", + "Status A-Z": "Statut A-Z", + "Status Z-A": "Statut Z-A", + "Closest start date": "Date de début la plus proche", + "Furthest start date": "Date de début la plus éloignée", + "Closest end date": "Date de fin la plus proche", + "Furthest end date": "Date de fin la plus éloignée", + "Newest first": "Plus récent en premier", + "Oldest first": "Plus ancien en premier", + "Recently Updated": "Récemment mis à jour", + "Least Recently Updated": "Le moins récemment mis à jour", + "Oldest First": "Plus ancien en premier", + "Newest First": "Plus récent en premier", + "Buyer Name A-Z": "Nom de l'acheteur A-Z", + "Buyer Name Z-A": "Nom de l'acheteur Z-A", + "Amount Ascending": "Montant croissant", + "Amount Descending": "Montant décroissant", + "Buyer Email A-Z": "Email de l'acheteur A-Z", + "Buyer Email Z-A": "Email de l'acheteur Z-A", + "Order # Ascending": "Numéro de commande croissant", + "Order # Descending": "Numéro de commande décroissant", + "Code Name A-Z": "Nom de code A-Z", + "Code Name Z-A": "Nom de code Z-A", + "Usage Count Ascending": "Nombre d'utilisations croissant", + "Usage Count Descending": "Nombre d'utilisations décroissant", + "Homepage order": "Ordre de la page d'accueil", + "Title A-Z": "Titre A-Z", + "Title Z-A": "Titre Z-A", + "Sale start date closest": "Date de début de vente la plus proche", + "Sale start date furthest": "Date de début de vente la plus éloignée", + "Sale end date closest": "Date de fin de vente la plus proche", + "Sale end date furthest": "Date de fin de vente la plus éloignée", + "Account registration is disabled": "L'inscription au compte est désactivée", + "The invitation has expired": "L'invitation a expiré", + "The invitation is invalid": "L'invitation est invalide", + "Invitation valid, but user not found": "Invitation valide, mais utilisateur non trouvé", + "No user found for this invitation. The invitation may have been revoked.": "Aucun utilisateur trouvé pour cette invitation. L'invitation a peut-être été révoquée.", + "Logout Successful": "Déconnexion réussie", + "Your password has been reset. Please login with your new password.": "Votre mot de passe a été réinitialisé. Veuillez vous connecter avec votre nouveau mot de passe.", + "No account ID found in token": "Aucun identifiant de compte trouvé dans le jeton", + "Event with ID :eventId is not live and user is not authenticated": "L'événement avec l'ID :eventId n'est pas en direct et l'utilisateur n'est pas authentifié", + "Sorry, we could not verify your session. Please restart your order.": "Désolé, nous n'avons pas pu vérifier votre session. Veuillez recommencer votre commande.", + "The email confirmation link has expired. Please request a new one.": "Le lien de confirmation de l'email a expiré. Veuillez en demander un nouveau.", + "The email confirmation link is invalid.": "Le lien de confirmation de l'email est invalide.", + "No invitation found for this user.": "Aucune invitation trouvée pour cet utilisateur.", + "User status is not Invited": "Le statut de l'utilisateur n'est pas Invité", + "Email is required": "L'email est requis", + "Email must be a valid email address": "L'email doit être une adresse email valide", + "First name is required": "Le prénom est requis", + "Last name is required": "Le nom de famille est requis", + "Ticket is required": "Le billet est requis", + "Ticket price is required": "Le prix du billet est requis", + "Please enter a valid hex color code. In the format #000000 or #000.": "Veuillez entrer un code couleur hexadécimal valide. Au format #000000 ou #000.", + "The maximum timeout is 2 hours.": "Le délai maximum est de 2 heures.", + "The address line 1 field is required": "Le champ de l'adresse ligne 1 est requis", + "The city field is required": "Le champ de la ville est requis", + "The zip or postal code field is required": "Le champ du code postal est requis", + "The country field is required": "Le champ du pays est requis", + "The country field should be a 2 character ISO 3166 code": "Le champ du pays doit être un code ISO 3166 à 2 caractères", + "Please select at least one ticket.": "Veuillez sélectionner au moins un billet.", + "The sale end date must be after the sale start date.": "La date de fin de vente doit être après la date de début de vente.", + "The sale end date must be a valid date.": "La date de fin de vente doit être une date valide.", + "The sale start date must be after the ticket sale start date.": "La date de début de vente doit être après la date de début de vente des billets.", + "Welcome to :app_name! Please confirm your email address": "Bienvenue sur :app_name! Veuillez confirmer votre adresse email", + "🎟️ Your Ticket for :event": "🎟️ Votre billet pour :event", + "Your order wasn't successful": "Votre commande n'a pas abouti", + "We were unable to process your order": "Nous n'avons pas pu traiter votre commande", + "New order for :amount for :event 🎉": "Nouvelle commande de :amount pour :event 🎉", + "New order for :event 🎉": "Nouvelle commande pour :event 🎉", + "Current account ID is not set": "L'ID du compte actuel n'est pas défini", + "User not found in this account": "Utilisateur non trouvé dans ce compte", + "User not found": "Utilisateur non trouvé", + "Username or Password are incorrect": "Nom d'utilisateur ou mot de passe incorrect", + "Account not found": "Compte non trouvé", + "Attempt to log in to a non-active account": "Tentative de connexion à un compte non actif", + "User account is not active": "Le compte utilisateur n'est pas actif", + "Invalid reset token": "Jeton de réinitialisation invalide", + "Reset token has expired": "Le jeton de réinitialisation a expiré", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "Les statistiques quotidiennes de l'événement ont été mises à jour pour l'événement :event_id avec un montant total remboursé de :amount", + "Event statistics updated for event :event_id with total refunded amount of :amount": "Les statistiques de l'événement ont été mises à jour pour l'événement :event_id avec un montant total remboursé de :amount", + "This promo code is invalid": "Ce code promo est invalide", + "You haven't selected any tickets": "Vous n'avez sélectionné aucun billet", + "The maximum number of tickets available for :tickets is :max": "Le nombre maximum de billets disponibles pour :tickets est de :max", + "You must order at least :min tickets for :ticket": "Vous devez commander au moins :min billets pour :ticket", + "The minimum amount is :price": "Le montant minimum est de :price", + "The ticket :ticket is sold out": "Le billet :ticket est épuisé", + ":field must be specified": ":field doit être spécifié", + "Invalid price ID": "ID de prix invalide", + "The maximum number of tickets available for :ticket is :max": "Le nombre maximum de billets disponibles pour :ticket est de :max", + "Ticket with id :id not found": "Billet avec ID :id non trouvé", + "Failed to refund stripe charge": "Échec du remboursement de la charge stripe", + "Payment was successful, but order has expired. Order: :id": "Le paiement a été effectué avec succès, mais la commande a expiré. Commande : :id", + "Order is not awaiting payment. Order: :id": "La commande n'attend pas de paiement. Commande : :id", + "There was an error communicating with the payment provider. Please try again later.": "Une erreur est survenue lors de la communication avec le fournisseur de paiement. Veuillez réessayer plus tard.", + "Stripe Connect account not found for the event organizer": "Compte Stripe Connect non trouvé pour l'organisateur de l'événement", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "Impossible de rembourser : compte Stripe Connect non trouvé et saas_mode_enabled est activé", + "Invalid calculation type": "Type de calcul invalide", + "One or more tax IDs are invalid": "Un ou plusieurs IDs fiscaux sont invalides", + "Invalid ticket ids: :ids": "IDs de billets invalides : :ids", + "Cannot delete ticket price with id :id because it has sales": "Impossible de supprimer le prix du billet avec l'ID :id car il y a des ventes", + "Order has no order items": "La commande n'a pas d'articles", + "There is already an account associated with this email. Please log in instead.": "Il existe déjà un compte associé à cet email. Veuillez vous connecter à la place.", + "Stripe Connect Account creation is only available in Saas Mode.": "La création de compte Stripe Connect est uniquement disponible en mode Saas.", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "Il y a des problèmes lors de la création ou de la récupération du compte Stripe Connect. Veuillez réessayer.", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "Il y a des problèmes lors de la création du lien de compte Stripe Connect. Veuillez réessayer.", + "Cannot check in attendee as they are not active.": "Impossible d'enregistrer le participant car il n'est pas actif.", + "in": "entrée", + "out": "sortie", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "Il n'y a pas de billets disponibles. ' .\n 'Si vous souhaitez attribuer un billet à ce participant,' .\n ' veuillez ajuster la quantité de billets disponible.", + "The ticket price ID is invalid.": "L'ID du prix du billet est invalide.", + "Ticket ID is not valid": "L'ID du billet n'est pas valide", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "Il n'y a pas de billets disponibles. ' .\n 'Si vous souhaitez attribuer ce billet à ce participant,' .\n ' veuillez ajuster la quantité de billets disponible.", + "Attendee ID is not valid": "L'ID du participant n'est pas valide", + "The invitation does not exist": "L'invitation n'existe pas", + "The invitation has already been accepted": "L'invitation a déjà été acceptée", + "Organizer :id not found": "Organisateur :id non trouvé", + "Continue": "Continuer", + "Event :id not found": "Événement :id non trouvé", + "You cannot change the currency of an event that has completed orders": "Vous ne pouvez pas changer la devise d'un événement qui a des commandes terminées", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "Vous devez vérifier votre compte avant de pouvoir mettre à jour le statut d'un événement.\n Vous pouvez renvoyer la confirmation en visitant votre page de profil.", + "You cannot send messages until your account is verified.": "Vous ne pouvez pas envoyer de messages tant que votre compte n'est pas vérifié.", + "Order not found": "Commande non trouvée", + "Order already cancelled": "Commande déjà annulée", + "Failed to create attendee": "Échec de la création du participant", + "This order is has already been processed": "Cette commande a déjà été traitée", + "This order has expired": "Cette commande a expiré", + "This order has already been processed": "Cette commande a déjà été traitée", + "There is an unexpected ticket price ID in the order": "Il y a un ID de prix de billet inattendu dans la commande", + "This event is not live.": "Cet événement n'est pas en direct.", + "Sorry, we could not verify your session. Please create a new order.": "Désolé, nous n'avons pas pu vérifier votre session. Veuillez créer une nouvelle commande.", + "There is no Stripe data associated with this order.": "Il n'y a pas de données Stripe associées à cette commande.", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "Il y a déjà un remboursement en attente pour cette commande.\n Veuillez attendre que le remboursement soit traité avant d'en demander un autre.", + "Promo code :code already exists": "Le code promo :code existe déjà", + "The code :code is already in use for this event": "Le code :code est déjà utilisé pour cet événement", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "Vous ne pouvez pas supprimer cette question car des réponses y sont associées. Vous pouvez masquer la question à la place.", + "One or more of the ordered question IDs do not exist for the event.": "Un ou plusieurs des IDs de questions commandées n'existent pas pour l'événement.", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "Vous ne pouvez pas supprimer ce billet car il y a des commandes associées. Vous pouvez le masquer à la place.", + "Ticket type cannot be changed as tickets have been registered for this type": "Le type de billet ne peut pas être changé car des billets ont été enregistrés pour ce type", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "Les IDs de billets commandés doivent correspondre exactement à tous les billets de l'événement sans IDs manquants ou supplémentaires.", + "No email change pending": "Aucun changement d'email en attente", + "The email :email already exists on this account": "L'email :email existe déjà sur ce compte", + "You are not authorized to perform this action.": "Vous n'êtes pas autorisé à effectuer cette action.", + "Your account is not active.": "Votre compte n'est pas actif.", + "Payload has expired or is invalid.": "La charge utile a expiré ou est invalide.", + "Payload could not be decrypted.": "La charge utile n'a pas pu être décryptée.", + "Could not upload image to :disk. Check :disk is configured correctly": "Impossible de télécharger l'image sur :disk. Vérifiez que :disk est correctement configuré", + "Could not upload image": "Impossible de télécharger l'image", + "Length must be a positive integer.": "La longueur doit être un entier positif.", + "Prefix length exceeds the total desired token length.": "La longueur du préfixe dépasse la longueur totale souhaitée du jeton.", + "A valid email is required": "Un email valide est requis", + "The title field is required": "Le champ du titre est requis", + "The attribute name is required": "Le nom de l'attribut est requis", + "The attribute value is required": "La valeur de l'attribut est requise", + "The attribute is_public fields is required": "Le champ is_public de l'attribut est requis", + "Required questions have not been answered. You may need to reload the page.": "Les questions requises n'ont pas été répondues. Vous devrez peut-être recharger la page.", + "This question is outdated. Please reload the page.": "Cette question est obsolète. Veuillez recharger la page.", + "Please select an option": "Veuillez sélectionner une option", + "This field is required.": "Ce champ est requis.", + "This field must be less than 255 characters.": "Ce champ doit contenir moins de 255 caractères.", + "This field must be at least 2 characters.": "Ce champ doit contenir au moins 2 caractères.", + "Welcome to :appName! We're excited to have you aboard!": "Bienvenue sur :appName! Nous sommes ravis de vous avoir à bord!", + "To get started and activate your account, please click the link below to confirm your email address:": "Pour commencer et activer votre compte, veuillez cliquer sur le lien ci-dessous pour confirmer votre adresse email :", + "Confirm Your Email": "Confirmez votre email", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "Si vous n'avez pas créé de compte chez nous, aucune action supplémentaire n'est requise. Votre adresse email ne sera pas utilisée sans confirmation.", + "Best Regards,": "Cordialement,", + "The :appName Team": "L'équipe de :appName", + "All rights reserved.": "Tous droits réservés.", + "Congratulations 🎉": "Félicitations 🎉", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "Un remboursement est déjà en attente pour cette commande. Veuillez attendre que le remboursement soit traité avant d'en demander un autre.", + "Hello": "Bonjour", + "You have requested to reset your password for your account on :appName.": "Vous avez demandé à réinitialiser votre mot de passe pour votre compte sur :appName.", + "Please click the link below to reset your password.": "Veuillez cliquer sur le lien ci-dessous pour réinitialiser votre mot de passe.", + "Reset Password": "Réinitialiser le mot de passe", + "If you did not request a password reset, please ignore this email or reply to let us know.": "Si vous n'avez pas demandé de réinitialisation de mot de passe, veuillez ignorer cet e-mail ou répondre pour nous en informer.", + "Thank you": "Merci", + "Your password has been reset for your account on :appName.": "Votre mot de passe a été réinitialisé pour votre compte sur :appName.", + "If you did not request a password reset, please immediately contact reset your password.": "Si vous n'avez pas demandé de réinitialisation de mot de passe, veuillez immédiatement contacter la réinitialisation de votre mot de passe.", + "You are receiving this communication because you are registered as an attendee for the following event:": "Vous recevez cette communication parce que vous êtes inscrit en tant que participant à l'événement suivant :", + "If you believe you have received this email in error,": "Si vous pensez avoir reçu cet e-mail par erreur,", + "please contact the event organizer at": "veuillez contacter l'organisateur de l'événement à", + "If you believe this is spam, please report it to": "Si vous pensez qu'il s'agit d'un spam, veuillez le signaler à", + "You're going to": "Vous allez à", + "Please find your ticket details below.": "Veuillez trouver les détails de votre billet ci-dessous.", + "View Ticket": "Voir le billet", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "Si vous avez des questions ou besoin d'aide, veuillez répondre à cet e-mail ou contacter l'organisateur de l'événement", + "at": "à", + "Best regards,": "Cordialement,", + "Your order for": "Votre commande pour", + "has been cancelled.": "a été annulée.", + "Order #:": "Commande n° :", + "If you have any questions or need assistance, please respond to this email.": "Si vous avez des questions ou besoin d'aide, veuillez répondre à cet e-mail.", + "Your recent order for": "Votre commande récente pour", + "was not successful.": "n'a pas été réussie.", + "View Event Homepage": "Voir la page d'accueil de l'événement", + "If you have any questions or need assistance, feel free to reach out to our support team": "Si vous avez des questions ou besoin d'aide, n'hésitez pas à contacter notre équipe de support", + "Best regards": "Cordialement", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "Vous avez reçu un remboursement de :refundAmount pour l'événement suivant : :eventTitle.", + "You've received a new order!": "Vous avez reçu une nouvelle commande !", + "Congratulations! You've received a new order for ": "Félicitations ! Vous avez reçu une nouvelle commande pour ", + "Please find the details below.": "Veuillez trouver les détails ci-dessous.", + "Order Amount:": "Montant de la commande :", + "Order ID:": "ID de la commande :", + "View Order": "Voir la commande", + "Ticket": "Billet", + "Price": "Prix", + "Total": "Total", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "Votre commande récente pour :eventTitle n'a pas été réussie. La commande a expiré pendant que vous complétiez le paiement. Nous avons émis un remboursement pour la commande.", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "Nous nous excusons pour le désagrément. Si vous avez des questions ou besoin d'aide, n'hésitez pas à nous contacter à", + "View Event Page": "Voir la page de l'événement", + "Hi.Events": "Hi.Events", + "Your Order is Confirmed! ": "Votre commande est confirmée ! ", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "Félicitations ! Votre commande pour :eventTitle le :eventDate à :eventTime a été réussie. Veuillez trouver les détails de votre commande ci-dessous.", + "Event Details": "Détails de l'événement", + "Event Name:": "Nom de l'événement :", + "Date & Time:": "Date & Heure :", + "Order Summary": "Résumé de la commande", + "Order Number:": "Numéro de commande :", + "Total Amount:": "Montant total :", + "View Order Summary & Tickets": "Voir le résumé de la commande et les billets", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "Si vous avez des questions ou besoin d'aide, n'hésitez pas à contacter notre équipe de support amicale à", + "What's Next?": "Quelle est la suite ?", + "Download Tickets:": "Télécharger les billets :", + "Please download your tickets from the order summary page.": "Veuillez télécharger vos billets depuis la page de résumé de la commande.", + "Prepare for the Event:": "Préparez-vous pour l'événement :", + "Make sure to note the event date, time, and location.": "Assurez-vous de noter la date, l'heure et le lieu de l'événement.", + "Stay Updated:": "Restez informé :", + "Keep an eye on your email for any updates from the event organizer.": "Gardez un œil sur vos e-mails pour toute mise à jour de l'organisateur de l'événement.", + "Hi :name": "Bonjour :name", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "Vous avez demandé à changer votre adresse e-mail en :pendingEmail. Veuillez cliquer sur le lien ci-dessous pour confirmer ce changement.", + "Confirm email change": "Confirmer le changement d'adresse e-mail", + "If you did not request this change, please immediately change your password.": "Si vous n'avez pas demandé ce changement, veuillez immédiatement changer votre mot de passe.", + "Thanks,": "Merci,", + "You've been invited to join :appName.": "Vous avez été invité à rejoindre :appName.", + "To accept the invitation, please click the link below:": "Pour accepter l'invitation, veuillez cliquer sur le lien ci-dessous :", + "Accept Invitation": "Accepter l'invitation", + "Your order has been cancelled": "Votre commande a été annulée", + "You've received a refund": "Vous avez reçu un remboursement", + "Your Order is Confirmed!": "Votre commande est confirmée!", + "Password reset": "Réinitialisation du mot de passe", + "Your password has been reset": "Votre mot de passe a été réinitialisé", + "You've been invited to join :appName": "Vous avez été invité à rejoindre :appName", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/lang/pt-br.json b/backend/lang/pt-br.json new file mode 100644 index 00000000..b0eb7d3f --- /dev/null +++ b/backend/lang/pt-br.json @@ -0,0 +1,263 @@ +{ + "Older First": "", + "Newer First": "", + "Recently Updated First": "", + "Recently Updated Last": "", + "First Name A-Z": "", + "First Name Z-A": "", + "Last Name A-Z": "", + "Last Name Z-A": "", + "Status A-Z": "", + "Status Z-A": "", + "Closest start date": "", + "Furthest start date": "", + "Closest end date": "", + "Furthest end date": "", + "Newest first": "", + "Oldest first": "", + "Recently Updated": "", + "Least Recently Updated": "", + "Oldest First": "", + "Newest First": "", + "Buyer Name A-Z": "", + "Buyer Name Z-A": "", + "Amount Ascending": "", + "Amount Descending": "", + "Buyer Email A-Z": "", + "Buyer Email Z-A": "", + "Order # Ascending": "", + "Order # Descending": "", + "Code Name A-Z": "", + "Code Name Z-A": "", + "Usage Count Ascending": "", + "Usage Count Descending": "", + "Homepage order": "", + "Title A-Z": "", + "Title Z-A": "", + "Sale start date closest": "", + "Sale start date furthest": "", + "Sale end date closest": "", + "Sale end date furthest": "", + "Account registration is disabled": "", + "The invitation has expired": "", + "The invitation is invalid": "", + "Invitation valid, but user not found": "", + "No user found for this invitation. The invitation may have been revoked.": "", + "Logout Successful": "", + "Your password has been reset. Please login with your new password.": "", + "No account ID found in token": "", + "Event with ID :eventId is not live and user is not authenticated": "", + "Sorry, we could not verify your session. Please restart your order.": "", + "The email confirmation link has expired. Please request a new one.": "", + "The email confirmation link is invalid.": "", + "No invitation found for this user.": "", + "User status is not Invited": "", + "Email is required": "", + "Email must be a valid email address": "", + "First name is required": "", + "Last name is required": "", + "Ticket is required": "", + "Ticket price is required": "", + "Please enter a valid hex color code. In the format #000000 or #000.": "", + "The maximum timeout is 2 hours.": "", + "The address line 1 field is required": "", + "The city field is required": "", + "The zip or postal code field is required": "", + "The country field is required": "", + "The country field should be a 2 character ISO 3166 code": "", + "Please select at least one ticket.": "", + "The sale end date must be after the sale start date.": "", + "The sale end date must be a valid date.": "", + "The sale start date must be after the ticket sale start date.": "", + "Welcome to :app_name! Please confirm your email address": "", + "🎟️ Your Ticket for :event": "", + "Your order wasn't successful": "", + "We were unable to process your order": "", + "New order for :amount for :event 🎉": "", + "New order for :event 🎉": "", + "Current account ID is not set": "", + "User not found in this account": "", + "User not found": "", + "Username or Password are incorrect": "", + "Account not found": "", + "Attempt to log in to a non-active account": "", + "User account is not active": "", + "Invalid reset token": "", + "Reset token has expired": "", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "", + "Event statistics updated for event :event_id with total refunded amount of :amount": "", + "This promo code is invalid": "", + "You haven't selected any tickets": "", + "The maximum number of tickets available for :tickets is :max": "", + "You must order at least :min tickets for :ticket": "", + "The minimum amount is :price": "", + "The ticket :ticket is sold out": "", + ":field must be specified": "", + "Invalid price ID": "", + "The maximum number of tickets available for :ticket is :max": "", + "Ticket with id :id not found": "", + "Failed to refund stripe charge": "", + "Payment was successful, but order has expired. Order: :id": "", + "Order is not awaiting payment. Order: :id": "", + "There was an error communicating with the payment provider. Please try again later.": "", + "Stripe Connect account not found for the event organizer": "", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "", + "Invalid calculation type": "", + "One or more tax IDs are invalid": "", + "Invalid ticket ids: :ids": "", + "Cannot delete ticket price with id :id because it has sales": "", + "Order has no order items": "", + "There is already an account associated with this email. Please log in instead.": "", + "Stripe Connect Account creation is only available in Saas Mode.": "", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "", + "Cannot check in attendee as they are not active.": "", + "in": "", + "out": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "The ticket price ID is invalid.": "", + "Ticket ID is not valid": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "Attendee ID is not valid": "", + "The invitation does not exist": "", + "The invitation has already been accepted": "", + "Organizer :id not found": "", + "Continue": "", + "Event :id not found": "", + "You cannot change the currency of an event that has completed orders": "", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "", + "You cannot send messages until your account is verified.": "", + "Order not found": "", + "Order already cancelled": "", + "Failed to create attendee": "", + "This order is has already been processed": "", + "This order has expired": "", + "This order has already been processed": "", + "There is an unexpected ticket price ID in the order": "", + "This event is not live.": "", + "Sorry, we could not verify your session. Please create a new order.": "", + "There is no Stripe data associated with this order.": "", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "", + "Promo code :code already exists": "", + "The code :code is already in use for this event": "", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "", + "One or more of the ordered question IDs do not exist for the event.": "", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "", + "Ticket type cannot be changed as tickets have been registered for this type": "", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "", + "No email change pending": "", + "The email :email already exists on this account": "", + "You are not authorized to perform this action.": "", + "Your account is not active.": "", + "Payload has expired or is invalid.": "", + "Payload could not be decrypted.": "", + "Could not upload image to :disk. Check :disk is configured correctly": "", + "Could not upload image": "", + "Length must be a positive integer.": "", + "Prefix length exceeds the total desired token length.": "", + "A valid email is required": "", + "The title field is required": "", + "The attribute name is required": "", + "The attribute value is required": "", + "The attribute is_public fields is required": "", + "Required questions have not been answered. You may need to reload the page.": "", + "This question is outdated. Please reload the page.": "", + "Please select an option": "", + "This field is required.": "", + "This field must be less than 255 characters.": "", + "This field must be at least 2 characters.": "", + "Hello": "", + "You have requested to reset your password for your account on :appName.": "", + "Please click the link below to reset your password.": "", + "Reset Password": "", + "If you did not request a password reset, please ignore this email or reply to let us know.": "", + "Thank you": "", + "Your password has been reset for your account on :appName.": "", + "If you did not request a password reset, please immediately contact reset your password.": "", + "You are receiving this communication because you are registered as an attendee for the following event:": "", + "If you believe you have received this email in error,": "", + "please contact the event organizer at": "", + "If you believe this is spam, please report it to": "", + "You're going to": "", + "Please find your ticket details below.": "", + "View Ticket": "", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "", + "at": "", + "Best regards,": "", + "Your order for": "", + "has been cancelled.": "", + "Order #:": "", + "If you have any questions or need assistance, please respond to this email.": "", + "Your recent order for": "", + "was not successful.": "", + "View Event Homepage": "", + "If you have any questions or need assistance, feel free to reach out to our support team": "", + "Best regards": "", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "", + "You've received a new order!": "", + "Congratulations! You've received a new order for ": "", + "Please find the details below.": "", + "Order Amount:": "", + "Order ID:": "", + "View Order": "", + "Ticket": "", + "Price": "", + "Total": "", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "", + "View Event Page": "", + "Hi.Events": "", + "Your Order is Confirmed! ": "", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "", + "Event Details": "", + "Event Name:": "", + "Date & Time:": "", + "Order Summary": "", + "Order Number:": "", + "Total Amount:": "", + "View Order Summary & Tickets": "", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "", + "What's Next?": "", + "Download Tickets:": "", + "Please download your tickets from the order summary page.": "", + "Prepare for the Event:": "", + "Make sure to note the event date, time, and location.": "", + "Stay Updated:": "", + "Keep an eye on your email for any updates from the event organizer.": "", + "Hi :name": "", + "Welcome to :appName! We're excited to have you aboard!": "", + "To get started and activate your account, please click the link below to confirm your email address:": "", + "Confirm Your Email": "", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "", + "Best Regards,": "", + "The :appName Team": "", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "", + "Confirm email change": "", + "If you did not request this change, please immediately change your password.": "", + "Thanks,": "", + "You've been invited to join :appName.": "", + "To accept the invitation, please click the link below:": "", + "Accept Invitation": "", + "All rights reserved.": "", + "Congratulations 🎉": "", + "Your order has been cancelled": "", + "You've received a refund": "", + "Your Order is Confirmed!": "", + "Password reset": "", + "Your password has been reset": "", + "You've been invited to join :appName": "", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/lang/pt.json b/backend/lang/pt.json new file mode 100644 index 00000000..b0eb7d3f --- /dev/null +++ b/backend/lang/pt.json @@ -0,0 +1,263 @@ +{ + "Older First": "", + "Newer First": "", + "Recently Updated First": "", + "Recently Updated Last": "", + "First Name A-Z": "", + "First Name Z-A": "", + "Last Name A-Z": "", + "Last Name Z-A": "", + "Status A-Z": "", + "Status Z-A": "", + "Closest start date": "", + "Furthest start date": "", + "Closest end date": "", + "Furthest end date": "", + "Newest first": "", + "Oldest first": "", + "Recently Updated": "", + "Least Recently Updated": "", + "Oldest First": "", + "Newest First": "", + "Buyer Name A-Z": "", + "Buyer Name Z-A": "", + "Amount Ascending": "", + "Amount Descending": "", + "Buyer Email A-Z": "", + "Buyer Email Z-A": "", + "Order # Ascending": "", + "Order # Descending": "", + "Code Name A-Z": "", + "Code Name Z-A": "", + "Usage Count Ascending": "", + "Usage Count Descending": "", + "Homepage order": "", + "Title A-Z": "", + "Title Z-A": "", + "Sale start date closest": "", + "Sale start date furthest": "", + "Sale end date closest": "", + "Sale end date furthest": "", + "Account registration is disabled": "", + "The invitation has expired": "", + "The invitation is invalid": "", + "Invitation valid, but user not found": "", + "No user found for this invitation. The invitation may have been revoked.": "", + "Logout Successful": "", + "Your password has been reset. Please login with your new password.": "", + "No account ID found in token": "", + "Event with ID :eventId is not live and user is not authenticated": "", + "Sorry, we could not verify your session. Please restart your order.": "", + "The email confirmation link has expired. Please request a new one.": "", + "The email confirmation link is invalid.": "", + "No invitation found for this user.": "", + "User status is not Invited": "", + "Email is required": "", + "Email must be a valid email address": "", + "First name is required": "", + "Last name is required": "", + "Ticket is required": "", + "Ticket price is required": "", + "Please enter a valid hex color code. In the format #000000 or #000.": "", + "The maximum timeout is 2 hours.": "", + "The address line 1 field is required": "", + "The city field is required": "", + "The zip or postal code field is required": "", + "The country field is required": "", + "The country field should be a 2 character ISO 3166 code": "", + "Please select at least one ticket.": "", + "The sale end date must be after the sale start date.": "", + "The sale end date must be a valid date.": "", + "The sale start date must be after the ticket sale start date.": "", + "Welcome to :app_name! Please confirm your email address": "", + "🎟️ Your Ticket for :event": "", + "Your order wasn't successful": "", + "We were unable to process your order": "", + "New order for :amount for :event 🎉": "", + "New order for :event 🎉": "", + "Current account ID is not set": "", + "User not found in this account": "", + "User not found": "", + "Username or Password are incorrect": "", + "Account not found": "", + "Attempt to log in to a non-active account": "", + "User account is not active": "", + "Invalid reset token": "", + "Reset token has expired": "", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "", + "Event statistics updated for event :event_id with total refunded amount of :amount": "", + "This promo code is invalid": "", + "You haven't selected any tickets": "", + "The maximum number of tickets available for :tickets is :max": "", + "You must order at least :min tickets for :ticket": "", + "The minimum amount is :price": "", + "The ticket :ticket is sold out": "", + ":field must be specified": "", + "Invalid price ID": "", + "The maximum number of tickets available for :ticket is :max": "", + "Ticket with id :id not found": "", + "Failed to refund stripe charge": "", + "Payment was successful, but order has expired. Order: :id": "", + "Order is not awaiting payment. Order: :id": "", + "There was an error communicating with the payment provider. Please try again later.": "", + "Stripe Connect account not found for the event organizer": "", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "", + "Invalid calculation type": "", + "One or more tax IDs are invalid": "", + "Invalid ticket ids: :ids": "", + "Cannot delete ticket price with id :id because it has sales": "", + "Order has no order items": "", + "There is already an account associated with this email. Please log in instead.": "", + "Stripe Connect Account creation is only available in Saas Mode.": "", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "", + "Cannot check in attendee as they are not active.": "", + "in": "", + "out": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "The ticket price ID is invalid.": "", + "Ticket ID is not valid": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "Attendee ID is not valid": "", + "The invitation does not exist": "", + "The invitation has already been accepted": "", + "Organizer :id not found": "", + "Continue": "", + "Event :id not found": "", + "You cannot change the currency of an event that has completed orders": "", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "", + "You cannot send messages until your account is verified.": "", + "Order not found": "", + "Order already cancelled": "", + "Failed to create attendee": "", + "This order is has already been processed": "", + "This order has expired": "", + "This order has already been processed": "", + "There is an unexpected ticket price ID in the order": "", + "This event is not live.": "", + "Sorry, we could not verify your session. Please create a new order.": "", + "There is no Stripe data associated with this order.": "", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "", + "Promo code :code already exists": "", + "The code :code is already in use for this event": "", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "", + "One or more of the ordered question IDs do not exist for the event.": "", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "", + "Ticket type cannot be changed as tickets have been registered for this type": "", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "", + "No email change pending": "", + "The email :email already exists on this account": "", + "You are not authorized to perform this action.": "", + "Your account is not active.": "", + "Payload has expired or is invalid.": "", + "Payload could not be decrypted.": "", + "Could not upload image to :disk. Check :disk is configured correctly": "", + "Could not upload image": "", + "Length must be a positive integer.": "", + "Prefix length exceeds the total desired token length.": "", + "A valid email is required": "", + "The title field is required": "", + "The attribute name is required": "", + "The attribute value is required": "", + "The attribute is_public fields is required": "", + "Required questions have not been answered. You may need to reload the page.": "", + "This question is outdated. Please reload the page.": "", + "Please select an option": "", + "This field is required.": "", + "This field must be less than 255 characters.": "", + "This field must be at least 2 characters.": "", + "Hello": "", + "You have requested to reset your password for your account on :appName.": "", + "Please click the link below to reset your password.": "", + "Reset Password": "", + "If you did not request a password reset, please ignore this email or reply to let us know.": "", + "Thank you": "", + "Your password has been reset for your account on :appName.": "", + "If you did not request a password reset, please immediately contact reset your password.": "", + "You are receiving this communication because you are registered as an attendee for the following event:": "", + "If you believe you have received this email in error,": "", + "please contact the event organizer at": "", + "If you believe this is spam, please report it to": "", + "You're going to": "", + "Please find your ticket details below.": "", + "View Ticket": "", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "", + "at": "", + "Best regards,": "", + "Your order for": "", + "has been cancelled.": "", + "Order #:": "", + "If you have any questions or need assistance, please respond to this email.": "", + "Your recent order for": "", + "was not successful.": "", + "View Event Homepage": "", + "If you have any questions or need assistance, feel free to reach out to our support team": "", + "Best regards": "", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "", + "You've received a new order!": "", + "Congratulations! You've received a new order for ": "", + "Please find the details below.": "", + "Order Amount:": "", + "Order ID:": "", + "View Order": "", + "Ticket": "", + "Price": "", + "Total": "", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "", + "View Event Page": "", + "Hi.Events": "", + "Your Order is Confirmed! ": "", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "", + "Event Details": "", + "Event Name:": "", + "Date & Time:": "", + "Order Summary": "", + "Order Number:": "", + "Total Amount:": "", + "View Order Summary & Tickets": "", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "", + "What's Next?": "", + "Download Tickets:": "", + "Please download your tickets from the order summary page.": "", + "Prepare for the Event:": "", + "Make sure to note the event date, time, and location.": "", + "Stay Updated:": "", + "Keep an eye on your email for any updates from the event organizer.": "", + "Hi :name": "", + "Welcome to :appName! We're excited to have you aboard!": "", + "To get started and activate your account, please click the link below to confirm your email address:": "", + "Confirm Your Email": "", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "", + "Best Regards,": "", + "The :appName Team": "", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "", + "Confirm email change": "", + "If you did not request this change, please immediately change your password.": "", + "Thanks,": "", + "You've been invited to join :appName.": "", + "To accept the invitation, please click the link below:": "", + "Accept Invitation": "", + "All rights reserved.": "", + "Congratulations 🎉": "", + "Your order has been cancelled": "", + "You've received a refund": "", + "Your Order is Confirmed!": "", + "Password reset": "", + "Your password has been reset": "", + "You've been invited to join :appName": "", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/lang/ru.json b/backend/lang/ru.json new file mode 100644 index 00000000..b0eb7d3f --- /dev/null +++ b/backend/lang/ru.json @@ -0,0 +1,263 @@ +{ + "Older First": "", + "Newer First": "", + "Recently Updated First": "", + "Recently Updated Last": "", + "First Name A-Z": "", + "First Name Z-A": "", + "Last Name A-Z": "", + "Last Name Z-A": "", + "Status A-Z": "", + "Status Z-A": "", + "Closest start date": "", + "Furthest start date": "", + "Closest end date": "", + "Furthest end date": "", + "Newest first": "", + "Oldest first": "", + "Recently Updated": "", + "Least Recently Updated": "", + "Oldest First": "", + "Newest First": "", + "Buyer Name A-Z": "", + "Buyer Name Z-A": "", + "Amount Ascending": "", + "Amount Descending": "", + "Buyer Email A-Z": "", + "Buyer Email Z-A": "", + "Order # Ascending": "", + "Order # Descending": "", + "Code Name A-Z": "", + "Code Name Z-A": "", + "Usage Count Ascending": "", + "Usage Count Descending": "", + "Homepage order": "", + "Title A-Z": "", + "Title Z-A": "", + "Sale start date closest": "", + "Sale start date furthest": "", + "Sale end date closest": "", + "Sale end date furthest": "", + "Account registration is disabled": "", + "The invitation has expired": "", + "The invitation is invalid": "", + "Invitation valid, but user not found": "", + "No user found for this invitation. The invitation may have been revoked.": "", + "Logout Successful": "", + "Your password has been reset. Please login with your new password.": "", + "No account ID found in token": "", + "Event with ID :eventId is not live and user is not authenticated": "", + "Sorry, we could not verify your session. Please restart your order.": "", + "The email confirmation link has expired. Please request a new one.": "", + "The email confirmation link is invalid.": "", + "No invitation found for this user.": "", + "User status is not Invited": "", + "Email is required": "", + "Email must be a valid email address": "", + "First name is required": "", + "Last name is required": "", + "Ticket is required": "", + "Ticket price is required": "", + "Please enter a valid hex color code. In the format #000000 or #000.": "", + "The maximum timeout is 2 hours.": "", + "The address line 1 field is required": "", + "The city field is required": "", + "The zip or postal code field is required": "", + "The country field is required": "", + "The country field should be a 2 character ISO 3166 code": "", + "Please select at least one ticket.": "", + "The sale end date must be after the sale start date.": "", + "The sale end date must be a valid date.": "", + "The sale start date must be after the ticket sale start date.": "", + "Welcome to :app_name! Please confirm your email address": "", + "🎟️ Your Ticket for :event": "", + "Your order wasn't successful": "", + "We were unable to process your order": "", + "New order for :amount for :event 🎉": "", + "New order for :event 🎉": "", + "Current account ID is not set": "", + "User not found in this account": "", + "User not found": "", + "Username or Password are incorrect": "", + "Account not found": "", + "Attempt to log in to a non-active account": "", + "User account is not active": "", + "Invalid reset token": "", + "Reset token has expired": "", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "", + "Event statistics updated for event :event_id with total refunded amount of :amount": "", + "This promo code is invalid": "", + "You haven't selected any tickets": "", + "The maximum number of tickets available for :tickets is :max": "", + "You must order at least :min tickets for :ticket": "", + "The minimum amount is :price": "", + "The ticket :ticket is sold out": "", + ":field must be specified": "", + "Invalid price ID": "", + "The maximum number of tickets available for :ticket is :max": "", + "Ticket with id :id not found": "", + "Failed to refund stripe charge": "", + "Payment was successful, but order has expired. Order: :id": "", + "Order is not awaiting payment. Order: :id": "", + "There was an error communicating with the payment provider. Please try again later.": "", + "Stripe Connect account not found for the event organizer": "", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "", + "Invalid calculation type": "", + "One or more tax IDs are invalid": "", + "Invalid ticket ids: :ids": "", + "Cannot delete ticket price with id :id because it has sales": "", + "Order has no order items": "", + "There is already an account associated with this email. Please log in instead.": "", + "Stripe Connect Account creation is only available in Saas Mode.": "", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "", + "Cannot check in attendee as they are not active.": "", + "in": "", + "out": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "The ticket price ID is invalid.": "", + "Ticket ID is not valid": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "Attendee ID is not valid": "", + "The invitation does not exist": "", + "The invitation has already been accepted": "", + "Organizer :id not found": "", + "Continue": "", + "Event :id not found": "", + "You cannot change the currency of an event that has completed orders": "", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "", + "You cannot send messages until your account is verified.": "", + "Order not found": "", + "Order already cancelled": "", + "Failed to create attendee": "", + "This order is has already been processed": "", + "This order has expired": "", + "This order has already been processed": "", + "There is an unexpected ticket price ID in the order": "", + "This event is not live.": "", + "Sorry, we could not verify your session. Please create a new order.": "", + "There is no Stripe data associated with this order.": "", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "", + "Promo code :code already exists": "", + "The code :code is already in use for this event": "", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "", + "One or more of the ordered question IDs do not exist for the event.": "", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "", + "Ticket type cannot be changed as tickets have been registered for this type": "", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "", + "No email change pending": "", + "The email :email already exists on this account": "", + "You are not authorized to perform this action.": "", + "Your account is not active.": "", + "Payload has expired or is invalid.": "", + "Payload could not be decrypted.": "", + "Could not upload image to :disk. Check :disk is configured correctly": "", + "Could not upload image": "", + "Length must be a positive integer.": "", + "Prefix length exceeds the total desired token length.": "", + "A valid email is required": "", + "The title field is required": "", + "The attribute name is required": "", + "The attribute value is required": "", + "The attribute is_public fields is required": "", + "Required questions have not been answered. You may need to reload the page.": "", + "This question is outdated. Please reload the page.": "", + "Please select an option": "", + "This field is required.": "", + "This field must be less than 255 characters.": "", + "This field must be at least 2 characters.": "", + "Hello": "", + "You have requested to reset your password for your account on :appName.": "", + "Please click the link below to reset your password.": "", + "Reset Password": "", + "If you did not request a password reset, please ignore this email or reply to let us know.": "", + "Thank you": "", + "Your password has been reset for your account on :appName.": "", + "If you did not request a password reset, please immediately contact reset your password.": "", + "You are receiving this communication because you are registered as an attendee for the following event:": "", + "If you believe you have received this email in error,": "", + "please contact the event organizer at": "", + "If you believe this is spam, please report it to": "", + "You're going to": "", + "Please find your ticket details below.": "", + "View Ticket": "", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "", + "at": "", + "Best regards,": "", + "Your order for": "", + "has been cancelled.": "", + "Order #:": "", + "If you have any questions or need assistance, please respond to this email.": "", + "Your recent order for": "", + "was not successful.": "", + "View Event Homepage": "", + "If you have any questions or need assistance, feel free to reach out to our support team": "", + "Best regards": "", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "", + "You've received a new order!": "", + "Congratulations! You've received a new order for ": "", + "Please find the details below.": "", + "Order Amount:": "", + "Order ID:": "", + "View Order": "", + "Ticket": "", + "Price": "", + "Total": "", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "", + "View Event Page": "", + "Hi.Events": "", + "Your Order is Confirmed! ": "", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "", + "Event Details": "", + "Event Name:": "", + "Date & Time:": "", + "Order Summary": "", + "Order Number:": "", + "Total Amount:": "", + "View Order Summary & Tickets": "", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "", + "What's Next?": "", + "Download Tickets:": "", + "Please download your tickets from the order summary page.": "", + "Prepare for the Event:": "", + "Make sure to note the event date, time, and location.": "", + "Stay Updated:": "", + "Keep an eye on your email for any updates from the event organizer.": "", + "Hi :name": "", + "Welcome to :appName! We're excited to have you aboard!": "", + "To get started and activate your account, please click the link below to confirm your email address:": "", + "Confirm Your Email": "", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "", + "Best Regards,": "", + "The :appName Team": "", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "", + "Confirm email change": "", + "If you did not request this change, please immediately change your password.": "", + "Thanks,": "", + "You've been invited to join :appName.": "", + "To accept the invitation, please click the link below:": "", + "Accept Invitation": "", + "All rights reserved.": "", + "Congratulations 🎉": "", + "Your order has been cancelled": "", + "You've received a refund": "", + "Your Order is Confirmed!": "", + "Password reset": "", + "Your password has been reset": "", + "You've been invited to join :appName": "", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/lang/zh-cn.json b/backend/lang/zh-cn.json new file mode 100644 index 00000000..b0eb7d3f --- /dev/null +++ b/backend/lang/zh-cn.json @@ -0,0 +1,263 @@ +{ + "Older First": "", + "Newer First": "", + "Recently Updated First": "", + "Recently Updated Last": "", + "First Name A-Z": "", + "First Name Z-A": "", + "Last Name A-Z": "", + "Last Name Z-A": "", + "Status A-Z": "", + "Status Z-A": "", + "Closest start date": "", + "Furthest start date": "", + "Closest end date": "", + "Furthest end date": "", + "Newest first": "", + "Oldest first": "", + "Recently Updated": "", + "Least Recently Updated": "", + "Oldest First": "", + "Newest First": "", + "Buyer Name A-Z": "", + "Buyer Name Z-A": "", + "Amount Ascending": "", + "Amount Descending": "", + "Buyer Email A-Z": "", + "Buyer Email Z-A": "", + "Order # Ascending": "", + "Order # Descending": "", + "Code Name A-Z": "", + "Code Name Z-A": "", + "Usage Count Ascending": "", + "Usage Count Descending": "", + "Homepage order": "", + "Title A-Z": "", + "Title Z-A": "", + "Sale start date closest": "", + "Sale start date furthest": "", + "Sale end date closest": "", + "Sale end date furthest": "", + "Account registration is disabled": "", + "The invitation has expired": "", + "The invitation is invalid": "", + "Invitation valid, but user not found": "", + "No user found for this invitation. The invitation may have been revoked.": "", + "Logout Successful": "", + "Your password has been reset. Please login with your new password.": "", + "No account ID found in token": "", + "Event with ID :eventId is not live and user is not authenticated": "", + "Sorry, we could not verify your session. Please restart your order.": "", + "The email confirmation link has expired. Please request a new one.": "", + "The email confirmation link is invalid.": "", + "No invitation found for this user.": "", + "User status is not Invited": "", + "Email is required": "", + "Email must be a valid email address": "", + "First name is required": "", + "Last name is required": "", + "Ticket is required": "", + "Ticket price is required": "", + "Please enter a valid hex color code. In the format #000000 or #000.": "", + "The maximum timeout is 2 hours.": "", + "The address line 1 field is required": "", + "The city field is required": "", + "The zip or postal code field is required": "", + "The country field is required": "", + "The country field should be a 2 character ISO 3166 code": "", + "Please select at least one ticket.": "", + "The sale end date must be after the sale start date.": "", + "The sale end date must be a valid date.": "", + "The sale start date must be after the ticket sale start date.": "", + "Welcome to :app_name! Please confirm your email address": "", + "🎟️ Your Ticket for :event": "", + "Your order wasn't successful": "", + "We were unable to process your order": "", + "New order for :amount for :event 🎉": "", + "New order for :event 🎉": "", + "Current account ID is not set": "", + "User not found in this account": "", + "User not found": "", + "Username or Password are incorrect": "", + "Account not found": "", + "Attempt to log in to a non-active account": "", + "User account is not active": "", + "Invalid reset token": "", + "Reset token has expired": "", + "Event daily statistics updated for event :event_id with total refunded amount of :amount": "", + "Event statistics updated for event :event_id with total refunded amount of :amount": "", + "This promo code is invalid": "", + "You haven't selected any tickets": "", + "The maximum number of tickets available for :tickets is :max": "", + "You must order at least :min tickets for :ticket": "", + "The minimum amount is :price": "", + "The ticket :ticket is sold out": "", + ":field must be specified": "", + "Invalid price ID": "", + "The maximum number of tickets available for :ticket is :max": "", + "Ticket with id :id not found": "", + "Failed to refund stripe charge": "", + "Payment was successful, but order has expired. Order: :id": "", + "Order is not awaiting payment. Order: :id": "", + "There was an error communicating with the payment provider. Please try again later.": "", + "Stripe Connect account not found for the event organizer": "", + "Cannot Refund: Stripe connect account not found and saas_mode_enabled is enabled": "", + "Invalid calculation type": "", + "One or more tax IDs are invalid": "", + "Invalid ticket ids: :ids": "", + "Cannot delete ticket price with id :id because it has sales": "", + "Order has no order items": "", + "There is already an account associated with this email. Please log in instead.": "", + "Stripe Connect Account creation is only available in Saas Mode.": "", + "There are issues with creating or fetching the Stripe Connect Account. Please try again.": "", + "There are issues with creating the Stripe Connect Account Link. Please try again.": "", + "Cannot check in attendee as they are not active.": "", + "in": "", + "out": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "The ticket price ID is invalid.": "", + "Ticket ID is not valid": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket's available quantity.": "", + "Attendee ID is not valid": "", + "The invitation does not exist": "", + "The invitation has already been accepted": "", + "Organizer :id not found": "", + "Continue": "", + "Event :id not found": "", + "You cannot change the currency of an event that has completed orders": "", + "You must verify your account before you can update an event's status.\n You can resend the confirmation by visiting your profile page.": "", + "You cannot send messages until your account is verified.": "", + "Order not found": "", + "Order already cancelled": "", + "Failed to create attendee": "", + "This order is has already been processed": "", + "This order has expired": "", + "This order has already been processed": "", + "There is an unexpected ticket price ID in the order": "", + "This event is not live.": "", + "Sorry, we could not verify your session. Please create a new order.": "", + "There is no Stripe data associated with this order.": "", + "There is already a refund pending for this order. '\n . 'Please wait for the refund to be processed before requesting another one.": "", + "Promo code :code already exists": "", + "The code :code is already in use for this event": "", + "You cannot delete this question as there as answers associated with it. You can hide the question instead.": "", + "One or more of the ordered question IDs do not exist for the event.": "", + "You cannot delete this ticket because it has orders associated with it. You can hide it instead.": "", + "Ticket type cannot be changed as tickets have been registered for this type": "", + "The ordered ticket IDs must exactly match all tickets for the event without missing or extra IDs.": "", + "No email change pending": "", + "The email :email already exists on this account": "", + "You are not authorized to perform this action.": "", + "Your account is not active.": "", + "Payload has expired or is invalid.": "", + "Payload could not be decrypted.": "", + "Could not upload image to :disk. Check :disk is configured correctly": "", + "Could not upload image": "", + "Length must be a positive integer.": "", + "Prefix length exceeds the total desired token length.": "", + "A valid email is required": "", + "The title field is required": "", + "The attribute name is required": "", + "The attribute value is required": "", + "The attribute is_public fields is required": "", + "Required questions have not been answered. You may need to reload the page.": "", + "This question is outdated. Please reload the page.": "", + "Please select an option": "", + "This field is required.": "", + "This field must be less than 255 characters.": "", + "This field must be at least 2 characters.": "", + "Hello": "", + "You have requested to reset your password for your account on :appName.": "", + "Please click the link below to reset your password.": "", + "Reset Password": "", + "If you did not request a password reset, please ignore this email or reply to let us know.": "", + "Thank you": "", + "Your password has been reset for your account on :appName.": "", + "If you did not request a password reset, please immediately contact reset your password.": "", + "You are receiving this communication because you are registered as an attendee for the following event:": "", + "If you believe you have received this email in error,": "", + "please contact the event organizer at": "", + "If you believe this is spam, please report it to": "", + "You're going to": "", + "Please find your ticket details below.": "", + "View Ticket": "", + "If you have any questions or need assistance, please reply to this email or contact the event organizer": "", + "at": "", + "Best regards,": "", + "Your order for": "", + "has been cancelled.": "", + "Order #:": "", + "If you have any questions or need assistance, please respond to this email.": "", + "Your recent order for": "", + "was not successful.": "", + "View Event Homepage": "", + "If you have any questions or need assistance, feel free to reach out to our support team": "", + "Best regards": "", + "You have received a refund of :refundAmount for the following event: :eventTitle.": "", + "You've received a new order!": "", + "Congratulations! You've received a new order for ": "", + "Please find the details below.": "", + "Order Amount:": "", + "Order ID:": "", + "View Order": "", + "Ticket": "", + "Price": "", + "Total": "", + "Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.": "", + "We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at": "", + "View Event Page": "", + "Hi.Events": "", + "Your Order is Confirmed! ": "", + "Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.": "", + "Event Details": "", + "Event Name:": "", + "Date & Time:": "", + "Order Summary": "", + "Order Number:": "", + "Total Amount:": "", + "View Order Summary & Tickets": "", + "If you have any questions or need assistance, feel free to reach out to our friendly support team at": "", + "What's Next?": "", + "Download Tickets:": "", + "Please download your tickets from the order summary page.": "", + "Prepare for the Event:": "", + "Make sure to note the event date, time, and location.": "", + "Stay Updated:": "", + "Keep an eye on your email for any updates from the event organizer.": "", + "Hi :name": "", + "Welcome to :appName! We're excited to have you aboard!": "", + "To get started and activate your account, please click the link below to confirm your email address:": "", + "Confirm Your Email": "", + "If you did not create an account with us, no further action is required. Your email address will not be used without confirmation.": "", + "Best Regards,": "", + "The :appName Team": "", + "You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.": "", + "Confirm email change": "", + "If you did not request this change, please immediately change your password.": "", + "Thanks,": "", + "You've been invited to join :appName.": "", + "To accept the invitation, please click the link below:": "", + "Accept Invitation": "", + "All rights reserved.": "", + "Congratulations 🎉": "", + "Your order has been cancelled": "", + "You've received a refund": "", + "Your Order is Confirmed!": "", + "Password reset": "", + "Your password has been reset": "", + "You've been invited to join :appName": "", + "There is already a refund pending for this order.\n Please wait for the refund to be processed before requesting another one.": "", + "Your order wasn\\'t successful": "", + "You\\'ve received a refund": "", + "You\\'ve been invited to join :appName": "", + "You haven\\'t selected any tickets": "", + "There are no tickets available. ' .\n 'If you would like to assign a ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "There are no tickets available. ' .\n 'If you would like to assign this ticket to this attendee,' .\n ' please adjust the ticket\\'s available quantity.": "", + "You must verify your account before you can update an event\\'s status.\n You can resend the confirmation by visiting your profile page.": "", + "You\\'re going to": "", + "You\\'ve received a new order!": "", + "Congratulations! You\\'ve received a new order for ": "", + "What\\'s Next?": "", + "Welcome to :appName! We\\'re excited to have you aboard!": "", + "You\\'ve been invited to join :appName.": "" +} \ No newline at end of file diff --git a/backend/resources/views/emails/auth/forgot-password.blade.php b/backend/resources/views/emails/auth/forgot-password.blade.php index b9594b88..d16f983c 100644 --- a/backend/resources/views/emails/auth/forgot-password.blade.php +++ b/backend/resources/views/emails/auth/forgot-password.blade.php @@ -2,16 +2,16 @@ @php /** @var string $link */ @endphp -Hello, +{{ __('Hello') }}, -You have requested to reset your password for your account on {{ config('app.name') }}. +{{ __('You have requested to reset your password for your account on :appName.', ['appName' => config('app.name')]) }} -Please click the link below to reset your password. +{{ __('Please click the link below to reset your password.') }} -Reset Password +{{ __('Reset Password') }} -If you did not request a password reset, please ignore this email or reply to let us know. +{{ __('If you did not request a password reset, please ignore this email or reply to let us know.') }} -Thank you +{{ __('Thank you') }} diff --git a/backend/resources/views/emails/auth/reset-password-success.blade.php b/backend/resources/views/emails/auth/reset-password-success.blade.php index d89eca7c..147b84c1 100644 --- a/backend/resources/views/emails/auth/reset-password-success.blade.php +++ b/backend/resources/views/emails/auth/reset-password-success.blade.php @@ -1,9 +1,15 @@ -Hello, +{{ __('Hello') }}, -Your password has been reset for your account on {{ config('app.name') }}. +{{ __('Your password has been reset for your account on :appName.', ['appName' => config('app.name')]) }} -If you did not request a password reset, please immediately contact reset your password. +{{ __('If you did not request a password reset, please immediately contact reset your password.') }} -Thank you +{{ __('Thank you') }} + + + + + + diff --git a/backend/resources/views/emails/event/message.blade.php b/backend/resources/views/emails/event/message.blade.php index 53934ff1..867fa948 100644 --- a/backend/resources/views/emails/event/message.blade.php +++ b/backend/resources/views/emails/event/message.blade.php @@ -10,11 +10,10 @@ {!! $eventSettings->getGetEmailFooterHtml() !!}
- You are receiving this communication because you are registered as an attendee for the following event: - {{ $event->getTitle() }}. If you believe you have received this email in error, - please contact the event organizer at {{$eventSettings->getSupportEmail()}}. - If you believe this is spam, please report it to {{config('mail.from.address')}}. +{{ __('You are receiving this communication because you are registered as an attendee for the following event:') }} +{{ $event->getTitle() }}. {{ __('If you believe you have received this email in error,') }} +{{ __('please contact the event organizer at') }} {{$eventSettings->getSupportEmail()}}. +{{ __('If you believe this is spam, please report it to') }} {{config('mail.from.address')}}.
- diff --git a/backend/resources/views/emails/orders/attendee-ticket.blade.php b/backend/resources/views/emails/orders/attendee-ticket.blade.php index 1579bf82..2f9d4f5e 100644 --- a/backend/resources/views/emails/orders/attendee-ticket.blade.php +++ b/backend/resources/views/emails/orders/attendee-ticket.blade.php @@ -6,20 +6,20 @@ @php /** @see \HiEvents\Mail\Attendee\AttendeeTicketMail */ @endphp -# You're going to {{ $event->getTitle() }}! 🎉 +# {{ __('You\'re going to') }} {{ $event->getTitle() }}! 🎉

-Please find your ticket details below. +{{ __('Please find your ticket details below.') }} - View Ticket +{{ __('View Ticket') }} -If you have any questions or need assistance, please reply to this email or contact the event organizer -at {{$eventSettings->getSupportEmail()}}. +{{ __('If you have any questions or need assistance, please reply to this email or contact the event organizer') }} +{{ __('at') }} {{$eventSettings->getSupportEmail()}}. -Best regards, +{{ __('Best regards,') }}
{{config('app.name')}}
diff --git a/backend/resources/views/emails/orders/order-cancelled.blade.php b/backend/resources/views/emails/orders/order-cancelled.blade.php index e7e1cc92..ea51ad40 100644 --- a/backend/resources/views/emails/orders/order-cancelled.blade.php +++ b/backend/resources/views/emails/orders/order-cancelled.blade.php @@ -6,19 +6,18 @@ @php /** @see \HiEvents\Mail\Order\OrderCancelled */ @endphp -Hello, +{{ __('Hello') }}, -Your order for {{$event->getTitle()}} has been cancelled. +{{ __('Your order for') }} {{$event->getTitle()}} {{ __('has been cancelled.') }}

-Order #: {{$order->getPublicId()}} +{{ __('Order #:') }} {{$order->getPublicId()}}

-If you have any questions or need assistance, please respond to this email. +{{ __('If you have any questions or need assistance, please respond to this email.') }}

-Thank you,
+{{ __('Thank you') }},
{{config('app.name')}} {!! $eventSettings->getGetEmailFooterHtml() !!} -
diff --git a/backend/resources/views/emails/orders/order-failed.blade.php b/backend/resources/views/emails/orders/order-failed.blade.php index 27b8b7ab..0e54cd66 100644 --- a/backend/resources/views/emails/orders/order-failed.blade.php +++ b/backend/resources/views/emails/orders/order-failed.blade.php @@ -6,21 +6,20 @@ @php /** @see \HiEvents\Mail\Order\OrderFailed */ @endphp -Hello, +{{ __('Hello') }}, -Your recent order for {{$event->getTitle()}} was not successful. +{{ __('Your recent order for') }} {{$event->getTitle()}} {{ __('was not successful.') }} - View Event Homepage +{{ __('View Event Homepage') }} -If you have any questions or need assistance, feel free to reach out to our support team -at {{ $supportEmail ?? 'hello@hi.events' }}. +{{ __('If you have any questions or need assistance, feel free to reach out to our support team') }} +{{ __('at') }} {{ $supportEmail ?? 'hello@hi.events' }}. -Best regards, +{{ __('Best regards') }},
{{config('app.name')}} - {!! $eventSettings->getGetEmailFooterHtml() !!}
diff --git a/backend/resources/views/emails/orders/order-refunded.blade.php b/backend/resources/views/emails/orders/order-refunded.blade.php index 48062335..e10e15f5 100644 --- a/backend/resources/views/emails/orders/order-refunded.blade.php +++ b/backend/resources/views/emails/orders/order-refunded.blade.php @@ -6,12 +6,11 @@ @php /** @see \HiEvents\Mail\Order\OrderRefunded */ @endphp -Hello, +{{ __('Hello') }}, -You have received a refund of {{$refundAmount}} for the following event: {{$event->getTitle()}}. +{{ __('You have received a refund of :refundAmount for the following event: :eventTitle.', ['refundAmount' => $refundAmount, 'eventTitle' => $event->getTitle()]) }} -Thank you +{{ __('Thank you') }} {!! $eventSettings->getGetEmailFooterHtml() !!} - diff --git a/backend/resources/views/emails/orders/organizer/summary-for-organizer.blade.php b/backend/resources/views/emails/orders/organizer/summary-for-organizer.blade.php index c594b223..dbfa0311 100644 --- a/backend/resources/views/emails/orders/organizer/summary-for-organizer.blade.php +++ b/backend/resources/views/emails/orders/organizer/summary-for-organizer.blade.php @@ -5,29 +5,28 @@ @php /** @var \HiEvents\DomainObjects\EventDomainObject $event */ @endphp -# You've received a new order! 🎉 +# {{ __('You\'ve received a new order!') }} 🎉
-Congratulations! You've got a new order for {{ $event->getTitle() }}! Please find the details below. +{{ __('Congratulations! You\'ve received a new order for ') }} {{ $event->getTitle() }}! {{ __('Please find the details below.') }}

-Order Amount: {{ Currency::format($order->getTotalGross(), $event->getCurrency()) }}
-Order ID: {{ $order->getPublicId() }} +{{ __('Order Amount:') }} {{ Currency::format($order->getTotalGross(), $event->getCurrency()) }}
+{{ __('Order ID:') }} {{ $order->getPublicId() }}
- View Order + {{ __('View Order') }} -
- - - + + + @@ -41,7 +40,7 @@ @endforeach
TicketPriceTotal{{ __('Ticket') }}{{ __('Price') }}{{ __('Total') }}
- Total + {{ __('Total') }} {{ Currency::format($order->getTotalGross(), $event->getCurrency()) }} @@ -51,7 +50,13 @@
-Best regards, +{{ __('Best regards') }},
{{config('app.name')}}
+ + + + + + diff --git a/backend/resources/views/emails/orders/payment-success-but-order-expired.blade.php b/backend/resources/views/emails/orders/payment-success-but-order-expired.blade.php index a981990c..a4574597 100644 --- a/backend/resources/views/emails/orders/payment-success-but-order-expired.blade.php +++ b/backend/resources/views/emails/orders/payment-success-but-order-expired.blade.php @@ -5,25 +5,22 @@ @php /** @see \HiEvents\Mail\Order\PaymentSuccessButOrderExpiredMail */ @endphp -Hello, +{{ __('Hello') }},

-Your recent order for {{$event->getTitle()}} was not successful. The order expired while you were completing -the payment. -We have issued a refund for the order. +{{ __('Your recent order for :eventTitle was not successful. The order expired while you were completing the payment. We have issued a refund for the order.', ['eventTitle' => $event->getTitle()]) }}

-We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us -at {{$organizer->getEmail()}}. +{{ __('We apologize for the inconvenience. If you have any questions or need assistance, feel free to reach us at') }} {{$organizer->getEmail()}}.

- View Event Page +{{ __('View Event Page') }} -Best regards,
-Hi.Events +{{ __('Best regards') }},
+{{ __('Hi.Events') }} {!! $eventSettings->getGetEmailFooterHtml() !!}
diff --git a/backend/resources/views/emails/orders/summary.blade.php b/backend/resources/views/emails/orders/summary.blade.php index caaa74f0..6074b41f 100644 --- a/backend/resources/views/emails/orders/summary.blade.php +++ b/backend/resources/views/emails/orders/summary.blade.php @@ -1,42 +1,37 @@ -@php use Carbon\Carbon;use HiEvents\Helper\Currency;use HiEvents\Helper\DateHelper; @endphp +@php use Carbon\Carbon; use HiEvents\Helper\Currency; use HiEvents\Helper\DateHelper; @endphp @php /** @var \HiEvents\DomainObjects\OrderDomainObject $order */ @endphp @php /** @var \HiEvents\DomainObjects\EventDomainObject $event */ @endphp @php /** @var string $orderUrl */ @endphp @php /** @see \HiEvents\Mail\Order\OrderSummary */ @endphp -# Your Order is Confirmed! 🎉 +# {{ __('Your Order is Confirmed! ') }} 🎉

-Congratulations! Your order for {{ $event->getTitle() }} on -{{ (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('F j, Y') }} -at {{ (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('g:i A') }} -was successful. Please find your order details below. +{{ __('Congratulations! Your order for :eventTitle on :eventDate at :eventTime was successful. Please find your order details below.', ['eventTitle' => $event->getTitle(), 'eventDate' => (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('F j, Y'), 'eventTime' => (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('g:i A')]) }}

- -## Event Details -- **Event Name:** {{ $event->getTitle() }} -- **Date & Time:** {{ (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('F j, Y') }} at {{ (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('g:i A') }} +## {{ __('Event Details') }} +- ** {{ __('Event Name:') }} ** {{ $event->getTitle() }} +- ** {{ __('Date & Time:') }} ** {{ (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('F j, Y') }} at {{ (new Carbon(DateHelper::convertFromUTC($event->getStartDate(), $event->getTimezone())))->format('g:i A') }}

-## Order Summary -- **Order Number:** {{ $order->getPublicId() }} -- **Total Amount:** {{ Currency::format($order->getTotalGross(), $event->getCurrency()) }} +## {{ __('Order Summary') }} +- **{{ __('Order Number:') }}** {{ $order->getPublicId() }} +- **{{ __('Total Amount:') }}** {{ Currency::format($order->getTotalGross(), $event->getCurrency()) }} - View Order Summary & Tickets + {{ __('View Order Summary & Tickets') }} -If you have any questions or need assistance, feel free to reach out to our friendly support team -at {{ $organizer->getEmail() }}. +{{ __('If you have any questions or need assistance, feel free to reach out to our friendly support team at') }} {{ $organizer->getEmail() }}. -## What's Next? -- **Download Tickets:** Please download your tickets from the order summary page. -- **Prepare for the Event:** Make sure to note the event date, time, and location. -- **Stay Updated:** Keep an eye on your email for any updates from the event organizer. +## {{ __('What\'s Next?') }} +- **{{ __('Download Tickets:') }}** {{ __('Please download your tickets from the order summary page.') }} +- **{{ __('Prepare for the Event:') }}** {{ __('Make sure to note the event date, time, and location.') }} +- **{{ __('Stay Updated:') }}** {{ __('Keep an eye on your email for any updates from the event organizer.') }} -Best regards, +{{ __('Best regards,') }}
{{ config('app.name') }}
diff --git a/backend/resources/views/emails/user/confirm-email-address.blade.php b/backend/resources/views/emails/user/confirm-email-address.blade.php index 689725ab..a6301031 100644 --- a/backend/resources/views/emails/user/confirm-email-address.blade.php +++ b/backend/resources/views/emails/user/confirm-email-address.blade.php @@ -2,7 +2,7 @@ @php /** @var string $link */ @endphp -Hi {{ $user->getFirstName() }}, +{{ __('Hi :name', ['name' => $user->getFirstName()]) }}, {{ __('Welcome to :appName! We\'re excited to have you aboard!', ['appName' => config('app.name')]) }} diff --git a/backend/resources/views/emails/user/confirm-email-change.blade.php b/backend/resources/views/emails/user/confirm-email-change.blade.php index e0226a5d..d65bb7c7 100644 --- a/backend/resources/views/emails/user/confirm-email-change.blade.php +++ b/backend/resources/views/emails/user/confirm-email-change.blade.php @@ -2,14 +2,13 @@ @php /** @var string $link */ @endphp -Hi {{ $user->getFirstName() }}, +{{ __('Hi :name', ['name' => $user->getFirstName()]) }}, -You have requested to change your email address to {{ $user->getPendingEmail() }}. Please click the link -below to confirm this change. +{!! __('You have requested to change your email address to :pendingEmail. Please click the link below to confirm this change.', ['pendingEmail' => $user->getPendingEmail()]) !!} -Confirm email change +{{ __('Confirm email change') }} -If you did not request this change, please immediately change your password. +{{ __('If you did not request this change, please immediately change your password.') }} -Thanks, +{{ __('Thanks,') }} diff --git a/backend/resources/views/emails/user/user-invited.blade.php b/backend/resources/views/emails/user/user-invited.blade.php index f27783b8..0a78eee0 100644 --- a/backend/resources/views/emails/user/user-invited.blade.php +++ b/backend/resources/views/emails/user/user-invited.blade.php @@ -3,14 +3,14 @@ @php /** @var string $appName */ @endphp -Hi {{ $invitedUser->getFirstName() }}, +{{ __('Hi :name', ['name' => $user->getFirstName()]) }}, -You've been invited to join {{ $appName }}. +{{ __('You\'ve been invited to join :appName.', ['appName' => $appName]) }} -To accept the invitation, please click the link below: +{{ __('To accept the invitation, please click the link below:') }} -Accept Invitation +{{ __('Accept Invitation') }} -Thank you,
+{{ __('Thank you') }},
{{ $appName }}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 808d0b15..c5d915d5 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,7 +4,7 @@ import {Notifications} from "@mantine/notifications"; import {i18n} from "@lingui/core"; import {I18nProvider} from "@lingui/react"; import {ModalsProvider} from "@mantine/modals"; -import {QueryClient, QueryClientProvider,} from "@tanstack/react-query"; +import {QueryClient, QueryClientProvider} from "@tanstack/react-query"; import {Helmet, HelmetProvider} from "react-helmet-async"; import "@mantine/core/styles/global.css"; @@ -41,19 +41,19 @@ const supportedLocales: Record = { }; export async function dynamicActivate(locale: string) { - i18n.load(locale, supportedLocales[locale || "en"] || {}); - i18n.activate(locale); + try { + i18n.load(locale, supportedLocales[locale || "en"] || {}); + i18n.activate(locale); + } catch (error) { + console.error(`Error loading locale ${locale}:`, error); + i18n.activate("en"); + } } -const getSupportedLocale = () => { - // if (typeof window !== "undefined") { - // const supportedLocalesKeys = Object.keys(supportedLocales); - // const userLocale = window.navigator.language.split("-")[0]; // Extracting the base language - // - // if (supportedLocalesKeys.includes(userLocale)) { - // return userLocale; - // } - // } +const getSupportedLocale = (userLocale: string) => { + if (Object.keys(supportedLocales).includes(userLocale)) { + return userLocale; + } return "en"; }; @@ -61,20 +61,21 @@ const getSupportedLocale = () => { export const App: FC< PropsWithChildren<{ queryClient: QueryClient; + locale: string; helmetContext?: any; }> > = (props) => { const [isLoadedOnBrowser, setIsLoadedOnBrowser] = React.useState(false); - const localeActivated = useRef(false); - - if (!localeActivated.current) { - localeActivated.current = true; - dynamicActivate(getSupportedLocale()); - } + const localeActivated = useRef(false); // Initialize localeActivated as a ref with the initial value false useEffect(() => { + if (!localeActivated.current && typeof window !== "undefined") { + localeActivated.current = true; + dynamicActivate(getSupportedLocale(props.locale)); + } + setIsLoadedOnBrowser(!isSsr()); - }, []) + }, []); return ( diff --git a/frontend/src/components/common/QuestionsTable/index.tsx b/frontend/src/components/common/QuestionsTable/index.tsx index 0e426b43..e21e4d4b 100644 --- a/frontend/src/components/common/QuestionsTable/index.tsx +++ b/frontend/src/components/common/QuestionsTable/index.tsx @@ -18,7 +18,7 @@ import {PageTitle} from "../PageTitle"; import {CreateQuestionModal} from "../../modals/CreateQuestionModal"; import {useDisclosure} from "@mantine/hooks"; import {Card} from "../Card"; -import {plural, t} from "@lingui/macro"; +import {plural, t, Trans} from "@lingui/macro"; import {useEffect, useState} from "react"; import {EditQuestionModal} from "../../modals/EditQuestionModal"; import {useDeleteQuestion} from "../../../mutations/useDeleteQuestion.ts"; @@ -264,10 +264,13 @@ export const QuestionsTable = ({questions}: QuestionsTableProp) => {
- {plural(questions.filter(question => question.is_hidden).length, { - one: "# hidden question", - other: "# hidden questions" - })} + + {questions.filter(question => question.is_hidden).length} + {questions.filter(question => question.is_hidden).length === 1 + ? " hidden question" + : " hidden questions" + } +