From 6b749294ce180abee650e1d682556da82b6e0547 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Tue, 19 Mar 2024 18:40:32 +0530 Subject: [PATCH 01/24] fix sepa issue --- server/pkg/controller/stripe.go | 126 ++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 31 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index dc9f57eaf..0b044e29b 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -6,9 +6,11 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ente-io/museum/pkg/controller/commonbilling" "net/http" "strconv" + "time" + + "github.com/ente-io/museum/pkg/controller/commonbilling" "github.com/ente-io/museum/pkg/controller/discord" "github.com/ente-io/museum/pkg/controller/offer" @@ -160,7 +162,7 @@ func (c *StripeController) HandleUSNotification(payload []byte, header string) e if err != nil { return stacktrace.Propagate(err, "") } - return c.handleWebhookEvent(event) + return c.handleWebhookEvent(event, ente.StripeUS) } func (c *StripeController) HandleINNotification(payload []byte, header string) error { @@ -168,10 +170,10 @@ func (c *StripeController) HandleINNotification(payload []byte, header string) e if err != nil { return stacktrace.Propagate(err, "") } - return c.handleWebhookEvent(event) + return c.handleWebhookEvent(event, ente.StripeIN) } -func (c *StripeController) handleWebhookEvent(event stripe.Event) error { +func (c *StripeController) handleWebhookEvent(event stripe.Event, country ente.StripeAccountCountry) error { // The event body would already have been logged by the upper layers by the // time we get here, so we can only handle the events that we care about. In // case we receive an unexpected event, we do log an error though. @@ -180,7 +182,7 @@ func (c *StripeController) handleWebhookEvent(event stripe.Event) error { log.Error("Received an unexpected webhook from stripe:", event.Type) return nil } - eventLog, err := handler(event) + eventLog, err := handler(event, country) if err != nil { return stacktrace.Propagate(err, "") } @@ -196,7 +198,7 @@ func (c *StripeController) handleWebhookEvent(event stripe.Event) error { return stacktrace.Propagate(err, "") } -func (c *StripeController) findHandlerForEvent(event stripe.Event) func(event stripe.Event) (ente.StripeEventLog, error) { +func (c *StripeController) findHandlerForEvent(event stripe.Event) func(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { switch event.Type { case "checkout.session.completed": return c.handleCheckoutSessionCompleted @@ -206,6 +208,8 @@ func (c *StripeController) findHandlerForEvent(event stripe.Event) func(event st return c.handleCustomerSubscriptionUpdated case "invoice.paid": return c.handleInvoicePaid + case "payment_intent.payment_failed": + return c.handlePaymentIntentFailed default: return nil } @@ -213,7 +217,7 @@ func (c *StripeController) findHandlerForEvent(event stripe.Event) func(event st // Payment is successful and the subscription is created. // You should provision the subscription. -func (c *StripeController) handleCheckoutSessionCompleted(event stripe.Event) (ente.StripeEventLog, error) { +func (c *StripeController) handleCheckoutSessionCompleted(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var session stripe.CheckoutSession json.Unmarshal(event.Data.Raw, &session) if session.ClientReferenceID != "" { // via payments.ente.io, where we inserted the userID @@ -269,7 +273,7 @@ func (c *StripeController) handleCheckoutSessionCompleted(event stripe.Event) (e } // Occurs whenever a customer's subscription ends. -func (c *StripeController) handleCustomerSubscriptionDeleted(event stripe.Event) (ente.StripeEventLog, error) { +func (c *StripeController) handleCustomerSubscriptionDeleted(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var stripeSubscription stripe.Subscription json.Unmarshal(event.Data.Raw, &stripeSubscription) currentSubscription, err := c.BillingRepo.GetSubscriptionForTransaction(stripeSubscription.ID, ente.Stripe) @@ -322,7 +326,7 @@ func (c *StripeController) handleCustomerSubscriptionDeleted(event stripe.Event) // Occurs whenever a subscription changes (e.g., switching from one plan to // another, or changing the status from trial to active). -func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event) (ente.StripeEventLog, error) { +func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var stripeSubscription stripe.Subscription json.Unmarshal(event.Data.Raw, &stripeSubscription) currentSubscription, err := c.BillingRepo.GetSubscriptionForTransaction(stripeSubscription.ID, ente.Stripe) @@ -336,8 +340,18 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event) } userID := currentSubscription.UserID - switch stripeSubscription.Status { - case stripe.SubscriptionStatusPastDue: + newSubscription, err := c.getEnteSubscriptionFromStripeSubscription(userID, stripeSubscription) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + if currentSubscription.ProductID == newSubscription.ProductID { + // Webhook is reporting an outdated update that was already verified + // no-op + log.Warn("Webhook is reporting an outdated purchase that was already verified stripeSubscriptionID:", stripeSubscription.ID) + return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil + } + c.BillingRepo.ReplaceSubscription(currentSubscription.ID, newSubscription) + if stripeSubscription.Status == stripe.SubscriptionStatusPastDue { user, err := c.UserRepo.Get(userID) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") @@ -349,26 +363,12 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } - case stripe.SubscriptionStatusActive: - newSubscription, err := c.getEnteSubscriptionFromStripeSubscription(userID, stripeSubscription) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - if currentSubscription.ProductID == newSubscription.ProductID { - // Webhook is reporting an outdated update that was already verified - // no-op - log.Warn("Webhook is reporting an outdated purchase that was already verified stripeSubscriptionID:", stripeSubscription.ID) - return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil - } - if newSubscription.ProductID != currentSubscription.ProductID { - c.BillingRepo.ReplaceSubscription(currentSubscription.ID, newSubscription) - } } return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil } // Continue to provision the subscription as payments continue to be made. -func (c *StripeController) handleInvoicePaid(event stripe.Event) (ente.StripeEventLog, error) { +func (c *StripeController) handleInvoicePaid(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var invoice stripe.Invoice json.Unmarshal(event.Data.Raw, &invoice) stripeSubscriptionID := invoice.Subscription.ID @@ -404,6 +404,69 @@ func (c *StripeController) handleInvoicePaid(event stripe.Event) (ente.StripeEve return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil } +func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { + var paymentIntent stripe.PaymentIntent + json.Unmarshal(event.Data.Raw, &paymentIntent) + // Figure out the user + invoiceID := paymentIntent.Invoice.ID + client := c.StripeClients[country] + invoice, err := client.Invoices.Get(invoiceID, nil) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + // void the invoice, in case the payment intent failed + // _, err = client.Invoices.VoidInvoice(invoiceID, nil) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + stripeSubscriptionID := invoice.Subscription.ID + currentSubscription, err := c.BillingRepo.GetSubscriptionForTransaction(stripeSubscriptionID, ente.Stripe) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + // See: Ignore webhooks received before user has been created + log.Warn("Webhook is reporting an event for un-verified subscription stripeSubscriptionID:", stripeSubscriptionID) + } + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + userID := currentSubscription.UserID + + stripeSubscription, err := client.Subscriptions.Get(stripeSubscriptionID, nil) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + + productID := stripeSubscription.Items.Data[0].Price.ID + // If the current subscription is not the same as the one in the webhook, then + // we don't need to do anything. + fmt.Printf("productID: %s, currentSubscription.ProductID: %s\n", productID, currentSubscription.ProductID) + if currentSubscription.ProductID != productID { + // Webhook is reporting an update failure that has not been verified + // no-op + log.Warn("Webhook is reporting un-verified subscription update", stripeSubscription.ID, "invoiceID:", invoiceID) + return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil + } + // If the current subscription is the same as the one in the webhook, then + // we need to expire the subscription, and send an email to the user. + newExpiryTime := time.Now().UnixMicro() // Set the expiry time to now + err = c.BillingRepo.UpdateSubscriptionExpiryTime( + currentSubscription.ID, newExpiryTime) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + // Send an email to the user + user, err := c.UserRepo.Get(userID) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", + ente.SubscriptionEndedEmailSubject, ente.SubscriptionEndedEmailTemplate, + map[string]interface{}{}, nil) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil +} + func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (ente.SubscriptionUpdateResponse, error) { subscription, err := c.BillingRepo.GetUserSubscription(userID) if err != nil { @@ -440,7 +503,7 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en Price: stripe.String(stripeID), }, }, - PaymentBehavior: stripe.String(string(stripe.SubscriptionPaymentBehaviorPendingIfIncomplete)), + PaymentBehavior: stripe.String(string(stripe.SubscriptionPaymentBehaviorAllowIncomplete)), } params.AddExpand("latest_invoice.payment_intent") newStripeSubscription, err := client.Subscriptions.Update(subscription.OriginalTransactionID, ¶ms) @@ -453,14 +516,15 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(err, "") } } - if newStripeSubscription.PendingUpdate != nil { - switch newStripeSubscription.LatestInvoice.PaymentIntent.Status { - case stripe.PaymentIntentStatusRequiresAction: + if newStripeSubscription.Status == stripe.SubscriptionStatusPastDue { + if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresAction { return ente.SubscriptionUpdateResponse{Status: "requires_action", ClientSecret: newStripeSubscription.LatestInvoice.PaymentIntent.ClientSecret}, nil - case stripe.PaymentIntentStatusRequiresPaymentMethod: + } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresPaymentMethod { inv := newStripeSubscription.LatestInvoice invoice.VoidInvoice(inv.ID, nil) return ente.SubscriptionUpdateResponse{Status: "requires_payment_method"}, nil + } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusProcessing { + return ente.SubscriptionUpdateResponse{Status: "success"}, nil } return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(ente.ErrBadRequest, "") } From db81f52cf13cbc5c8de6ab9bdd0684be96680742 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 20 Mar 2024 14:31:01 +0530 Subject: [PATCH 02/24] Update mail when subscription is on-hold --- server/mail-templates/on_hold.html | 4 ++-- server/pkg/controller/stripe.go | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/mail-templates/on_hold.html b/server/mail-templates/on_hold.html index 612570aec..b53ac5df8 100644 --- a/server/mail-templates/on_hold.html +++ b/server/mail-templates/on_hold.html @@ -215,11 +215,11 @@ has informed us that they were unable to renew your - ente subscription. + subscription. Please update your payment method within - {{.PaymentProvider}} + the app so that your subscription can be renewed. diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 115cb3c1d..d20abc9d7 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -464,8 +464,9 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", - ente.SubscriptionEndedEmailSubject, ente.SubscriptionEndedEmailTemplate, - map[string]interface{}{}, nil) + ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ + "PaymentProvider": "Stripe", + }, nil) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } From 49893d973255cf7005a9819ddbe1ef53768b9a7f Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 20 Mar 2024 14:31:33 +0530 Subject: [PATCH 03/24] Update on-hold email subject --- server/ente/billing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/ente/billing.go b/server/ente/billing.go index 5a0ff08a8..20c37bdb5 100644 --- a/server/ente/billing.go +++ b/server/ente/billing.go @@ -42,7 +42,7 @@ const ( OnHoldTemplate = "on_hold.html" // AccountOnHoldEmailSubject is the subject of account on hold email - AccountOnHoldEmailSubject = "ente account on hold" + AccountOnHoldEmailSubject = "Ente account on hold" // Template for the email we send out when the user's subscription ends, // either because the user cancelled their subscription, or because it From 4e074770d2538b677b8c042f368ebc2130946222 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Thu, 21 Mar 2024 06:48:32 +0530 Subject: [PATCH 04/24] invoice client specific invoice api --- server/pkg/controller/stripe.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index d20abc9d7..d57017121 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -26,7 +26,6 @@ import ( "github.com/spf13/viper" "github.com/stripe/stripe-go/v72" "github.com/stripe/stripe-go/v72/client" - "github.com/stripe/stripe-go/v72/invoice" "github.com/stripe/stripe-go/v72/webhook" "golang.org/x/text/currency" ) @@ -527,7 +526,7 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en return ente.SubscriptionUpdateResponse{Status: "requires_action", ClientSecret: newStripeSubscription.LatestInvoice.PaymentIntent.ClientSecret}, nil } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresPaymentMethod { inv := newStripeSubscription.LatestInvoice - invoice.VoidInvoice(inv.ID, nil) + client.Invoices.VoidInvoice(inv.ID, nil) return ente.SubscriptionUpdateResponse{Status: "requires_payment_method"}, nil } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusProcessing { return ente.SubscriptionUpdateResponse{Status: "success"}, nil From 520f7ab64ce01d2f5090eed06af625a6b08affcd Mon Sep 17 00:00:00 2001 From: Abhinav Date: Thu, 21 Mar 2024 07:18:28 +0530 Subject: [PATCH 05/24] only use PaymentBehaviorAllowIncomplete for SEPA payment method --- server/pkg/controller/stripe.go | 55 +++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index d57017121..0eb3f7cf5 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -420,9 +420,9 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country } // void the invoice, in case the payment intent failed // _, err = client.Invoices.VoidInvoice(invoiceID, nil) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } + // if err != nil { + // return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + // } stripeSubscriptionID := invoice.Subscription.ID currentSubscription, err := c.BillingRepo.GetSubscriptionForTransaction(stripeSubscriptionID, ente.Stripe) if err != nil { @@ -496,11 +496,20 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en } client := c.StripeClients[subscription.Attributes.StripeAccountCountry] - stripeSubscription, err := client.Subscriptions.Get(subscription.OriginalTransactionID, nil) + params := stripe.SubscriptionParams{} + params.AddExpand("default_payment_method") + stripeSubscription, err := client.Subscriptions.Get(subscription.OriginalTransactionID, ¶ms) if err != nil { return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(err, "") } - params := stripe.SubscriptionParams{ + isSEPA := stripeSubscription.DefaultPaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit + var paymentBehavior stripe.SubscriptionPaymentBehavior + if isSEPA { + paymentBehavior = stripe.SubscriptionPaymentBehaviorAllowIncomplete + } else { + paymentBehavior = stripe.SubscriptionPaymentBehaviorPendingIfIncomplete + } + params = stripe.SubscriptionParams{ ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorAlwaysInvoice)), Items: []*stripe.SubscriptionItemsParams{ { @@ -508,7 +517,7 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en Price: stripe.String(stripeID), }, }, - PaymentBehavior: stripe.String(string(stripe.SubscriptionPaymentBehaviorAllowIncomplete)), + PaymentBehavior: stripe.String(string(paymentBehavior)), } params.AddExpand("latest_invoice.payment_intent") newStripeSubscription, err := client.Subscriptions.Update(subscription.OriginalTransactionID, ¶ms) @@ -521,17 +530,31 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(err, "") } } - if newStripeSubscription.Status == stripe.SubscriptionStatusPastDue { - if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresAction { - return ente.SubscriptionUpdateResponse{Status: "requires_action", ClientSecret: newStripeSubscription.LatestInvoice.PaymentIntent.ClientSecret}, nil - } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresPaymentMethod { - inv := newStripeSubscription.LatestInvoice - client.Invoices.VoidInvoice(inv.ID, nil) - return ente.SubscriptionUpdateResponse{Status: "requires_payment_method"}, nil - } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusProcessing { - return ente.SubscriptionUpdateResponse{Status: "success"}, nil + if isSEPA { + if newStripeSubscription.Status == stripe.SubscriptionStatusPastDue { + if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresAction { + return ente.SubscriptionUpdateResponse{Status: "requires_action", ClientSecret: newStripeSubscription.LatestInvoice.PaymentIntent.ClientSecret}, nil + } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresPaymentMethod { + // inv := newStripeSubscription.LatestInvoice + // client.Invoices.VoidInvoice(inv.ID, nil) + return ente.SubscriptionUpdateResponse{Status: "requires_payment_method"}, nil + } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusProcessing { + return ente.SubscriptionUpdateResponse{Status: "success"}, nil + } + return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(ente.ErrBadRequest, "") + } + } else { + if newStripeSubscription.PendingUpdate != nil { + switch newStripeSubscription.LatestInvoice.PaymentIntent.Status { + case stripe.PaymentIntentStatusRequiresAction: + return ente.SubscriptionUpdateResponse{Status: "requires_action", ClientSecret: newStripeSubscription.LatestInvoice.PaymentIntent.ClientSecret}, nil + case stripe.PaymentIntentStatusRequiresPaymentMethod: + inv := newStripeSubscription.LatestInvoice + client.Invoices.VoidInvoice(inv.ID, nil) + return ente.SubscriptionUpdateResponse{Status: "requires_payment_method"}, nil + } + return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(ente.ErrBadRequest, "") } - return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(ente.ErrBadRequest, "") } return ente.SubscriptionUpdateResponse{Status: "success"}, nil From 5635e63cb735b0999bca1708382799680fd38e37 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 13:29:42 +0530 Subject: [PATCH 06/24] Update handling for subscription updated events --- server/pkg/controller/stripe.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 0eb3f7cf5..0f6600af0 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -328,8 +328,12 @@ func (c *StripeController) handleCustomerSubscriptionDeleted(event stripe.Event, return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil } -// Occurs whenever a subscription changes (e.g., switching from one plan to -// another, or changing the status from trial to active). +// Stripe fires this when a subscription starts or changes. For example, +// renewing a subscription, adding a coupon, applying a discount, adding an +// invoice item, and changing plans all trigger this event. In our case, we use +// this only to track plan changes or subscriptions going past due. The rest +// (subscription creations, deletions, renewals and failures) are tracked by +// individual events. func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var stripeSubscription stripe.Subscription json.Unmarshal(event.Data.Raw, &stripeSubscription) @@ -348,13 +352,6 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } - if currentSubscription.ProductID == newSubscription.ProductID { - // Webhook is reporting an outdated update that was already verified - // no-op - log.Warn("Webhook is reporting an outdated purchase that was already verified stripeSubscriptionID:", stripeSubscription.ID) - return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil - } - c.BillingRepo.ReplaceSubscription(currentSubscription.ID, newSubscription) if stripeSubscription.Status == stripe.SubscriptionStatusPastDue { user, err := c.UserRepo.Get(userID) if err != nil { @@ -368,6 +365,12 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } } + // If the customer has changed the plan, we update state in the database. If + // the plan has not changed, we will ignore this webhook and rely on other + // events to update the state + if currentSubscription.ProductID != newSubscription.ProductID { + c.BillingRepo.ReplaceSubscription(currentSubscription.ID, newSubscription) + } return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil } From 78e5e3bdb1badc4d616b3eda67bebb8266512ea8 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 13:31:46 +0530 Subject: [PATCH 07/24] Minor refactor --- server/pkg/controller/stripe.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 0f6600af0..4b275fc47 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -348,10 +348,6 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, } userID := currentSubscription.UserID - newSubscription, err := c.getEnteSubscriptionFromStripeSubscription(userID, stripeSubscription) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } if stripeSubscription.Status == stripe.SubscriptionStatusPastDue { user, err := c.UserRepo.Get(userID) if err != nil { @@ -365,6 +361,11 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } } + + newSubscription, err := c.getEnteSubscriptionFromStripeSubscription(userID, stripeSubscription) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } // If the customer has changed the plan, we update state in the database. If // the plan has not changed, we will ignore this webhook and rely on other // events to update the state From 859af52c646822a90e99a05159cfc69647ac126e Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 13:55:42 +0530 Subject: [PATCH 08/24] Remove commented code --- server/pkg/controller/stripe.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 4b275fc47..0713a511b 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -539,8 +539,6 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresAction { return ente.SubscriptionUpdateResponse{Status: "requires_action", ClientSecret: newStripeSubscription.LatestInvoice.PaymentIntent.ClientSecret}, nil } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusRequiresPaymentMethod { - // inv := newStripeSubscription.LatestInvoice - // client.Invoices.VoidInvoice(inv.ID, nil) return ente.SubscriptionUpdateResponse{Status: "requires_payment_method"}, nil } else if newStripeSubscription.LatestInvoice.PaymentIntent.Status == stripe.PaymentIntentStatusProcessing { return ente.SubscriptionUpdateResponse{Status: "success"}, nil From 1f17f2442a4fcf089e3d76e3a2c089a93bca609f Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 14:33:10 +0530 Subject: [PATCH 09/24] Handle SEPA failures --- server/pkg/controller/stripe.go | 35 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 0713a511b..e6a7ab6ff 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -412,22 +412,34 @@ func (c *StripeController) handleInvoicePaid(event stripe.Event, country ente.St return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil } +// Event used to ONLY handle failures to SEPA payments, since we set +// SubscriptionPaymentBehaviorAllowIncomplete only for SEPA. Other payment modes +// will fail and will be handled synchronously func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var paymentIntent stripe.PaymentIntent json.Unmarshal(event.Data.Raw, &paymentIntent) - // Figure out the user - invoiceID := paymentIntent.Invoice.ID client := c.StripeClients[country] + params := stripe.PaymentIntentParams{} + params.AddExpand("payment_method") + fullPaymentIntent, err := client.PaymentIntents.Get(paymentIntent.ID, ¶ms) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + + isSEPA := fullPaymentIntent.PaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit + if !isSEPA { + // Ignore events for other payment methods, since they will be handled + // synchronously + return ente.StripeEventLog{}, nil + } + + invoiceID := paymentIntent.Invoice.ID invoice, err := client.Invoices.Get(invoiceID, nil) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } - // void the invoice, in case the payment intent failed - // _, err = client.Invoices.VoidInvoice(invoiceID, nil) - // if err != nil { - // return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - // } stripeSubscriptionID := invoice.Subscription.ID + currentSubscription, err := c.BillingRepo.GetSubscriptionForTransaction(stripeSubscriptionID, ente.Stripe) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -444,18 +456,17 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country } productID := stripeSubscription.Items.Data[0].Price.ID - // If the current subscription is not the same as the one in the webhook, then - // we don't need to do anything. + // If the current subscription is not the same as the one in the webhook, + // then ignore fmt.Printf("productID: %s, currentSubscription.ProductID: %s\n", productID, currentSubscription.ProductID) if currentSubscription.ProductID != productID { - // Webhook is reporting an update failure that has not been verified // no-op log.Warn("Webhook is reporting un-verified subscription update", stripeSubscription.ID, "invoiceID:", invoiceID) return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil } // If the current subscription is the same as the one in the webhook, then // we need to expire the subscription, and send an email to the user. - newExpiryTime := time.Now().UnixMicro() // Set the expiry time to now + newExpiryTime := time.Now().UnixMicro() // Set the expiry time to 7 days from now err = c.BillingRepo.UpdateSubscriptionExpiryTime( currentSubscription.ID, newExpiryTime) if err != nil { @@ -466,9 +477,11 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } + // TODO: Inform customer that payment_failed.html with invoice.HostedInvoiceURL err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ "PaymentProvider": "Stripe", + "InvoiceURL": invoice.HostedInvoiceURL, }, nil) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") From 3cf680eec13e589997515c320fbc96cb5c849fa5 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 14:42:38 +0530 Subject: [PATCH 10/24] [WiP] Prevent subscription cancellation --- server/pkg/controller/stripe.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index e6a7ab6ff..4b2081799 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -87,11 +87,8 @@ func (c *StripeController) GetCheckoutSession(productID string, userID int64, re } } if subscription.PaymentProvider == ente.Stripe && !subscription.Attributes.IsCancelled { - // user had bought a stripe subscription earlier, - err := c.cancelExistingStripeSubscription(subscription, userID) - if err != nil { - return "", stacktrace.Propagate(err, "") - } + // TODO: Check Stripe's cancellation state instead of our own + return "", stacktrace.Propagate(err, "") } stripeSuccessURL := redirectRootURL + viper.GetString("stripe.path.success") stripeCancelURL := redirectRootURL + viper.GetString("stripe.path.cancel") @@ -466,7 +463,8 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country } // If the current subscription is the same as the one in the webhook, then // we need to expire the subscription, and send an email to the user. - newExpiryTime := time.Now().UnixMicro() // Set the expiry time to 7 days from now + // TODO: Set the expiry time to 7 days from now + newExpiryTime := time.Now().UnixMicro() err = c.BillingRepo.UpdateSubscriptionExpiryTime( currentSubscription.ID, newExpiryTime) if err != nil { @@ -481,7 +479,7 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ "PaymentProvider": "Stripe", - "InvoiceURL": invoice.HostedInvoiceURL, + "InvoiceURL": invoice.HostedInvoiceURL, }, nil) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") From b95d7c241d7d5fcf99aca1de387f8df72e9154cc Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 14:48:29 +0530 Subject: [PATCH 11/24] Create new subs only if the existing subscription is in a cancelled state --- server/pkg/controller/stripe.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 4b2081799..b3a0376fa 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -86,9 +86,15 @@ func (c *StripeController) GetCheckoutSession(productID string, userID int64, re return "", stacktrace.Propagate(ente.ErrBadRequest, "") } } - if subscription.PaymentProvider == ente.Stripe && !subscription.Attributes.IsCancelled { - // TODO: Check Stripe's cancellation state instead of our own - return "", stacktrace.Propagate(err, "") + if hasStripeSubscription { + client := c.StripeClients[subscription.Attributes.StripeAccountCountry] + stripeSubscription, err := client.Subscriptions.Get(subscription.OriginalTransactionID, nil) + if err != nil { + return "", stacktrace.Propagate(err, "") + } + if stripeSubscription.Status != stripe.SubscriptionStatusCanceled { + return "", stacktrace.Propagate(ente.ErrBadRequest, "") + } } stripeSuccessURL := redirectRootURL + viper.GetString("stripe.path.success") stripeCancelURL := redirectRootURL + viper.GetString("stripe.path.cancel") From e634310cb11e7f6482c9d0119b8159b3a64d8b40 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 21 Mar 2024 14:49:37 +0530 Subject: [PATCH 12/24] Remove unused method --- server/pkg/controller/stripe.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index b3a0376fa..12a64f70f 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -782,35 +782,3 @@ func (c *StripeController) CancelSubAndDeleteCustomer(subscription ente.Subscrip } return nil } - -// cancel the earlier past_due subscription -// and add skip mail metadata entry to avoid sending account deletion mail while re-subscription -func (c *StripeController) cancelExistingStripeSubscription(subscription ente.Subscription, userID int64) error { - updateParams := &stripe.SubscriptionParams{} - updateParams.AddMetadata(SkipMailKey, "true") - client := c.StripeClients[subscription.Attributes.StripeAccountCountry] - _, err := client.Subscriptions.Update(subscription.OriginalTransactionID, updateParams) - if err != nil { - stripeError := err.(*stripe.Error) - log.Warn(fmt.Sprintf("subscription updation failed msg= %s for userID=%d", stripeError.Msg, userID)) - // ignore if subscription doesn't exist, already deleted - if stripeError.HTTPStatusCode != 404 { - return stacktrace.Propagate(err, "") - } - } else { - _, err = client.Subscriptions.Cancel(subscription.OriginalTransactionID, nil) - if err != nil { - stripeError := err.(*stripe.Error) - log.Warn(fmt.Sprintf("subscription cancel failed msg= %s for userID=%d", stripeError.Msg, userID)) - // ignore if subscription doesn't exist, already deleted - if stripeError.HTTPStatusCode != 404 { - return stacktrace.Propagate(err, "") - } - } - err = c.BillingRepo.UpdateSubscriptionCancellationStatus(userID, true) - if err != nil { - return stacktrace.Propagate(err, "") - } - } - return nil -} From a275ab774051a2e0a9906a05f17da04f77fa8955 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Sat, 23 Mar 2024 14:37:29 +0530 Subject: [PATCH 13/24] Set subscription to expire 7 days after payment failure --- server/pkg/controller/stripe.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 12a64f70f..67f02456c 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -8,7 +8,6 @@ import ( "fmt" "net/http" "strconv" - "time" "github.com/ente-io/museum/pkg/controller/commonbilling" @@ -21,6 +20,7 @@ import ( "github.com/ente-io/museum/pkg/repo" "github.com/ente-io/museum/pkg/utils/billing" "github.com/ente-io/museum/pkg/utils/email" + "github.com/ente-io/museum/pkg/utils/time" "github.com/ente-io/stacktrace" log "github.com/sirupsen/logrus" "github.com/spf13/viper" @@ -51,6 +51,8 @@ type StripeController struct { // account deletion. const SkipMailKey = "skip_mail" +const BufferPeriodOnPaymentFailureInDays = 7 + // Return a new instance of StripeController func NewStripeController(plans ente.BillingPlansPerAccount, stripeClients ente.StripeClientPerAccount, billingRepo *repo.BillingRepository, fileRepo *repo.FileRepository, userRepo *repo.UserRepository, storageBonusRepo *storagebonus.Repository, discordController *discord.DiscordController, emailNotificationController *emailCtrl.EmailNotificationController, offerController *offer.OfferController, commonBillCtrl *commonbilling.Controller) *StripeController { return &StripeController{ @@ -469,8 +471,7 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country } // If the current subscription is the same as the one in the webhook, then // we need to expire the subscription, and send an email to the user. - // TODO: Set the expiry time to 7 days from now - newExpiryTime := time.Now().UnixMicro() + newExpiryTime := time.NDaysFromNow(BufferPeriodOnPaymentFailureInDays) err = c.BillingRepo.UpdateSubscriptionExpiryTime( currentSubscription.ID, newExpiryTime) if err != nil { From d003542e42f076454a8ddd710b421dc1b234ee22 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 25 Mar 2024 23:13:56 +0530 Subject: [PATCH 14/24] Simplify how last payment method is fetched --- server/pkg/controller/stripe.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 67f02456c..fd4340326 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -423,21 +423,15 @@ func (c *StripeController) handleInvoicePaid(event stripe.Event, country ente.St func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var paymentIntent stripe.PaymentIntent json.Unmarshal(event.Data.Raw, &paymentIntent) - client := c.StripeClients[country] - params := stripe.PaymentIntentParams{} - params.AddExpand("payment_method") - fullPaymentIntent, err := client.PaymentIntents.Get(paymentIntent.ID, ¶ms) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - - isSEPA := fullPaymentIntent.PaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit + isSEPA := paymentIntent.LastPaymentError.PaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit if !isSEPA { // Ignore events for other payment methods, since they will be handled // synchronously + log.Info("Ignoring payment intent failed event for non-SEPA payment method") return ente.StripeEventLog{}, nil } + client := c.StripeClients[country] invoiceID := paymentIntent.Invoice.ID invoice, err := client.Invoices.Get(invoiceID, nil) if err != nil { @@ -577,7 +571,6 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en } } return ente.SubscriptionUpdateResponse{Status: "success"}, nil - } func (c *StripeController) UpdateSubscriptionCancellationStatus(userID int64, status bool) (ente.Subscription, error) { From 29245b73b9f4ea58c883d7eb0d5c4df099b7da54 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 25 Mar 2024 23:15:43 +0530 Subject: [PATCH 15/24] Cancel subscriptions on SEPA failures immediately --- server/pkg/controller/stripe.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index fd4340326..57fdbc584 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" "strconv" + "time" "github.com/ente-io/museum/pkg/controller/commonbilling" @@ -20,7 +21,6 @@ import ( "github.com/ente-io/museum/pkg/repo" "github.com/ente-io/museum/pkg/utils/billing" "github.com/ente-io/museum/pkg/utils/email" - "github.com/ente-io/museum/pkg/utils/time" "github.com/ente-io/stacktrace" log "github.com/sirupsen/logrus" "github.com/spf13/viper" @@ -465,7 +465,7 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country } // If the current subscription is the same as the one in the webhook, then // we need to expire the subscription, and send an email to the user. - newExpiryTime := time.NDaysFromNow(BufferPeriodOnPaymentFailureInDays) + newExpiryTime := time.Now().UnixMicro() err = c.BillingRepo.UpdateSubscriptionExpiryTime( currentSubscription.ID, newExpiryTime) if err != nil { From 2dcf5daf54868b37d4e2c5f08cf2d1b10fa9116d Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 25 Mar 2024 23:16:20 +0530 Subject: [PATCH 16/24] Handle cases where default payment method might not be specified --- server/pkg/controller/stripe.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 57fdbc584..5447a43d0 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -518,7 +518,12 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en if err != nil { return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(err, "") } - isSEPA := stripeSubscription.DefaultPaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit + isSEPA := false + if stripeSubscription.DefaultPaymentMethod != nil { + isSEPA = stripeSubscription.DefaultPaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit + } else { + log.Info("No default payment method found") + } var paymentBehavior stripe.SubscriptionPaymentBehavior if isSEPA { paymentBehavior = stripe.SubscriptionPaymentBehaviorAllowIncomplete From 4afc056a9fc467d72a084751ea620b5060e86ddc Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 25 Mar 2024 23:26:48 +0530 Subject: [PATCH 17/24] Stop listening to subscription deleted events --- server/pkg/controller/stripe.go | 60 --------------------------------- 1 file changed, 60 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 5447a43d0..f36d55659 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -1,7 +1,6 @@ package controller import ( - "context" "database/sql" "encoding/json" "errors" @@ -206,8 +205,6 @@ func (c *StripeController) findHandlerForEvent(event stripe.Event) func(event st switch event.Type { case "checkout.session.completed": return c.handleCheckoutSessionCompleted - case "customer.subscription.deleted": - return c.handleCustomerSubscriptionDeleted case "customer.subscription.updated": return c.handleCustomerSubscriptionUpdated case "invoice.paid": @@ -276,63 +273,6 @@ func (c *StripeController) handleCheckoutSessionCompleted(event stripe.Event, co return ente.StripeEventLog{}, nil } -// Occurs whenever a customer's subscription ends. -func (c *StripeController) handleCustomerSubscriptionDeleted(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { - var stripeSubscription stripe.Subscription - json.Unmarshal(event.Data.Raw, &stripeSubscription) - currentSubscription, err := c.BillingRepo.GetSubscriptionForTransaction(stripeSubscription.ID, ente.Stripe) - if err != nil { - // Ignore webhooks received before user has been created - // - // This would happen when we get webhook events out of order, e.g. we - // get a "customer.subscription.updated" before - // "checkout.session.completed", and the customer has not yet been - // created in our database. - if errors.Is(err, sql.ErrNoRows) { - log.Warn("Webhook is reporting an event for un-verified subscription stripeSubscriptionID:", stripeSubscription.ID) - return ente.StripeEventLog{}, nil - } - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - userID := currentSubscription.UserID - user, err := c.UserRepo.Get(userID) - if err != nil { - if errors.Is(err, ente.ErrUserDeleted) { - // no-op user has already been deleted - return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil - } - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - - err = c.BillingRepo.UpdateSubscriptionCancellationStatus(userID, true) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - - skipMail := stripeSubscription.Metadata[SkipMailKey] - // Send a cancellation notification email for folks who are either on - // individual plan or admin of a family plan. - if skipMail != "true" && - (user.FamilyAdminID == nil || *user.FamilyAdminID == userID) { - storage, surpErr := c.StorageBonusRepo.GetPaidAddonSurplusStorage(context.Background(), userID) - if surpErr != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(surpErr, "") - } - if storage == nil || *storage <= 0 { - err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", - ente.SubscriptionEndedEmailSubject, ente.SubscriptionEndedEmailTemplate, - map[string]interface{}{}, nil) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - } else { - log.WithField("storage", storage).Info("User has surplus storage, not sending email") - } - } - // TODO: Add cron to delete files of users with expired subscriptions - return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil -} - // Stripe fires this when a subscription starts or changes. For example, // renewing a subscription, adding a coupon, applying a discount, adding an // invoice item, and changing plans all trigger this event. In our case, we use From f2aac262b1a1e17c382f9f907fb4c9deb25e68a0 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 25 Mar 2024 23:27:39 +0530 Subject: [PATCH 18/24] Remove unused flag --- server/pkg/controller/stripe.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index f36d55659..d065714ef 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -43,13 +43,6 @@ type StripeController struct { CommonBillCtrl *commonbilling.Controller } -// A flag we set on Stripe subscriptions to indicate that we should skip on -// sending out the email when the subscription has been cancelled. -// -// This is needed e.g. if this cancellation was as part of a user initiated -// account deletion. -const SkipMailKey = "skip_mail" - const BufferPeriodOnPaymentFailureInDays = 7 // Return a new instance of StripeController @@ -669,9 +662,7 @@ func (c *StripeController) CancelSubAndDeleteCustomer(subscription ente.Subscrip if !subscription.Attributes.IsCancelled { prorateRefund := true logger.Info("cancelling sub with prorated refund") - updateParams := &stripe.SubscriptionParams{} - updateParams.AddMetadata(SkipMailKey, "true") - _, err := client.Subscriptions.Update(subscription.OriginalTransactionID, updateParams) + _, err := client.Subscriptions.Update(subscription.OriginalTransactionID, nil) if err != nil { stripeError := err.(*stripe.Error) errorMsg := fmt.Sprintf("subscription updation failed during account deletion: %s, %s", stripeError.Msg, stripeError.Code) From b78a66a2748ed7d71afebd5edca524f86c2ae4ca Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 26 Mar 2024 19:59:22 +0530 Subject: [PATCH 19/24] [mobile] Update behavior of the payment page --- mobile/lib/generated/intl/messages_de.dart | 128 ++++++++++--------- mobile/lib/generated/intl/messages_en.dart | 130 ++++++++++---------- mobile/lib/generated/intl/messages_es.dart | 112 ++++++++--------- mobile/lib/generated/intl/messages_fr.dart | 128 ++++++++++--------- mobile/lib/generated/intl/messages_it.dart | 124 +++++++++---------- mobile/lib/generated/intl/messages_nl.dart | 128 ++++++++++--------- mobile/lib/generated/intl/messages_pt.dart | 128 ++++++++++--------- mobile/lib/generated/intl/messages_zh.dart | 127 ++++++++++--------- mobile/lib/generated/l10n.dart | 10 +- mobile/lib/l10n/intl_en.arb | 2 +- mobile/lib/ui/payment/payment_web_page.dart | 39 +++--- 11 files changed, 508 insertions(+), 548 deletions(-) diff --git a/mobile/lib/generated/intl/messages_de.dart b/mobile/lib/generated/intl/messages_de.dart index ca3be9e41..39fdb3b96 100644 --- a/mobile/lib/generated/intl/messages_de.dart +++ b/mobile/lib/generated/intl/messages_de.dart @@ -131,90 +131,87 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Bitte kontaktiere den Support von ${providerName}, falls etwas abgebucht wurde"; - static String m38(reason) => - "Leider ist deine Zahlung aus folgendem Grund fehlgeschlagen: ${reason}"; - - static String m39(endDate) => + static String m38(endDate) => "Kostenlose Testversion gültig bis ${endDate}.\nSie können anschließend ein bezahltes Paket auswählen."; - static String m40(toEmail) => "Bitte sende uns eine E-Mail an ${toEmail}"; + static String m39(toEmail) => "Bitte sende uns eine E-Mail an ${toEmail}"; - static String m41(toEmail) => "Bitte sende die Protokolle an ${toEmail}"; + static String m40(toEmail) => "Bitte sende die Protokolle an ${toEmail}"; - static String m42(storeName) => "Bewerte uns auf ${storeName}"; + static String m41(storeName) => "Bewerte uns auf ${storeName}"; - static String m43(storageInGB) => + static String m42(storageInGB) => "3. Ihr beide erhaltet ${storageInGB} GB* kostenlos"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} wird aus diesem geteilten Album entfernt\n\nAlle von ihnen hinzugefügte Fotos werden ebenfalls aus dem Album entfernt"; - static String m45(endDate) => "Erneuert am ${endDate}"; + static String m44(endDate) => "Erneuert am ${endDate}"; - static String m46(count) => + static String m45(count) => "${Intl.plural(count, one: '${count} Ergebnis gefunden', other: '${count} Ergebnisse gefunden')}"; - static String m47(count) => "${count} ausgewählt"; + static String m46(count) => "${count} ausgewählt"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} ausgewählt (${yourCount} von Ihnen)"; - static String m49(verificationID) => + static String m48(verificationID) => "Hier ist meine Verifizierungs-ID: ${verificationID} für ente.io."; - static String m50(verificationID) => + static String m49(verificationID) => "Hey, kannst du bestätigen, dass dies deine ente.io Verifizierungs-ID ist: ${verificationID}"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "ente Weiterempfehlungs-Code: ${referralCode} \n\nEinlösen unter Einstellungen → Allgemein → Weiterempfehlungen, um ${referralStorageInGB} GB kostenlos zu erhalten, sobald Sie einen kostenpflichtigen Tarif abgeschlossen haben\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Teile mit bestimmten Personen', one: 'Teilen mit 1 Person', other: 'Teilen mit ${numberOfPeople} Personen')}"; - static String m53(emailIDs) => "Geteilt mit ${emailIDs}"; + static String m52(emailIDs) => "Geteilt mit ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "Dieses ${fileType} wird von deinem Gerät gelöscht."; - static String m55(fileType) => + static String m54(fileType) => "Dieses ${fileType} existiert auf ente.io und deinem Gerät."; - static String m56(fileType) => + static String m55(fileType) => "Dieses ${fileType} wird auf ente.io gelöscht."; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} von ${totalAmount} ${totalStorageUnit} verwendet"; - static String m59(id) => + static String m58(id) => "Ihr ${id} ist bereits mit einem anderen \'ente\'-Konto verknüpft.\nWenn Sie Ihre ${id} mit diesem Konto verwenden möchten, kontaktieren Sie bitte unseren Support\'"; - static String m60(endDate) => "Ihr Abo endet am ${endDate}"; + static String m59(endDate) => "Ihr Abo endet am ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} Erinnerungsstücke gesichert"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "Diese erhalten auch ${storageAmountInGB} GB"; - static String m63(email) => "Dies ist ${email}s Verifizierungs-ID"; + static String m62(email) => "Dies ist ${email}s Verifizierungs-ID"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '', one: '1 Tag', other: '${count} Tage')}"; - static String m65(endDate) => "Gültig bis ${endDate}"; + static String m64(endDate) => "Gültig bis ${endDate}"; - static String m66(email) => "Verifiziere ${email}"; + static String m65(email) => "Verifiziere ${email}"; - static String m67(email) => + static String m66(email) => "Wir haben eine E-Mail an ${email} gesendet"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: 'vor einem Jahr', other: 'vor ${count} Jahren')}"; - static String m69(storageSaved) => + static String m68(storageSaved) => "Du hast ${storageSaved} erfolgreich freigegeben!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -1026,7 +1023,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Zahlung fehlgeschlagen"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Ausstehende Elemente"), "pendingSync": @@ -1053,7 +1049,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinAlbum": MessageLookupByLibrary.simpleMessage("Album anheften"), "playOnTv": MessageLookupByLibrary.simpleMessage( "Album auf dem Fernseher wiedergeben"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore Abo"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1065,12 +1061,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Bitte wenden Sie sich an den Support, falls das Problem weiterhin besteht"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Bitte erteile die nötigen Berechtigungen"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Bitte logge dich erneut ein"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Bitte versuche es erneut"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1106,7 +1102,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Ticket erstellen"), "rateTheApp": MessageLookupByLibrary.simpleMessage("App bewerten"), "rateUs": MessageLookupByLibrary.simpleMessage("Bewerte uns"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Wiederherstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Konto wiederherstellen"), @@ -1139,7 +1135,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Gib diesen Code an deine Freunde"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Sie schließen ein bezahltes Abo ab"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Weiterempfehlungen"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Einlösungen sind derzeit pausiert"), @@ -1165,7 +1161,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Link entfernen"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Teilnehmer entfernen"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Öffentlichen Link entfernen"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1179,7 +1175,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Datei umbenennen"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonnement erneuern"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "reportBug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "resendEmail": @@ -1242,7 +1238,7 @@ class MessageLookup extends MessageLookupByLibrary { "Gruppiere Fotos, die innerhalb des Radius eines bestimmten Fotos aufgenommen wurden"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Laden Sie Personen ein, damit Sie geteilte Fotos hier einsehen können"), - "searchResultCount": m46, + "searchResultCount": m45, "security": MessageLookupByLibrary.simpleMessage("Sicherheit"), "selectALocation": MessageLookupByLibrary.simpleMessage("Standort auswählen"), @@ -1269,8 +1265,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Ausgewählte Elemente werden aus allen Alben gelöscht und in den Papierkorb verschoben."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Absenden"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-Mail senden"), "sendInvite": MessageLookupByLibrary.simpleMessage("Einladung senden"), @@ -1293,16 +1289,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Teile jetzt ein Album"), "shareLink": MessageLookupByLibrary.simpleMessage("Link teilen"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Teile mit ausgewählten Personen"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Lade ente herunter, damit wir einfach Fotos und Videos in höchster Qualität teilen können\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Mit Nicht-Ente-Benutzern teilen"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Teile dein erstes Album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1313,7 +1309,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Neue geteilte Fotos"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Erhalte Benachrichtigungen, wenn jemand ein Foto zu einem gemeinsam genutzten Album hinzufügt, dem du angehörst"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Mit mir geteilt"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Mit dir geteilt"), @@ -1328,11 +1324,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Andere Geräte abmelden"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Ich stimme den Nutzungsbedingungen und der Datenschutzerklärung zu"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Es wird aus allen Alben gelöscht."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Überspringen"), "social": MessageLookupByLibrary.simpleMessage("Social Media"), "someItemsAreInBothEnteAndYourDevice": @@ -1374,13 +1370,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Speicherplatz"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familie"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Sie"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Speichergrenze überschritten"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Stark"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("Abonnieren"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Sieht aus, als sei dein Abonnement abgelaufen. Bitte abonniere, um das Teilen zu aktivieren."), @@ -1397,7 +1393,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Verbesserung vorschlagen"), "support": MessageLookupByLibrary.simpleMessage("Support"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Synchronisierung angehalten"), "syncing": MessageLookupByLibrary.simpleMessage("Synchronisiere …"), @@ -1426,7 +1422,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Diese Elemente werden von deinem Gerät gelöscht."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Sie werden aus allen Alben gelöscht."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1442,7 +1438,7 @@ class MessageLookup extends MessageLookupByLibrary { "Diese E-Mail-Adresse wird bereits verwendet"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Dieses Bild hat keine Exif-Daten"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Dies ist deine Verifizierungs-ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1459,7 +1455,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("Gesamt"), "totalSize": MessageLookupByLibrary.simpleMessage("Gesamtgröße"), "trash": MessageLookupByLibrary.simpleMessage("Papierkorb"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("Erneut versuchen"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Aktiviere die Sicherung, um automatisch neu hinzugefügte Dateien dieses Ordners auf ente hochzuladen."), @@ -1514,7 +1510,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ausgewähltes Foto verwenden"), "usedSpace": MessageLookupByLibrary.simpleMessage("Belegter Speicherplatz"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verifizierung fehlgeschlagen, bitte versuchen Sie es erneut"), @@ -1523,7 +1519,7 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Überprüfen"), "verifyEmail": MessageLookupByLibrary.simpleMessage("E-Mail-Adresse verifizieren"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Überprüfen"), "verifyPasskey": MessageLookupByLibrary.simpleMessage("Passkey verifizieren"), @@ -1556,12 +1552,12 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Wir unterstützen keine Bearbeitung von Fotos und Alben, die du noch nicht besitzt"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Schwach"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Willkommen zurück!"), "yearly": MessageLookupByLibrary.simpleMessage("Jährlich"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Ja"), "yesCancel": MessageLookupByLibrary.simpleMessage("Ja, kündigen"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1591,7 +1587,7 @@ class MessageLookup extends MessageLookupByLibrary { "Du kannst nicht mit dir selbst teilen"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Du hast keine archivierten Elemente."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Dein Benutzerkonto wurde gelöscht"), "yourMap": MessageLookupByLibrary.simpleMessage("Deine Karte"), diff --git a/mobile/lib/generated/intl/messages_en.dart b/mobile/lib/generated/intl/messages_en.dart index 624a7cfb2..86fa10ecf 100644 --- a/mobile/lib/generated/intl/messages_en.dart +++ b/mobile/lib/generated/intl/messages_en.dart @@ -129,89 +129,86 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Please talk to ${providerName} support if you were charged"; - static String m38(reason) => - "Unfortunately your payment failed due to ${reason}"; - - static String m39(endDate) => + static String m38(endDate) => "Free trial valid till ${endDate}.\nYou can choose a paid plan afterwards."; - static String m40(toEmail) => "Please email us at ${toEmail}"; + static String m39(toEmail) => "Please email us at ${toEmail}"; - static String m41(toEmail) => "Please send the logs to \n${toEmail}"; + static String m40(toEmail) => "Please send the logs to \n${toEmail}"; - static String m42(storeName) => "Rate us on ${storeName}"; + static String m41(storeName) => "Rate us on ${storeName}"; - static String m43(storageInGB) => + static String m42(storageInGB) => "3. Both of you get ${storageInGB} GB* free"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} will be removed from this shared album\n\nAny photos added by them will also be removed from the album"; - static String m45(endDate) => "Subscription renews on ${endDate}"; + static String m44(endDate) => "Subscription renews on ${endDate}"; - static String m46(count) => + static String m45(count) => "${Intl.plural(count, one: '${count} result found', other: '${count} results found')}"; - static String m47(count) => "${count} selected"; + static String m46(count) => "${count} selected"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} selected (${yourCount} yours)"; - static String m49(verificationID) => + static String m48(verificationID) => "Here\'s my verification ID: ${verificationID} for ente.io."; - static String m50(verificationID) => + static String m49(verificationID) => "Hey, can you confirm that this is your ente.io verification ID: ${verificationID}"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "ente referral code: ${referralCode} \n\nApply it in Settings → General → Referrals to get ${referralStorageInGB} GB free after you signup for a paid plan\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Share with specific people', one: 'Shared with 1 person', other: 'Shared with ${numberOfPeople} people')}"; - static String m53(emailIDs) => "Shared with ${emailIDs}"; + static String m52(emailIDs) => "Shared with ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "This ${fileType} will be deleted from your device."; - static String m55(fileType) => + static String m54(fileType) => "This ${fileType} is in both ente and your device."; - static String m56(fileType) => "This ${fileType} will be deleted from ente."; + static String m55(fileType) => "This ${fileType} will be deleted from ente."; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} of ${totalAmount} ${totalStorageUnit} used"; - static String m59(id) => + static String m58(id) => "Your ${id} is already linked to another ente account.\nIf you would like to use your ${id} with this account, please contact our support\'\'"; - static String m60(endDate) => + static String m59(endDate) => "Your subscription will be cancelled on ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} memories preserved"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "They also get ${storageAmountInGB} GB"; - static String m63(email) => "This is ${email}\'s Verification ID"; + static String m62(email) => "This is ${email}\'s Verification ID"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '', one: '1 day', other: '${count} days')}"; - static String m65(endDate) => "Valid till ${endDate}"; + static String m64(endDate) => "Valid till ${endDate}"; - static String m66(email) => "Verify ${email}"; + static String m65(email) => "Verify ${email}"; - static String m67(email) => "We have sent a mail to ${email}"; + static String m66(email) => "We have sent a mail to ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: '${count} year ago', other: '${count} years ago')}"; - static String m69(storageSaved) => + static String m68(storageSaved) => "You have successfully freed up ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -982,8 +979,9 @@ class MessageLookup extends MessageLookupByLibrary { "paymentDetails": MessageLookupByLibrary.simpleMessage("Payment details"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Payment failed"), + "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( + "Unfortunately your payment failed. Please contact support and we\'ll help you out!"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Pending items"), "pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"), "peopleUsingYourCode": @@ -1007,7 +1005,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Pick center point"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Pin album"), "playOnTv": MessageLookupByLibrary.simpleMessage("Play album on TV"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore subscription"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1019,12 +1017,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Please contact support if the problem persists"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Please grant permissions"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Please login again"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Please try again"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1059,7 +1057,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Raise ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Rate the app"), "rateUs": MessageLookupByLibrary.simpleMessage("Rate us"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Recover"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recover account"), @@ -1090,7 +1088,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Give this code to your friends"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. They sign up for a paid plan"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Referrals"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Referrals are currently paused"), @@ -1114,7 +1112,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Remove link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Remove participant"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Remove public link"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1128,7 +1126,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Rename file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renew subscription"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Report a bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Report bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Resend email"), @@ -1188,7 +1186,7 @@ class MessageLookup extends MessageLookupByLibrary { "Group photos that are taken within some radius of a photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invite people, and you\'ll see all photos shared by them here"), - "searchResultCount": m46, + "searchResultCount": m45, "security": MessageLookupByLibrary.simpleMessage("Security"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), @@ -1215,8 +1213,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Selected items will be deleted from all albums and moved to trash."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Send"), "sendEmail": MessageLookupByLibrary.simpleMessage("Send email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Send invite"), @@ -1238,16 +1236,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Share an album now"), "shareLink": MessageLookupByLibrary.simpleMessage("Share link"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Share only with the people you want"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Download ente so we can easily share original quality photos and videos\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("Share with non-ente users"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Share your first album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1258,7 +1256,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("New shared photos"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Receive notifications when someone adds a photo to a shared album that you\'re a part of"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Shared with me"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Shared with you"), @@ -1272,11 +1270,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sign out other devices"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "I agree to the terms of service and privacy policy"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "It will be deleted from all albums."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Skip"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1314,13 +1312,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Storage"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Family"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("You"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Storage limit exceeded"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Strong"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("Subscribe"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Looks like your subscription has expired. Please subscribe to enable sharing."), @@ -1337,7 +1335,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Suggest features"), "support": MessageLookupByLibrary.simpleMessage("Support"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Sync stopped"), "syncing": MessageLookupByLibrary.simpleMessage("Syncing..."), "systemTheme": MessageLookupByLibrary.simpleMessage("System"), @@ -1363,7 +1361,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "These items will be deleted from your device."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "They will be deleted from all albums."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1379,7 +1377,7 @@ class MessageLookup extends MessageLookupByLibrary { "This email is already in use"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage("This image has no exif data"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "This is your Verification ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1395,7 +1393,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("total"), "totalSize": MessageLookupByLibrary.simpleMessage("Total size"), "trash": MessageLookupByLibrary.simpleMessage("Trash"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("Try again"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Turn on backup to automatically upload files added to this device folder to ente."), @@ -1447,7 +1445,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Use selected photo"), "usedSpace": MessageLookupByLibrary.simpleMessage("Used space"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verification failed, please try again"), @@ -1455,7 +1453,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verification ID"), "verify": MessageLookupByLibrary.simpleMessage("Verify"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Verify email"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verify"), "verifyPasskey": MessageLookupByLibrary.simpleMessage("Verify passkey"), "verifyPassword": @@ -1486,11 +1484,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "We don\'t support editing photos and albums that you don\'t own yet"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Weak"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Welcome back!"), "yearly": MessageLookupByLibrary.simpleMessage("Yearly"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Yes"), "yesCancel": MessageLookupByLibrary.simpleMessage("Yes, cancel"), "yesConvertToViewer": @@ -1520,7 +1518,7 @@ class MessageLookup extends MessageLookupByLibrary { "You cannot share with yourself"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "You don\'t have any archived items."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Your account has been deleted"), "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), diff --git a/mobile/lib/generated/intl/messages_es.dart b/mobile/lib/generated/intl/messages_es.dart index 0c2673d46..8ceb97ad3 100644 --- a/mobile/lib/generated/intl/messages_es.dart +++ b/mobile/lib/generated/intl/messages_es.dart @@ -121,79 +121,76 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Por favor hable con el soporte de ${providerName} si se le cobró"; - static String m38(reason) => - "Lamentablemente tu pago falló debido a ${reason}"; - - static String m40(toEmail) => + static String m39(toEmail) => "Por favor, envíanos un correo electrónico a ${toEmail}"; - static String m41(toEmail) => "Por favor, envíe los registros a ${toEmail}"; + static String m40(toEmail) => "Por favor, envíe los registros a ${toEmail}"; - static String m42(storeName) => "Califícanos en ${storeName}"; + static String m41(storeName) => "Califícanos en ${storeName}"; - static String m43(storageInGB) => + static String m42(storageInGB) => "3. Ambos obtienen ${storageInGB} GB* gratis"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} será eliminado de este álbum compartido\n\nCualquier foto añadida por ellos también será eliminada del álbum"; - static String m45(endDate) => "Se renueva el ${endDate}"; + static String m44(endDate) => "Se renueva el ${endDate}"; - static String m47(count) => "${count} seleccionados"; + static String m46(count) => "${count} seleccionados"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} seleccionados (${yourCount} tuyos)"; - static String m49(verificationID) => + static String m48(verificationID) => "Aquí está mi ID de verificación: ${verificationID} para ente.io."; - static String m50(verificationID) => + static String m49(verificationID) => "Hola, ¿puedes confirmar que esta es tu ID de verificación ente.io: ${verificationID}?"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "ente código de referencia: ${referralCode} \n\nAplicarlo en Ajustes → General → Referencias para obtener ${referralStorageInGB} GB gratis después de registrarse en un plan de pago\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Compartir con personas específicas', one: 'Compartido con 1 persona', other: 'Compartido con ${numberOfPeople} personas')}"; - static String m53(emailIDs) => "Compartido con ${emailIDs}"; + static String m52(emailIDs) => "Compartido con ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "Este ${fileType} se eliminará de tu dispositivo."; - static String m55(fileType) => + static String m54(fileType) => "Este ${fileType} está tanto en ente como en tu dispositivo."; - static String m56(fileType) => "Este ${fileType} se eliminará de ente."; + static String m55(fileType) => "Este ${fileType} se eliminará de ente."; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} de ${totalAmount} ${totalStorageUnit} usados"; - static String m59(id) => + static String m58(id) => "Su ${id} ya está vinculado a otra cuenta ente.\nSi desea utilizar su ${id} con esta cuenta, póngase en contacto con nuestro servicio de asistencia\'\'"; - static String m60(endDate) => "Tu suscripción se cancelará el ${endDate}"; + static String m59(endDate) => "Tu suscripción se cancelará el ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} recuerdos conservados"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "También obtienen ${storageAmountInGB} GB"; - static String m63(email) => "Este es el ID de verificación de ${email}"; + static String m62(email) => "Este es el ID de verificación de ${email}"; - static String m66(email) => "Verificar ${email}"; + static String m65(email) => "Verificar ${email}"; - static String m67(email) => + static String m66(email) => "Hemos enviado un correo a ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: '${count} hace un año', other: '${count} hace años')}"; - static String m69(storageSaved) => "¡Has liberado ${storageSaved} con éxito!"; + static String m68(storageSaved) => "¡Has liberado ${storageSaved} con éxito!"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -875,7 +872,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Detalles de pago"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Pago fallido"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronización pendiente"), "peopleUsingYourCode": @@ -902,12 +898,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Por favor contacte a soporte técnico si el problema persiste"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Por favor, concede permiso"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Por favor, vuelva a iniciar sesión"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Por favor, inténtalo nuevamente"), "pleaseVerifyTheCodeYouHaveEntered": @@ -941,7 +937,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Evalúa la aplicación"), "rateUs": MessageLookupByLibrary.simpleMessage("Califícanos"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Recuperar"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperar cuenta"), @@ -973,7 +969,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Dale este código a tus amigos"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Se inscriben a un plan pagado"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Referidos"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Las referencias están actualmente en pausa"), @@ -998,7 +994,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Eliminar enlace"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Quitar participante"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Quitar enlace público"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1012,7 +1008,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Renombrar archivo"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renovar suscripción"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Reportar un error"), "reportBug": MessageLookupByLibrary.simpleMessage("Reportar error"), "resendEmail": @@ -1074,8 +1070,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Los archivos seleccionados serán eliminados de todos los álbumes y movidos a la papelera."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Enviar"), "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar correo electrónico"), @@ -1100,32 +1096,32 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Compartir un álbum ahora"), "shareLink": MessageLookupByLibrary.simpleMessage("Compartir enlace"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Comparte sólo con la gente que quieres"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Descarga ente para que podamos compartir fácilmente fotos y videos en su calidad original\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Compartir con usuarios no ente"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Comparte tu primer álbum"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( "Crear álbumes compartidos y colaborativos con otros usuarios ente, incluyendo usuarios en planes gratuitos."), "sharedByMe": MessageLookupByLibrary.simpleMessage("Compartido por mí"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartido conmigo"), "sharing": MessageLookupByLibrary.simpleMessage("Compartiendo..."), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Estoy de acuerdo con los términos del servicio y la política de privacidad"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Se borrará de todos los álbumes."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Omitir"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1160,13 +1156,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Almacenamiento"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familia"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Usted"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Límite de datos excedido"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Segura"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("Suscribirse"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Parece que su suscripción ha caducado. Por favor, suscríbase para habilitar el compartir."), @@ -1179,7 +1175,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Sugerir una característica"), "support": MessageLookupByLibrary.simpleMessage("Soporte"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Sincronización detenida"), "syncing": MessageLookupByLibrary.simpleMessage("Sincronizando..."), @@ -1207,7 +1203,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Estos elementos se eliminarán de tu dispositivo."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Se borrarán de todos los álbumes."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1223,7 +1219,7 @@ class MessageLookup extends MessageLookupByLibrary { "Este correo electrónico ya está en uso"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Esta imagen no tiene datos exif"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Esta es tu ID de verificación"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1293,7 +1289,7 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyEmail": MessageLookupByLibrary.simpleMessage( "Verificar correo electrónico"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Verificar contraseña"), @@ -1316,12 +1312,12 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "No admitimos la edición de fotos y álbunes que aún no son tuyos"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Poco segura"), "welcomeBack": MessageLookupByLibrary.simpleMessage("¡Bienvenido de nuevo!"), "yearly": MessageLookupByLibrary.simpleMessage("Anualmente"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Sí"), "yesCancel": MessageLookupByLibrary.simpleMessage("Sí, cancelar"), "yesConvertToViewer": @@ -1351,7 +1347,7 @@ class MessageLookup extends MessageLookupByLibrary { "No puedes compartir contigo mismo"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "No tienes nada de elementos archivados."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Su cuenta ha sido eliminada"), "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), diff --git a/mobile/lib/generated/intl/messages_fr.dart b/mobile/lib/generated/intl/messages_fr.dart index 6bef1659c..035d6c232 100644 --- a/mobile/lib/generated/intl/messages_fr.dart +++ b/mobile/lib/generated/intl/messages_fr.dart @@ -126,89 +126,86 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Veuillez contacter le support ${providerName} si vous avez été facturé"; - static String m38(reason) => - "Malheureusement, votre paiement a échoué pour ${reason}"; - - static String m39(endDate) => + static String m38(endDate) => "Essai gratuit valable jusqu\'à ${endDate}.\nVous pouvez choisir un plan payant par la suite."; - static String m40(toEmail) => "Merci de nous envoyer un e-mail à ${toEmail}"; + static String m39(toEmail) => "Merci de nous envoyer un e-mail à ${toEmail}"; - static String m41(toEmail) => "Envoyez les logs à ${toEmail}"; + static String m40(toEmail) => "Envoyez les logs à ${toEmail}"; - static String m42(storeName) => "Notez-nous sur ${storeName}"; + static String m41(storeName) => "Notez-nous sur ${storeName}"; - static String m43(storageInGB) => + static String m42(storageInGB) => "3. Vous recevez tous les deux ${storageInGB} GB* gratuits"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} sera retiré de cet album partagé\n\nToutes les photos ajoutées par eux seront également retirées de l\'album"; - static String m45(endDate) => "Renouvellement le ${endDate}"; + static String m44(endDate) => "Renouvellement le ${endDate}"; - static String m46(count) => + static String m45(count) => "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}"; - static String m47(count) => "${count} sélectionné(s)"; + static String m46(count) => "${count} sélectionné(s)"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} sélectionné(s) (${yourCount} à vous)"; - static String m49(verificationID) => + static String m48(verificationID) => "Voici mon ID de vérification : ${verificationID} pour ente.io."; - static String m50(verificationID) => + static String m49(verificationID) => "Hé, pouvez-vous confirmer qu\'il s\'agit de votre ID de vérification ente.io : ${verificationID}"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "code de parrainage ente : ${referralCode} \n\nAppliquez le dans Paramètres → Général → Références pour obtenir ${referralStorageInGB} Go gratuitement après votre inscription à un plan payant\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Partagez avec des personnes spécifiques', one: 'Partagé avec 1 personne', other: 'Partagé avec ${numberOfPeople} des gens')}"; - static String m53(emailIDs) => "Partagé avec ${emailIDs}"; + static String m52(emailIDs) => "Partagé avec ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "Elle ${fileType} sera supprimée de votre appareil."; - static String m55(fileType) => + static String m54(fileType) => "Cette ${fileType} est à la fois sur ente et sur votre appareil."; - static String m56(fileType) => "Ce ${fileType} sera supprimé de ente."; + static String m55(fileType) => "Ce ${fileType} sera supprimé de ente."; - static String m57(storageAmountInGB) => "${storageAmountInGB} Go"; + static String m56(storageAmountInGB) => "${storageAmountInGB} Go"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} sur ${totalAmount} ${totalStorageUnit} utilisé"; - static String m59(id) => + static String m58(id) => "Votre ${id} est déjà lié à un autre compte ente.\nSi vous souhaitez utiliser votre ${id} avec ce compte, veuillez contacter notre support"; - static String m60(endDate) => "Votre abonnement sera annulé le ${endDate}"; + static String m59(endDate) => "Votre abonnement sera annulé le ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} souvenirs préservés"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "Ils obtiennent aussi ${storageAmountInGB} Go"; - static String m63(email) => "Ceci est l\'ID de vérification de ${email}"; + static String m62(email) => "Ceci est l\'ID de vérification de ${email}"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '0 jour', one: '1 jour', other: '${count} jours')}"; - static String m65(endDate) => "Valable jusqu\'au ${endDate}"; + static String m64(endDate) => "Valable jusqu\'au ${endDate}"; - static String m66(email) => "Vérifier ${email}"; + static String m65(email) => "Vérifier ${email}"; - static String m67(email) => + static String m66(email) => "Nous avons envoyé un e-mail à ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: 'il y a ${count} an', other: 'il y a ${count} ans')}"; - static String m69(storageSaved) => + static String m68(storageSaved) => "Vous avez libéré ${storageSaved} avec succès !"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -1000,7 +997,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Échec du paiement"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingSync": MessageLookupByLibrary.simpleMessage("Synchronisation en attente"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage( @@ -1023,7 +1019,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage( "Sélectionner le point central"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Épingler l\'album"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abonnement au PlayStore"), "pleaseContactSupportAndWeWillBeHappyToHelp": @@ -1032,12 +1028,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Merci de contacter l\'assistance si cette erreur persiste"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Veuillez accorder la permission"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Veuillez vous reconnecter"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Veuillez réessayer"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1073,7 +1069,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Évaluer l\'application"), "rateUs": MessageLookupByLibrary.simpleMessage("Évaluez-nous"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Récupérer"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Récupérer un compte"), @@ -1104,7 +1100,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Donnez ce code à vos amis"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ils s\'inscrivent à une offre payante"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Parrainages"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Les recommandations sont actuellement en pause"), @@ -1130,7 +1126,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Supprimer le lien"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Supprimer le participant"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Supprimer le lien public"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1146,7 +1142,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Renommer le fichier"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renouveler l’abonnement"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Signaler un bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Signaler un bug"), "resendEmail": @@ -1211,7 +1207,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grouper les photos qui sont prises dans un certain angle d\'une photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"), - "searchResultCount": m46, + "searchResultCount": m45, "security": MessageLookupByLibrary.simpleMessage("Sécurité"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), @@ -1240,8 +1236,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Les éléments sélectionnés seront supprimés de tous les albums et déplacés dans la corbeille."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Envoyer"), "sendEmail": MessageLookupByLibrary.simpleMessage("Envoyer un e-mail"), "sendInvite": @@ -1267,16 +1263,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage( "Partagez un album maintenant"), "shareLink": MessageLookupByLibrary.simpleMessage("Partager le lien"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Partager uniquement avec les personnes que vous voulez"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Téléchargez ente pour que nous puissions facilement partager des photos et des vidéos de qualité originale\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Partager avec des utilisateurs non-ente"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Partagez votre premier album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1287,7 +1283,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nouvelles photos partagées"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Recevoir des notifications quand quelqu\'un ajoute une photo à un album partagé dont vous faites partie"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Partagés avec moi"), "sharedWithYou": @@ -1297,11 +1293,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Montrer les souvenirs"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "J\'accepte les conditions d\'utilisation et la politique de confidentialité"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Elle sera supprimée de tous les albums."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Ignorer"), "social": MessageLookupByLibrary.simpleMessage("Réseaux Sociaux"), "someItemsAreInBothEnteAndYourDevice": @@ -1341,14 +1337,14 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Stockage"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Famille"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Vous"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Limite de stockage atteinte"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Securité forte"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("S\'abonner"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Il semble que votre abonnement ait expiré. Veuillez vous abonner pour activer le partage."), @@ -1365,7 +1361,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage( "Suggérer des fonctionnalités"), "support": MessageLookupByLibrary.simpleMessage("Support"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Synchronisation arrêtée ?"), "syncing": MessageLookupByLibrary.simpleMessage( @@ -1394,7 +1390,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Ces éléments seront supprimés de votre appareil."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Ils seront supprimés de tous les albums."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1410,7 +1406,7 @@ class MessageLookup extends MessageLookupByLibrary { "Cette adresse mail est déjà utilisé"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Cette image n\'a pas de données exif"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Ceci est votre ID de vérification"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1426,7 +1422,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("total"), "totalSize": MessageLookupByLibrary.simpleMessage("Taille totale"), "trash": MessageLookupByLibrary.simpleMessage("Corbeille"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("Réessayer"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Activez la sauvegarde pour télécharger automatiquement les fichiers ajoutés à ce dossier de l\'appareil sur ente."), @@ -1484,7 +1480,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage( "Utiliser la photo sélectionnée"), "usedSpace": MessageLookupByLibrary.simpleMessage("Mémoire utilisée"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "La vérification a échouée, veuillez réessayer"), @@ -1493,7 +1489,7 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Vérifier"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Vérifier l\'email"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Vérifier"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Vérifier le mot de passe"), @@ -1522,11 +1518,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Nous ne prenons pas en charge l\'édition des photos et des albums que vous ne possédez pas encore"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Securité Faible"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bienvenue !"), "yearly": MessageLookupByLibrary.simpleMessage("Annuel"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Oui"), "yesCancel": MessageLookupByLibrary.simpleMessage("Oui, annuler"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1557,7 +1553,7 @@ class MessageLookup extends MessageLookupByLibrary { "Vous ne pouvez pas partager avec vous-même"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Vous n\'avez aucun élément archivé."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Votre compte a été supprimé"), "yourMap": MessageLookupByLibrary.simpleMessage("Votre carte"), diff --git a/mobile/lib/generated/intl/messages_it.dart b/mobile/lib/generated/intl/messages_it.dart index 8b9b28b35..c3cbb0b74 100644 --- a/mobile/lib/generated/intl/messages_it.dart +++ b/mobile/lib/generated/intl/messages_it.dart @@ -124,86 +124,83 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Si prega di parlare con il supporto di ${providerName} se ti è stato addebitato qualcosa"; - static String m38(reason) => - "Purtroppo il tuo pagamento non è riuscito a causa di ${reason}"; - - static String m39(endDate) => + static String m38(endDate) => "Prova gratuita valida fino al ${endDate}.\nPuoi scegliere un piano a pagamento in seguito."; - static String m40(toEmail) => "Per favore invia un\'email a ${toEmail}"; + static String m39(toEmail) => "Per favore invia un\'email a ${toEmail}"; - static String m41(toEmail) => "Invia i log a \n${toEmail}"; + static String m40(toEmail) => "Invia i log a \n${toEmail}"; - static String m42(storeName) => "Valutaci su ${storeName}"; + static String m41(storeName) => "Valutaci su ${storeName}"; - static String m43(storageInGB) => + static String m42(storageInGB) => "3. Ottenete entrambi ${storageInGB} GB* gratis"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} verrà rimosso da questo album condiviso\n\nQualsiasi foto aggiunta dall\'utente verrà rimossa dall\'album"; - static String m45(endDate) => "Si rinnova il ${endDate}"; + static String m44(endDate) => "Si rinnova il ${endDate}"; - static String m47(count) => "${count} selezionati"; + static String m46(count) => "${count} selezionati"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} selezionato (${yourCount} tuoi)"; - static String m49(verificationID) => + static String m48(verificationID) => "Ecco il mio ID di verifica: ${verificationID} per ente.io."; - static String m50(verificationID) => + static String m49(verificationID) => "Hey, puoi confermare che questo è il tuo ID di verifica: ${verificationID} su ente.io"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "ente referral code: ${referralCode} \n\nApplicalo in Impostazioni → Generale → Referral per ottenere ${referralStorageInGB} GB gratis dopo la registrazione di un piano a pagamento\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Condividi con persone specifiche', one: 'Condividi con una persona', other: 'Condividi con ${numberOfPeople} persone')}"; - static String m53(emailIDs) => "Condiviso con ${emailIDs}"; + static String m52(emailIDs) => "Condiviso con ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "Questo ${fileType} verrà eliminato dal tuo dispositivo."; - static String m55(fileType) => + static String m54(fileType) => "Questo ${fileType} è sia su ente che sul tuo dispositivo."; - static String m56(fileType) => "Questo ${fileType} verrà eliminato su ente."; + static String m55(fileType) => "Questo ${fileType} verrà eliminato su ente."; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} di ${totalAmount} ${totalStorageUnit} utilizzati"; - static String m59(id) => + static String m58(id) => "Il tuo ${id} è già collegato ad un altro account ente.\nSe desideri utilizzare il tuo ${id} con questo account, contatta il nostro supporto\'\'"; - static String m60(endDate) => "L\'abbonamento verrà cancellato il ${endDate}"; + static String m59(endDate) => "L\'abbonamento verrà cancellato il ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} ricordi conservati"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "Anche loro riceveranno ${storageAmountInGB} GB"; - static String m63(email) => "Questo è l\'ID di verifica di ${email}"; + static String m62(email) => "Questo è l\'ID di verifica di ${email}"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '', one: '1 giorno', other: '${count} giorni')}"; - static String m65(endDate) => "Valido fino al ${endDate}"; + static String m64(endDate) => "Valido fino al ${endDate}"; - static String m66(email) => "Verifica ${email}"; + static String m65(email) => "Verifica ${email}"; - static String m67(email) => + static String m66(email) => "Abbiamo inviato una mail a ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: '${count} anno fa', other: '${count} anni fa')}"; - static String m69(storageSaved) => + static String m68(storageSaved) => "Hai liberato con successo ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -967,7 +964,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Pagamento non riuscito"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronizzazione in sospeso"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage( @@ -987,7 +983,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage( "Selezionare il punto centrale"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Fissa l\'album"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abbonamento su PlayStore"), "pleaseContactSupportAndWeWillBeHappyToHelp": @@ -996,12 +992,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Riprova. Se il problema persiste, ti invitiamo a contattare l\'assistenza"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Concedi i permessi"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Effettua nuovamente l\'accesso"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Riprova"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage( @@ -1035,7 +1031,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Invia ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Valuta l\'app"), "rateUs": MessageLookupByLibrary.simpleMessage("Lascia una recensione"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Recupera"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recupera account"), @@ -1067,7 +1063,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Condividi questo codice con i tuoi amici"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Si iscrivono per un piano a pagamento"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Invita un Amico"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "I referral code sono attualmente in pausa"), @@ -1091,7 +1087,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Elimina link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Rimuovi partecipante"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Rimuovi link pubblico"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1105,7 +1101,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Rinomina file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Rinnova abbonamento"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Segnala un bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Segnala un bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Rinvia email"), @@ -1170,8 +1166,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Gli elementi selezionati verranno eliminati da tutti gli album e spostati nel cestino."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Invia"), "sendEmail": MessageLookupByLibrary.simpleMessage("Invia email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Invita"), @@ -1195,16 +1191,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Condividi un album"), "shareLink": MessageLookupByLibrary.simpleMessage("Condividi link"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Condividi solo con le persone che vuoi"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Scarica ente in modo da poter facilmente condividere foto e video senza perdita di qualità\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Condividi con utenti che non hanno un account ente"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Condividi il tuo primo album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1215,7 +1211,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nuove foto condivise"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Ricevi notifiche quando qualcuno aggiunge una foto a un album condiviso, di cui fai parte"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Condivisi con me"), "sharedWithYou": @@ -1225,11 +1221,11 @@ class MessageLookup extends MessageLookupByLibrary { "showMemories": MessageLookupByLibrary.simpleMessage("Mostra ricordi"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Accetto i termini di servizio e la politica sulla privacy"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Verrà eliminato da tutti gli album."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Salta"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1270,13 +1266,13 @@ class MessageLookup extends MessageLookupByLibrary { "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Famiglia"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Tu"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Limite d\'archiviazione superato"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Forte"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("Iscriviti"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Sembra che il tuo abbonamento sia scaduto. Iscriviti per abilitare la condivisione."), @@ -1293,7 +1289,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Suggerisci una funzionalità"), "support": MessageLookupByLibrary.simpleMessage("Assistenza"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Sincronizzazione interrotta"), "syncing": MessageLookupByLibrary.simpleMessage( @@ -1322,7 +1318,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Questi file verranno eliminati dal tuo dispositivo."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Verranno eliminati da tutti gli album."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1339,7 +1335,7 @@ class MessageLookup extends MessageLookupByLibrary { "Questo indirizzo email è già registrato"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Questa immagine non ha dati EXIF"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Questo è il tuo ID di verifica"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1355,7 +1351,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("totale"), "totalSize": MessageLookupByLibrary.simpleMessage("Dimensioni totali"), "trash": MessageLookupByLibrary.simpleMessage("Cestino"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("Riprova"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Attiva il backup per caricare automaticamente i file aggiunti in questa cartella del dispositivo su ente."), @@ -1412,7 +1408,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Usa la foto selezionata"), "usedSpace": MessageLookupByLibrary.simpleMessage("Spazio utilizzato"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verifica fallita, per favore prova di nuovo"), @@ -1420,7 +1416,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ID di verifica"), "verify": MessageLookupByLibrary.simpleMessage("Verifica"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Verifica email"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verifica"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Verifica password"), @@ -1447,11 +1443,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Non puoi modificare foto e album che non possiedi"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Debole"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bentornato/a!"), "yearly": MessageLookupByLibrary.simpleMessage("Annuale"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Si"), "yesCancel": MessageLookupByLibrary.simpleMessage("Sì, cancella"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1481,7 +1477,7 @@ class MessageLookup extends MessageLookupByLibrary { "Non puoi condividere con te stesso"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Non hai nulla di archiviato."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Il tuo account è stato eliminato"), "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), diff --git a/mobile/lib/generated/intl/messages_nl.dart b/mobile/lib/generated/intl/messages_nl.dart index 1f53a6ffe..fe49550d6 100644 --- a/mobile/lib/generated/intl/messages_nl.dart +++ b/mobile/lib/generated/intl/messages_nl.dart @@ -131,91 +131,88 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Praat met ${providerName} klantenservice als u in rekening bent gebracht"; - static String m38(reason) => - "Helaas is uw betaling mislukt vanwege ${reason}"; - - static String m39(endDate) => + static String m38(endDate) => "Gratis proefperiode geldig tot ${endDate}.\nU kunt naderhand een betaald abonnement kiezen."; - static String m40(toEmail) => "Stuur ons een e-mail op ${toEmail}"; + static String m39(toEmail) => "Stuur ons een e-mail op ${toEmail}"; - static String m41(toEmail) => + static String m40(toEmail) => "Verstuur de logboeken alstublieft naar ${toEmail}"; - static String m42(storeName) => "Beoordeel ons op ${storeName}"; + static String m41(storeName) => "Beoordeel ons op ${storeName}"; - static String m43(storageInGB) => + static String m42(storageInGB) => "Jullie krijgen allebei ${storageInGB} GB* gratis"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} zal worden verwijderd uit dit gedeelde album\n\nAlle door hen toegevoegde foto\'s worden ook uit het album verwijderd"; - static String m45(endDate) => "Wordt verlengd op ${endDate}"; + static String m44(endDate) => "Wordt verlengd op ${endDate}"; - static String m46(count) => + static String m45(count) => "${Intl.plural(count, one: '${count} resultaat gevonden', other: '${count} resultaten gevonden')}"; - static String m47(count) => "${count} geselecteerd"; + static String m46(count) => "${count} geselecteerd"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} geselecteerd (${yourCount} van jou)"; - static String m49(verificationID) => + static String m48(verificationID) => "Hier is mijn verificatie-ID: ${verificationID} voor ente.io."; - static String m50(verificationID) => + static String m49(verificationID) => "Hey, kunt u bevestigen dat dit uw ente.io verificatie-ID is: ${verificationID}"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "ente verwijzingscode: ${referralCode} \n\nPas het toe bij Instellingen → Algemeen → Verwijzingen om ${referralStorageInGB} GB gratis te krijgen nadat je je hebt aangemeld voor een betaald abonnement\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Deel met specifieke mensen', one: 'Gedeeld met 1 persoon', other: 'Gedeeld met ${numberOfPeople} mensen')}"; - static String m53(emailIDs) => "Gedeeld met ${emailIDs}"; + static String m52(emailIDs) => "Gedeeld met ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "Deze ${fileType} zal worden verwijderd van jouw apparaat."; - static String m55(fileType) => + static String m54(fileType) => "Deze ${fileType} staat zowel in ente als op jouw apparaat."; - static String m56(fileType) => + static String m55(fileType) => "Deze ${fileType} zal worden verwijderd uit ente."; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} van ${totalAmount} ${totalStorageUnit} gebruikt"; - static String m59(id) => + static String m58(id) => "Uw ${id} is al aan een ander ente account gekoppeld.\nAls u uw ${id} wilt gebruiken met dit account, neem dan contact op met onze klantenservice"; - static String m60(endDate) => "Uw abonnement loopt af op ${endDate}"; + static String m59(endDate) => "Uw abonnement loopt af op ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} herinneringen bewaard"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "Zij krijgen ook ${storageAmountInGB} GB"; - static String m63(email) => "Dit is de verificatie-ID van ${email}"; + static String m62(email) => "Dit is de verificatie-ID van ${email}"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '', one: '1 dag', other: '${count} dagen')}"; - static String m65(endDate) => "Geldig tot ${endDate}"; + static String m64(endDate) => "Geldig tot ${endDate}"; - static String m66(email) => "Verifieer ${email}"; + static String m65(email) => "Verifieer ${email}"; - static String m67(email) => + static String m66(email) => "We hebben een e-mail gestuurd naar ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: '${count} jaar geleden', other: '${count} jaar geleden')}"; - static String m69(storageSaved) => + static String m68(storageSaved) => "Je hebt ${storageSaved} succesvol vrijgemaakt!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -1020,7 +1017,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Betaling mislukt"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Bestanden in behandeling"), "pendingSync": MessageLookupByLibrary.simpleMessage( @@ -1048,7 +1044,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Album bovenaan vastzetten"), "playOnTv": MessageLookupByLibrary.simpleMessage("Album afspelen op TV"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore abonnement"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1060,12 +1056,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Neem contact op met klantenservice als het probleem aanhoudt"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Geef alstublieft toestemming"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Log opnieuw in"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Probeer het nog eens"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1100,7 +1096,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Meld probleem"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Beoordeel de app"), "rateUs": MessageLookupByLibrary.simpleMessage("Beoordeel ons"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Herstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Account herstellen"), @@ -1131,7 +1127,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Geef deze code aan je vrienden"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ze registreren voor een betaald plan"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Referenties"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Verwijzingen zijn momenteel gepauzeerd"), @@ -1157,7 +1153,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Verwijder link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Deelnemer verwijderen"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Verwijder publieke link"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1173,7 +1169,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bestandsnaam wijzigen"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonnement verlengen"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Een fout melden"), "reportBug": MessageLookupByLibrary.simpleMessage("Fout melden"), "resendEmail": @@ -1235,7 +1231,7 @@ class MessageLookup extends MessageLookupByLibrary { "Foto\'s groeperen die in een bepaalde straal van een foto worden genomen"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Nodig mensen uit, en je ziet alle foto\'s die door hen worden gedeeld hier"), - "searchResultCount": m46, + "searchResultCount": m45, "security": MessageLookupByLibrary.simpleMessage("Beveiliging"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selecteer een locatie"), @@ -1262,8 +1258,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Geselecteerde bestanden worden verwijderd uit alle albums en verplaatst naar de prullenbak."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Verzenden"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-mail versturen"), "sendInvite": @@ -1287,16 +1283,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Deel nu een album"), "shareLink": MessageLookupByLibrary.simpleMessage("Link delen"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Deel alleen met de mensen die u wilt"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Download ente zodat we gemakkelijk foto\'s en video\'s van originele kwaliteit kunnen delen\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Delen met niet-ente gebruikers"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Deel jouw eerste album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1307,7 +1303,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nieuwe gedeelde foto\'s"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Ontvang meldingen wanneer iemand een foto toevoegt aan een gedeeld album waar je deel van uitmaakt"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Gedeeld met mij"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Gedeeld met jou"), @@ -1322,11 +1318,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Log uit op andere apparaten"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Ik ga akkoord met de gebruiksvoorwaarden en privacybeleid"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Het wordt uit alle albums verwijderd."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Overslaan"), "social": MessageLookupByLibrary.simpleMessage("Sociale media"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( @@ -1364,13 +1360,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Opslagruimte"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familie"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Jij"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Opslaglimiet overschreden"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Sterk"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("Abonneer"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Het lijkt erop dat je abonnement is verlopen. Abonneer om delen mogelijk te maken."), @@ -1387,7 +1383,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Features voorstellen"), "support": MessageLookupByLibrary.simpleMessage("Ondersteuning"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Synchronisatie gestopt"), "syncing": MessageLookupByLibrary.simpleMessage("Synchroniseren..."), @@ -1415,7 +1411,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Deze bestanden zullen worden verwijderd van uw apparaat."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Ze zullen uit alle albums worden verwijderd."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1431,7 +1427,7 @@ class MessageLookup extends MessageLookupByLibrary { "Dit e-mailadres is al in gebruik"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Deze foto heeft geen exif gegevens"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage("Dit is uw verificatie-ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1448,7 +1444,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("totaal"), "totalSize": MessageLookupByLibrary.simpleMessage("Totale grootte"), "trash": MessageLookupByLibrary.simpleMessage("Prullenbak"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("Probeer opnieuw"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Schakel back-up in om bestanden die toegevoegd zijn aan deze map op dit apparaat automatisch te uploaden."), @@ -1504,7 +1500,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Gebruik geselecteerde foto"), "usedSpace": MessageLookupByLibrary.simpleMessage("Gebruikte ruimte"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verificatie mislukt, probeer het opnieuw"), @@ -1512,7 +1508,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verificatie ID"), "verify": MessageLookupByLibrary.simpleMessage("Verifiëren"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Bevestig e-mail"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verifiëren"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Bevestig wachtwoord"), @@ -1541,11 +1537,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "We ondersteunen het bewerken van foto\'s en albums waar je niet de eigenaar van bent nog niet"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Zwak"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Welkom terug!"), "yearly": MessageLookupByLibrary.simpleMessage("Jaarlijks"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Ja"), "yesCancel": MessageLookupByLibrary.simpleMessage("Ja, opzeggen"), "yesConvertToViewer": @@ -1575,7 +1571,7 @@ class MessageLookup extends MessageLookupByLibrary { "Je kunt niet met jezelf delen"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "U heeft geen gearchiveerde bestanden."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Je account is verwijderd"), "yourMap": MessageLookupByLibrary.simpleMessage("Jouw kaart"), diff --git a/mobile/lib/generated/intl/messages_pt.dart b/mobile/lib/generated/intl/messages_pt.dart index ffdc0d257..a9a5bc0da 100644 --- a/mobile/lib/generated/intl/messages_pt.dart +++ b/mobile/lib/generated/intl/messages_pt.dart @@ -130,88 +130,85 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "Por favor, fale com o suporte ${providerName} se você foi cobrado"; - static String m38(reason) => - "Infelizmente o seu pagamento falhou devido a ${reason}"; - - static String m39(endDate) => + static String m38(endDate) => "Teste gratuito válido até ${endDate}.\nVocê pode escolher um plano pago depois."; - static String m40(toEmail) => + static String m39(toEmail) => "Por favor, envie-nos um e-mail para ${toEmail}"; - static String m41(toEmail) => "Por favor, envie os logs para \n${toEmail}"; + static String m40(toEmail) => "Por favor, envie os logs para \n${toEmail}"; - static String m42(storeName) => "Avalie-nos em ${storeName}"; + static String m41(storeName) => "Avalie-nos em ${storeName}"; - static String m43(storageInGB) => "3. Ambos ganham ${storageInGB} GB* grátis"; + static String m42(storageInGB) => "3. Ambos ganham ${storageInGB} GB* grátis"; - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} será removido deste álbum compartilhado\n\nQuaisquer fotos adicionadas por eles também serão removidas do álbum"; - static String m45(endDate) => "Renovação de assinatura em ${endDate}"; + static String m44(endDate) => "Renovação de assinatura em ${endDate}"; - static String m46(count) => + static String m45(count) => "${Intl.plural(count, one: '${count} resultado encontrado', other: '${count} resultado encontrado')}"; - static String m47(count) => "${count} Selecionados"; + static String m46(count) => "${count} Selecionados"; - static String m48(count, yourCount) => + static String m47(count, yourCount) => "${count} Selecionado (${yourCount} seus)"; - static String m49(verificationID) => + static String m48(verificationID) => "Aqui está meu ID de verificação para o Ente.io: ${verificationID}"; - static String m50(verificationID) => + static String m49(verificationID) => "Ei, você pode confirmar que este é seu ID de verificação do Ente.io? ${verificationID}"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "Código de referência do ente: ${referralCode} \n\nAplique em Configurações → Geral → Indicações para obter ${referralStorageInGB} GB gratuitamente após a sua inscrição em um plano pago\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Compartilhe com pessoas específicas', one: 'Compartilhado com 1 pessoa', other: 'Compartilhado com ${numberOfPeople} pessoas')}"; - static String m53(emailIDs) => "Compartilhado com ${emailIDs}"; + static String m52(emailIDs) => "Compartilhado com ${emailIDs}"; - static String m54(fileType) => + static String m53(fileType) => "Este ${fileType} será excluído do seu dispositivo."; - static String m55(fileType) => + static String m54(fileType) => "Este ${fileType} está em ente e no seu dispositivo."; - static String m56(fileType) => "Este ${fileType} será excluído do ente."; + static String m55(fileType) => "Este ${fileType} será excluído do ente."; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} de ${totalAmount} ${totalStorageUnit} usado"; - static String m59(id) => + static String m58(id) => "Seu ${id} já está vinculado a outra conta ente.\nSe você gostaria de usar seu ${id} com esta conta, por favor contate nosso suporte\'\'"; - static String m60(endDate) => "Sua assinatura será cancelada em ${endDate}"; + static String m59(endDate) => "Sua assinatura será cancelada em ${endDate}"; - static String m61(completed, total) => + static String m60(completed, total) => "${completed}/${total} memórias preservadas"; - static String m62(storageAmountInGB) => + static String m61(storageAmountInGB) => "Eles também recebem ${storageAmountInGB} GB"; - static String m63(email) => "Este é o ID de verificação de ${email}"; + static String m62(email) => "Este é o ID de verificação de ${email}"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '', one: '1 dia', other: '${count} dias')}"; - static String m65(endDate) => "Válido até ${endDate}"; + static String m64(endDate) => "Válido até ${endDate}"; - static String m66(email) => "Verificar ${email}"; + static String m65(email) => "Verificar ${email}"; - static String m67(email) => "Enviamos um e-mail à ${email}"; + static String m66(email) => "Enviamos um e-mail à ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: '${count} anos atrás', other: '${count} anos atrás')}"; - static String m69(storageSaved) => + static String m68(storageSaved) => "Você liberou ${storageSaved} com sucesso!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -1015,7 +1012,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Falha no pagamento"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Itens pendentes"), "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronização pendente"), @@ -1041,7 +1037,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinAlbum": MessageLookupByLibrary.simpleMessage("Fixar álbum"), "playOnTv": MessageLookupByLibrary.simpleMessage("Reproduzir álbum na TV"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Assinatura da PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1053,12 +1049,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Por favor, contate o suporte se o problema persistir"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Por favor, conceda as permissões"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Por favor, faça login novamente"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Por favor, tente novamente"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1095,7 +1091,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Avalie o aplicativo"), "rateUs": MessageLookupByLibrary.simpleMessage("Avalie-nos"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("Recuperar"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperar conta"), @@ -1127,7 +1123,7 @@ class MessageLookup extends MessageLookupByLibrary { "Envie esse código aos seus amigos"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Eles se inscreveram para um plano pago"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("Indicações"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Referências estão atualmente pausadas"), @@ -1151,7 +1147,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Remover link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Remover participante"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("Remover link público"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1165,7 +1161,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Renomear arquivo"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renovar assinatura"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("Reportar um problema"), "reportBug": @@ -1230,7 +1226,7 @@ class MessageLookup extends MessageLookupByLibrary { "Fotos de grupo que estão sendo tiradas em algum raio da foto"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Convide pessoas e você verá todas as fotos compartilhadas por elas aqui"), - "searchResultCount": m46, + "searchResultCount": m45, "security": MessageLookupByLibrary.simpleMessage("Segurança"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selecionar um local"), @@ -1258,8 +1254,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Os itens selecionados serão excluídos de todos os álbuns e movidos para o lixo."), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("Enviar"), "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar e-mail"), "sendInvite": MessageLookupByLibrary.simpleMessage("Enviar convite"), @@ -1283,16 +1279,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Compartilhar um álbum agora"), "shareLink": MessageLookupByLibrary.simpleMessage("Compartilhar link"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Compartilhar apenas com as pessoas que você quiser"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Baixe o Ente para podermos compartilhar facilmente fotos e vídeos de alta qualidade\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Compartilhar com usuários não-Ente"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Compartilhar seu primeiro álbum"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1305,7 +1301,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Novas fotos compartilhadas"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Receber notificações quando alguém adicionar uma foto em um álbum compartilhado que você faz parte"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartilhado comigo"), "sharedWithYou": @@ -1321,11 +1317,11 @@ class MessageLookup extends MessageLookupByLibrary { "Terminar sessão em outros dispositivos"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Eu concordo com os termos de serviço e a política de privacidade"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Ele será excluído de todos os álbuns."), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("Pular"), "social": MessageLookupByLibrary.simpleMessage("Redes sociais"), "someItemsAreInBothEnteAndYourDevice": @@ -1366,13 +1362,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Armazenamento"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Família"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Você"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Limite de armazenamento excedido"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("Forte"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("Assinar"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Parece que sua assinatura expirou. Por favor inscreva-se para ativar o compartilhamento."), @@ -1389,7 +1385,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Sugerir funcionalidades"), "support": MessageLookupByLibrary.simpleMessage("Suporte"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("Sincronização interrompida"), "syncing": MessageLookupByLibrary.simpleMessage("Sincronizando..."), @@ -1416,7 +1412,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Estes itens serão excluídos do seu dispositivo."), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Ele será excluído de todos os álbuns."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1432,7 +1428,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Este e-mail já está em uso"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Esta imagem não tem dados exif"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Este é o seu ID de verificação"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1448,7 +1444,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("total"), "totalSize": MessageLookupByLibrary.simpleMessage("Tamanho total"), "trash": MessageLookupByLibrary.simpleMessage("Lixeira"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("Tente novamente"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Ative o backup para enviar automaticamente arquivos adicionados a esta pasta do dispositivo para o ente."), @@ -1501,7 +1497,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Utilizar foto selecionada"), "usedSpace": MessageLookupByLibrary.simpleMessage("Espaço em uso"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Falha na verificação, por favor, tente novamente"), @@ -1509,7 +1505,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ID de Verificação"), "verify": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Verificar email"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyPasskey": MessageLookupByLibrary.simpleMessage("Verificar chave de acesso"), @@ -1542,12 +1538,12 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Não suportamos a edição de fotos e álbuns que você ainda não possui"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("Fraca"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bem-vindo de volta!"), "yearly": MessageLookupByLibrary.simpleMessage("Anual"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("Sim"), "yesCancel": MessageLookupByLibrary.simpleMessage("Sim, cancelar"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1578,7 +1574,7 @@ class MessageLookup extends MessageLookupByLibrary { "Você não pode compartilhar consigo mesmo"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Você não tem nenhum item arquivado."), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Sua conta foi excluída"), "yourMap": MessageLookupByLibrary.simpleMessage("Seu mapa"), diff --git a/mobile/lib/generated/intl/messages_zh.dart b/mobile/lib/generated/intl/messages_zh.dart index ca420142b..0b0ef9ee1 100644 --- a/mobile/lib/generated/intl/messages_zh.dart +++ b/mobile/lib/generated/intl/messages_zh.dart @@ -122,79 +122,77 @@ class MessageLookup extends MessageLookupByLibrary { static String m37(providerName) => "如果您被收取费用,请用英语与 ${providerName} 的客服聊天"; - static String m38(reason) => "很抱歉,您的支付因 ${reason} 而失败"; + static String m38(endDate) => "免费试用有效期至 ${endDate}。\n之后您可以选择付费计划。"; - static String m39(endDate) => "免费试用有效期至 ${endDate}。\n之后您可以选择付费计划。"; + static String m39(toEmail) => "请给我们发送电子邮件至 ${toEmail}"; - static String m40(toEmail) => "请给我们发送电子邮件至 ${toEmail}"; + static String m40(toEmail) => "请将日志发送至 \n${toEmail}"; - static String m41(toEmail) => "请将日志发送至 \n${toEmail}"; + static String m41(storeName) => "在 ${storeName} 上给我们评分"; - static String m42(storeName) => "在 ${storeName} 上给我们评分"; + static String m42(storageInGB) => "3. 你和朋友都将免费获得 ${storageInGB} GB*"; - static String m43(storageInGB) => "3. 你和朋友都将免费获得 ${storageInGB} GB*"; - - static String m44(userEmail) => + static String m43(userEmail) => "${userEmail} 将从这个共享相册中删除\n\nTA们添加的任何照片也将从相册中删除"; - static String m45(endDate) => "在 ${endDate} 前续费"; + static String m44(endDate) => "在 ${endDate} 前续费"; - static String m46(count) => + static String m45(count) => "${Intl.plural(count, other: '已找到 ${count} 个结果')}"; - static String m47(count) => "已选择 ${count} 个"; + static String m46(count) => "已选择 ${count} 个"; - static String m48(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; + static String m47(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; - static String m49(verificationID) => "这是我的ente.io 的验证 ID: ${verificationID}。"; + static String m48(verificationID) => "这是我的ente.io 的验证 ID: ${verificationID}。"; - static String m50(verificationID) => + static String m49(verificationID) => "嘿,你能确认这是你的 ente.io 验证 ID吗:${verificationID}"; - static String m51(referralCode, referralStorageInGB) => + static String m50(referralCode, referralStorageInGB) => "ente推荐码: ${referralCode} \n\n注册付费计划后在设置 → 常规 → 推荐中应用它以免费获得 ${referralStorageInGB} GB空间\n\nhttps://ente.io"; - static String m52(numberOfPeople) => + static String m51(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: '与特定人员共享', one: '与 1 人共享', other: '与 ${numberOfPeople} 人共享')}"; - static String m53(emailIDs) => "与 ${emailIDs} 共享"; + static String m52(emailIDs) => "与 ${emailIDs} 共享"; - static String m54(fileType) => "此 ${fileType} 将从您的设备中删除。"; + static String m53(fileType) => "此 ${fileType} 将从您的设备中删除。"; - static String m55(fileType) => "此 ${fileType} 同时在ente和您的设备中。"; + static String m54(fileType) => "此 ${fileType} 同时在ente和您的设备中。"; - static String m56(fileType) => "此 ${fileType} 将从ente中删除。"; + static String m55(fileType) => "此 ${fileType} 将从ente中删除。"; - static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m56(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m58( + static String m57( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "已使用 ${usedAmount} ${usedStorageUnit} / ${totalAmount} ${totalStorageUnit}"; - static String m59(id) => + static String m58(id) => "您的 ${id} 已经链接到另一个ente账户。\n如果您想要通过此账户使用您的 ${id} ,请联系我们的客服\'\'"; - static String m60(endDate) => "您的订阅将于 ${endDate} 取消"; + static String m59(endDate) => "您的订阅将于 ${endDate} 取消"; - static String m61(completed, total) => "已保存的回忆 ${completed}/共 ${total}"; + static String m60(completed, total) => "已保存的回忆 ${completed}/共 ${total}"; - static String m62(storageAmountInGB) => "他们也会获得 ${storageAmountInGB} GB"; + static String m61(storageAmountInGB) => "他们也会获得 ${storageAmountInGB} GB"; - static String m63(email) => "这是 ${email} 的验证ID"; + static String m62(email) => "这是 ${email} 的验证ID"; - static String m64(count) => + static String m63(count) => "${Intl.plural(count, zero: '', one: '1天', other: '${count} 天')}"; - static String m65(endDate) => "有效期至 ${endDate}"; + static String m64(endDate) => "有效期至 ${endDate}"; - static String m66(email) => "验证 ${email}"; + static String m65(email) => "验证 ${email}"; - static String m67(email) => "我们已经发送邮件到 ${email}"; + static String m66(email) => "我们已经发送邮件到 ${email}"; - static String m68(count) => + static String m67(count) => "${Intl.plural(count, one: '${count} 年前', other: '${count} 年前')}"; - static String m69(storageSaved) => "您已成功释放了 ${storageSaved}!"; + static String m68(storageSaved) => "您已成功释放了 ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -838,7 +836,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentDetails": MessageLookupByLibrary.simpleMessage("付款明细"), "paymentFailed": MessageLookupByLibrary.simpleMessage("支付失败"), "paymentFailedTalkToProvider": m37, - "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("待处理项目"), "pendingSync": MessageLookupByLibrary.simpleMessage("正在等待同步"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("使用您的代码的人"), @@ -856,7 +853,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage("选择中心点"), "pinAlbum": MessageLookupByLibrary.simpleMessage("置顶相册"), "playOnTv": MessageLookupByLibrary.simpleMessage("在电视上播放相册"), - "playStoreFreeTrialValidTill": m39, + "playStoreFreeTrialValidTill": m38, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore 订阅"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -866,10 +863,10 @@ class MessageLookup extends MessageLookupByLibrary { "请用英语联系 support@ente.io ,我们将乐意提供帮助!"), "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage("如果问题仍然存在,请联系支持"), - "pleaseEmailUsAt": m40, + "pleaseEmailUsAt": m39, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("请授予权限"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("请重新登录"), - "pleaseSendTheLogsTo": m41, + "pleaseSendTheLogsTo": m40, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("请重试"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage("请验证您输入的代码"), @@ -895,7 +892,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("提升工单"), "rateTheApp": MessageLookupByLibrary.simpleMessage("为此应用评分"), "rateUs": MessageLookupByLibrary.simpleMessage("给我们评分"), - "rateUsOnStore": m42, + "rateUsOnStore": m41, "recover": MessageLookupByLibrary.simpleMessage("恢复"), "recoverAccount": MessageLookupByLibrary.simpleMessage("恢复账户"), "recoverButton": MessageLookupByLibrary.simpleMessage("恢复"), @@ -920,7 +917,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("把我们推荐给你的朋友然后获得延长一倍的订阅计划"), "referralStep1": MessageLookupByLibrary.simpleMessage("1. 将此代码提供给您的朋友"), "referralStep2": MessageLookupByLibrary.simpleMessage("2. 他们注册一个付费计划"), - "referralStep3": m43, + "referralStep3": m42, "referrals": MessageLookupByLibrary.simpleMessage("推荐人"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("推荐已暂停"), @@ -939,7 +936,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeFromFavorite": MessageLookupByLibrary.simpleMessage("从收藏中移除"), "removeLink": MessageLookupByLibrary.simpleMessage("移除链接"), "removeParticipant": MessageLookupByLibrary.simpleMessage("移除参与者"), - "removeParticipantBody": m44, + "removeParticipantBody": m43, "removePublicLink": MessageLookupByLibrary.simpleMessage("删除公开链接"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage("您要删除的某些项目是由其他人添加的,您将无法访问它们"), @@ -950,7 +947,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameAlbum": MessageLookupByLibrary.simpleMessage("重命名相册"), "renameFile": MessageLookupByLibrary.simpleMessage("重命名文件"), "renewSubscription": MessageLookupByLibrary.simpleMessage("续费订阅"), - "renewsOn": m45, + "renewsOn": m44, "reportABug": MessageLookupByLibrary.simpleMessage("报告错误"), "reportBug": MessageLookupByLibrary.simpleMessage("报告错误"), "resendEmail": MessageLookupByLibrary.simpleMessage("重新发送电子邮件"), @@ -997,7 +994,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"), - "searchResultCount": m46, + "searchResultCount": m45, "security": MessageLookupByLibrary.simpleMessage("安全"), "selectALocation": MessageLookupByLibrary.simpleMessage("选择一个位置"), "selectALocationFirst": @@ -1017,8 +1014,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("所选文件夹将被加密和备份"), "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage("所选项目将从所有相册中删除并移动到回收站。"), - "selectedPhotos": m47, - "selectedPhotosWithYours": m48, + "selectedPhotos": m46, + "selectedPhotosWithYours": m47, "send": MessageLookupByLibrary.simpleMessage("发送"), "sendEmail": MessageLookupByLibrary.simpleMessage("发送电子邮件"), "sendInvite": MessageLookupByLibrary.simpleMessage("发送邀请"), @@ -1037,16 +1034,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("打开相册并点击右上角的分享按钮进行分享"), "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("立即分享相册"), "shareLink": MessageLookupByLibrary.simpleMessage("分享链接"), - "shareMyVerificationID": m49, + "shareMyVerificationID": m48, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage("仅与您想要的人分享"), - "shareTextConfirmOthersVerificationID": m50, + "shareTextConfirmOthersVerificationID": m49, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "下载 ente,以便我们轻松分享原始质量的照片和视频\n\nhttps://ente.io"), - "shareTextReferralCode": m51, + "shareTextReferralCode": m50, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("与非ente 用户分享"), - "shareWithPeopleSectionTitle": m52, + "shareWithPeopleSectionTitle": m51, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("分享您的第一个相册"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1057,7 +1054,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("新共享的照片"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage("当有人将照片添加到您所属的共享相册时收到通知"), - "sharedWith": m53, + "sharedWith": m52, "sharedWithMe": MessageLookupByLibrary.simpleMessage("与我共享"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("已与您共享"), "sharing": MessageLookupByLibrary.simpleMessage("正在分享..."), @@ -1069,11 +1066,11 @@ class MessageLookup extends MessageLookupByLibrary { "signOutOtherDevices": MessageLookupByLibrary.simpleMessage("登出其他设备"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "我同意 服务条款隐私政策"), - "singleFileDeleteFromDevice": m54, + "singleFileDeleteFromDevice": m53, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage("它将从所有相册中删除。"), - "singleFileInBothLocalAndRemote": m55, - "singleFileInRemoteOnly": m56, + "singleFileInBothLocalAndRemote": m54, + "singleFileInRemoteOnly": m55, "skip": MessageLookupByLibrary.simpleMessage("跳过"), "social": MessageLookupByLibrary.simpleMessage("社交"), "someItemsAreInBothEnteAndYourDevice": @@ -1104,12 +1101,12 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("存储空间"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("家庭"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("您"), - "storageInGB": m57, + "storageInGB": m56, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("已超出存储限制"), - "storageUsageInfo": m58, + "storageUsageInfo": m57, "strongStrength": MessageLookupByLibrary.simpleMessage("强"), - "subAlreadyLinkedErrMessage": m59, - "subWillBeCancelledOn": m60, + "subAlreadyLinkedErrMessage": m58, + "subWillBeCancelledOn": m59, "subscribe": MessageLookupByLibrary.simpleMessage("订阅"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage("您的订阅似乎已过期。请订阅以启用分享。"), @@ -1122,7 +1119,7 @@ class MessageLookup extends MessageLookupByLibrary { "successfullyUnhid": MessageLookupByLibrary.simpleMessage("已成功取消隐藏"), "suggestFeatures": MessageLookupByLibrary.simpleMessage("建议新功能"), "support": MessageLookupByLibrary.simpleMessage("支持"), - "syncProgress": m61, + "syncProgress": m60, "syncStopped": MessageLookupByLibrary.simpleMessage("同步已停止"), "syncing": MessageLookupByLibrary.simpleMessage("正在同步···"), "systemTheme": MessageLookupByLibrary.simpleMessage("适应系统"), @@ -1145,7 +1142,7 @@ class MessageLookup extends MessageLookupByLibrary { "theme": MessageLookupByLibrary.simpleMessage("主题"), "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage("这些项目将从您的设备中删除。"), - "theyAlsoGetXGb": m62, + "theyAlsoGetXGb": m61, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage("他们将从所有相册中删除。"), "thisActionCannotBeUndone": @@ -1159,7 +1156,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("这个邮箱地址已经被使用"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage("此图像没有Exif 数据"), - "thisIsPersonVerificationId": m63, + "thisIsPersonVerificationId": m62, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage("这是您的验证 ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1173,7 +1170,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("总计"), "totalSize": MessageLookupByLibrary.simpleMessage("总大小"), "trash": MessageLookupByLibrary.simpleMessage("回收站"), - "trashDaysLeft": m64, + "trashDaysLeft": m63, "tryAgain": MessageLookupByLibrary.simpleMessage("请再试一次"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage("打开备份以自动上传添加到此设备文件夹的文件。"), @@ -1216,13 +1213,13 @@ class MessageLookup extends MessageLookupByLibrary { "useRecoveryKey": MessageLookupByLibrary.simpleMessage("使用恢复密钥"), "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("使用所选照片"), "usedSpace": MessageLookupByLibrary.simpleMessage("已用空间"), - "validTill": m65, + "validTill": m64, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage("验证失败,请重试"), "verificationId": MessageLookupByLibrary.simpleMessage("验证 ID"), "verify": MessageLookupByLibrary.simpleMessage("验证"), "verifyEmail": MessageLookupByLibrary.simpleMessage("验证电子邮件"), - "verifyEmailID": m66, + "verifyEmailID": m65, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("验证"), "verifyPasskey": MessageLookupByLibrary.simpleMessage("验证通行密钥"), "verifyPassword": MessageLookupByLibrary.simpleMessage("验证密码"), @@ -1246,11 +1243,11 @@ class MessageLookup extends MessageLookupByLibrary { "weAreOpenSource": MessageLookupByLibrary.simpleMessage("我们是开源的 !"), "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage("我们不支持编辑您尚未拥有的照片和相册"), - "weHaveSendEmailTo": m67, + "weHaveSendEmailTo": m66, "weakStrength": MessageLookupByLibrary.simpleMessage("弱"), "welcomeBack": MessageLookupByLibrary.simpleMessage("欢迎回来!"), "yearly": MessageLookupByLibrary.simpleMessage("每年"), - "yearsAgo": m68, + "yearsAgo": m67, "yes": MessageLookupByLibrary.simpleMessage("是"), "yesCancel": MessageLookupByLibrary.simpleMessage("是的,取消"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("是的,转换为查看者"), @@ -1276,7 +1273,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("莫开玩笑,您不能与自己分享"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage("您没有任何存档的项目。"), - "youHaveSuccessfullyFreedUp": m69, + "youHaveSuccessfullyFreedUp": m68, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("您的账户已删除"), "yourMap": MessageLookupByLibrary.simpleMessage("您的地图"), diff --git a/mobile/lib/generated/l10n.dart b/mobile/lib/generated/l10n.dart index 78e376d48..41e24e7aa 100644 --- a/mobile/lib/generated/l10n.dart +++ b/mobile/lib/generated/l10n.dart @@ -4465,13 +4465,13 @@ class S { ); } - /// `Unfortunately your payment failed due to {reason}` - String paymentFailedWithReason(Object reason) { + /// `Unfortunately your payment failed. Please contact support and we'll help you out!` + String get paymentFailedMessage { return Intl.message( - 'Unfortunately your payment failed due to $reason', - name: 'paymentFailedWithReason', + 'Unfortunately your payment failed. Please contact support and we\'ll help you out!', + name: 'paymentFailedMessage', desc: '', - args: [reason], + args: [], ); } diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index eff0f8940..5bf175140 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -640,7 +640,7 @@ "thankYou": "Thank you", "failedToVerifyPaymentStatus": "Failed to verify payment status", "pleaseWaitForSometimeBeforeRetrying": "Please wait for sometime before retrying", - "paymentFailedWithReason": "Unfortunately your payment failed due to {reason}", + "paymentFailedMessage": "Unfortunately your payment failed. Please contact support and we'll help you out!", "youAreOnAFamilyPlan": "You are on a family plan!", "contactFamilyAdmin": "Please contact {familyAdminEmail} to manage your subscription", "leaveFamily": "Leave family", diff --git a/mobile/lib/ui/payment/payment_web_page.dart b/mobile/lib/ui/payment/payment_web_page.dart index 39f4ea9d0..cbe55f671 100644 --- a/mobile/lib/ui/payment/payment_web_page.dart +++ b/mobile/lib/ui/payment/payment_web_page.dart @@ -5,14 +5,15 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:logging/logging.dart'; +import "package:photos/core/constants.dart"; import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/models/subscription.dart'; import 'package:photos/services/billing_service.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/ui/common/loading_widget.dart'; -import 'package:photos/ui/common/progress_dialog.dart'; import 'package:photos/utils/dialog_util.dart'; +import "package:photos/utils/email_util.dart"; class PaymentWebPage extends StatefulWidget { final String? planId; @@ -30,7 +31,6 @@ class _PaymentWebPageState extends State { final UserService userService = UserService.instance; final BillingService billingService = BillingService.instance; final String basePaymentUrl = kWebPaymentBaseEndpoint; - late ProgressDialog _dialog; InAppWebViewController? webView; double progress = 0; Uri? initPaymentUrl; @@ -49,11 +49,6 @@ class _PaymentWebPageState extends State { @override Widget build(BuildContext context) { - _dialog = createProgressDialog( - context, - S.of(context).pleaseWait, - isDismissible: true, - ); if (initPaymentUrl == null) { return const EnteLoadingWidget(); } @@ -93,27 +88,20 @@ class _PaymentWebPageState extends State { return NavigationActionPolicy.ALLOW; }, onConsoleMessage: (controller, consoleMessage) { - _logger.info(consoleMessage); + _logger.info("onConsoleMessage $consoleMessage"); }, onLoadStart: (controller, navigationAction) async { - if (!_dialog.isShowing()) { - await _dialog.show(); - } + _logger.info("onLoadStart $navigationAction"); }, onLoadError: (controller, navigationAction, code, msg) async { - if (_dialog.isShowing()) { - await _dialog.hide(); - } + _logger.severe("onLoadError $navigationAction $code $msg"); }, onLoadHttpError: (controller, navigationAction, code, msg) async { _logger.info("onHttpError with $code and msg = $msg"); }, onLoadStop: (controller, navigationAction) async { - _logger.info("loadStart" + navigationAction.toString()); - if (_dialog.isShowing()) { - await _dialog.hide(); - } + _logger.info("onLoadStop $navigationAction"); }, ), ), @@ -125,7 +113,6 @@ class _PaymentWebPageState extends State { @override void dispose() { - _dialog.hide(); super.dispose(); } @@ -207,12 +194,17 @@ class _PaymentWebPageState extends State { barrierDismissible: false, builder: (context) => AlertDialog( title: Text(S.of(context).paymentFailed), - content: Text(S.of(context).paymentFailedWithReason(reason)), + content: Text(S.of(context).paymentFailedMessage), actions: [ TextButton( - child: Text(S.of(context).ok), - onPressed: () { + child: Text(S.of(context).contactSupport), + onPressed: () async { Navigator.of(context).pop('dialog'); + await sendEmail( + context, + to: supportEmail, + subject: "Billing issue", + ); }, ), ], @@ -224,7 +216,6 @@ class _PaymentWebPageState extends State { // return true if verifySubscription didn't throw any exceptions Future _handlePaymentSuccess(Map queryParams) async { final checkoutSessionID = queryParams['session_id'] ?? ''; - await _dialog.show(); try { // ignore: unused_local_variable final response = await billingService.verifySubscription( @@ -232,7 +223,6 @@ class _PaymentWebPageState extends State { checkoutSessionID, paymentProvider: stripe, ); - await _dialog.hide(); final content = widget.actionType == 'buy' ? S.of(context).yourPurchaseWasSuccessful : S.of(context).yourSubscriptionWasUpdatedSuccessfully; @@ -242,7 +232,6 @@ class _PaymentWebPageState extends State { ); } catch (error) { _logger.severe(error); - await _dialog.hide(); await _showExitPageDialog( title: S.of(context).failedToVerifyPaymentStatus, content: S.of(context).pleaseWaitForSometimeBeforeRetrying, From a131c16f4e82f33afe754ba5c6a1a91a955ad0d3 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 26 Mar 2024 20:29:55 +0530 Subject: [PATCH 20/24] Depend on subscription-past-due events to trigger the account-on-hold email --- server/pkg/controller/stripe.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index d065714ef..c8c70cc58 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -404,20 +404,6 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } - // Send an email to the user - user, err := c.UserRepo.Get(userID) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - // TODO: Inform customer that payment_failed.html with invoice.HostedInvoiceURL - err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", - ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ - "PaymentProvider": "Stripe", - "InvoiceURL": invoice.HostedInvoiceURL, - }, nil) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil } From 31d3319d20174f605a59f4c2085b9b1f39cffe34 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 26 Mar 2024 20:59:02 +0530 Subject: [PATCH 21/24] Revert "Depend on subscription-past-due events to trigger the account-on-hold email" This reverts commit a131c16f4e82f33afe754ba5c6a1a91a955ad0d3. --- server/pkg/controller/stripe.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index c8c70cc58..d065714ef 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -404,6 +404,20 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } + // Send an email to the user + user, err := c.UserRepo.Get(userID) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + // TODO: Inform customer that payment_failed.html with invoice.HostedInvoiceURL + err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", + ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ + "PaymentProvider": "Stripe", + "InvoiceURL": invoice.HostedInvoiceURL, + }, nil) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil } From 888aca7e6c16142f0d1771d7fb3d1cbbe4458290 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 26 Mar 2024 21:11:57 +0530 Subject: [PATCH 22/24] Extract common code --- server/pkg/controller/stripe.go | 34 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index d065714ef..7a98f8bb7 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -287,14 +287,7 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, userID := currentSubscription.UserID if stripeSubscription.Status == stripe.SubscriptionStatusPastDue { - user, err := c.UserRepo.Get(userID) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", - ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ - "PaymentProvider": "Stripe", - }, nil) + err = c.sendAccountOnHoldEmail(userID) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } @@ -404,20 +397,11 @@ func (c *StripeController) handlePaymentIntentFailed(event stripe.Event, country if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } - // Send an email to the user - user, err := c.UserRepo.Get(userID) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - // TODO: Inform customer that payment_failed.html with invoice.HostedInvoiceURL - err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", - ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ - "PaymentProvider": "Stripe", - "InvoiceURL": invoice.HostedInvoiceURL, - }, nil) + err = c.sendAccountOnHoldEmail(userID) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } + return ente.StripeEventLog{UserID: userID, StripeSubscription: *stripeSubscription, Event: event}, nil } @@ -563,6 +547,18 @@ func (c *StripeController) GetStripeCustomerPortal(userID int64, redirectRootURL return ps.URL, nil } +func (c *StripeController) sendAccountOnHoldEmail(userID int64) error { + user, err := c.UserRepo.Get(userID) + if err != nil { + return stacktrace.Propagate(err, "") + } + err = email.SendTemplatedEmail([]string{user.Email}, "ente", "support@ente.io", + ente.AccountOnHoldEmailSubject, ente.OnHoldTemplate, map[string]interface{}{ + "PaymentProvider": "Stripe", + }, nil) + return err +} + func (c *StripeController) getStripeSubscriptionFromSession(userID int64, checkoutSessionID string) (stripe.Subscription, error) { subscription, err := c.BillingRepo.GetUserSubscription(userID) if err != nil { From c9618d8038a909ac77c14c9028c696f348d6b39c Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 26 Mar 2024 21:31:29 +0530 Subject: [PATCH 23/24] Update copy --- server/mail-templates/on_hold.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/mail-templates/on_hold.html b/server/mail-templates/on_hold.html index b53ac5df8..6cce9e6c9 100644 --- a/server/mail-templates/on_hold.html +++ b/server/mail-templates/on_hold.html @@ -234,7 +234,7 @@ from {{.PaymentProvider}} within the next - 30 days, our systems + 31 days, our systems may remove your account and all associated data with From 25a054287aa4193bf90fcfb88df7fba1ec9c1bfe Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 27 Mar 2024 14:22:30 +0530 Subject: [PATCH 24/24] Prevent duplicate emails for SEPA --- server/pkg/controller/stripe.go | 67 ++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/server/pkg/controller/stripe.go b/server/pkg/controller/stripe.go index 7a98f8bb7..f9da66c19 100644 --- a/server/pkg/controller/stripe.go +++ b/server/pkg/controller/stripe.go @@ -269,9 +269,8 @@ func (c *StripeController) handleCheckoutSessionCompleted(event stripe.Event, co // Stripe fires this when a subscription starts or changes. For example, // renewing a subscription, adding a coupon, applying a discount, adding an // invoice item, and changing plans all trigger this event. In our case, we use -// this only to track plan changes or subscriptions going past due. The rest -// (subscription creations, deletions, renewals and failures) are tracked by -// individual events. +// this only to track plan changes and renewal failures resulting in +// subscriptions going past due. func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, country ente.StripeAccountCountry) (ente.StripeEventLog, error) { var stripeSubscription stripe.Subscription json.Unmarshal(event.Data.Raw, &stripeSubscription) @@ -284,15 +283,7 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, } return ente.StripeEventLog{}, stacktrace.Propagate(err, "") } - userID := currentSubscription.UserID - if stripeSubscription.Status == stripe.SubscriptionStatusPastDue { - err = c.sendAccountOnHoldEmail(userID) - if err != nil { - return ente.StripeEventLog{}, stacktrace.Propagate(err, "") - } - } - newSubscription, err := c.getEnteSubscriptionFromStripeSubscription(userID, stripeSubscription) if err != nil { return ente.StripeEventLog{}, stacktrace.Propagate(err, "") @@ -303,6 +294,24 @@ func (c *StripeController) handleCustomerSubscriptionUpdated(event stripe.Event, if currentSubscription.ProductID != newSubscription.ProductID { c.BillingRepo.ReplaceSubscription(currentSubscription.ID, newSubscription) } + + fullStripeSub, err := c.getStripeSubscriptionWithPaymentMethod(currentSubscription) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + isSEPA := isSEPASubscription(fullStripeSub) + + if stripeSubscription.Status == stripe.SubscriptionStatusPastDue && !isSEPA { + // Unfortunately, customer.subscription.updated is only fired for SEPA + // payments in case of updation failures (not for purchase or renewal + // failures). So for consistency (and to avoid duplicate mails), we + // trigger on-hold emails for SEPA within handlePaymentIntentFailed. + err = c.sendAccountOnHoldEmail(userID) + if err != nil { + return ente.StripeEventLog{}, stacktrace.Propagate(err, "") + } + } + return ente.StripeEventLog{UserID: userID, StripeSubscription: stripeSubscription, Event: event}, nil } @@ -428,26 +437,18 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en log.Info("Usage is good") } - client := c.StripeClients[subscription.Attributes.StripeAccountCountry] - params := stripe.SubscriptionParams{} - params.AddExpand("default_payment_method") - stripeSubscription, err := client.Subscriptions.Get(subscription.OriginalTransactionID, ¶ms) + stripeSubscription, err := c.getStripeSubscriptionWithPaymentMethod(subscription) if err != nil { return ente.SubscriptionUpdateResponse{}, stacktrace.Propagate(err, "") } - isSEPA := false - if stripeSubscription.DefaultPaymentMethod != nil { - isSEPA = stripeSubscription.DefaultPaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit - } else { - log.Info("No default payment method found") - } + isSEPA := isSEPASubscription(stripeSubscription) var paymentBehavior stripe.SubscriptionPaymentBehavior if isSEPA { paymentBehavior = stripe.SubscriptionPaymentBehaviorAllowIncomplete } else { paymentBehavior = stripe.SubscriptionPaymentBehaviorPendingIfIncomplete } - params = stripe.SubscriptionParams{ + params := stripe.SubscriptionParams{ ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorAlwaysInvoice)), Items: []*stripe.SubscriptionItemsParams{ { @@ -458,6 +459,7 @@ func (c *StripeController) UpdateSubscription(stripeID string, userID int64) (en PaymentBehavior: stripe.String(string(paymentBehavior)), } params.AddExpand("latest_invoice.payment_intent") + client := c.StripeClients[subscription.Attributes.StripeAccountCountry] newStripeSubscription, err := client.Subscriptions.Update(subscription.OriginalTransactionID, ¶ms) if err != nil { stripeError := err.(*stripe.Error) @@ -547,6 +549,17 @@ func (c *StripeController) GetStripeCustomerPortal(userID int64, redirectRootURL return ps.URL, nil } +func (c *StripeController) getStripeSubscriptionWithPaymentMethod(subscription ente.Subscription) (stripe.Subscription, error) { + client := c.StripeClients[subscription.Attributes.StripeAccountCountry] + params := &stripe.SubscriptionParams{} + params.AddExpand("default_payment_method") + stripeSubscription, err := client.Subscriptions.Get(subscription.OriginalTransactionID, params) + if err != nil { + return stripe.Subscription{}, stacktrace.Propagate(err, "") + } + return *stripeSubscription, nil +} + func (c *StripeController) sendAccountOnHoldEmail(userID int64) error { user, err := c.UserRepo.Get(userID) if err != nil { @@ -708,3 +721,13 @@ func (c *StripeController) CancelSubAndDeleteCustomer(subscription ente.Subscrip } return nil } + +func isSEPASubscription(stripeSubscription stripe.Subscription) bool { + isSEPA := false + if stripeSubscription.DefaultPaymentMethod != nil { + isSEPA = stripeSubscription.DefaultPaymentMethod.Type == stripe.PaymentMethodTypeSepaDebit + } else { + log.Info("No default payment method found") + } + return isSEPA +}