mirror of
https://github.com/logto-io/logto.git
synced 2025-02-10 21:58:23 -05:00
feat(console): add payment overdue reminder (#4203)
This commit is contained in:
parent
7b97571f1c
commit
437be82a27
37 changed files with 208 additions and 38 deletions
|
@ -11,17 +11,17 @@ import * as styles from './index.module.scss';
|
|||
|
||||
type Props = {
|
||||
cost: number;
|
||||
isManagePaymentVisible?: boolean;
|
||||
};
|
||||
|
||||
function NextBillInfo({ cost }: Props) {
|
||||
function BillInfo({ cost, isManagePaymentVisible }: Props) {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.billInfo}>
|
||||
<div className={styles.price}>
|
||||
<span>{`$${cost.toLocaleString()}`}</span>
|
||||
{}
|
||||
<span>{`$${(cost / 100).toLocaleString()}`}</span>
|
||||
{cost > 0 && (
|
||||
<ToggleTip content={<DynamicT forKey="subscription.next_bill_tip" />}>
|
||||
<IconButton size="small">
|
||||
|
@ -46,7 +46,7 @@ function NextBillInfo({ cost }: Props) {
|
|||
</Trans>
|
||||
</div>
|
||||
</div>
|
||||
{cost > 0 && (
|
||||
{isManagePaymentVisible && (
|
||||
<Button
|
||||
title="subscription.manage_payment"
|
||||
onClick={() => {
|
||||
|
@ -58,4 +58,4 @@ function NextBillInfo({ cost }: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default NextBillInfo;
|
||||
export default BillInfo;
|
|
@ -0,0 +1,7 @@
|
|||
.linkButton {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.strong {
|
||||
font-weight: 500;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
import { conditional } from '@silverhand/essentials';
|
||||
import { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import ReactModal from 'react-modal';
|
||||
|
||||
import { contactEmailLink } from '@/consts';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import InlineNotification from '@/ds-components/InlineNotification';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import useInvoices from '@/hooks/use-invoices';
|
||||
import * as modalStyles from '@/scss/modal.module.scss';
|
||||
import { getLatestUnpaidInvoice } from '@/utils/subscription';
|
||||
|
||||
import BillInfo from '../BillInfo';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
function PaymentOverdueModal() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { currentTenant, currentTenantId } = useContext(TenantsContext);
|
||||
const { data: invoices, error } = useInvoices(currentTenantId);
|
||||
const isLoadingInvoices = !invoices && !error;
|
||||
|
||||
const latestUnpaidInvoice = useMemo(() => {
|
||||
return conditional(invoices && getLatestUnpaidInvoice(invoices));
|
||||
}, [invoices]);
|
||||
|
||||
const [hasClosed, setHasClosed] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setHasClosed(true);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoadingInvoices || hasClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (latestUnpaidInvoice) {
|
||||
setIsOpen(true);
|
||||
}
|
||||
}, [hasClosed, isLoadingInvoices, latestUnpaidInvoice]);
|
||||
|
||||
if (isLoadingInvoices || !latestUnpaidInvoice || hasClosed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactModal
|
||||
shouldCloseOnEsc
|
||||
isOpen={isOpen}
|
||||
className={modalStyles.content}
|
||||
overlayClassName={modalStyles.overlay}
|
||||
onRequestClose={handleCloseModal}
|
||||
>
|
||||
<ModalLayout
|
||||
title="upsell.payment_overdue_modal.title"
|
||||
footer={
|
||||
<>
|
||||
<a href={contactEmailLink} target="_blank" className={styles.linkButton} rel="noopener">
|
||||
<Button title="upsell.contact_us" />
|
||||
</a>
|
||||
<Button
|
||||
type="primary"
|
||||
title="upsell.payment_overdue_modal.update_payment"
|
||||
onClick={() => {
|
||||
// Todo: @xiaoyijun Update payment
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
onClose={handleCloseModal}
|
||||
>
|
||||
{currentTenant && (
|
||||
<InlineNotification severity="error">
|
||||
<Trans components={{ span: <span className={styles.strong} /> }}>
|
||||
{t('upsell.payment_overdue_modal.notification', { name: currentTenant.name })}
|
||||
</Trans>
|
||||
</InlineNotification>
|
||||
)}
|
||||
<FormField title="upsell.payment_overdue_modal.unpaid_bills">
|
||||
<BillInfo cost={latestUnpaidInvoice.amountDue} />
|
||||
</FormField>
|
||||
</ModalLayout>
|
||||
</ReactModal>
|
||||
);
|
||||
}
|
||||
|
||||
export default PaymentOverdueModal;
|
|
@ -4,6 +4,7 @@ import { Navigate, Outlet, useParams } from 'react-router-dom';
|
|||
|
||||
import AppLoading from '@/components/AppLoading';
|
||||
import MauExceededModal from '@/components/MauExceededModal';
|
||||
import PaymentOverdueModal from '@/components/PaymentOverdueModal';
|
||||
import { isCloud, isProduction } from '@/consts/env';
|
||||
import useConfigs from '@/hooks/use-configs';
|
||||
import useScroll from '@/hooks/use-scroll';
|
||||
|
@ -38,7 +39,12 @@ export default function AppContent() {
|
|||
</div>
|
||||
{isCloud && <Broadcast />}
|
||||
{/* Todo: @xiaoyijun remove this condition on subscription features ready. */}
|
||||
{!isProduction && isCloud && <MauExceededModal />}
|
||||
{!isProduction && isCloud && (
|
||||
<>
|
||||
<MauExceededModal />
|
||||
<PaymentOverdueModal />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { conditional } from '@silverhand/essentials';
|
||||
import { useContext, useMemo } from 'react';
|
||||
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import InlineNotification from '@/ds-components/InlineNotification';
|
||||
import useInvoices from '@/hooks/use-invoices';
|
||||
import { getLatestUnpaidInvoice } from '@/utils/subscription';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
function PaymentOverdueNotification({ className }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { data: invoices, error } = useInvoices(currentTenantId);
|
||||
const isLoadingInvoices = !invoices && !error;
|
||||
const latestUnpaidInvoice = useMemo(
|
||||
() => conditional(invoices && getLatestUnpaidInvoice(invoices)),
|
||||
[invoices]
|
||||
);
|
||||
|
||||
if (isLoadingInvoices || !latestUnpaidInvoice) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<InlineNotification
|
||||
severity="error"
|
||||
action="subscription.update_payment"
|
||||
className={className}
|
||||
onClick={() => {
|
||||
// Todo @xiaoyijun manage payment
|
||||
}}
|
||||
>
|
||||
<DynamicT
|
||||
forKey="subscription.payment_error"
|
||||
interpolation={{ price: latestUnpaidInvoice.amountDue / 100 }}
|
||||
/>
|
||||
</InlineNotification>
|
||||
);
|
||||
}
|
||||
|
||||
export default PaymentOverdueNotification;
|
|
@ -1,4 +1,5 @@
|
|||
import { type SubscriptionUsage, type Subscription } from '@/cloud/types/router';
|
||||
import BillInfo from '@/components/BillInfo';
|
||||
import FormCard from '@/components/FormCard';
|
||||
import PlanDescription from '@/components/PlanDescription';
|
||||
import PlanName from '@/components/PlanName';
|
||||
|
@ -7,7 +8,7 @@ import FormField from '@/ds-components/FormField';
|
|||
import { type SubscriptionPlan } from '@/types/subscriptions';
|
||||
|
||||
import MauLimitExceedNotification from './MauLimitExceededNotification';
|
||||
import NextBillInfo from './NextBillInfo';
|
||||
import PaymentOverdueNotification from './PaymentOverdueNotification';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
|
@ -37,13 +38,17 @@ function CurrentPlan({ subscription, subscriptionPlan, subscriptionUsage }: Prop
|
|||
/>
|
||||
</FormField>
|
||||
<FormField title="subscription.next_bill">
|
||||
<NextBillInfo cost={subscriptionUsage.cost} />
|
||||
<BillInfo
|
||||
cost={subscriptionUsage.cost}
|
||||
isManagePaymentVisible={Boolean(subscriptionUsage.cost)}
|
||||
/>
|
||||
</FormField>
|
||||
<MauLimitExceedNotification
|
||||
activeUsers={subscriptionUsage.activeUsers}
|
||||
currentPlan={subscriptionPlan}
|
||||
className={styles.notification}
|
||||
/>
|
||||
<PaymentOverdueNotification className={styles.notification} />
|
||||
</FormCard>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Sie haben Ihr Quotenlimit erreicht. Um Probleme zu vermeiden, upgraden Sie den Plan.',
|
||||
upgrade_pro: 'Pro upgraden',
|
||||
update_payment: 'Zahlung aktualisieren',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Es wurde ein Zahlungsproblem festgestellt. Der Betrag von ${{price, number}} für den vorherigen Zyklus kann nicht verarbeitet werden. Aktualisieren Sie die Zahlung, um eine Aussetzung des Logto-Dienstes zu vermeiden.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Zahlungsrückstand für Rechnung',
|
||||
notification:
|
||||
'Hoppla! Die Zahlung für die Rechnung des Tenants {{name}} ist im letzten Abrechnungszeitraum fehlgeschlagen. Bitte zahlen Sie die Rechnung umgehend, um die Aussetzung des Logto-Dienstes zu vermeiden.',
|
||||
unpaid_bills_last_cycle: 'Unbezahlte Rechnungen im letzten Abrechnungszeitraum',
|
||||
'Hoppla! Die Zahlung für die Rechnung des Mieters <span>{{name}}</span> ist fehlgeschlagen. Bitte zahlen Sie die Rechnung umgehend, um eine Sperrung des Logto-Dienstes zu vermeiden.',
|
||||
unpaid_bills: 'Ausstehende Rechnungen',
|
||||
update_payment: 'Zahlung aktualisieren',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'You have reached your quota limit. To prevent any issues, upgrade the plan.',
|
||||
upgrade_pro: 'Upgrade Pro',
|
||||
update_payment: 'Update payment',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Payment issue detected. Unable to process ${{price, number}} for previous cycle. Update payment to avoid Logto service suspension.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Bill payment overdue',
|
||||
notification:
|
||||
'Oops! Payment for tenant {{name}} bill failed last cycle. Please pay the bill promptly to avoid suspension of Logto service.',
|
||||
unpaid_bills_last_cycle: 'Unpaid bills last cycle',
|
||||
'Oops! Payment for tenant <span>{{name}}</span> bill failed. Please pay the bill promptly to avoid suspension of Logto service.',
|
||||
unpaid_bills: 'Unpaid bills',
|
||||
update_payment: 'Update Payment',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Ha alcanzado el límite de su cuota. Para evitar problemas, actualice el plan.',
|
||||
upgrade_pro: 'Actualizar a Pro',
|
||||
update_payment: 'Actualizar pago',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Se ha detectado un problema de pago. No se puede procesar ${ {price, number}} para el ciclo anterior. Actualice el pago para evitar la suspensión del servicio Logto.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Factura con pagos atrasados',
|
||||
notification:
|
||||
'¡Vaya! El pago de la factura del tenant {{name}} falló en el último ciclo. Por favor, paga la factura a tiempo para evitar la suspensión del servicio de Logto.',
|
||||
unpaid_bills_last_cycle: 'Facturas impagadas del último ciclo',
|
||||
'¡Ups! El pago de la factura del inquilino <span>{{name}}</span> ha fallado. Por favor, pague la factura a tiempo para evitar la suspensión del servicio de Logto.',
|
||||
unpaid_bills: 'Facturas impagas',
|
||||
update_payment: 'Actualizar pago',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Vous avez atteint votre limite de quota. Pour éviter tout problème, passez à un plan supérieur.',
|
||||
upgrade_pro: 'Passer au Plan Professionnel',
|
||||
update_payment: 'Mettre à jour le paiement',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Problème de paiement détecté. Impossible de traiter ${{price, number}} pour le cycle précédent. Mettez à jour le paiement pour éviter la suspension du service Logto.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Paiement de facture en retard',
|
||||
notification:
|
||||
'Oups ! Le paiement de la facture du locataire {{name}} a échoué lors du dernier cycle. Veuillez payer la facture rapidement pour éviter la suspension du service Logto.',
|
||||
unpaid_bills_last_cycle: 'Factures impayées du dernier cycle',
|
||||
'Oups ! Le paiement de la facture du locataire <span>{{name}}</span> a échoué. Veuillez payer la facture rapidement pour éviter la suspension du service Logto.',
|
||||
unpaid_bills: 'Factures impayées',
|
||||
update_payment: 'Mettre à jour le paiement',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
"Hai raggiunto il limite del tuo contingente. Per evitare eventuali problemi, esegui l'upgrade del piano.",
|
||||
upgrade_pro: "Esegui l'upgrade a Pro",
|
||||
update_payment: 'Aggiorna pagamento',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Rilevato un problema di pagamento. Impossibile elaborare ${{price, number}} per il ciclo precedente. Aggiorna il pagamento per evitare la sospensione del servizio Logto.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Pagamento della fattura in ritardo',
|
||||
notification:
|
||||
"Oops! Il pagamento della fattura del tenant {{name}} è fallito l'ultimo ciclo. Effettua il pagamento della fattura tempestivamente per evitare la sospensione del servizio Logto.",
|
||||
unpaid_bills_last_cycle: "Fatture non pagate l'ultimo ciclo",
|
||||
"Oops! Il pagamento della fattura dell'affittuario <span>{{name}}</span> è fallito. Si prega di pagare tempestivamente la fattura per evitare la sospensione del servizio Logto.",
|
||||
unpaid_bills: 'Fatture non pagate',
|
||||
update_payment: 'Aggiorna pagamento',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'クォータ制限に到達しました。問題を防ぐために、プランをアップグレードしてください。',
|
||||
upgrade_pro: 'プロプランにアップグレード',
|
||||
update_payment: '支払いを更新する',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'支払いに問題が発生しました。前回のサイクルで ${{price, number}} を処理できませんでした。Logtoのサービス停止を回避するために支払いを更新してください。',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: '請求書の支払いが期限切れです',
|
||||
notification:
|
||||
'おっと!テナント{{name}}の請求書の支払いが前回のサイクルで失敗しました。サービスの停止を回避するために、迅速に請求書をお支払いください。',
|
||||
unpaid_bills_last_cycle: '前回のサイクルの未払い請求書',
|
||||
'おっと!テナント<span>{{name}}</span>の請求書の支払いが失敗しました。Logtoサービスの停止を避けるために、すみやかに請求書をお支払いください。',
|
||||
unpaid_bills: '未払いの請求書',
|
||||
update_payment: '支払いを更新',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'할당량 한도에 도달했습니다. 문제를 방지하기 위해 요금제를 업그레이드하세요.',
|
||||
upgrade_pro: '프로 업그레이드',
|
||||
update_payment: '결제 정보 업데이트',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'결제 문제가 발생했습니다. 이전 주기에 ${{price, number}}을(를) 처리할 수 없습니다. Logto 서비스 중단을 피하기 위해 결제를 업데이트하세요.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: '청구서 지불 연체',
|
||||
notification:
|
||||
'이런! 지난 사이클에 테넌트 {{name}}의 청구서 지불이 실패했습니다. 로그토 서비스 중단을 피하기 위해 청구서를 신속히 지불하세요.',
|
||||
unpaid_bills_last_cycle: '지난 사이클 미납 청구서',
|
||||
'이런! 테넌트 <span>{{name}}</span>의 청구서 결제에 실패했습니다. Logto 서비스 중단을 피하기 위해 즉시 청구서를 지불하십시오.',
|
||||
unpaid_bills: '미납 청구서',
|
||||
update_payment: '지불 업데이트',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Osiągnąłeś limit swojej puli. Aby uniknąć problemów, zaktualizuj swój plan.',
|
||||
upgrade_pro: 'Uaktualnij do Pro',
|
||||
update_payment: 'Zaktualizuj płatność',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Wykryto problem z płatnością. Nie można przetworzyć ${{price, number}} za poprzedni cykl. Zaktualizuj płatność, aby uniknąć zawieszenia usługi Logto.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Opłata za fakturę zaległa',
|
||||
notification:
|
||||
'Ups! Opłata za fakturę dla najemcy {{name}} nie została opłacona w ostatnim cyklu. Proszę natychmiast uiścić opłatę, aby uniknąć zawieszenia usługi Logto.',
|
||||
unpaid_bills_last_cycle: 'Niezapłacone faktury z ostatniego cyklu',
|
||||
'Ups! Płatność za fakturę najemcy <span>{{name}}</span> nie powiodła się. Proszę zapłacić fakturę w odpowiednim terminie, aby uniknąć zawieszenia usługi Logto.',
|
||||
unpaid_bills: 'Nieuregulowane faktury',
|
||||
update_payment: 'Zaktualizuj płatność',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Você atingiu o limite de cota. Para evitar problemas, faça upgrade do plano.',
|
||||
upgrade_pro: 'Upgrade Pro',
|
||||
update_payment: 'Atualizar pagamento',
|
||||
payment_error:
|
||||
'Detectado um problema de pagamento. Não é possível processar $ {{price, number}} para o ciclo anterior. Atualize o pagamento para evitar a suspensão do serviço Logto.',
|
||||
downgrade: 'Downgrade',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Pagamento da fatura em atraso',
|
||||
notification:
|
||||
'Ops! O pagamento da fatura do inquilino {{name}} falhou no último ciclo. Por favor, efetue o pagamento da fatura a tempo para evitar a suspensão do serviço do Logto.',
|
||||
unpaid_bills_last_cycle: 'Faturas em atraso no último ciclo',
|
||||
'Oops! O pagamento da fatura do inquilino <span>{{name}}</span> falhou. Por favor, pague a fatura prontamente para evitar a suspensão do serviço Logto.',
|
||||
unpaid_bills: 'Faturas não pagas',
|
||||
update_payment: 'Atualizar pagamento',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Você atingiu o limite da sua cota. Para evitar problemas, faça upgrade do plano.',
|
||||
upgrade_pro: 'Atualizar para Pro',
|
||||
update_payment: 'Atualizar pagamento',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Problema de pagamento detectado. Não é possível processar ${{price, number}} para o ciclo anterior. Atualize o pagamento para evitar a suspensão do serviço Logto.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Pagamento da fatura em atraso',
|
||||
notification:
|
||||
'Ops! O pagamento da fatura do inquilino {{name}} falhou no último ciclo. Por favor, efetue o pagamento da fatura a tempo para evitar a suspensão do serviço do Logto.',
|
||||
unpaid_bills_last_cycle: 'Faturas em atraso no último ciclo',
|
||||
'Oops! O pagamento da fatura do inquilino <span>{{name}}</span> falhou. Por favor, pague a fatura prontamente para evitar a suspensão do serviço Logto.',
|
||||
unpaid_bills: 'Faturas não pagas',
|
||||
update_payment: 'Atualizar pagamento',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Вы достигли лимита вашего квоты. Чтобы избежать возможных проблем, повысьте план.',
|
||||
upgrade_pro: 'Повысить уровень до Pro',
|
||||
update_payment: 'Обновить платеж',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Обнаружена ошибка платежа. Невозможно обработать сумму ${{price, number}} за предыдущий цикл. Обновите платежную информацию, чтобы избежать блокировки сервиса Logto.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Просрочен платеж за счет',
|
||||
notification:
|
||||
'Упс! Платеж за арендатора {{name}} не был произведен в прошлом цикле. Пожалуйста, незамедлительно оплатите счет, чтобы избежать приостановки сервиса Logto.',
|
||||
unpaid_bills_last_cycle: 'Просроченные счета за последний цикл',
|
||||
'Упс! Оплата счета арендатора <span>{{name}}</span> не удалась. Пожалуйста, оплатите счет немедленно, чтобы избежать приостановки сервиса Logto.',
|
||||
unpaid_bills: 'Неоплаченные счета',
|
||||
update_payment: 'Обновить платеж',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ const subscription = {
|
|||
overfill_quota_warning:
|
||||
'Kota sınırınıza ulaştınız. Herhangi bir sorunu önlemek için planı yükseltin.',
|
||||
upgrade_pro: "Pro'ya yükselt",
|
||||
update_payment: 'Ödemeyi Güncelle',
|
||||
payment_error:
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'Ödeme hatası tespit edildi. Önceki döngü için ${{price, number}} işlenemedi. Logto hizmeti askıya alınmasını önlemek için ödemeleri güncelleyin.',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: 'Fatura ödemesi gecikti',
|
||||
notification:
|
||||
'Ups! Kiracı {{name}} faturasının ödemesi son döngüde başarısız oldu. Logto hizmetinin askıya alınmasını önlemek için faturayı hemen ödeyin.',
|
||||
unpaid_bills_last_cycle: 'Son döngüde ödenmemiş faturalar',
|
||||
'Oops! Kiracı <span>{{name}}</span> faturasının ödemesi başarısız oldu. Logto hizmetinin askıya alınmaması için faturayı zamanında ödeyin.',
|
||||
unpaid_bills: 'Ödenmemiş faturalar',
|
||||
update_payment: 'Ödemeyi Güncelle',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ const subscription = {
|
|||
manage_payment: '管理付款',
|
||||
overfill_quota_warning: '您已达到配额限制。为防止任何问题,请升级计划。',
|
||||
upgrade_pro: '升级专业计划',
|
||||
update_payment: '更新付款信息',
|
||||
payment_error:
|
||||
'检测到付款问题。无法处理前一周期的{{price, number}}美元。更新付款以避免 Logto 服务中断。',
|
||||
downgrade: '降级',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: '账单逾期未付',
|
||||
notification:
|
||||
'糟糕!上一周期租户 {{name}} 的账单支付失败。请立即支付账单,以避免 Logto 服务的暂停。',
|
||||
unpaid_bills_last_cycle: '上一周期未支付账单',
|
||||
'糟糕!租户<span>{{name}}</span>的账单支付失败。请尽快支付账单,以避免Logto服务中止。',
|
||||
unpaid_bills: '未付账单',
|
||||
update_payment: '更新支付',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ const subscription = {
|
|||
manage_payment: '管理付款',
|
||||
overfill_quota_warning: '您已達到配額限制。請升級計劃以防止任何問題。',
|
||||
upgrade_pro: '升級到專業版',
|
||||
update_payment: '更新付款信息',
|
||||
payment_error:
|
||||
'檢測到付款問題。無法處理前一個週期的$ {{price, number}}。更新付款以避免Logto服務暫停。',
|
||||
downgrade: '降級',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: '賬單逾期未付',
|
||||
notification:
|
||||
'糟糕!上一周期租戶 {{name}} 的賬單支付失敗。請立即支付賬單,以避免 Logto 服務的暫停。',
|
||||
unpaid_bills_last_cycle: '上一周期未支付賬單',
|
||||
'糟糕!租戶<span>{{name}}</span>的賬單支付失敗。請儘快支付賬單,以避免Logto服務中止。',
|
||||
unpaid_bills: '未付賬單',
|
||||
update_payment: '更新支付',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ const subscription = {
|
|||
manage_payment: '管理付款',
|
||||
overfill_quota_warning: '您已達到配額限制。為防止出現問題,請升級計畫。',
|
||||
upgrade_pro: '升級專業',
|
||||
update_payment: '更新付款信息',
|
||||
payment_error:
|
||||
'偵測到付款問題。無法處理以前週期的 {{price, number}}$ 。更新付款以避免 Logto 服務中止。',
|
||||
downgrade: '降級',
|
||||
|
|
|
@ -81,8 +81,8 @@ const upsell = {
|
|||
payment_overdue_modal: {
|
||||
title: '賬單逾期未付',
|
||||
notification:
|
||||
'糟糕!上一周期租戶 {{name}} 的賬單支付失敗。請立即支付賬單,以避免 Logto 服務的暫停。',
|
||||
unpaid_bills_last_cycle: '上一周期未支付賬單',
|
||||
'糟糕!租戶<span>{{name}}</span>的賬單支付失敗。請儘快支付賬單,以避免Logto服務中止。',
|
||||
unpaid_bills: '未付賬單',
|
||||
update_payment: '更新支付',
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue