0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

refactor(console): update plan comparison data and styles (#5181)

This commit is contained in:
Xiao Yijun 2023-12-28 18:32:07 +08:00 committed by GitHub
parent 7e2016d20e
commit 0bc84aaf61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 247 additions and 155 deletions

View file

@ -87,7 +87,7 @@ export const allowedUsersPerOrganizationMap: Record<string, Nullable<number> | u
export const invitationEnabledMap: Record<string, boolean | undefined> = {
[ReservedPlanId.Free]: false,
[ReservedPlanId.Hobby]: true,
[ReservedPlanId.Pro]: undefined,
[ReservedPlanId.Pro]: true,
};
export const orgRolesLimitMap: Record<string, Nullable<number> | undefined> = {
@ -105,7 +105,7 @@ export const orgPermissionsLimitMap: Record<string, Nullable<number> | undefined
export const justInTimeProvisioningEnabledMap: Record<string, boolean | undefined> = {
[ReservedPlanId.Free]: false,
[ReservedPlanId.Hobby]: true,
[ReservedPlanId.Pro]: undefined,
[ReservedPlanId.Pro]: true,
};
export const soc2ReportEnabledMap: Record<string, boolean | undefined> = {
@ -155,6 +155,8 @@ const enterprisePlanTable: SubscriptionPlanTable = {
communitySupportEnabled: true,
ticketSupportResponseTime: undefined,
organizationsEnabled: undefined,
invitationEnabled: true,
justInTimeProvisioningEnabled: true,
ssoEnabled: undefined,
soc2ReportEnabled: true,
hipaaOrBaaReportEnabled: true,
@ -170,7 +172,7 @@ export const enterprisePlanTableData: SubscriptionPlanTableData = {
};
export const planTableGroupKeyMap: SubscriptionPlanTableGroupKeyMap = Object.freeze({
[SubscriptionPlanTableGroupKey.base]: ['basePrice', 'mauLimit'],
[SubscriptionPlanTableGroupKey.base]: ['basePrice', 'mauLimit', 'tokenLimit'],
[SubscriptionPlanTableGroupKey.applications]: ['applicationsLimit', 'machineToMachineLimit'],
[SubscriptionPlanTableGroupKey.resources]: ['resourcesLimit', 'scopesPerResourceLimit'],
[SubscriptionPlanTableGroupKey.branding]: [

View file

@ -1,20 +1,20 @@
import { cond, type Nullable } from '@silverhand/essentials';
import { cond } from '@silverhand/essentials';
import { type TFuncKey } from 'i18next';
import DynamicT from '@/ds-components/DynamicT';
import { type SubscriptionPlanTable } from '@/types/subscriptions';
import TableDataWrapper from '../components/TableDataWrapper';
const planQuotaKeyPhraseMap: {
[key in keyof Required<SubscriptionPlanTable>]: Nullable<
TFuncKey<'translation', 'admin_console.subscription.quota_table'>
[key in keyof Required<SubscriptionPlanTable>]: TFuncKey<
'translation',
'admin_console.subscription.quota_table'
>;
} = {
basePrice: 'quota.base_price',
mauLimit: 'quota.mau_limit',
/**
* Token limit is required in the plan quota table but we don't display it as a row data.
*/
tokenLimit: null,
tokenLimit: 'quota.included_tokens',
applicationsLimit: 'application.total',
machineToMachineLimit: 'application.m2m',
resourcesLimit: 'resource.resource_count',
@ -51,13 +51,31 @@ const planQuotaKeyPhraseMap: {
hipaaOrBaaReportEnabled: 'support.hipaa_or_baa_report',
};
const planQuotaTipPhraseMap: Partial<
Record<
keyof Required<SubscriptionPlanTable>,
TFuncKey<'translation', 'admin_console.subscription.quota_table'>
>
> = {
mauLimit: 'mau_tip',
tokenLimit: 'tokens_tip',
};
type Props = {
quotaKey: keyof SubscriptionPlanTable;
};
function PlanQuotaKeyLabel({ quotaKey }: Props) {
const phraseKey = planQuotaKeyPhraseMap[quotaKey];
return cond(phraseKey && <DynamicT forKey={`subscription.quota_table.${phraseKey}`} />) ?? <>-</>;
const quotaTip = planQuotaTipPhraseMap[quotaKey];
return (
<TableDataWrapper
isLeftAligned
tip={cond(quotaTip && <DynamicT forKey={`subscription.quota_table.${quotaTip}`} />)}
>
<DynamicT forKey={`subscription.quota_table.${planQuotaKeyPhraseMap[quotaKey]}`} />
</TableDataWrapper>
);
}
export default PlanQuotaKeyLabel;

View file

@ -4,5 +4,9 @@
display: flex;
align-items: center;
justify-content: center;
gap: _.unit(2);
gap: _.unit(1);
&.leftAligned {
justify-content: flex-start;
}
}

View file

@ -1,3 +1,4 @@
import classNames from 'classnames';
import { type ReactNode } from 'react';
import Tip from '@/assets/icons/tip.svg';
@ -9,11 +10,12 @@ import * as styles from './index.module.scss';
type Props = {
children: ReactNode;
tip?: ReactNode;
isLeftAligned?: boolean;
};
function QuotaValueWrapper({ children, tip }: Props) {
function TableDataWrapper({ children, tip, isLeftAligned }: Props) {
return (
<div className={styles.quotaValue}>
<div className={classNames(styles.quotaValue, isLeftAligned && styles.leftAligned)}>
{children}
{tip && (
<ToggleTip content={tip}>
@ -26,4 +28,4 @@ function QuotaValueWrapper({ children, tip }: Props) {
);
}
export default QuotaValueWrapper;
export default TableDataWrapper;

View file

@ -13,21 +13,12 @@
width: 100%;
thead {
background-color: var(--color-layer-light);
border-radius: 6px;
padding: 0 _.unit(3);
tr th {
font: var(--font-title-2);
padding: _.unit(3);
&:first-child {
border-radius: 6px 0 0 6px;
}
&:last-child {
border-radius: 0 6px 6px 0;
}
}
}
@ -36,29 +27,19 @@
font: var(--font-body-2);
text-align: center;
padding: _.unit(3);
&:first-child {
border-radius: 6px 0 0 6px;
}
&:last-child {
border-radius: 0 6px 6px 0;
}
}
.groupLabel {
font: var(--font-title-2);
text-align: left;
background-color: var(--color-layer-light);
border-radius: 6px;
}
.quotaKeyColumn {
padding: _.unit(4) _.unit(6);
text-align: left;
}
.colorRow {
background-color: var(--color-layer-light);
}
}
}
}

View file

@ -1,4 +1,3 @@
import { cond } from '@silverhand/essentials';
import { Fragment, useMemo } from 'react';
import PlanName from '@/components/PlanName';
@ -42,16 +41,13 @@ function PlanComparisonTable({ subscriptionPlans }: Props) {
{Object.entries(planTableGroupKeyMap).map(([groupKey, quotaKeys]) => (
<Fragment key={groupKey}>
<tr>
<td className={styles.groupLabel}>
<td colSpan={planTableDataArray.length + 1} className={styles.groupLabel}>
{/* eslint-disable-next-line no-restricted-syntax */}
<PlanQuotaGroupKeyLabel groupKey={groupKey as SubscriptionPlanTableGroupKey} />
</td>
</tr>
{quotaKeys.map((quotaKey, index) => (
<tr
key={`${groupKey}-${quotaKey}`}
className={cond(index % 2 === 0 && styles.colorRow)}
>
{quotaKeys.map((quotaKey) => (
<tr key={`${groupKey}-${quotaKey}`}>
<td className={styles.quotaKeyColumn}>
<PlanQuotaKeyLabel quotaKey={quotaKey} />
</td>

View file

@ -1,6 +1,6 @@
import DynamicT from '@/ds-components/DynamicT';
import QuotaValueWrapper from './QuotaValueWrapper';
import TableDataWrapper from '../components/TableDataWrapper';
type Props = {
value?: string;
@ -15,12 +15,12 @@ function BasePrice({ value }: Props) {
* `basePrice` is a string value representing the price in cents, we need to convert the value from cents to dollars.
*/
return (
<QuotaValueWrapper>
<TableDataWrapper>
<DynamicT
forKey="subscription.quota_table.monthly_price"
interpolation={{ value: Number(value) / 100 }}
/>
</QuotaValueWrapper>
</TableDataWrapper>
);
}

View file

@ -4,7 +4,7 @@ import { type TFuncKey } from 'i18next';
import Success from '@/assets/icons/success.svg';
import DynamicT from '@/ds-components/DynamicT';
import QuotaValueWrapper from './QuotaValueWrapper';
import TableDataWrapper from '../components/TableDataWrapper';
type Props = {
/**
@ -55,7 +55,7 @@ function GenericFeatureFlag({ isEnabled, isBeta, tipPhraseKey, paymentType }: Pr
}
return (
<QuotaValueWrapper
<TableDataWrapper
tip={cond(tipPhraseKey && <DynamicT forKey={`subscription.quota_table.${tipPhraseKey}`} />)}
>
{isEnabled
@ -69,7 +69,7 @@ function GenericFeatureFlag({ isEnabled, isBeta, tipPhraseKey, paymentType }: Pr
/>
)
: '-'}
</QuotaValueWrapper>
</TableDataWrapper>
);
}

View file

@ -1,17 +1,18 @@
import { cond, type Nullable } from '@silverhand/essentials';
import { type TFuncKey } from 'i18next';
import { type ReactNode } from 'react';
import Success from '@/assets/icons/success.svg';
import DynamicT from '@/ds-components/DynamicT';
import QuotaValueWrapper from './QuotaValueWrapper';
import TableDataWrapper from '../components/TableDataWrapper';
type Props = {
quota?: Nullable<number>;
tipPhraseKey?: TFuncKey<'translation', 'admin_console.subscription.quota_table'>;
tipInterpolation?: Record<string, unknown>;
hasCheckmark?: boolean;
formatter?: (quota: number) => string;
formatter?: (quota: number) => string | ReactNode;
};
function GenericQuotaLimit({
@ -36,15 +37,15 @@ function GenericQuotaLimit({
if (quota === null) {
return (
<QuotaValueWrapper tip={tipContent}>
<TableDataWrapper tip={tipContent}>
{hasCheckmark && <Success />}
<DynamicT forKey="subscription.quota_table.unlimited" />
</QuotaValueWrapper>
</TableDataWrapper>
);
}
return (
<QuotaValueWrapper tip={tipContent}>
<TableDataWrapper tip={tipContent}>
{quota === 0 ? (
'-'
) : (
@ -53,7 +54,7 @@ function GenericQuotaLimit({
{formatter?.(quota) ?? quota.toLocaleString()}
</>
)}
</QuotaValueWrapper>
</TableDataWrapper>
);
}

View file

@ -3,6 +3,7 @@ import { cond } from '@silverhand/essentials';
import { t } from 'i18next';
import { type ReactNode } from 'react';
import DynamicT from '@/ds-components/DynamicT';
import { type SubscriptionPlanTable, type SubscriptionPlanTableData } from '@/types/subscriptions';
import BasePrice from './BasePrice';
@ -15,14 +16,21 @@ export const quotaValueRenderer: Record<
> = {
// Base
basePrice: ({ table: { basePrice } }) => <BasePrice value={basePrice} />,
tokenLimit: () => <div />, // Dummy: We don't display token limit as an item in the plan comparison table.
mauLimit: ({ id, table: { tokenLimit, mauLimit } }) => (
mauLimit: ({ table: { mauLimit } }) => <GenericQuotaLimit quota={mauLimit} />,
tokenLimit: ({ id, table: { tokenLimit } }) => (
<GenericQuotaLimit
quota={mauLimit}
tipPhraseKey={cond(
tokenLimit && (id === ReservedPlanId.Free ? 'free_token_limit_tip' : 'paid_token_limit_tip')
)}
tipInterpolation={cond(typeof tokenLimit === 'number' && { value: tokenLimit / 1_000_000 })}
quota={tokenLimit}
tipPhraseKey={cond(tokenLimit && id !== ReservedPlanId.Free && 'paid_quota_limit_tip')}
formatter={(quota) => {
return quota >= 1_000_000 ? (
<DynamicT
forKey="subscription.quota_table.million"
interpolation={{ value: quota / 1_000_000 }}
/>
) : (
quota.toLocaleString()
);
}}
/>
),
// Applications
@ -120,16 +128,22 @@ export const quotaValueRenderer: Record<
allowedUsersPerOrganization: ({ table: { allowedUsersPerOrganization } }) => (
<GenericQuotaLimit quota={allowedUsersPerOrganization} />
),
invitationEnabled: ({ table: { invitationEnabled } }) => (
<GenericFeatureFlag isEnabled={invitationEnabled} />
),
invitationEnabled: ({ table: { invitationEnabled } }) =>
invitationEnabled ? (
<DynamicT forKey="general.coming_soon" />
) : (
<GenericFeatureFlag isEnabled={invitationEnabled} />
),
orgRolesLimit: ({ table: { orgRolesLimit } }) => <GenericQuotaLimit quota={orgRolesLimit} />,
orgPermissionsLimit: ({ table: { orgPermissionsLimit } }) => (
<GenericQuotaLimit quota={orgPermissionsLimit} />
),
justInTimeProvisioningEnabled: ({ table: { justInTimeProvisioningEnabled } }) => (
<GenericFeatureFlag isEnabled={justInTimeProvisioningEnabled} />
),
justInTimeProvisioningEnabled: ({ table: { justInTimeProvisioningEnabled } }) =>
justInTimeProvisioningEnabled ? (
<DynamicT forKey="general.coming_soon" />
) : (
<GenericFeatureFlag isEnabled={justInTimeProvisioningEnabled} />
),
// Audit logs
auditLogsRetentionDays: ({ table: { auditLogsRetentionDays } }) => (
<GenericQuotaLimit
@ -150,10 +164,16 @@ export const quotaValueRenderer: Record<
formatter={(quota) => `(${quota}h)`}
/>
),
soc2ReportEnabled: ({ table: { soc2ReportEnabled } }) => (
<GenericFeatureFlag isEnabled={soc2ReportEnabled} />
),
hipaaOrBaaReportEnabled: ({ table: { hipaaOrBaaReportEnabled } }) => (
<GenericFeatureFlag isEnabled={hipaaOrBaaReportEnabled} />
),
soc2ReportEnabled: ({ table: { soc2ReportEnabled } }) =>
soc2ReportEnabled ? (
<DynamicT forKey="general.coming_soon" />
) : (
<GenericFeatureFlag isEnabled={soc2ReportEnabled} />
),
hipaaOrBaaReportEnabled: ({ table: { hipaaOrBaaReportEnabled } }) =>
hipaaOrBaaReportEnabled ? (
<DynamicT forKey="general.coming_soon" />
) : (
<GenericFeatureFlag isEnabled={hipaaOrBaaReportEnabled} />
),
};

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Kontingent',
tenant_limit: 'Mieter-Limit',
title: 'Grundlagen',
base_price: 'Grundpreis',
mau_limit: 'MAU-Limit',
included_tokens: 'Inkludierte Tokens',
},
application: {
title: 'Anwendungen',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organisationen',
monthly_active_organization: 'Monatlich aktive Organisationen',
allowed_users_per_org: 'Erlaubte Benutzer pro Organisation',
invitation: 'Einladung (in Kürze)',
invitation: 'Einladung',
org_roles: 'Org Rollen',
org_permissions: 'Org Berechtigungen',
just_in_time_provisioning: 'Bedarfsgesteuerte Bereitstellung',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Support-Ticket',
premium: 'Premium',
email_ticket_support: 'E-Mail-Ticket-Support',
soc2_report: 'SOC2-Bericht (in Kürze)',
hipaa_or_baa_report: 'HIPAA/BAA-Bericht (in Kürze)',
soc2_report: 'SOC2-Bericht',
hipaa_or_baa_report: 'HIPAA/BAA-Bericht',
},
unlimited: 'Unbegrenzt',
contact: 'Kontakt',
@ -88,6 +88,11 @@ const quota_table = {
'Während der Beta-Phase kostenfrei zu benutzen. Wir werden mit der finalen Festlegung der organisationsbasierten nutzungsabhängigen Preise beginnen.',
beta: 'Beta',
add_on_beta: 'Add-on (Beta)',
million: '{{value, number}} Millionen',
mau_tip:
'MAU (monatlich aktive Benutzer) bedeutet die Anzahl der eindeutigen Benutzer, die in einem Abrechnungsmonat mindestens einen Token mit Logto ausgetauscht haben.',
tokens_tip:
'Alle Arten von Tokens, die von Logto ausgegeben wurden, einschließlich Zugriffstoken, Aktualisierungstoken, usw.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Quota',
tenant_limit: 'Tenant limit',
title: 'Basics',
base_price: 'Base price',
mau_limit: 'MAU limit',
included_tokens: 'Included tokens',
},
application: {
title: 'Applications',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizations',
monthly_active_organization: 'Monthly active organization',
allowed_users_per_org: 'Allowed users per org',
invitation: 'Invitation (Coming soon)',
invitation: 'Invitation',
org_roles: 'Org roles',
org_permissions: 'Org permissions',
just_in_time_provisioning: 'Just-in-time provisioning',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Ticket support',
premium: 'Premium',
email_ticket_support: 'Email ticket support',
soc2_report: 'SOC2 report (Coming soon)',
hipaa_or_baa_report: 'HIPAA/BAA report (Coming soon)',
soc2_report: 'SOC2 report',
hipaa_or_baa_report: 'HIPAA/BAA report',
},
unlimited: 'Unlimited',
contact: 'Contact',
@ -88,6 +88,11 @@ const quota_table = {
'Free to use during the beta phase. We will begin charging once we finalize the org usage-based pricing.',
beta: 'Beta',
add_on_beta: 'Add-on (Beta)',
million: '{{value, number}} million',
mau_tip:
'MAU (monthly active user) means the number of unique users who have exchanged at least one token with Logto in a billing month.',
tokens_tip:
'All kinds of tokens that issued by Logto, including access token, refresh token, etc.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Cuota',
tenant_limit: 'Límite de inquilinos',
title: 'Conceptos básicos',
base_price: 'Precio base',
mau_limit: 'Límite de MAU',
included_tokens: 'Tokens incluidos',
},
application: {
title: 'Aplicaciones',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizaciones',
monthly_active_organization: 'Organización activa mensualmente',
allowed_users_per_org: 'Usuarios permitidos por organización',
invitation: 'Invitación (Próximamente)',
invitation: 'Invitación',
org_roles: 'Roles de organización',
org_permissions: 'Permisos de organización',
just_in_time_provisioning: 'Provisión justo a tiempo',
@ -88,6 +88,11 @@ const quota_table = {
'Gratis durante la fase beta. Comenzaremos a cobrar una vez que finalicemos los precios basados en el uso de la organización.',
beta: 'Beta',
add_on_beta: 'Complemento (Beta)',
million: '{{value, number}} millones',
mau_tip:
'MAU (usuario activo mensual) significa el número de usuarios únicos que han intercambiado al menos un token con Logto en un mes de facturación.',
tokens_tip:
'Todo tipo de tokens emitidos por Logto, incluyendo tokens de acceso, tokens de actualización, etc.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Quota',
tenant_limit: 'Limite de locataire',
title: 'Basiques',
base_price: 'Prix de base',
mau_limit: 'Limite MAU',
mau_limit: 'Limite de MAU',
included_tokens: 'Jetons inclus',
},
application: {
title: 'Applications',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organisations',
monthly_active_organization: 'Organisation active mensuelle',
allowed_users_per_org: 'Utilisateurs autorisés par organisation',
invitation: 'Invitation (Bientôt disponible)',
invitation: 'Invitation',
org_roles: "Rôles d'organisation",
org_permissions: "Permissions d'organisation",
just_in_time_provisioning: 'Fourniture juste-à-temps',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Ticket de support',
premium: 'Premium',
email_ticket_support: 'Support par ticket électronique',
soc2_report: 'Rapport SOC2 (prochainement)',
hipaa_or_baa_report: 'Rapport HIPAA/BAA (prochainement)',
soc2_report: 'Rapport SOC2',
hipaa_or_baa_report: 'Rapport HIPAA/BAA',
},
unlimited: 'Illimité',
contact: 'Contact',
@ -88,6 +88,11 @@ const quota_table = {
"Gratuit à utiliser pendant la phase bêta. Nous commencerons à facturer une fois que nous aurons finalisé les tarifs basés sur l'usage de l'organisation.",
beta: 'Bêta',
add_on_beta: 'Module complémentaire (Bêta)',
million: '{{value, number}} million',
mau_tip:
"MAU (utilisateur actif mensuel) signifie le nombre d'utilisateurs uniques qui ont échangé au moins un jeton avec Logto au cours d'un mois de facturation.",
tokens_tip:
"Tous types de jetons émis par Logto, y compris les jetons d'accès, les jetons de rafraîchissement, etc.",
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Quota',
tenant_limit: 'Limite tenant',
title: 'Principi',
base_price: 'Prezzo base',
mau_limit: 'Limite MAU',
mau_limit: 'Limite di MAU',
included_tokens: 'Token inclusi',
},
application: {
title: 'Applicazioni',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizzazioni',
monthly_active_organization: 'Organizzazione attive mensili',
allowed_users_per_org: 'Utenti permessi per org',
invitation: 'Invito (In arrivo)',
invitation: 'Invito',
org_roles: 'Ruoli org',
org_permissions: 'Permessi org',
just_in_time_provisioning: 'Provisioning just-in-time',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Ticket di assistenza',
premium: 'Premium',
email_ticket_support: 'Supporto tramite ticket e-mail',
soc2_report: 'Rapporto SOC2 (In arrivo)',
hipaa_or_baa_report: 'Rapporto HIPAA/BAA (In arrivo)',
soc2_report: 'Rapporto SOC2',
hipaa_or_baa_report: 'Rapporto HIPAA/BAA',
},
unlimited: 'Illimitato',
contact: 'Contatta',
@ -88,6 +88,11 @@ const quota_table = {
"Gratuito durante la fase beta. Inizieremo a addebitare una volta che finalizziamo i prezzi basati sull'utilizzo dell'org.",
beta: 'Beta',
add_on_beta: 'Componente Aggiuntivo (Beta)',
million: '{{value, number}} milioni',
mau_tip:
'MAU (utente attivo mensile) significa il numero di utenti unici che hanno scambiato almeno un token con Logto in un mese di fatturazione.',
tokens_tip:
'Tutti i tipi di token emessi da Logto, inclusi token di accesso, token di aggiornamento, ecc.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'クォータ',
tenant_limit: 'テナント制限',
title: '基本',
base_price: '基本価格',
mau_limit: 'MAU制限',
mau_limit: 'MAU 制限',
included_tokens: '含まれるトークン',
},
application: {
title: 'アプリケーション',
@ -56,7 +56,7 @@ const quota_table = {
organizations: '組織',
monthly_active_organization: '月間アクティブ組織',
allowed_users_per_org: '組織ごとの許可ユーザー数',
invitation: '招待状(近日公開)',
invitation: '招待状',
org_roles: '組織ロール',
org_permissions: '組織権限',
just_in_time_provisioning: 'ジャストインタイムプロビジョニング',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'カスタマーチケット',
premium: 'プレミアム',
email_ticket_support: 'Emailチケットサポート',
soc2_report: 'SOC2レポート(近日公開)',
hipaa_or_baa_report: 'HIPAA/BAAレポート(近日公開)',
soc2_report: 'SOC2レポート',
hipaa_or_baa_report: 'HIPAA/BAAレポート',
},
unlimited: '無制限',
contact: 'お問い合わせ',
@ -88,6 +88,11 @@ const quota_table = {
'ベータフェーズ中は無料です。組織の使用に基づく価格設定が最終決定した後、請求を開始します。',
beta: 'ベータ',
add_on_beta: 'アドオン(ベータ版)',
million: '{{value, number}} 万',
mau_tip:
'MAU月間アクティブユーザーとは、請求月において少なくとも1つのトークンをLogtoと交換したユニークなユーザーの数を指します。',
tokens_tip:
'Logtoによって発行されたすべての種類のトークン、アクセストークン、リフレッシュトークンなどを含みます。',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: '할당량',
tenant_limit: '테넌트 제한',
title: '기본',
base_price: '기본 가격',
mau_limit: 'MAU 제한',
mau_limit: 'MAU 한도',
included_tokens: '포함된 토큰',
},
application: {
title: '애플리케이션',
@ -56,7 +56,7 @@ const quota_table = {
organizations: '조직',
monthly_active_organization: '월간 활성 조직',
allowed_users_per_org: '조직 당 허용된 사용자',
invitation: '초대장 (곧 제공 예정)',
invitation: '초대장',
org_roles: '조직 역할',
org_permissions: '조직 권한',
just_in_time_provisioning: '적시 프로비저닝',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: '지원 티켓',
premium: '프리미엄',
email_ticket_support: '이메일 티켓 지원',
soc2_report: 'SOC2 보고서 (곧 제공 예정)',
hipaa_or_baa_report: 'HIPAA/BAA 보고서 (곧 제공 예정)',
soc2_report: 'SOC2 보고서',
hipaa_or_baa_report: 'HIPAA/BAA 보고서',
},
unlimited: '무제한',
contact: '문의',
@ -87,6 +87,10 @@ const quota_table = {
'베타 단계에서 무료입니다. 조직 사용량 기반 요금 책정 후 요금이 부과됩니다.',
beta: '베타',
add_on_beta: '부가 기능 (베타)',
million: '{{value, number}} 백만',
mau_tip:
'MAU (월간 활성 사용자)는 빌링 월에 Logto와 적어도 하나의 토큰을 교환한 고유 사용자 수를 의미합니다.',
tokens_tip: 'Logto에서 발행한 모든 종류의 토큰, 액세스 토큰, 리프레시 토큰 등을 포함합니다.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Limit',
tenant_limit: 'Limit lokatora',
title: 'Podstawy',
base_price: 'Cena podstawowa',
mau_limit: 'Limit MAU',
included_tokens: 'Zawarte tokeny',
},
application: {
title: 'Aplikacje',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizacje',
monthly_active_organization: 'Miesięczna liczba aktywnych organizacji',
allowed_users_per_org: 'Dozwolona liczba użytkowników na organizację',
invitation: 'Zaproszenie (Wkrótce)',
invitation: 'Zaproszenie',
org_roles: 'Role organizacji',
org_permissions: 'Uprawnienia organizacji',
just_in_time_provisioning: 'Provisioning w trybie just-in-time',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Zgłoszenie wsparcia',
premium: 'Premium',
email_ticket_support: 'Wsparcie za pośrednictwem biletów e-mail',
soc2_report: 'Raport SOC2 (Wkrótce)',
hipaa_or_baa_report: 'Raport HIPAA/BAA (Wkrótce)',
soc2_report: 'Raport SOC2',
hipaa_or_baa_report: 'Raport HIPAA/BAA',
},
unlimited: 'Nieograniczone',
contact: 'Kontakt',
@ -88,6 +88,11 @@ const quota_table = {
'Darmowe w trakcie fazy beta. Będziemy pobierać opłaty po zakończeniu fazy beta przy ustaleniu opłat w oparciu o użycie organizacji.',
beta: 'Beta',
add_on_beta: 'Dodatkowy (Beta)',
million: '{{value, number}} milion',
mau_tip:
'MAU (miesięczny aktywny użytkownik) oznacza liczbę unikalnych użytkowników, którzy wymienili co najmniej jeden token z Logto w miesiącu rozliczeniowym.',
tokens_tip:
'Wszystkie rodzaje tokenów wydanych przez Logto, w tym tokeny dostępu, tokeny odświeżania, itp.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Cota',
tenant_limit: 'Limite de inquilino',
title: 'Básico',
base_price: 'Preço base',
mau_limit: 'Limite de MAU',
included_tokens: 'Tokens incluídos',
},
application: {
title: 'Aplicações',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizações',
monthly_active_organization: 'Organização ativa mensal',
allowed_users_per_org: 'Usuários permitidos por organização',
invitation: 'Convite (Em breve)',
invitation: 'Convite',
org_roles: 'Funções de organização',
org_permissions: 'Permissões de organização',
just_in_time_provisioning: 'Provisionamento just-in-time',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Ticket de suporte',
premium: 'Premium',
email_ticket_support: 'Suporte via e-mail',
soc2_report: 'Relatório SOC2 (Em breve)',
hipaa_or_baa_report: 'Relatório HIPAA/BAA (Em breve)',
soc2_report: 'Relatório SOC2',
hipaa_or_baa_report: 'Relatório HIPAA/BAA',
},
unlimited: 'Ilimitado',
contact: 'Contato',
@ -88,6 +88,11 @@ const quota_table = {
'Grátis durante a fase beta. Começaremos a cobrar uma vez que finalizarmos os preços baseados no uso da organização.',
beta: 'Beta',
add_on_beta: 'Complemento (Beta)',
million: '{{value, number}} milhão',
mau_tip:
'MAU (usuário ativo mensal) significa o número de usuários únicos que trocaram pelo menos um token com o Logto em um mês de faturamento.',
tokens_tip:
'Todos os tipos de tokens emitidos pelo Logto, incluindo token de acesso, token de atualização, etc.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Quota',
tenant_limit: 'Limite do inquilino',
title: 'Básicos',
base_price: 'Preço base',
mau_limit: 'Limite MAU',
mau_limit: 'Limite de MAU',
included_tokens: 'Tokens incluídos',
},
application: {
title: 'Aplicações',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizações',
monthly_active_organization: 'Organização ativa mensalmente',
allowed_users_per_org: 'Utilizadores permitidos por org',
invitation: 'Convite (Em breve)',
invitation: 'Convite',
org_roles: 'Funções da organização',
org_permissions: 'Permissões da organização',
just_in_time_provisioning: 'Provisionamento just-in-time',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Bilhete de suporte',
premium: 'Premium',
email_ticket_support: 'Suporte por bilhete de e-mail',
soc2_report: 'Relatório SOC2 (Em breve)',
hipaa_or_baa_report: 'Relatório HIPAA/BAA (Em breve)',
soc2_report: 'Relatório SOC2',
hipaa_or_baa_report: 'Relatório HIPAA/BAA',
},
unlimited: 'Ilimitado',
contact: 'Contactar',
@ -88,6 +88,11 @@ const quota_table = {
'Gratuito durante a fase beta. Começaremos a cobrar assim que finalizarmos os preços baseados no uso da organização.',
beta: 'Beta',
add_on_beta: 'Suplemento (Beta)',
million: '{{value, number}} milhão',
mau_tip:
'MAU (utilizador ativo mensal) significa o número de utilizadores únicos que trocaram pelo menos um token com o Logto num mês de faturação.',
tokens_tip:
'Todos os tipos de tokens emitidos pelo Logto, incluindo token de acesso, token de atualização, etc.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Квота',
tenant_limit: 'Лимит арендатора',
title: 'Основы',
base_price: 'Базовая цена',
mau_limit: 'Лимит активных пользователей (MAU)',
mau_limit: 'Лимит MAU',
included_tokens: 'Включенные токены',
},
application: {
title: 'Приложения',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Организации',
monthly_active_organization: 'Активная организация в месяц',
allowed_users_per_org: 'Разрешенные пользователи в организации',
invitation: 'Приглашение (Скоро)',
invitation: 'Приглашение',
org_roles: 'Роли организации',
org_permissions: 'Права организации',
just_in_time_provisioning: 'Пакетная настройка по запросу',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Техническая поддержка',
premium: 'Премиум',
email_ticket_support: 'Поддержка по электронной почте',
soc2_report: 'Отчет SOC2 (Скоро)',
hipaa_or_baa_report: 'Отчет HIPAA/BAA (Скоро)',
soc2_report: 'Отчет SOC2',
hipaa_or_baa_report: 'Отчет HIPAA/BAA',
},
unlimited: 'Неограниченно',
contact: 'Связаться',
@ -88,6 +88,11 @@ const quota_table = {
'Бесплатно во время бета-тестирования. Мы начнем взимать плату, как только установим цены на использование по организации.',
beta: 'Бета-тестирование',
add_on_beta: 'Дополнение (бета-тестирование)',
million: '{{value, number}} миллионов',
mau_tip:
'MAU (месячно активные пользователи) означает количество уникальных пользователей, которые обменялись хотя бы одним токеном с Logto за месяц расчета.',
tokens_tip:
'Все виды токенов, выпущенных Logto, включая токены доступа, токены обновления и т. д.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: 'Kota',
tenant_limit: 'Kiracı limiti',
title: 'Temel',
base_price: 'Temel fiyat',
mau_limit: 'MAU limiti',
included_tokens: 'Dahil olan jetonlar',
},
application: {
title: 'Uygulamalar',
@ -56,7 +56,7 @@ const quota_table = {
organizations: 'Organizasyonlar',
monthly_active_organization: 'Aylık aktif organizasyon',
allowed_users_per_org: 'Organizasyon başına izin verilen kullanıcılar',
invitation: 'Davet (Yakında)',
invitation: 'Davet',
org_roles: 'Org rolleri',
org_permissions: 'Org izinleri',
just_in_time_provisioning: 'İstisnai olana kadar temin',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: 'Müşteri destek bileti',
premium: 'Premium',
email_ticket_support: 'E-posta bileti desteği',
soc2_report: 'SOC2 raporu (Yakında)',
hipaa_or_baa_report: 'HIPAA/BAA raporu (Yakında)',
soc2_report: 'SOC2 raporu',
hipaa_or_baa_report: 'HIPAA/BAA raporu',
},
unlimited: 'Sınırsız',
contact: 'İletişim',
@ -88,6 +88,11 @@ const quota_table = {
'Free to use during the beta phase. We will begin charging once we finalize the org usage-based pricing.',
beta: 'Beta',
add_on_beta: 'Ek hizmet (Beta)',
million: '{{value, number}} milyon',
mau_tip:
'MAU (aylık aktif kullanıcı) Logto ile en az bir token değiştiren benzersiz kullanıcı sayısını ifade eder.',
tokens_tip:
'Logto tarafından ihraç edilen erişim tokeni, yenileme tokeni vb. dahil olmak üzere tüm token türleri.',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: '配额',
tenant_limit: '租户限制',
base_price: '基本价格',
title: '基础',
base_price: '基础价格',
mau_limit: 'MAU 限制',
included_tokens: '包含的令牌',
},
application: {
title: '应用',
@ -56,7 +56,7 @@ const quota_table = {
organizations: '组织',
monthly_active_organization: '每月活跃组织',
allowed_users_per_org: '每组织允许的用户数',
invitation: '邀请(即将推出)',
invitation: '邀请',
org_roles: '组织角色',
org_permissions: '组织权限',
just_in_time_provisioning: '即时配置',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: '客户支持票据',
premium: '高级版',
email_ticket_support: '邮件支持票据',
soc2_report: 'SOC2报告(即将推出)',
hipaa_or_baa_report: 'HIPAA/BAA报告(即将推出)',
soc2_report: 'SOC2报告',
hipaa_or_baa_report: 'HIPAA/BAA报告',
},
unlimited: '无限制',
contact: '联系',
@ -86,6 +86,9 @@ const quota_table = {
'在测试阶段免费使用。一旦我们确定基于组织使用情况的定价,我们将开始收费。',
beta: '测试版',
add_on_beta: '附加功能(测试版)',
million: '{{value, number}} 百万',
mau_tip: 'MAU月活跃用户表示在一个计费月内与 Logto 交换过至少一个令牌的独立用户数量。',
tokens_tip: 'Logto 发行的所有类型令牌,包括访问令牌、刷新令牌等。',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: '配額',
tenant_limit: '租戶限制',
title: '基本',
base_price: '基本價格',
mau_limit: 'MAU 限制',
included_tokens: '包含的令牌',
},
application: {
title: '應用程式',
@ -56,7 +56,7 @@ const quota_table = {
organizations: '組織',
monthly_active_organization: '每月活躍組織',
allowed_users_per_org: '允許的組織用戶',
invitation: '邀請(即將推出)',
invitation: '邀請',
org_roles: '組織角色',
org_permissions: '組織權限',
just_in_time_provisioning: '即時規定',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: '客戶支援票據',
premium: '高級版',
email_ticket_support: 'Email ticket support',
soc2_report: 'SOC2報告(即將推出)',
hipaa_or_baa_report: 'HIPAA/BAA報告(即將推出)',
soc2_report: 'SOC2報告',
hipaa_or_baa_report: 'HIPAA/BAA報告',
},
unlimited: '無限制',
contact: '聯絡',
@ -86,6 +86,9 @@ const quota_table = {
'在測試版階段免費使用。我們確定組織基於使用情況的價格後將開始收費。',
beta: '測試版',
add_on_beta: '附加功能(測試版)',
million: '{{value, number}} 百萬',
mau_tip: 'MAU月活躍用戶表示在一個結算月內與 Logto 交換過至少一個令牌的獨立用戶數量。',
tokens_tip: 'Logto 發行的所有類型令牌,包括訪問令牌、刷新令牌等。',
};
export default Object.freeze(quota_table);

View file

@ -1,9 +1,9 @@
const quota_table = {
quota: {
title: '配額',
tenant_limit: '租戶限制',
title: '基本',
base_price: '基本價格',
mau_limit: 'MAU 限制',
included_tokens: '包含的令牌',
},
application: {
title: '應用程式',
@ -56,7 +56,7 @@ const quota_table = {
organizations: '組織',
monthly_active_organization: '每月活躍組織',
allowed_users_per_org: '組織允許用戶數',
invitation: '邀請(即將推出)',
invitation: '邀請',
org_roles: '組織角色',
org_permissions: '組織權限',
just_in_time_provisioning: '即時供應管理',
@ -67,8 +67,8 @@ const quota_table = {
customer_ticket: '客戶支援票證',
premium: '進階版',
email_ticket_support: '郵件票證支援',
soc2_report: 'SOC2 報告(即將推出)',
hipaa_or_baa_report: 'HIPAA/BAA 報告(即將推出)',
soc2_report: 'SOC2 報告',
hipaa_or_baa_report: 'HIPAA/BAA 報告',
},
unlimited: '無限制',
contact: '聯絡',
@ -87,6 +87,9 @@ const quota_table = {
'在測試版階段免費使用。一旦我們確定組織使用量的定價,我們將開始收費。',
beta: '測試版',
add_on_beta: '附加功能(測試版)',
million: '{{value, number}} 百萬',
mau_tip: 'MAU月活躍使用者表示在一個計費月內與 Logto 交換過至少一個令牌的獨立使用者數量。',
tokens_tip: 'Logto 發行的所有類型令牌,包括訪問令牌、刷新令牌等。',
};
export default Object.freeze(quota_table);