0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-24 22:41:28 -05:00

refactor(console): move organization template into a single page (#5590)

* refactor(console): move organization template into a single page

* feat(phrases): add org template translations
This commit is contained in:
Xiao Yijun 2024-04-01 10:20:54 +08:00 committed by GitHub
parent 982aa918e6
commit 9bf9f07f17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 870 additions and 11 deletions

View file

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.5585 14.0248L15.8335 12.2582C15.4624 11.9055 14.9944 11.6718 14.4895 11.5871C13.9846 11.5025 13.4659 11.5707 13.0002 11.7832L12.2502 11.0332C13.134 9.85226 13.5376 8.38039 13.3798 6.91386C13.222 5.44732 12.5145 4.09502 11.3997 3.12916C10.2849 2.16331 8.8456 1.65563 7.37154 1.70832C5.89748 1.76101 4.49811 2.37015 3.45513 3.41314C2.41215 4.45612 1.803 5.85549 1.75031 7.32955C1.69762 8.80361 2.2053 10.2429 3.17115 11.3577C4.13701 12.4725 5.48932 13.18 6.95585 13.3378C8.42239 13.4956 9.89425 13.092 11.0752 12.2082L11.8168 12.9498C11.5794 13.4162 11.4943 13.9453 11.5735 14.4626C11.6528 14.9799 11.8924 15.4593 12.2585 15.8332L14.0252 17.5998C14.4939 18.068 15.1293 18.331 15.7918 18.331C16.4543 18.331 17.0897 18.068 17.5585 17.5998C17.7966 17.367 17.9858 17.0889 18.115 16.782C18.2441 16.475 18.3107 16.1454 18.3107 15.8123C18.3107 15.4793 18.2441 15.1496 18.115 14.8427C17.9858 14.5357 17.7966 14.2577 17.5585 14.0248ZM10.4918 10.4915C9.90868 11.0732 9.16624 11.469 8.35827 11.6289C7.55031 11.7888 6.71307 11.7057 5.95232 11.39C5.19158 11.0743 4.54146 10.5403 4.08408 9.85528C3.62671 9.1703 3.3826 8.36514 3.3826 7.5415C3.3826 6.71786 3.62671 5.91269 4.08408 5.22771C4.54146 4.54274 5.19158 4.00868 5.95232 3.69301C6.71307 3.37733 7.55031 3.2942 8.35827 3.45412C9.16624 3.61404 9.90868 4.00983 10.4918 4.5915C10.8798 4.97854 11.1877 5.43834 11.3978 5.94455C11.6078 6.45076 11.7159 6.99343 11.7159 7.5415C11.7159 8.08956 11.6078 8.63223 11.3978 9.13844C11.1877 9.64465 10.8798 10.1044 10.4918 10.4915ZM16.3835 16.3832C16.306 16.4613 16.2139 16.5233 16.1123 16.5656C16.0108 16.6079 15.9018 16.6297 15.7918 16.6297C15.6818 16.6297 15.5729 16.6079 15.4713 16.5656C15.3698 16.5233 15.2776 16.4613 15.2002 16.3832L13.4335 14.6165C13.3554 14.539 13.2934 14.4469 13.2511 14.3453C13.2088 14.2438 13.187 14.1348 13.187 14.0248C13.187 13.9148 13.2088 13.8059 13.2511 13.7043C13.2934 13.6028 13.3554 13.5106 13.4335 13.4332C13.511 13.3551 13.6031 13.2931 13.7047 13.2508C13.8062 13.2084 13.9151 13.1867 14.0252 13.1867C14.1352 13.1867 14.2441 13.2084 14.3456 13.2508C14.4472 13.2931 14.5394 13.3551 14.6168 13.4332L16.3835 15.1998C16.4616 15.2773 16.5236 15.3695 16.5659 15.471C16.6082 15.5726 16.63 15.6815 16.63 15.7915C16.63 15.9015 16.6082 16.0104 16.5659 16.112C16.5236 16.2135 16.4616 16.3057 16.3835 16.3832Z" fill="#5D34F2"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -24,3 +24,9 @@ export const logtoThirdPartyAppPermissionsLink =
'/docs/recipes/logto-as-idp/permissions-management/';
export const logtoThirdPartyAppBrandingLink = '/docs/recipes/logto-as-idp/branding-customization/';
export const signingKeysLink = '/docs/recipes/openid-connect/signing-keys-rotation/';
export const organizationTemplateLink =
'/docs/recipes/organizations/understand-how-it-works/#organization-template';
export const organizationRoleLink =
'/docs/recipes/organizations/understand-how-it-works/#organization-role';
export const organizationPermissionLink =
'/docs/recipes/organizations/understand-how-it-works/#organization-permission';

View file

@ -47,3 +47,8 @@ export enum EnterpriseSsoDetailsTabs {
Connection = 'connection',
Experience = 'experience',
}
export enum OrganizationTemplateTabs {
OrgRoles = 'org-roles',
OrgPermissions = 'org-permissions',
}

View file

@ -99,6 +99,11 @@ export const useSidebarMenuItems = (): {
Icon: Role,
title: 'roles',
},
{
Icon: Role,
title: 'organization_template',
isHidden: !isDevFeaturesEnabled,
},
],
},
{

View file

@ -11,6 +11,7 @@ import {
TenantSettingsTabs,
ApplicationDetailsTabs,
EnterpriseSsoDetailsTabs,
OrganizationTemplateTabs,
} from '@/consts';
import { isCloud, isDevFeaturesEnabled } from '@/consts/env';
import { TenantsContext } from '@/contexts/TenantsProvider';
@ -34,6 +35,9 @@ import JwtClaims from '@/pages/JwtClaims';
import Mfa from '@/pages/Mfa';
import NotFound from '@/pages/NotFound';
import OrganizationDetails from '@/pages/OrganizationDetails';
import OrganizationTemplate from '@/pages/OrganizationTemplate';
import OrgPermissions from '@/pages/OrganizationTemplate/OrgPermissions';
import OrgRoles from '@/pages/OrganizationTemplate/OrgRoles';
import Organizations from '@/pages/Organizations';
import OrganizationGuide from '@/pages/Organizations/Guide';
import Profile from '@/pages/Profile';
@ -182,6 +186,19 @@ function ConsoleContent() {
<Route path={RoleDetailsTabs.M2mApps} element={<RoleApplications />} />
</Route>
</Route>
{isDevFeaturesEnabled && (
<Route path="organization-template" element={<OrganizationTemplate />}>
<Route
index
element={<Navigate replace to={OrganizationTemplateTabs.OrgRoles} />}
/>
<Route path={OrganizationTemplateTabs.OrgRoles} element={<OrgRoles />} />
<Route
path={OrganizationTemplateTabs.OrgPermissions}
element={<OrgPermissions />}
/>
</Route>
)}
<Route path="organizations">
<Route index element={<Organizations />} />
<Route path="create" element={<Organizations />} />

View file

@ -21,10 +21,6 @@
color: var(--color-text-secondary);
}
.learnMore:not(:first-child) {
margin-left: _.unit(1);
}
&.large {
.title {
font: var(--font-title-1);

View file

@ -55,13 +55,14 @@ function CardTitle({
<span>{typeof subtitle === 'string' ? <DynamicT forKey={subtitle} /> : subtitle}</span>
)}
{learnMoreLink?.href && (
<TextLink
href={learnMoreLink.href}
targetBlank={learnMoreLink.targetBlank}
className={styles.learnMore}
>
{t('general.learn_more')}
</TextLink>
<>
{/* Use a space to keep the link and the text separate.
* Avoid using `margin-left` since it will cause an unexpected gap when the "learn more" text is at the start of a new line
*/}{' '}
<TextLink href={learnMoreLink.href} targetBlank={learnMoreLink.targetBlank}>
{t('general.learn_more')}
</TextLink>
</>
)}
</div>
)}

View file

@ -0,0 +1,11 @@
@use '@/scss/underscore' as _;
.filter {
display: flex;
justify-content: space-between;
align-items: center;
.createButton {
margin-left: _.unit(2);
}
}

View file

@ -0,0 +1,139 @@
import { type OrganizationScope } from '@logto/schemas';
import { cond } from '@silverhand/essentials';
import { useTranslation } from 'react-i18next';
import useSWR from 'swr';
import Plus from '@/assets/icons/plus.svg';
import PermissionsEmptyDark from '@/assets/images/permissions-empty-dark.svg';
import PermissionsEmpty from '@/assets/images/permissions-empty.svg';
import ActionsButton from '@/components/ActionsButton';
import Breakable from '@/components/Breakable';
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
import { organizationPermissionLink } from '@/consts';
import Button from '@/ds-components/Button';
import DynamicT from '@/ds-components/DynamicT';
import Search from '@/ds-components/Search';
import Table from '@/ds-components/Table';
import TablePlaceholder from '@/ds-components/Table/TablePlaceholder';
import Tag from '@/ds-components/Tag';
import { type RequestError } from '@/hooks/use-api';
import useDocumentationUrl from '@/hooks/use-documentation-url';
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
import { buildUrl, formatSearchKeyword } from '@/utils/url';
import * as styles from './index.module.scss';
function OrgPermissions() {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { getDocumentationUrl } = useDocumentationUrl();
const [{ keyword }, updateSearchParameters] = useSearchParametersWatcher({
keyword: '',
});
const { data, error, mutate, isLoading } = useSWR<OrganizationScope[], RequestError>(
buildUrl('api/organization-scopes', {
...cond(keyword && { q: formatSearchKeyword(keyword) }),
})
);
return (
<Table
rowGroups={[{ key: 'orgPermissions', data }]}
rowIndexKey="id"
columns={[
{
title: <DynamicT forKey="organization_template.org_permissions.permission_column" />,
dataIndex: 'name',
colSpan: 7,
render: ({ name }) => {
return (
<Tag variant="cell">
<Breakable>{name}</Breakable>
</Tag>
);
},
},
{
title: <DynamicT forKey="organization_template.org_permissions.description_column" />,
dataIndex: 'scopes',
colSpan: 8,
render: ({ description }) => <Breakable>{description ?? '-'}</Breakable>,
},
{
title: null,
dataIndex: 'action',
colSpan: 1,
render: () => (
<ActionsButton
fieldName="organization_template.org_permissions.permission_column"
deleteConfirmation="organization_template.org_permissions.delete_confirm"
onEdit={() => {
// Todo @xiaoyijun implement edit
}}
onDelete={async () => {
// Todo @xiaoyijun implement deletion
}}
/>
),
},
]}
filter={
<div className={styles.filter}>
<Search
placeholder={t('organization_template.org_permissions.search_placeholder')}
defaultValue={keyword}
isClearable={Boolean(keyword)}
onSearch={(keyword) => {
updateSearchParameters({ keyword });
}}
onClearSearch={() => {
updateSearchParameters({ keyword: '' });
}}
/>
<Button
title="organization_template.org_permissions.create_org_permission"
className={styles.createButton}
type="primary"
size="large"
icon={<Plus />}
onClick={() => {
// Todo @xiaoyijun implement org permission creation
}}
/>
</div>
}
placeholder={
keyword ? (
<EmptyDataPlaceholder />
) : (
<TablePlaceholder
image={<PermissionsEmpty />}
imageDark={<PermissionsEmptyDark />}
title="organization_template.org_permissions.placeholder_title"
description="organization_template.org_permissions.placeholder_description"
learnMoreLink={{
href: getDocumentationUrl(organizationPermissionLink),
targetBlank: 'noopener',
}}
action={
<Button
title="organization_template.org_permissions.create_org_permission"
type="primary"
size="large"
icon={<Plus />}
onClick={() => {
// Todo @xiaoyijun implement org permission creation
}}
/>
}
/>
)
}
isLoading={isLoading}
errorMessage={error?.body?.message ?? error?.message}
onRetry={async () => mutate(undefined, true)}
/>
);
}
export default OrgPermissions;

View file

@ -0,0 +1,13 @@
@use '@/scss/underscore' as _;
.permissions {
display: flex;
flex-wrap: wrap;
gap: _.unit(2);
}
.filter {
display: flex;
flex-direction: row-reverse;
align-items: center;
}

View file

@ -0,0 +1,126 @@
import { type OrganizationRoleWithScopes } from '@logto/schemas';
import useSWR from 'swr';
import Plus from '@/assets/icons/plus.svg';
import OrgRoleIcon from '@/assets/icons/role-feature.svg';
import RolesEmptyDark from '@/assets/images/roles-empty-dark.svg';
import RolesEmpty from '@/assets/images/roles-empty.svg';
import Breakable from '@/components/Breakable';
import ItemPreview from '@/components/ItemPreview';
import ThemedIcon from '@/components/ThemedIcon';
import { defaultPageSize, organizationRoleLink } from '@/consts';
import Button from '@/ds-components/Button';
import DynamicT from '@/ds-components/DynamicT';
import Table from '@/ds-components/Table';
import TablePlaceholder from '@/ds-components/Table/TablePlaceholder';
import Tag from '@/ds-components/Tag';
import { type RequestError } from '@/hooks/use-api';
import useDocumentationUrl from '@/hooks/use-documentation-url';
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
import { buildUrl } from '@/utils/url';
import * as styles from './index.module.scss';
function OrgRoles() {
const { getDocumentationUrl } = useDocumentationUrl();
const [{ page }, updateSearchParameters] = useSearchParametersWatcher({
page: 1,
});
const { data, error, mutate, isLoading } = useSWR<
[OrganizationRoleWithScopes[], number],
RequestError
>(
buildUrl('api/organization-roles', {
page: String(page),
page_size: String(defaultPageSize),
})
);
const [orgRoles, totalCount] = data ?? [];
return (
<Table
rowGroups={[{ key: 'orgRoles', data: orgRoles }]}
rowIndexKey="id"
columns={[
{
title: <DynamicT forKey="organization_template.org_roles.org_role_column" />,
dataIndex: 'name',
colSpan: 4,
render: ({ name }) => {
return <ItemPreview title={name} icon={<ThemedIcon for={OrgRoleIcon} />} />;
},
},
{
title: <DynamicT forKey="organization_template.org_roles.permissions_column" />,
dataIndex: 'scopes',
colSpan: 12,
render: ({ scopes }) => {
return scopes.length === 0 ? (
'-'
) : (
<div className={styles.permissions}>
{scopes.map(({ id, name }) => (
<Tag key={id} variant="cell">
<Breakable>{name}</Breakable>
</Tag>
))}
</div>
);
},
},
]}
filter={
<div className={styles.filter}>
<Button
title="organization_template.org_roles.create_org_roles"
type="primary"
size="large"
icon={<Plus />}
onClick={() => {
// Todo @xiaoyijun implment create org role
}}
/>
</div>
}
placeholder={
<TablePlaceholder
image={<RolesEmpty />}
imageDark={<RolesEmptyDark />}
title="organization_template.org_roles.placeholder_title"
description="organization_template.org_roles.placeholder_description"
learnMoreLink={{
href: getDocumentationUrl(organizationRoleLink),
targetBlank: 'noopener',
}}
action={
<Button
title="organization_template.org_roles.create_org_roles"
type="primary"
size="large"
icon={<Plus />}
onClick={() => {
// Todo @xiaoyijun implment create org role
}}
/>
}
/>
}
pagination={{
page,
totalCount,
pageSize: defaultPageSize,
onChange: (page) => {
updateSearchParameters({ page });
},
}}
isLoading={isLoading}
errorMessage={error?.body?.message ?? error?.message}
onRetry={async () => mutate(undefined, true)}
/>
);
}
export default OrgRoles;

View file

@ -0,0 +1,8 @@
@use '@/scss/underscore' as _;
.container {
> *:not(:first-child) {
margin-top: _.unit(4);
}
}

View file

@ -0,0 +1,56 @@
import { withAppInsights } from '@logto/app-insights/react/AppInsightsReact';
import classNames from 'classnames';
import { Outlet } from 'react-router-dom';
import Research from '@/assets/icons/research.svg';
import PageMeta from '@/components/PageMeta';
import { OrganizationTemplateTabs, organizationTemplateLink } from '@/consts';
import Button from '@/ds-components/Button';
import CardTitle from '@/ds-components/CardTitle';
import DynamicT from '@/ds-components/DynamicT';
import TabNav, { TabNavItem } from '@/ds-components/TabNav';
import useDocumentationUrl from '@/hooks/use-documentation-url';
import * as pageLayout from '@/scss/page-layout.module.scss';
import * as styles from './index.module.scss';
const basePathname = '/organization-template';
function OrganizationTemplate() {
const { getDocumentationUrl } = useDocumentationUrl();
return (
<div className={classNames(pageLayout.container, styles.container)}>
<PageMeta titleKey="organization_template.title" />
<div className={pageLayout.headline}>
<CardTitle
title="organization_template.title"
subtitle="organization_template.subtitle"
learnMoreLink={{
href: getDocumentationUrl(organizationTemplateLink),
targetBlank: 'noopener',
}}
/>
<Button
icon={<Research />}
title="application_details.check_guide"
type="outline"
onClick={() => {
// Todo @xiaoyijun implement guide
}}
/>
</div>
<TabNav>
<TabNavItem href={`${basePathname}/${OrganizationTemplateTabs.OrgRoles}`}>
<DynamicT forKey="organization_template.org_roles.tab_name" />
</TabNavItem>
<TabNavItem href={`${basePathname}/${OrganizationTemplateTabs.OrgPermissions}`}>
<DynamicT forKey="organization_template.org_permissions.tab_name" />
</TabNavItem>
</TabNav>
<Outlet />
</div>
);
}
export default withAppInsights(OrganizationTemplate);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Organisationsvorlage',
subtitle:
'In Multi-Tenant-SaaS-Anwendungen ist es üblich, dass mehrere Organisationen identische Zugriffskontrollrichtlinien teilen, einschließlich Berechtigungen und Rollen. In Logto wird dieses Konzept als "Organisationsvorlage" bezeichnet. Ihre Verwendung vereinfacht den Prozess des Aufbaus und Entwurfs Ihres Autorisierungsmodells.',
org_roles: {
tab_name: 'Org Rollen',
search_placeholder: 'Nach Rollennamen suchen',
create_org_roles: 'Org Rolle erstellen',
org_role_column: 'Org Rolle',
permissions_column: 'Berechtigungen',
placeholder_title: 'Organisationsrolle',
placeholder_description:
'Eine Organisationsrolle ist eine Gruppierung von Berechtigungen, die Benutzern zugewiesen werden können. Die Berechtigungen müssen aus den vordefinierten Organisationsberechtigungen stammen.',
},
org_permissions: {
tab_name: 'Org Berechtigungen',
search_placeholder: 'Nach Berechtigungsnamen suchen',
create_org_permission: 'Org Berechtigung erstellen',
permission_column: 'Berechtigung',
description_column: 'Beschreibung',
placeholder_title: 'Organisationsberechtigung',
placeholder_description:
'Organisationsberechtigung bezieht sich auf die Autorisierung, auf eine Ressource im Kontext der Organisation zuzugreifen.',
delete_confirm:
'Wenn diese Berechtigung gelöscht wird, verlieren alle Organisationsrollen, die diese Berechtigung beinhalten, diese Berechtigung und Benutzer, die diese Berechtigung hatten, verlieren den Zugang, der durch sie gewährt wurde.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Signierschlüssel',
organization_template: 'Organisationstemplate',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Organization template',
subtitle:
'In multi-tenant SaaS applications, it\'s common for multiple organizations to share identical access control policies, including permissions and roles. In Logto, this concept is termed "organization template." Using it streamlines the process of constructing and designing your authorization model.',
org_roles: {
tab_name: 'Org roles',
search_placeholder: 'Search by role name',
create_org_roles: 'Create org role',
org_role_column: 'Org role',
permissions_column: 'Permissions',
placeholder_title: 'Organization role',
placeholder_description:
'Organization role is a grouping of permissions that can be assigned to users. The permissions must come from the predefined organization permissions.',
},
org_permissions: {
tab_name: 'Org permissions',
search_placeholder: 'Search by permission name',
create_org_permission: 'Create org permission',
permission_column: 'Permission',
description_column: 'Description',
placeholder_title: 'Organization permission',
placeholder_description:
'Organization permission refers to the authorization to access a resource in the context of organization.',
delete_confirm:
'If this permission is deleted, all organization roles including this permission will lose this permission, and users who had this permission will lose the access granted by it.',
},
};
export default Object.freeze(organization_template);

View file

@ -16,6 +16,7 @@ const tabs = {
mfa: 'Multi-factor auth',
jwt_customizer: 'JWT Claims',
signing_keys: 'Signing keys',
organization_template: 'Organization template',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Plantilla de organización',
subtitle:
'En aplicaciones SaaS multiinquilino, es común que múltiples organizaciones compartan políticas de control de acceso idénticas, incluyendo permisos y roles. En Logto, este concepto se denomina "plantilla de organización". Usarla simplifica el proceso de construir y diseñar tu modelo de autorización.',
org_roles: {
tab_name: 'Roles de org',
search_placeholder: 'Buscar por nombre de rol',
create_org_roles: 'Crear rol de org',
org_role_column: 'Rol de org',
permissions_column: 'Permisos',
placeholder_title: 'Rol de organización',
placeholder_description:
'El rol de organización es un agrupamiento de permisos que se pueden asignar a los usuarios. Los permisos deben provenir de los permisos de organización predefinidos.',
},
org_permissions: {
tab_name: 'Permisos de org',
search_placeholder: 'Buscar por nombre de permiso',
create_org_permission: 'Crear permiso de org',
permission_column: 'Permiso',
description_column: 'Descripción',
placeholder_title: 'Permiso de organización',
placeholder_description:
'El permiso de organización se refiere a la autorización para acceder a un recurso en el contexto de la organización.',
delete_confirm:
'Si se elimina este permiso, todos los roles de organización que incluyan este permiso perderán dicho permiso, y los usuarios que tenían este permiso perderán el acceso concedido por él.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Claves de firma',
organization_template: 'Plantilla de organización',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Modèle dorganisation',
subtitle:
'Dans les applications SaaS multi-locataires, il est courant que plusieurs organisations partagent des politiques de contrôle daccès identiques, incluant les permissions et les rôles. Chez Logto, ce concept est désigné par "modèle dorganisation". Son utilisation simplifie le processus de construction et de conception de votre modèle dautorisation.',
org_roles: {
tab_name: 'Rôles org',
search_placeholder: 'Rechercher par nom de rôle',
create_org_roles: 'Créer un rôle org',
org_role_column: 'Rôle org',
permissions_column: 'Permissions',
placeholder_title: 'Rôle dorganisation',
placeholder_description:
'Un rôle dorganisation est un groupement de permissions qui peuvent être attribuées aux utilisateurs. Les permissions doivent provenir des permissions dorganisation prédéfinies.',
},
org_permissions: {
tab_name: 'Permissions org',
search_placeholder: 'Rechercher par nom de permission',
create_org_permission: 'Créer une permission org',
permission_column: 'Permission',
description_column: 'Description',
placeholder_title: 'Permission dorganisation',
placeholder_description:
'La permission dorganisation se réfère à lautorisation daccéder à une ressource dans le contexte de lorganisation.',
delete_confirm:
'Si cette permission est supprimée, tous les rôles dorganisation incluant cette permission perdront cette permission, et les utilisateurs qui avaient cette permission perdront laccès accordé par celle-ci.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Clés de signature',
organization_template: "Modèle d'organisation",
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Modello di organizzazione',
subtitle:
'Nelle applicazioni SaaS multi-tenant, è comune che più organizzazioni condividano politiche di controllo dellaccesso identiche, incluse autorizzazioni e ruoli. In Logto, questo concetto è denominato "modello di organizzazione". Utilizzarlo semplifica il processo di costruzione e progettazione del tuo modello di autorizzazione.',
org_roles: {
tab_name: 'Ruoli org',
search_placeholder: 'Cerca per nome del ruolo',
create_org_roles: 'Crea ruolo org',
org_role_column: 'Ruolo org',
permissions_column: 'Permessi',
placeholder_title: 'Ruolo di organizzazione',
placeholder_description:
'Il ruolo di organizzazione è un raggruppamento di permessi che possono essere assegnati agli utenti. I permessi devono provenire dai permessi di organizzazione predefiniti.',
},
org_permissions: {
tab_name: 'Permessi org',
search_placeholder: 'Cerca per nome del permesso',
create_org_permission: 'Crea permesso org',
permission_column: 'Permesso',
description_column: 'Descrizione',
placeholder_title: 'Permesso di organizzazione',
placeholder_description:
'Il permesso di organizzazione si riferisce allautorizzazione ad accedere a una risorsa nel contesto dellorganizzazione.',
delete_confirm:
'Se questo permesso viene eliminato, tutti i ruoli di organizzazione che includono questo permesso perderanno tale permesso, e gli utenti che avevano questo permesso perderanno laccesso concesso da esso.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Chiavi di firma',
organization_template: 'Modello di organizzazione',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: '組織テンプレート',
subtitle:
'マルチテナントSaaSアプリケーションでは、複数の組織が同一のアクセス制御ポリシーを共有することが一般的です。これには、権限と役割が含まれます。Logtoでは、この概念を「組織テンプレート」と呼びます。これを使用することで、認証モデルの構築と設計のプロセスが簡素化されます。',
org_roles: {
tab_name: '組織の役割',
search_placeholder: '役割名で検索',
create_org_roles: '組織の役割を作成',
org_role_column: '組織の役割',
permissions_column: '権限',
placeholder_title: '組織の役割',
placeholder_description:
'組織の役割は、ユーザーに割り当てることができる権限のグループです。権限は、事前に定義された組織の権限から来なければなりません。',
},
org_permissions: {
tab_name: '組織の権限',
search_placeholder: '権限名で検索',
create_org_permission: '組織の権限を作成',
permission_column: '権限',
description_column: '説明',
placeholder_title: '組織の権限',
placeholder_description:
'組織の権限は、組織の文脈でリソースにアクセスするための認可を指します。',
delete_confirm:
'この権限が削除されると、この権限を含むすべての組織の役割がこの権限を失い、この権限を持っていたユーザーはそれによって与えられたアクセスを失います。',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: '署名キー',
organization_template: '組織テンプレート',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,28 @@
const organization_template = {
title: '조직 템플릿',
subtitle:
'멀티-테넌트 SaaS 애플리케이션에서는 여러 조직이 동일한 접근 제어 정책을 공유하는 것이 일반적입니다. 이에는 권한과 역할이 포함됩니다. Logto에서는 이 개념을 "조직 템플릿"이라고 합니다. 이를 사용하면 권한 모델을 구축하고 설계하는 과정이 간소화됩니다.',
org_roles: {
tab_name: '조직 역할',
search_placeholder: '역할 이름으로 검색',
create_org_roles: '조직 역할 생성',
org_role_column: '조직 역할',
permissions_column: '권한',
placeholder_title: '조직 역할',
placeholder_description:
'조직 역할은 사용자에게 할당될 수 있는 권한의 그룹입니다. 권한은 미리 정의된 조직 권한에서 와야 합니다.',
},
org_permissions: {
tab_name: '조직 권한',
search_placeholder: '권한 이름으로 검색',
create_org_permission: '조직 권한 생성',
permission_column: '권한',
description_column: '설명',
placeholder_title: '조직 권한',
placeholder_description: '조직 권한은 조직의 맥락에서 자원에 접근할 수 있는 권한을 의미합니다.',
delete_confirm:
'이 권한이 삭제되면, 이 권한을 포함하는 모든 조직 역할이 이 권한을 잃게 되며, 이 권한을 가진 사용자는 그것에 의해 부여된 접근을 잃게 됩니다.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: '서명 키',
organization_template: '조직 템플릿',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Szablon organizacji',
subtitle:
'W aplikacjach SaaS wieloklienckich jest powszechne, że wiele organizacji dzieli identyczne polityki kontroli dostępu, w tym uprawnienia i role. W Logto, ten koncept jest określany jako "szablon organizacji". Jego użycie usprawnia proces budowania i projektowania modelu autoryzacji.',
org_roles: {
tab_name: 'Role org',
search_placeholder: 'Szukaj po nazwie roli',
create_org_roles: 'Utwórz rolę org',
org_role_column: 'Rola org',
permissions_column: 'Uprawnienia',
placeholder_title: 'Rola organizacyjna',
placeholder_description:
'Rola organizacyjna to grupowanie uprawnień, które można przypisać użytkownikom. Uprawnienia muszą pochodzić z wcześniej zdefiniowanych uprawnień organizacyjnych.',
},
org_permissions: {
tab_name: 'Uprawnienia org',
search_placeholder: 'Szukaj po nazwie uprawnienia',
create_org_permission: 'Utwórz uprawnienie org',
permission_column: 'Uprawnienie',
description_column: 'Opis',
placeholder_title: 'Uprawnienie organizacyjne',
placeholder_description:
'Uprawnienie organizacyjne odnosi się do autoryzacji dostępu do zasobu w kontekście organizacji.',
delete_confirm:
'Jeśli to uprawnienie zostanie usunięte, wszystkie role organizacyjne zawierające to uprawnienie stracą je, a użytkownicy, którzy mieli to uprawnienie, stracą dostęp przyznany przez nie.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Klucze do podpisu',
organization_template: 'Szablon organizacji',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Template de organização',
subtitle:
'Em aplicações SaaS multi-tenant, é comum que várias organizações compartilhem políticas de controle de acesso idênticas, incluindo permissões e papéis. No Logto, este conceito é chamado de "template de organização". Usá-lo simplifica o processo de construção e design do seu modelo de autorização.',
org_roles: {
tab_name: 'Papéis da org',
search_placeholder: 'Buscar por nome do papel',
create_org_roles: 'Criar papel da org',
org_role_column: 'Papel da org',
permissions_column: 'Permissões',
placeholder_title: 'Papel da organização',
placeholder_description:
'Papel da organização é um agrupamento de permissões que podem ser atribuídas aos usuários. As permissões devem vir das permissões organizacionais predefinidas.',
},
org_permissions: {
tab_name: 'Permissões da org',
search_placeholder: 'Buscar por nome da permissão',
create_org_permission: 'Criar permissão da org',
permission_column: 'Permissão',
description_column: 'Descrição',
placeholder_title: 'Permissão da organização',
placeholder_description:
'Permissão da organização refere-se à autorização para acessar um recurso no contexto da organização.',
delete_confirm:
'Se esta permissão for deletada, todos os papéis da organização que incluírem esta permissão perderão a mesma, e usuários que tinham esta permissão perderão o acesso concedido por ela.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Chaves de assinatura',
organization_template: 'Modelo de organização',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Modelo de organização',
subtitle:
'Em aplicações SaaS multi-inquilino, é comum várias organizações partilharem políticas de controlo de acesso idênticas, incluindo permissões e papéis. No Logto, este conceito é denominado "modelo de organização". A sua utilização simplifica o processo de construção e desenho do seu modelo de autorização.',
org_roles: {
tab_name: 'Papéis da org',
search_placeholder: 'Procurar por nome do papel',
create_org_roles: 'Criar papel da org',
org_role_column: 'Papel da org',
permissions_column: 'Permissões',
placeholder_title: 'Papel da organização',
placeholder_description:
'O papel da organização é um agrupamento de permissões que podem ser atribuídas a utilizadores. As permissões devem provir das permissões organizacionais predefinidas.',
},
org_permissions: {
tab_name: 'Permissões da org',
search_placeholder: 'Procurar por nome da permissão',
create_org_permission: 'Criar permissão da org',
permission_column: 'Permissão',
description_column: 'Descrição',
placeholder_title: 'Permissão da organização',
placeholder_description:
'A permissão da organização refere-se à autorização para aceder a um recurso no contexto da organização.',
delete_confirm:
'Se esta permissão for apagada, todos os papéis da organização que incluam esta permissão perderão a mesma, e utilizadores que tinham esta permissão perderão o acesso concedido por ela.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Chaves de assinatura',
organization_template: 'Modelo de organização',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Шаблон организации',
subtitle:
'В многоарендных SaaS-приложениях обычно несколько организаций делят идентичные политики контроля доступа, включая разрешения и роли. В Logto этот концепт называется "шаблон организации". Его использование упрощает процесс построения и проектирования вашей модели авторизации.',
org_roles: {
tab_name: 'Роли орг',
search_placeholder: 'Поиск по названию роли',
create_org_roles: 'Создать роль орг',
org_role_column: 'Роль орг',
permissions_column: 'Разрешения',
placeholder_title: 'Роль организации',
placeholder_description:
'Роль организации - это группировка разрешений, которые могут быть назначены пользователям. Разрешения должны происходить из предопределенных разрешений организации.',
},
org_permissions: {
tab_name: 'Разрешения орг',
search_placeholder: 'Поиск по названию разрешения',
create_org_permission: 'Создать разрешение орг',
permission_column: 'Разрешение',
description_column: 'Описание',
placeholder_title: 'Разрешение организации',
placeholder_description:
'Разрешение организации относится к авторизации на доступ к ресурсу в контексте организации.',
delete_confirm:
'Если это разрешение будет удалено, все роли организации, включающие это разрешение, потеряют его, и пользователи, имевшие это разрешение, потеряют доступ, предоставленный им.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'Ключи подписи',
organization_template: 'Шаблон организации',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,29 @@
const organization_template = {
title: 'Organizasyon şablonu',
subtitle:
'Çok kiracılı SaaS uygulamalarında, birden fazla organizasyonun aynı erişim kontrol politikalarını, izinleri ve rolleri dahil olmak üzere paylaşması yaygındır. Logto\'da bu kavram "organizasyon şablonu" olarak adlandırılır. Bunu kullanmak, yetkilendirme modelinizi oluşturma ve tasarlama sürecini basitleştirir.',
org_roles: {
tab_name: 'Org rolleri',
search_placeholder: 'Role adı ile ara',
create_org_roles: 'Org rolü oluştur',
org_role_column: 'Org rolü',
permissions_column: 'İzinler',
placeholder_title: 'Organizasyon rolü',
placeholder_description:
'Organizasyon rolü, kullanıcılara atanabilecek izinlerin bir gruplamasıdır. İzinler, önceden belirlenmiş organizasyon izinlerinden gelmelidir.',
},
org_permissions: {
tab_name: 'Org izinleri',
search_placeholder: 'İzin adı ile ara',
create_org_permission: 'Org izni oluştur',
permission_column: 'İzin',
description_column: 'Açıklama',
placeholder_title: 'Organizasyon izni',
placeholder_description:
'Organizasyon izni, organizasyon bağlamında bir kaynağa erişim yetkisi anlamına gelir.',
delete_confirm:
'Bu izin silinirse, bu izni içeren tüm organizasyon rolleri bu izni kaybeder ve bu izne sahip kullanıcılar, bu izin tarafından verilen erişimi kaybeder.',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: 'İmza anahtarları',
organization_template: 'Kuruluş şablonu',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,27 @@
const organization_template = {
title: '组织模板',
subtitle:
'在多租户SaaS应用中多个组织共享相同的访问控制政策包括权限和角色是很常见的。在Logto中这一概念被称为“组织模板”。使用它可以简化构建和设计授权模型的过程。',
org_roles: {
tab_name: '组织角色',
search_placeholder: '按角色名称搜索',
create_org_roles: '创建组织角色',
org_role_column: '组织角色',
permissions_column: '权限',
placeholder_title: '组织角色',
placeholder_description: '组织角色是一组可以分配给用户的权限。权限必须来自预定义的组织权限。',
},
org_permissions: {
tab_name: '组织权限',
search_placeholder: '按权限名称搜索',
create_org_permission: '创建组织权限',
permission_column: '权限',
description_column: '描述',
placeholder_title: '组织权限',
placeholder_description: '组织权限指的是在组织上下文中访问资源的授权。',
delete_confirm:
'如果删除此权限,包括此权限的所有组织角色都将失去此权限,拥有此权限的用户将失去由此权限授予的访问权限。',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: '签名密钥',
organization_template: '组织模板',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,27 @@
const organization_template = {
title: '組織模板',
subtitle:
'在多租戶SaaS應用中多個組織共享相同的訪問控制政策包括權限和角色是很常見的。在Logto中這一概念被稱為“組織模板”。使用它可以簡化構建和設計授權模型的過程。',
org_roles: {
tab_name: '組織角色',
search_placeholder: '按角色名稱搜索',
create_org_roles: '創建組織角色',
org_role_column: '組織角色',
permissions_column: '權限',
placeholder_title: '組織角色',
placeholder_description: '組織角色是一組可以分配給用戶的權限。權限必須來自預定義的組織權限。',
},
org_permissions: {
tab_name: '組織權限',
search_placeholder: '按權限名稱搜索',
create_org_permission: '創建組織權限',
permission_column: '權限',
description_column: '描述',
placeholder_title: '組織權限',
placeholder_description: '組織權限指的是在組織上下文中訪問資源的授權。',
delete_confirm:
'如果刪除此權限,包括此權限的所有組織角色都將失去此權限,擁有此權限的用戶將失去由此權限授予的訪問權限。',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: '簽署密鑰',
organization_template: '組織模板',
};
export default Object.freeze(tabs);

View file

@ -22,6 +22,7 @@ import logs from './logs.js';
import menu from './menu.js';
import mfa from './mfa.js';
import organization_details from './organization-details.js';
import organization_template from './organization-template.js';
import organizations from './organizations.js';
import permissions from './permissions.js';
import profile from './profile.js';
@ -93,6 +94,7 @@ const admin_console = {
jwt_claims,
invitation,
signing_keys,
organization_template,
};
export default Object.freeze(admin_console);

View file

@ -0,0 +1,27 @@
const organization_template = {
title: '組織模板',
subtitle:
'在多租戶SaaS應用中多個組織共享相同的訪問控制政策包括權限和角色是很常見的。在Logto中這一概念被稱為“組織模板”。使用它可以簡化建立和設計授權模型的過程。',
org_roles: {
tab_name: '組織角色',
search_placeholder: '按角色名稱搜尋',
create_org_roles: '創建組織角色',
org_role_column: '組織角色',
permissions_column: '權限',
placeholder_title: '組織角色',
placeholder_description: '組織角色是一組可以分配給使用者的權限。權限必須來自預定義的組織權限。',
},
org_permissions: {
tab_name: '組織權限',
search_placeholder: '按權限名稱搜尋',
create_org_permission: '創建組織權限',
permission_column: '權限',
description_column: '描述',
placeholder_title: '組織權限',
placeholder_description: '組織權限指的是在組織上下文中訪問資源的授權。',
delete_confirm:
'如果刪除此權限,包括此權限的所有組織角色都將失去此權限,擁有此權限的使用者將失去由此權限授予的訪問權限。',
},
};
export default Object.freeze(organization_template);

View file

@ -17,6 +17,7 @@ const tabs = {
/** UNTRANSLATED */
jwt_customizer: 'JWT Claims',
signing_keys: '簽署密鑰',
organization_template: '組織模板',
};
export default Object.freeze(tabs);