From 68fd2463f4781f25663fbd924c5f5cddaa1e3913 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Fri, 24 Oct 2025 17:21:14 +0530 Subject: [PATCH] [WEB-5230 | WEB-5231] chore: new empty state implementation (#7972) --- .gitignore | 2 + .../[projectId]/cycles/(list)/page.tsx | 31 +- .../settings/account/api-tokens/page.tsx | 33 +- .../analytics/insight-table/data-table.tsx | 19 +- .../analytics/overview/project-insights.tsx | 14 +- .../work-items/created-vs-resolved.tsx | 14 +- .../analytics/work-items/priority-chart.tsx | 14 +- apps/web/core/components/estimates/root.tsx | 17 +- .../home/widgets/empty-states/links.tsx | 13 +- .../home/widgets/empty-states/recents.tsx | 23 +- .../home/widgets/empty-states/stickies.tsx | 10 +- apps/web/core/components/inbox/root.tsx | 6 +- .../core/components/inbox/sidebar/root.tsx | 43 +-- .../issue-layouts/empty-states/cycle.tsx | 81 +++-- .../empty-states/global-view.tsx | 73 ++--- .../issue-layouts/empty-states/module.tsx | 71 ++--- .../empty-states/project-issues.tsx | 63 ++-- .../empty-states/project-view.tsx | 41 ++- .../issues/workspace-draft/empty-state.tsx | 28 +- .../issues/workspace-draft/root.tsx | 28 +- .../labels/project-setting-label-list.tsx | 29 +- .../components/modules/modules-list-view.tsx | 61 ++-- .../pages/pages-list-main-content.tsx | 124 +++----- .../components/profile/overview/activity.tsx | 7 +- .../overview/priority-distribution.tsx | 17 +- .../profile/overview/state-distribution.tsx | 13 +- .../web/core/components/project/card-list.tsx | 79 +++-- apps/web/core/components/views/views-list.tsx | 54 ++-- .../workspace-notifications/root.tsx | 6 +- .../sidebar/empty-state.tsx | 36 +-- .../workspace-notifications/sidebar/root.tsx | 2 +- .../layouts/auth-layout/project-wrapper.tsx | 31 +- packages/i18n/src/constants/language.ts | 1 + packages/i18n/src/locales/cs/empty-state.ts | 181 +++++++++++ packages/i18n/src/locales/de/empty-state.ts | 190 +++++++++++ packages/i18n/src/locales/en/empty-state.ts | 176 +++++++++++ packages/i18n/src/locales/es/empty-state.ts | 185 +++++++++++ packages/i18n/src/locales/fr/empty-state.ts | 188 +++++++++++ packages/i18n/src/locales/id/empty-state.ts | 185 +++++++++++ packages/i18n/src/locales/index.ts | 20 ++ packages/i18n/src/locales/it/empty-state.ts | 185 +++++++++++ packages/i18n/src/locales/ja/empty-state.ts | 175 +++++++++++ packages/i18n/src/locales/ko/empty-state.ts | 174 +++++++++++ packages/i18n/src/locales/pl/empty-state.ts | 186 +++++++++++ .../i18n/src/locales/pt-BR/empty-state.ts | 185 +++++++++++ packages/i18n/src/locales/ro/empty-state.ts | 184 +++++++++++ packages/i18n/src/locales/ru/empty-state.ts | 187 +++++++++++ packages/i18n/src/locales/sk/empty-state.ts | 184 +++++++++++ .../i18n/src/locales/tr-TR/empty-state.ts | 183 +++++++++++ packages/i18n/src/locales/ua/empty-state.ts | 186 +++++++++++ .../i18n/src/locales/vi-VN/empty-state.ts | 184 +++++++++++ .../i18n/src/locales/zh-CN/empty-state.ts | 170 ++++++++++ .../i18n/src/locales/zh-TW/empty-state.ts | 170 ++++++++++ .../empty-state/assets-showcase.stories.tsx | 204 ++++++++++++ .../src/empty-state/assets/asset-registry.tsx | 130 ++++++++ .../src/empty-state/assets/asset-types.ts | 52 +++ .../assets/horizontal-stack/constant.tsx | 5 + .../assets/horizontal-stack/index.ts | 1 + .../assets/horizontal-stack/project.tsx | 69 ++++ .../assets/illustration/constant.tsx | 12 + .../empty-state/assets/illustration/inbox.tsx | 134 ++++++++ .../empty-state/assets/illustration/index.ts | 2 + .../assets/illustration/search.tsx | 58 ++++ .../propel/src/empty-state/assets/index.ts | 7 +- .../compact-empty-state.stories.tsx | 142 +++++++++ .../src/empty-state/compact-empty-state.tsx | 60 ++++ .../detailed-empty-state.stories.tsx | 295 ++++++++++++++++++ .../src/empty-state/detailed-empty-state.tsx | 52 +++ .../src/empty-state/empty-state.stories.tsx | 100 ------ .../propel/src/empty-state/empty-state.tsx | 93 +++--- packages/propel/src/empty-state/index.ts | 4 + packages/propel/src/empty-state/types.ts | 24 ++ 72 files changed, 5260 insertions(+), 746 deletions(-) create mode 100644 packages/i18n/src/locales/cs/empty-state.ts create mode 100644 packages/i18n/src/locales/de/empty-state.ts create mode 100644 packages/i18n/src/locales/en/empty-state.ts create mode 100644 packages/i18n/src/locales/es/empty-state.ts create mode 100644 packages/i18n/src/locales/fr/empty-state.ts create mode 100644 packages/i18n/src/locales/id/empty-state.ts create mode 100644 packages/i18n/src/locales/it/empty-state.ts create mode 100644 packages/i18n/src/locales/ja/empty-state.ts create mode 100644 packages/i18n/src/locales/ko/empty-state.ts create mode 100644 packages/i18n/src/locales/pl/empty-state.ts create mode 100644 packages/i18n/src/locales/pt-BR/empty-state.ts create mode 100644 packages/i18n/src/locales/ro/empty-state.ts create mode 100644 packages/i18n/src/locales/ru/empty-state.ts create mode 100644 packages/i18n/src/locales/sk/empty-state.ts create mode 100644 packages/i18n/src/locales/tr-TR/empty-state.ts create mode 100644 packages/i18n/src/locales/ua/empty-state.ts create mode 100644 packages/i18n/src/locales/vi-VN/empty-state.ts create mode 100644 packages/i18n/src/locales/zh-CN/empty-state.ts create mode 100644 packages/i18n/src/locales/zh-TW/empty-state.ts create mode 100644 packages/propel/src/empty-state/assets-showcase.stories.tsx create mode 100644 packages/propel/src/empty-state/assets/asset-registry.tsx create mode 100644 packages/propel/src/empty-state/assets/asset-types.ts create mode 100644 packages/propel/src/empty-state/assets/horizontal-stack/project.tsx create mode 100644 packages/propel/src/empty-state/assets/illustration/constant.tsx create mode 100644 packages/propel/src/empty-state/assets/illustration/inbox.tsx create mode 100644 packages/propel/src/empty-state/assets/illustration/index.ts create mode 100644 packages/propel/src/empty-state/assets/illustration/search.tsx create mode 100644 packages/propel/src/empty-state/compact-empty-state.stories.tsx create mode 100644 packages/propel/src/empty-state/compact-empty-state.tsx create mode 100644 packages/propel/src/empty-state/detailed-empty-state.stories.tsx create mode 100644 packages/propel/src/empty-state/detailed-empty-state.tsx delete mode 100644 packages/propel/src/empty-state/empty-state.stories.tsx create mode 100644 packages/propel/src/empty-state/types.ts diff --git a/.gitignore b/.gitignore index 0edc47dccb..053db6d29e 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ dev-editor storybook-static CLAUDE.md + +temp/ \ No newline at end of file diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(list)/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(list)/page.tsx index 681ec22e0d..643ee2850d 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(list)/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(list)/page.tsx @@ -6,6 +6,7 @@ import { useParams } from "next/navigation"; // plane imports import { EUserPermissionsLevel, CYCLE_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import type { TCycleFilters } from "@plane/types"; import { EUserProjectRoles } from "@plane/types"; // components @@ -15,7 +16,6 @@ import { PageHead } from "@/components/core/page-title"; import { CycleAppliedFiltersList } from "@/components/cycles/applied-filters"; import { CyclesView } from "@/components/cycles/cycles-view"; import { CycleCreateUpdateModal } from "@/components/cycles/modal"; -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { CycleModuleListLayoutLoader } from "@/components/ui/loader/cycle-module-list-loader"; // hooks @@ -96,22 +96,19 @@ const ProjectCyclesPage = observer(() => { /> {totalCycles === 0 ? (
- { - setCreateModal(true); - }} - disabled={!hasMemberLevelPermission} - /> - } + setCreateModal(true), + variant: "primary", + disabled: !hasMemberLevelPermission, + "data-ph-element": CYCLE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON, + }, + ]} />
) : ( diff --git a/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx index d37711e38f..0cf57fa187 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx @@ -7,18 +7,17 @@ import useSWR from "swr"; import { PROFILE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // component +import { EmptyStateCompact } from "@plane/propel/empty-state"; import { APITokenService } from "@plane/services"; import { CreateApiTokenModal } from "@/components/api-token/modal/create-token-modal"; import { ApiTokenListItem } from "@/components/api-token/token-list-item"; import { PageHead } from "@/components/core/page-title"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { SettingsHeading } from "@/components/settings/heading"; import { APITokenSettingsLoader } from "@/components/ui/loader/settings/api-token"; import { API_TOKENS_LIST } from "@/constants/fetch-keys"; // store hooks import { captureClick } from "@/helpers/event-tracker.helper"; import { useWorkspace } from "@/hooks/store/use-workspace"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; const apiTokenService = new APITokenService(); @@ -30,8 +29,6 @@ const ApiTokensPage = observer(() => { const { t } = useTranslation(); // store hooks const { currentWorkspace } = useWorkspace(); - // derived values - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/workspace-settings/api-tokens" }); const { data: tokens } = useSWR(API_TOKENS_LIST, () => apiTokenService.list()); @@ -70,7 +67,7 @@ const ApiTokensPage = observer(() => { ) : ( -
+
{ }, }} /> -
- { captureClick({ elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.EMPTY_STATE_ADD_PAT_BUTTON, }); setIsCreateTokenModalOpen(true); }, - }} - /> -
+ }, + ]} + align="start" + rootClassName="py-20" + />
)} diff --git a/apps/web/core/components/analytics/insight-table/data-table.tsx b/apps/web/core/components/analytics/insight-table/data-table.tsx index be802457eb..b2729411d0 100644 --- a/apps/web/core/components/analytics/insight-table/data-table.tsx +++ b/apps/web/core/components/analytics/insight-table/data-table.tsx @@ -14,18 +14,16 @@ import { getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, - getPaginationRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table"; import { Search, X } from "lucide-react"; // plane package imports import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@plane/propel/table"; import { cn } from "@plane/utils"; // plane web components -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; -import AnalyticsEmptyState from "../empty-state"; interface DataTableProps { columns: ColumnDef[]; @@ -42,7 +40,6 @@ export function DataTable({ columns, data, searchPlaceholder, act const { t } = useTranslation(); const inputRef = React.useRef(null); const [isSearchOpen, setIsSearchOpen] = React.useState(false); - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-table" }); const table = useReactTable({ data, @@ -156,14 +153,12 @@ export function DataTable({ columns, data, searchPlaceholder, act ) : ( -
- -
+
)} diff --git a/apps/web/core/components/analytics/overview/project-insights.tsx b/apps/web/core/components/analytics/overview/project-insights.tsx index a72c79b834..c1fd6584e0 100644 --- a/apps/web/core/components/analytics/overview/project-insights.tsx +++ b/apps/web/core/components/analytics/overview/project-insights.tsx @@ -4,15 +4,14 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; // plane package imports import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import type { TChartData } from "@plane/types"; // hooks import { useAnalytics } from "@/hooks/store/use-analytics"; // services -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; import { AnalyticsService } from "@/services/analytics.service"; // plane web components import AnalyticsSectionWrapper from "../analytics-section-wrapper"; -import AnalyticsEmptyState from "../empty-state"; import { ProjectInsightsLoader } from "../loaders"; const RadarChart = dynamic(() => @@ -29,7 +28,6 @@ const ProjectInsights = observer(() => { const workspaceSlug = params.workspaceSlug.toString(); const { selectedDuration, selectedDurationLabel, selectedProjects, selectedCycle, selectedModule, isPeekView } = useAnalytics(); - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-radar" }); const { data: projectInsightsData, isLoading: isLoadingProjectInsight } = useSWR( `radar-chart-project-insights-${workspaceSlug}-${selectedDuration}-${selectedProjects}-${selectedCycle}-${selectedModule}-${isPeekView}`, @@ -56,11 +54,11 @@ const ProjectInsights = observer(() => { {isLoadingProjectInsight ? ( ) : projectInsightsData && projectInsightsData?.length == 0 ? ( - ) : (
diff --git a/apps/web/core/components/analytics/work-items/created-vs-resolved.tsx b/apps/web/core/components/analytics/work-items/created-vs-resolved.tsx index 56c7bbd80a..7b40ccdb92 100644 --- a/apps/web/core/components/analytics/work-items/created-vs-resolved.tsx +++ b/apps/web/core/components/analytics/work-items/created-vs-resolved.tsx @@ -5,16 +5,15 @@ import useSWR from "swr"; // plane package imports import { useTranslation } from "@plane/i18n"; import { AreaChart } from "@plane/propel/charts/area-chart"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import type { IChartResponse, TChartData } from "@plane/types"; import { renderFormattedDate } from "@plane/utils"; // hooks import { useAnalytics } from "@/hooks/store/use-analytics"; // services -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; import { AnalyticsService } from "@/services/analytics.service"; // plane web components import AnalyticsSectionWrapper from "../analytics-section-wrapper"; -import AnalyticsEmptyState from "../empty-state"; import { ChartLoader } from "../loaders"; const analyticsService = new AnalyticsService(); @@ -31,7 +30,6 @@ const CreatedVsResolved = observer(() => { const params = useParams(); const { t } = useTranslation(); const workspaceSlug = params.workspaceSlug.toString(); - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-area" }); const { data: createdVsResolvedData, isLoading: isCreatedVsResolvedLoading } = useSWR( `created-vs-resolved-${workspaceSlug}-${selectedDuration}-${selectedProjects}-${selectedCycle}-${selectedModule}-${isPeekView}-${isEpic}`, () => @@ -121,11 +119,11 @@ const CreatedVsResolved = observer(() => { }} /> ) : ( - )} diff --git a/apps/web/core/components/analytics/work-items/priority-chart.tsx b/apps/web/core/components/analytics/work-items/priority-chart.tsx index f77248d49f..857eca2030 100644 --- a/apps/web/core/components/analytics/work-items/priority-chart.tsx +++ b/apps/web/core/components/analytics/work-items/priority-chart.tsx @@ -11,15 +11,14 @@ import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES, CHART_COLOR_PALETTES, import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { BarChart } from "@plane/propel/charts/bar-chart"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import type { TBarItem, TChart, TChartDatum, ChartXAxisProperty, ChartYAxisMetric } from "@plane/types"; // plane web components import { generateExtendedColors, parseChartData } from "@/components/chart/utils"; // hooks import { useAnalytics } from "@/hooks/store/use-analytics"; import { useProjectState } from "@/hooks/store/use-project-state"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; import { AnalyticsService } from "@/services/analytics.service"; -import AnalyticsEmptyState from "../empty-state"; import { exportCSV } from "../export"; import { DataTable } from "../insight-table/data-table"; import { ChartLoader } from "../loaders"; @@ -46,7 +45,6 @@ const analyticsService = new AnalyticsService(); const PriorityChart = observer((props: Props) => { const { x_axis, y_axis, group_by } = props; const { t } = useTranslation(); - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-bar" }); // store hooks const { selectedDuration, selectedProjects, selectedCycle, selectedModule, isPeekView, isEpic } = useAnalytics(); const { workspaceStates } = useProjectState(); @@ -232,11 +230,11 @@ const PriorityChart = observer((props: Props) => { /> ) : ( - )}
diff --git a/apps/web/core/components/estimates/root.tsx b/apps/web/core/components/estimates/root.tsx index f562d924c3..01ac55a6a0 100644 --- a/apps/web/core/components/estimates/root.tsx +++ b/apps/web/core/components/estimates/root.tsx @@ -5,6 +5,7 @@ import useSWR from "swr"; // plane imports import { useTranslation } from "@plane/i18n"; // hooks +import { EmptyStateCompact } from "@plane/propel/empty-state"; import { useProjectEstimates } from "@/hooks/store/estimates"; import { useProject } from "@/hooks/store/use-project"; // plane web components @@ -13,7 +14,6 @@ import { UpdateEstimateModal } from "@/plane-web/components/estimates"; import { SettingsHeading } from "../settings/heading"; import { CreateEstimateModal } from "./create/modal"; import { DeleteEstimateModal } from "./delete/modal"; -import { EstimateEmptyScreen } from "./empty-screen"; import { EstimateDisableSwitch } from "./estimate-disable-switch"; import { EstimateList } from "./estimate-list"; import { EstimateLoaderScreen } from "./loader-screen"; @@ -76,7 +76,20 @@ export const EstimateRoot: FC = observer((props) => { />
) : ( - setIsEstimateCreateModalOpen(true)} /> + setIsEstimateCreateModalOpen(true), + }, + ]} + align="start" + rootClassName="py-20" + /> )} {/* archived estimates section */} diff --git a/apps/web/core/components/home/widgets/empty-states/links.tsx b/apps/web/core/components/home/widgets/empty-states/links.tsx index 37e04fea73..d442934325 100644 --- a/apps/web/core/components/home/widgets/empty-states/links.tsx +++ b/apps/web/core/components/home/widgets/empty-states/links.tsx @@ -1,14 +1,15 @@ -import { Link2 } from "lucide-react"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; export const LinksEmptyState = () => { const { t } = useTranslation(); return ( -
-
- -
{t("home.quick_links.empty")}
-
+
+
); }; diff --git a/apps/web/core/components/home/widgets/empty-states/recents.tsx b/apps/web/core/components/home/widgets/empty-states/recents.tsx index 4839e9bfa9..bca5bf603c 100644 --- a/apps/web/core/components/home/widgets/empty-states/recents.tsx +++ b/apps/web/core/components/home/widgets/empty-states/recents.tsx @@ -1,41 +1,40 @@ -import { History } from "lucide-react"; import { useTranslation } from "@plane/i18n"; -import { PageIcon, ProjectIcon, WorkItemsIcon } from "@plane/propel/icons"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; +import type { CompactAssetType } from "@plane/propel/empty-state"; -const getDisplayContent = (type: string) => { +const getDisplayContent = (type: string): { assetKey: CompactAssetType; text: string } => { switch (type) { case "project": return { - icon: , + assetKey: "project", text: "home.recents.empty.project", }; case "page": return { - icon: , + assetKey: "note", text: "home.recents.empty.page", }; case "issue": return { - icon: , + assetKey: "work-item", text: "home.recents.empty.issue", }; default: return { - icon: , + assetKey: "work-item", text: "home.recents.empty.default", }; } }; + export const RecentsEmptyState = ({ type }: { type: string }) => { const { t } = useTranslation(); - const { icon, text } = getDisplayContent(type); + const { assetKey, text } = getDisplayContent(type); return ( -
-
- {icon}
{t(text)}
-
+
+
); }; diff --git a/apps/web/core/components/home/widgets/empty-states/stickies.tsx b/apps/web/core/components/home/widgets/empty-states/stickies.tsx index 5a639ceef4..37a3299dac 100644 --- a/apps/web/core/components/home/widgets/empty-states/stickies.tsx +++ b/apps/web/core/components/home/widgets/empty-states/stickies.tsx @@ -1,15 +1,11 @@ -// plane ui import { useTranslation } from "@plane/i18n"; -import { RecentStickyIcon } from "@plane/propel/icons"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; export const StickiesEmptyState = () => { const { t } = useTranslation(); return ( -
-
- -
{t("stickies.empty_state.simple")}
-
+
+
); }; diff --git a/apps/web/core/components/inbox/root.tsx b/apps/web/core/components/inbox/root.tsx index 4327c3aefa..a8660ecce3 100644 --- a/apps/web/core/components/inbox/root.tsx +++ b/apps/web/core/components/inbox/root.tsx @@ -4,11 +4,11 @@ import { observer } from "mobx-react"; import { PanelLeft } from "lucide-react"; // plane imports import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import { IntakeIcon } from "@plane/propel/icons"; import { EInboxIssueCurrentTab } from "@plane/types"; import { cn } from "@plane/utils"; // components -import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; import { InboxContentRoot } from "@/components/inbox/content"; import { InboxSidebar } from "@/components/inbox/sidebar"; import { InboxLayoutLoader } from "@/components/ui/loader/layouts/project-inbox/inbox-layout-loader"; @@ -101,9 +101,7 @@ export const InboxIssueRoot: FC = observer((props) => { inboxIssueId={inboxIssueId.toString()} /> ) : ( -
- -
+ )}
diff --git a/apps/web/core/components/inbox/sidebar/root.tsx b/apps/web/core/components/inbox/sidebar/root.tsx index b76c638342..88b59dc62a 100644 --- a/apps/web/core/components/inbox/sidebar/root.tsx +++ b/apps/web/core/components/inbox/sidebar/root.tsx @@ -4,20 +4,19 @@ import type { FC } from "react"; import { useCallback, useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import type { TInboxIssueCurrentTab } from "@plane/types"; import { EInboxIssueCurrentTab } from "@plane/types"; // plane imports import { Header, Loader, EHeaderVariant } from "@plane/ui"; import { cn } from "@plane/utils"; // components -import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; import { InboxSidebarLoader } from "@/components/ui/loader/layouts/project-inbox/inbox-sidebar-loader"; // hooks import { useProject } from "@/hooks/store/use-project"; import { useProjectInbox } from "@/hooks/store/use-project-inbox"; import { useAppRouter } from "@/hooks/use-app-router"; import { useIntersectionObserver } from "@/hooks/use-intersection-observer"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // local imports import { FiltersRoot } from "../inbox-filter"; import { InboxIssueAppliedFilters } from "../inbox-filter/applied-filters/root"; @@ -62,11 +61,6 @@ export const InboxSidebar: FC = observer((props) => { getAppliedFiltersCount, } = useProjectInbox(); // derived values - const sidebarAssetPath = useResolvedAssetPath({ basePath: "/empty-state/intake/intake-issue" }); - const sidebarFilterAssetPath = useResolvedAssetPath({ - basePath: "/empty-state/intake/filter-issue", - }); - const fetchNextPages = useCallback(() => { if (!workspaceSlug || !projectId) return; fetchInboxPaginationIssues(workspaceSlug.toString(), projectId.toString()); @@ -141,22 +135,33 @@ export const InboxSidebar: FC = observer((props) => { ) : (
{getAppliedFiltersCount > 0 ? ( - ) : currentTab === EInboxIssueCurrentTab.OPEN ? ( - router.push(`/${workspaceSlug}/projects/${projectId}/intake`), + variant: "primary", + }, + ]} /> ) : ( - )}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx index 30a82d476c..c7ae0e89f5 100644 --- a/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx @@ -7,19 +7,18 @@ import { useParams } from "next/navigation"; // plane imports import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { ISearchIssueResponse } from "@plane/types"; import { EIssuesStoreType, EUserProjectRoles } from "@plane/types"; // components import { ExistingIssuesListModal } from "@/components/core/modals/existing-issues-list-modal"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { captureClick } from "@/helpers/event-tracker.helper"; import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useCycle } from "@/hooks/store/use-cycle"; import { useIssues } from "@/hooks/store/use-issues"; import { useUserPermissions } from "@/hooks/store/user"; import { useWorkItemFilterInstance } from "@/hooks/store/work-item-filters/use-work-item-filter-instance"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const CycleEmptyState: React.FC = observer(() => { // router @@ -33,31 +32,18 @@ export const CycleEmptyState: React.FC = observer(() => { const { t } = useTranslation(); // store hooks const { getCycleById } = useCycle(); - const { issues, issuesFilter } = useIssues(EIssuesStoreType.CYCLE); + const { issues } = useIssues(EIssuesStoreType.CYCLE); const { toggleCreateIssueModal } = useCommandPalette(); const { allowPermissions } = useUserPermissions(); // derived values const cycleWorkItemFilter = cycleId ? useWorkItemFilterInstance(EIssuesStoreType.CYCLE, cycleId) : undefined; const cycleDetails = cycleId ? getCycleById(cycleId) : undefined; - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; const isCompletedCycleSnapshotAvailable = !isEmpty(cycleDetails?.progress_snapshot ?? {}); const isCompletedAndEmpty = isCompletedCycleSnapshotAvailable || cycleDetails?.status?.toLowerCase() === "completed"; - const additionalPath = activeLayout ?? "list"; const canPerformEmptyStateActions = allowPermissions( [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER], EUserPermissionsLevel.PROJECT ); - const emptyFilterResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/empty-filters/", - additionalPath: additionalPath, - }); - const noIssueResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/cycle-issues/", - additionalPath: additionalPath, - }); - const completedNoIssuesResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/cycle/completed-no-issues", - }); const handleAddIssuesToCycle = async (data: ISearchIssueResponse[]) => { if (!workspaceSlug || !projectId || !cycleId) return; @@ -94,39 +80,50 @@ export const CycleEmptyState: React.FC = observer(() => { />
{isCompletedAndEmpty ? ( - ) : cycleWorkItemFilter?.hasActiveFilters ? ( - ) : ( - { - captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE }); - toggleCreateIssueModal(true, EIssuesStoreType.CYCLE); + { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE }); + toggleCreateIssueModal(true, EIssuesStoreType.CYCLE); + }, + disabled: !canPerformEmptyStateActions, + variant: "primary", + "data-ph-element": WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE, }, - disabled: !canPerformEmptyStateActions, - }} - secondaryButton={{ - text: t("project_cycles.empty_state.no_issues.secondary_button.text"), - onClick: () => setCycleIssuesListModal(true), - disabled: !canPerformEmptyStateActions, - }} + { + label: t("project.cycle_work_items.cta_secondary"), + onClick: () => setCycleIssuesListModal(true), + disabled: !canPerformEmptyStateActions, + variant: "outline-primary", + "data-ph-element": WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE, + }, + ]} /> )}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx index 00935f1cd1..e8ded291e1 100644 --- a/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx @@ -1,21 +1,16 @@ import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; // plane imports import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EIssuesStoreType, EUserWorkspaceRoles } from "@plane/types"; -// components -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; // hooks import { captureClick } from "@/helpers/event-tracker.helper"; import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useProject } from "@/hooks/store/use-project"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const GlobalViewEmptyState: React.FC = observer(() => { - const { globalViewId } = useParams(); // plane imports const { t } = useTranslation(); // store hooks @@ -27,56 +22,46 @@ export const GlobalViewEmptyState: React.FC = observer(() => { [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], EUserPermissionsLevel.WORKSPACE ); - const isDefaultView = ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId?.toString() ?? ""); - const currentView = isDefaultView && globalViewId ? globalViewId : "custom-view"; - const resolvedCurrentView = currentView?.toString(); - const noProjectResolvedPath = useResolvedAssetPath({ basePath: "/empty-state/onboarding/projects" }); - const globalViewsResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/all-issues/", - additionalPath: resolvedCurrentView, - }); if (workspaceProjectIds?.length === 0) { return ( - { + assetKey="project" + assetClassName="size-40" + actions={[ + { + label: t("workspace_projects.empty_state.no_projects.primary_button.text"), + onClick: () => { toggleCreateProjectModal(true); captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW }); - }} - disabled={!hasMemberLevelPermission} - /> - } + }, + disabled: !hasMemberLevelPermission, + variant: "primary", + }, + ]} /> ); } return ( - { - captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW }); - toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); - }, - disabled: !hasMemberLevelPermission, - } - : undefined - } + { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW }); + toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); + }, + disabled: !hasMemberLevelPermission, + variant: "primary", + }, + ]} /> ); }); diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx index 2510f5b5d4..f884de82d6 100644 --- a/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx @@ -6,19 +6,18 @@ import { useParams } from "next/navigation"; // plane imports import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { ISearchIssueResponse } from "@plane/types"; import { EIssuesStoreType, EUserProjectRoles } from "@plane/types"; // components import { ExistingIssuesListModal } from "@/components/core/modals/existing-issues-list-modal"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { captureClick } from "@/helpers/event-tracker.helper"; // hooks import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useIssues } from "@/hooks/store/use-issues"; import { useUserPermissions } from "@/hooks/store/user"; import { useWorkItemFilterInstance } from "@/hooks/store/work-item-filters/use-work-item-filter-instance"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const ModuleEmptyState: React.FC = observer(() => { // router @@ -31,25 +30,15 @@ export const ModuleEmptyState: React.FC = observer(() => { // plane hooks const { t } = useTranslation(); // store hooks - const { issues, issuesFilter } = useIssues(EIssuesStoreType.MODULE); + const { issues } = useIssues(EIssuesStoreType.MODULE); const { toggleCreateIssueModal } = useCommandPalette(); const { allowPermissions } = useUserPermissions(); // derived values const moduleWorkItemFilter = moduleId ? useWorkItemFilterInstance(EIssuesStoreType.MODULE, moduleId) : undefined; - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; - const additionalPath = activeLayout ?? "list"; const canPerformEmptyStateActions = allowPermissions( [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER], EUserPermissionsLevel.PROJECT ); - const emptyFilterResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/empty-filters/", - additionalPath: additionalPath, - }); - const moduleIssuesResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/module-issues/", - additionalPath: additionalPath, - }); const handleAddIssuesToModule = async (data: ISearchIssueResponse[]) => { if (!workspaceSlug || !projectId || !moduleId) return; @@ -85,33 +74,41 @@ export const ModuleEmptyState: React.FC = observer(() => { />
{moduleWorkItemFilter?.hasActiveFilters ? ( - ) : ( - { - captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.MODULE }); - toggleCreateIssueModal(true, EIssuesStoreType.MODULE); + { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.MODULE }); + toggleCreateIssueModal(true, EIssuesStoreType.MODULE); + }, + disabled: !canPerformEmptyStateActions, + variant: "primary", }, - disabled: !canPerformEmptyStateActions, - }} - secondaryButton={{ - text: t("project_module.empty_state.no_issues.secondary_button.text"), - onClick: () => setModuleIssuesListModal(true), - disabled: !canPerformEmptyStateActions, - }} + { + label: t("project.module_work_items.cta_secondary"), + onClick: () => setModuleIssuesListModal(true), + disabled: !canPerformEmptyStateActions, + variant: "outline-primary", + }, + ]} /> )}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx index c8a776850e..dd52019d6b 100644 --- a/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx @@ -3,17 +3,14 @@ import { useParams } from "next/navigation"; // plane imports import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EIssuesStoreType, EUserProjectRoles } from "@plane/types"; // components -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { captureClick } from "@/helpers/event-tracker.helper"; // hooks import { useCommandPalette } from "@/hooks/store/use-command-palette"; -import { useIssues } from "@/hooks/store/use-issues"; import { useUserPermissions } from "@/hooks/store/user"; import { useWorkItemFilterInstance } from "@/hooks/store/work-item-filters/use-work-item-filter-instance"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const ProjectEmptyState: React.FC = observer(() => { // router @@ -23,53 +20,47 @@ export const ProjectEmptyState: React.FC = observer(() => { const { t } = useTranslation(); // store hooks const { toggleCreateIssueModal } = useCommandPalette(); - const { issuesFilter } = useIssues(EIssuesStoreType.PROJECT); const { allowPermissions } = useUserPermissions(); // derived values const projectWorkItemFilter = projectId ? useWorkItemFilterInstance(EIssuesStoreType.PROJECT, projectId) : undefined; - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; - const additionalPath = projectWorkItemFilter?.hasActiveFilters ? (activeLayout ?? "list") : undefined; + const canPerformEmptyStateActions = allowPermissions( [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER], EUserPermissionsLevel.PROJECT ); - const emptyFilterResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/empty-filters/", - additionalPath: additionalPath, - }); - const projectIssuesResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/onboarding/issues", - }); return (
{projectWorkItemFilter?.hasActiveFilters ? ( - ) : ( - { + { captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.WORK_ITEMS }); toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); - }} - disabled={!canPerformEmptyStateActions} - /> - } + }, + disabled: !canPerformEmptyStateActions, + variant: "primary", + }, + ]} /> )}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx index 6b03a61e0f..1652631776 100644 --- a/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx @@ -1,15 +1,12 @@ import { observer } from "mobx-react"; -import { PlusIcon } from "lucide-react"; // components import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EIssuesStoreType } from "@plane/types"; -import { EmptyState } from "@/components/common/empty-state"; import { captureClick } from "@/helpers/event-tracker.helper"; // hooks import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useUserPermissions } from "@/hooks/store/user"; -// assets -import emptyIssue from "@/public/empty-state/issue.svg"; export const ProjectViewEmptyState: React.FC = observer(() => { // store hooks @@ -23,24 +20,22 @@ export const ProjectViewEmptyState: React.FC = observer(() => { ); return ( -
- , - onClick: () => { - captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.PROJECT_VIEW }); - toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW); - }, - } - : undefined - } - /> -
+ // TODO: Add translation + { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.PROJECT_VIEW }); + toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW); + }, + disabled: !isCreatingIssueAllowed, + variant: "primary", + }, + ]} + /> ); }); diff --git a/apps/web/core/components/issues/workspace-draft/empty-state.tsx b/apps/web/core/components/issues/workspace-draft/empty-state.tsx index 4d6a195a51..89ff7cb141 100644 --- a/apps/web/core/components/issues/workspace-draft/empty-state.tsx +++ b/apps/web/core/components/issues/workspace-draft/empty-state.tsx @@ -6,12 +6,11 @@ import { Fragment, useState } from "react"; import { observer } from "mobx-react"; import { EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EIssuesStoreType, EUserWorkspaceRoles } from "@plane/types"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { CreateUpdateIssueModal } from "@/components/issues/issue-modal/modal"; // constants import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const WorkspaceDraftEmptyState: FC = observer(() => { // state @@ -24,7 +23,6 @@ export const WorkspaceDraftEmptyState: FC = observer(() => { [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], EUserPermissionsLevel.WORKSPACE ); - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/onboarding/cycles" }); return ( @@ -35,17 +33,21 @@ export const WorkspaceDraftEmptyState: FC = observer(() => { isDraft />
- { - setIsDraftIssueModalOpen(true); + { + setIsDraftIssueModalOpen(true); + }, + disabled: !canPerformEmptyStateActions, + variant: "primary", }, - disabled: !canPerformEmptyStateActions, - }} + ]} />
diff --git a/apps/web/core/components/issues/workspace-draft/root.tsx b/apps/web/core/components/issues/workspace-draft/root.tsx index cf74383a97..636b898e39 100644 --- a/apps/web/core/components/issues/workspace-draft/root.tsx +++ b/apps/web/core/components/issues/workspace-draft/root.tsx @@ -7,11 +7,10 @@ import useSWR from "swr"; // plane imports import { EUserPermissionsLevel, EDraftIssuePaginationType, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EUserWorkspaceRoles } from "@plane/types"; // components import { cn } from "@plane/utils"; -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { captureClick } from "@/helpers/event-tracker.helper"; // constants @@ -70,23 +69,22 @@ export const WorkspaceDraftIssuesRoot: FC = observer( if (workspaceProjectIds?.length === 0) return ( - { + assetKey="project" + assetClassName="size-40" + actions={[ + { + label: t("workspace_projects.empty_state.no_projects.primary_button.text"), + onClick: () => { toggleCreateProjectModal(true); captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); - }} - disabled={!hasMemberLevelPermission} - /> - } + }, + disabled: !hasMemberLevelPermission, + variant: "primary", + }, + ]} /> ); diff --git a/apps/web/core/components/labels/project-setting-label-list.tsx b/apps/web/core/components/labels/project-setting-label-list.tsx index d634e248b2..62f60250ef 100644 --- a/apps/web/core/components/labels/project-setting-label-list.tsx +++ b/apps/web/core/components/labels/project-setting-label-list.tsx @@ -6,9 +6,9 @@ import { useParams } from "next/navigation"; // plane imports import { EUserPermissions, EUserPermissionsLevel, PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import type { IIssueLabel } from "@plane/types"; import { Loader } from "@plane/ui"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import type { TLabelOperationsCallbacks } from "@/components/labels"; import { CreateUpdateLabelInline, @@ -20,7 +20,6 @@ import { import { captureClick } from "@/helpers/event-tracker.helper"; import { useLabel } from "@/hooks/store/use-label"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // local imports import { SettingsHeading } from "../settings/heading"; @@ -40,7 +39,6 @@ export const ProjectSettingsLabelList: React.FC = observer(() => { const { allowPermissions } = useUserPermissions(); // derived values const isEditable = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT); - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/project-settings/labels" }); const labelOperationsCallbacks: TLabelOperationsCallbacks = { createLabel: (data: Partial) => createLabel(workspaceSlug?.toString(), projectId?.toString(), data), updateLabel: (labelId: string, data: Partial) => @@ -111,24 +109,25 @@ export const ProjectSettingsLabelList: React.FC = observer(() => { )} {projectLabels ? ( projectLabels.length === 0 && !showLabelForm ? ( -
- { newLabel(); captureClick({ elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.LABELS_EMPTY_STATE_CREATE_BUTTON, }); }, - }} - assetPath={resolvedPath} - className="w-full !px-0 !py-0" - size="md" - /> -
+ }, + ]} + align="start" + rootClassName="py-20" + /> ) : ( projectLabelsTree && (
diff --git a/apps/web/core/components/modules/modules-list-view.tsx b/apps/web/core/components/modules/modules-list-view.tsx index 877855c8e7..5d80ccf2cc 100644 --- a/apps/web/core/components/modules/modules-list-view.tsx +++ b/apps/web/core/components/modules/modules-list-view.tsx @@ -1,14 +1,12 @@ import { observer } from "mobx-react"; -import Image from "next/image"; import { useParams, useSearchParams } from "next/navigation"; // components import { EUserPermissionsLevel, MODULE_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EUserProjectRoles } from "@plane/types"; import { ContentWrapper, Row, ERowVariant } from "@plane/ui"; import { ListLayout } from "@/components/core/list"; -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttChartView } from "@/components/modules"; import { CycleModuleBoardLayoutLoader } from "@/components/ui/loader/cycle-module-board-loader"; import { CycleModuleListLayoutLoader } from "@/components/ui/loader/cycle-module-list-loader"; @@ -18,9 +16,6 @@ import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useModule } from "@/hooks/store/use-module"; import { useModuleFilter } from "@/hooks/store/use-module-filter"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; -import AllFiltersImage from "@/public/empty-state/module/all-filters.svg"; -import NameFilterImage from "@/public/empty-state/module/name-filter.svg"; export const ModulesListView: React.FC = observer(() => { // router @@ -32,7 +27,7 @@ export const ModulesListView: React.FC = observer(() => { // store hooks const { toggleCreateModuleModal } = useCommandPalette(); const { getProjectModuleIds, getFilteredModuleIds, loader } = useModule(); - const { currentProjectDisplayFilters: displayFilters, searchQuery } = useModuleFilter(); + const { currentProjectDisplayFilters: displayFilters } = useModuleFilter(); const { allowPermissions } = useUserPermissions(); // derived values const projectModuleIds = projectId ? getProjectModuleIds(projectId.toString()) : undefined; @@ -41,9 +36,6 @@ export const ModulesListView: React.FC = observer(() => { [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER], EUserPermissionsLevel.PROJECT ); - const generalViewResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/onboarding/modules", - }); if (loader || !projectModuleIds || !filteredModuleIds) return ( @@ -56,42 +48,29 @@ export const ModulesListView: React.FC = observer(() => { if (projectModuleIds.length === 0) return ( - { - toggleCreateModuleModal(true); - }} - disabled={!canPerformEmptyStateActions} - /> - } + toggleCreateModuleModal(true), + disabled: !canPerformEmptyStateActions, + variant: "primary", + "data-ph-element": MODULE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON, + }, + ]} /> ); if (filteredModuleIds.length === 0) return ( -
-
- No matching modules -
No matching modules
-

- {searchQuery.trim() === "" - ? "Remove the filters to see all modules" - : "Remove the search criteria to see all modules"} -

-
-
+ ); return ( diff --git a/apps/web/core/components/pages/pages-list-main-content.tsx b/apps/web/core/components/pages/pages-list-main-content.tsx index ee39f38c0b..42fbf1cce7 100644 --- a/apps/web/core/components/pages/pages-list-main-content.tsx +++ b/apps/web/core/components/pages/pages-list-main-content.tsx @@ -1,7 +1,6 @@ "use client"; import { useState } from "react"; import { observer } from "mobx-react"; -import Image from "next/image"; // plane imports import { useParams, useRouter } from "next/navigation"; import { @@ -11,16 +10,15 @@ import { PROJECT_PAGE_TRACKER_EVENTS, } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { TPage, TPageNavigationTabs } from "@plane/types"; import { EUserProjectRoles } from "@plane/types"; // components -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { PageLoader } from "@/components/pages/loaders/page-loader"; import { captureClick, captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useProject } from "@/hooks/store/use-project"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // plane web hooks import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store"; @@ -52,23 +50,6 @@ export const PagesListMainContent: React.FC = observer((props) => { [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER], EUserPermissionsLevel.PROJECT ); - const generalPageResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/onboarding/pages", - }); - const publicPageResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/wiki/public", - }); - const privatePageResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/wiki/private", - }); - const archivedPageResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/wiki/archived", - }); - const resolvedFiltersImage = useResolvedAssetPath({ basePath: "/empty-state/wiki/all-filters", extension: "svg" }); - const resolvedNameFilterImage = useResolvedAssetPath({ - basePath: "/empty-state/wiki/name-filter", - extension: "svg", - }); // handle page create const handleCreatePage = async () => { @@ -111,80 +92,79 @@ export const PagesListMainContent: React.FC = observer((props) => { if (!isAnyPageAvailable || pageIds?.length === 0) { if (!isAnyPageAvailable) { return ( - { - handleCreatePage(); - captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + { + handleCreatePage(); + captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + }, + variant: "primary", + disabled: !canPerformEmptyStateActions || isCreatingPage, }, - disabled: !canPerformEmptyStateActions || isCreatingPage, - }} + ]} /> ); } if (pageType === "public") return ( - { - handleCreatePage(); - captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + { + handleCreatePage(); + captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + }, + variant: "primary", + disabled: !canPerformEmptyStateActions || isCreatingPage, }, - disabled: !canPerformEmptyStateActions || isCreatingPage, - }} + ]} /> ); if (pageType === "private") return ( - { - handleCreatePage(); - captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + { + handleCreatePage(); + captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + }, + variant: "primary", + disabled: !canPerformEmptyStateActions || isCreatingPage, }, - disabled: !canPerformEmptyStateActions || isCreatingPage, - }} + ]} /> ); if (pageType === "archived") return ( - ); } // if no pages match the filter criteria if (filteredPageIds?.length === 0) return ( -
-
- 0 ? resolvedNameFilterImage : resolvedFiltersImage} - className="h-36 sm:h-48 w-36 sm:w-48 mx-auto" - alt="No matching modules" - /> -
No matching pages
-

- {filters.searchQuery.length > 0 - ? "Remove the search criteria to see all pages" - : "Remove the filters to see all pages"} -

-
-
+ ); return
{children}
; diff --git a/apps/web/core/components/profile/overview/activity.tsx b/apps/web/core/components/profile/overview/activity.tsx index f52255400e..2af5e2079d 100644 --- a/apps/web/core/components/profile/overview/activity.tsx +++ b/apps/web/core/components/profile/overview/activity.tsx @@ -5,6 +5,7 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; // ui import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import { Loader, Card } from "@plane/ui"; import { calculateTimeAgo, getFileURL } from "@plane/utils"; // components @@ -83,11 +84,7 @@ export const ProfileActivity = observer(() => { ))}
) : ( - + ) ) : ( diff --git a/apps/web/core/components/profile/overview/priority-distribution.tsx b/apps/web/core/components/profile/overview/priority-distribution.tsx index d97a687321..98f79a5189 100644 --- a/apps/web/core/components/profile/overview/priority-distribution.tsx +++ b/apps/web/core/components/profile/overview/priority-distribution.tsx @@ -3,13 +3,10 @@ // plane imports import { useTranslation } from "@plane/i18n"; import { BarChart } from "@plane/propel/charts/bar-chart"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import type { IUserProfileData } from "@plane/types"; import { Loader, Card } from "@plane/ui"; import { capitalizeFirstLetter } from "@plane/utils"; -// components -import { ProfileEmptyState } from "@/components/ui/profile-empty-state"; -// assets -import emptyBarGraph from "@/public/empty-state/empty_bar_graph.svg"; type Props = { userProfile: IUserProfileData | undefined; @@ -62,13 +59,11 @@ export const ProfilePriorityDistribution: React.FC = ({ userProfile }) => barSize={20} /> ) : ( -
- -
+ )} ) : ( diff --git a/apps/web/core/components/profile/overview/state-distribution.tsx b/apps/web/core/components/profile/overview/state-distribution.tsx index 9b7c15f42b..0b4024f21a 100644 --- a/apps/web/core/components/profile/overview/state-distribution.tsx +++ b/apps/web/core/components/profile/overview/state-distribution.tsx @@ -2,13 +2,10 @@ import { STATE_GROUPS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { PieChart } from "@plane/propel/charts/pie-chart"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import type { IUserProfileData, IUserStateDistribution } from "@plane/types"; import { Card } from "@plane/ui"; import { capitalizeFirstLetter } from "@plane/utils"; -// components -import { ProfileEmptyState } from "@/components/ui/profile-empty-state"; -// assets -import stateGraph from "@/public/empty-state/state_graph.svg"; type Props = { stateDistribution: IUserStateDistribution[]; @@ -74,10 +71,10 @@ export const ProfileStateDistribution: React.FC = ({ stateDistribution, u
) : ( - )} diff --git a/apps/web/core/components/project/card-list.tsx b/apps/web/core/components/project/card-list.tsx index ba8f7a6bb5..05a74028b5 100644 --- a/apps/web/core/components/project/card-list.tsx +++ b/apps/web/core/components/project/card-list.tsx @@ -1,12 +1,11 @@ import { observer } from "mobx-react"; -import Image from "next/image"; // plane imports import { EUserPermissionsLevel, EUserPermissions, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { ContentWrapper } from "@plane/ui"; // components -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; +import { calculateTotalFilters } from "@plane/utils"; import { ProjectsLoader } from "@/components/ui/loader/projects-loader"; import { captureClick } from "@/helpers/event-tracker.helper"; // hooks @@ -14,7 +13,6 @@ import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useProject } from "@/hooks/store/use-project"; import { useProjectFilter } from "@/hooks/store/use-project-filter"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // local imports import { ProjectCard } from "./card"; @@ -36,20 +34,9 @@ export const ProjectCardList = observer((props: TProjectCardListProps) => { filteredProjectIds: storeFilteredProjectIds, getProjectById, } = useProject(); - const { searchQuery, currentWorkspaceDisplayFilters } = useProjectFilter(); + const { currentWorkspaceDisplayFilters, currentWorkspaceFilters } = useProjectFilter(); const { allowPermissions } = useUserPermissions(); - // helper hooks - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/onboarding/projects" }); - const resolvedFiltersImage = useResolvedAssetPath({ - basePath: "/empty-state/project/all-filters", - extension: "svg", - }); - const resolvedNameFilterImage = useResolvedAssetPath({ - basePath: "/empty-state/project/name-filter", - extension: "svg", - }); - // derived values const workspaceProjectIds = totalProjectIdsProps ?? storeWorkspaceProjectIds; const filteredProjectIds = filteredProjectIdsProps ?? storeFilteredProjectIds; @@ -65,42 +52,48 @@ export const ProjectCardList = observer((props: TProjectCardListProps) => { if (workspaceProjectIds?.length === 0 && !currentWorkspaceDisplayFilters?.archived_projects) return ( - { + assetKey="project" + assetClassName="size-40" + actions={[ + { + label: t("workspace_projects.empty_state.general.primary_button.text"), + onClick: () => { toggleCreateProjectModal(true); captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); - }} - disabled={!canPerformEmptyStateActions} - /> - } + }, + disabled: !canPerformEmptyStateActions, + variant: "primary", + }, + ]} /> ); if (filteredProjectIds.length === 0) return ( -
-
- No matching projects -
{t("workspace_projects.empty_state.filter.title")}
-

- {searchQuery.trim() === "" - ? t("workspace_projects.empty_state.filter.description") - : t("workspace_projects.empty_state.search.description")} -

-
-
+ ); return ( diff --git a/apps/web/core/components/views/views-list.tsx b/apps/web/core/components/views/views-list.tsx index 33d19cbe09..e078131b3f 100644 --- a/apps/web/core/components/views/views-list.tsx +++ b/apps/web/core/components/views/views-list.tsx @@ -1,21 +1,17 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EUserPermissionsLevel, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; +import { EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EUserProjectRoles } from "@plane/types"; // components import { ListLayout } from "@/components/core/list"; -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; -import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; import { ViewListLoader } from "@/components/ui/loader/view-list-loader"; // hooks -import { captureClick } from "@/helpers/event-tracker.helper"; import { useCommandPalette } from "@/hooks/store/use-command-palette"; import { useProjectView } from "@/hooks/store/use-project-view"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // local imports import { ProjectViewListItem } from "./view-list-item"; @@ -34,24 +30,16 @@ export const ProjectViewsList = observer(() => { [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER, EUserProjectRoles.GUEST], EUserPermissionsLevel.PROJECT ); - const generalViewResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/onboarding/views", - }); - const filteredViewResolvedPath = useResolvedAssetPath({ - basePath: "/empty-state/search/views", - }); if (loader || !projectViews || !filteredProjectViews) return ; if (filteredProjectViews.length === 0 && projectViews.length > 0) { return ( -
- -
+ ); } @@ -68,22 +56,18 @@ export const ProjectViewsList = observer(() => { ) : ( - { - toggleCreateViewModal(true); - captureClick({ elementName: PROJECT_VIEW_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); - }} - disabled={!canPerformEmptyStateActions} - /> - } + toggleCreateViewModal(true), + disabled: !canPerformEmptyStateActions, + variant: "primary", + }, + ]} /> )} diff --git a/apps/web/core/components/workspace-notifications/root.tsx b/apps/web/core/components/workspace-notifications/root.tsx index 108bcb66c6..406f8beaee 100644 --- a/apps/web/core/components/workspace-notifications/root.tsx +++ b/apps/web/core/components/workspace-notifications/root.tsx @@ -6,10 +6,10 @@ import useSWR from "swr"; // plane imports import { ENotificationLoader, ENotificationQueryParamType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; import { cn } from "@plane/utils"; // components import { LogoSpinner } from "@/components/common/logo-spinner"; -import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; // hooks import { useWorkspaceNotifications } from "@/hooks/store/notifications"; import { useWorkspace } from "@/hooks/store/use-workspace"; @@ -87,8 +87,8 @@ export const NotificationsRoot = observer(({ workspaceSlug }: NotificationsRootP return (
{!currentSelectedNotificationId ? ( -
- +
+
) : ( <> diff --git a/apps/web/core/components/workspace-notifications/sidebar/empty-state.tsx b/apps/web/core/components/workspace-notifications/sidebar/empty-state.tsx index 7d61fcc6be..0c81aed47b 100644 --- a/apps/web/core/components/workspace-notifications/sidebar/empty-state.tsx +++ b/apps/web/core/components/workspace-notifications/sidebar/empty-state.tsx @@ -4,33 +4,29 @@ import type { FC } from "react"; import { observer } from "mobx-react"; // plane imports import { ENotificationTab } from "@plane/constants"; -// components import { useTranslation } from "@plane/i18n"; -import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; -// constants -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; +import { EmptyStateCompact } from "@plane/propel/empty-state"; -export const NotificationEmptyState: FC = observer(() => { +type TNotificationEmptyStateProps = { + currentNotificationTab: ENotificationTab; +}; + +export const NotificationEmptyState: FC = observer(({ currentNotificationTab }) => { // plane imports const { t } = useTranslation(); - // derived values - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/search/notification" }); return ( <> - {ENotificationTab.ALL ? ( - - ) : ( - - )} + ); }); diff --git a/apps/web/core/components/workspace-notifications/sidebar/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/root.tsx index 39478550c4..080f5afe70 100644 --- a/apps/web/core/components/workspace-notifications/sidebar/root.tsx +++ b/apps/web/core/components/workspace-notifications/sidebar/root.tsx @@ -107,7 +107,7 @@ export const NotificationsSidebarRoot: FC = observer(() => { ) : (
- +
)} diff --git a/apps/web/core/layouts/auth-layout/project-wrapper.tsx b/apps/web/core/layouts/auth-layout/project-wrapper.tsx index 77d3050655..a341f202d1 100644 --- a/apps/web/core/layouts/auth-layout/project-wrapper.tsx +++ b/apps/web/core/layouts/auth-layout/project-wrapper.tsx @@ -7,12 +7,11 @@ import useSWR from "swr"; // plane imports import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EmptyStateDetailed } from "@plane/propel/empty-state"; import { EProjectNetwork } from "@plane/types"; // components import { JoinProject } from "@/components/auth-screens/project/join-project"; import { LogoSpinner } from "@/components/common/logo-spinner"; -import { ComicBoxButton } from "@/components/empty-state/comic-box-button"; -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; import { ETimeLineTypeType } from "@/components/gantt-chart/contexts"; import { captureClick } from "@/helpers/event-tracker.helper"; // hooks @@ -26,7 +25,6 @@ import { useProject } from "@/hooks/store/use-project"; import { useProjectState } from "@/hooks/store/use-project-state"; import { useProjectView } from "@/hooks/store/use-project-view"; import { useUserPermissions } from "@/hooks/store/user"; -import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; import { useTimeLineChart } from "@/hooks/use-timeline-chart"; // local import { persistence } from "@/local-db/storage.sqlite"; @@ -58,9 +56,6 @@ export const ProjectAuthWrapper: FC = observer((props) => { const { fetchProjectLabels } = useLabel(); const { getProjectEstimates } = useProjectEstimates(); - // helper hooks - const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/onboarding/projects" }); - // derived values const projectExists = projectId ? getProjectById(projectId.toString()) : null; const projectMemberInfo = getProjectRoleByWorkspaceSlugAndProjectId(workspaceSlug, projectId); @@ -184,22 +179,22 @@ export const ProjectAuthWrapper: FC = observer((props) => { if (loader === "loaded" && projectId && !!hasPermissionToCurrentProject === false) return (
- { + assetKey="project" + assetClassName="size-40" + actions={[ + { + label: t("workspace_projects.empty_state.general.primary_button.text"), + onClick: () => { toggleCreateProjectModal(true); captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); - }} - disabled={!canPerformEmptyStateActions} - /> - } + }, + disabled: !canPerformEmptyStateActions, + variant: "primary", + }, + ]} />
); diff --git a/packages/i18n/src/constants/language.ts b/packages/i18n/src/constants/language.ts index 4dc0408bdd..efcc9aada3 100644 --- a/packages/i18n/src/constants/language.ts +++ b/packages/i18n/src/constants/language.ts @@ -32,6 +32,7 @@ export enum ETranslationFiles { TRANSLATIONS = "translations", ACCESSIBILITY = "accessibility", EDITOR = "editor", + EMPTY_STATE = "emptyState", } export const LANGUAGE_STORAGE_KEY = "userLanguage"; diff --git a/packages/i18n/src/locales/cs/empty-state.ts b/packages/i18n/src/locales/cs/empty-state.ts new file mode 100644 index 0000000000..3c1641a0fb --- /dev/null +++ b/packages/i18n/src/locales/cs/empty-state.ts @@ -0,0 +1,181 @@ +export default { + common: { + progress: { + title: "Zatím nejsou k dispozici žádné metriky pokroku.", + description: "Začněte nastavovat hodnoty vlastností v pracovních položkách, abyste zde viděli metriky pokroku.", + }, + updates: { + title: "Zatím žádné aktualizace.", + description: "Jakmile členové projektu přidají aktualizace, zobrazí se zde", + }, + search: { + title: "Žádné odpovídající výsledky.", + description: "Nebyly nalezeny žádné výsledky. Zkuste upravit vyhledávací výrazy.", + }, + not_found: { + title: "Jejda! Něco se zdá být v nepořádku", + description: "Momentálně se nám nedaří načíst váš účet plane. Může se jednat o chybu sítě.", + cta_primary: "Zkuste znovu načíst", + }, + server_error: { + title: "Chyba serveru", + description: "Nemůžeme se připojit a načíst data z našeho serveru. Nebojte se, pracujeme na tom.", + cta_primary: "Zkuste znovu načíst", + }, + }, + project: { + work_items: { + title: "Začněte s vaší první pracovní položkou.", + description: + "Pracovní položky jsou stavebními kameny vašeho projektu — přiřazujte vlastníky, nastavujte priority a snadno sledujte pokrok.", + cta_primary: "Vytvořte svou první pracovní položku", + }, + cycles: { + title: "Seskupujte a časově omezte svou práci v cyklech.", + description: + "Rozdělte práci do časově omezených bloků, pracujte zpětně od termínu projektu pro nastavení dat a dosahujte hmatatelného pokroku jako tým.", + cta_primary: "Nastavte svůj první cyklus", + }, + cycle_work_items: { + title: "V tomto cyklu nejsou žádné pracovní položky k zobrazení", + description: + "Vytvořte pracovní položky pro zahájení sledování pokroku vašeho týmu v tomto cyklu a dosažení vašich cílů včas.", + cta_primary: "Vytvořit pracovní položku", + cta_secondary: "Přidat existující pracovní položku", + }, + modules: { + title: "Namapujte cíle vašeho projektu na moduly a snadno sledujte.", + description: + "Moduly se skládají z propojených pracovních položek. Pomáhají sledovat pokrok prostřednictvím fází projektu, z nichž každá má specifické termíny a analytiku, která ukazuje, jak blízko jste dosažení těchto fází.", + cta_primary: "Nastavte svůj první modul", + }, + module_work_items: { + title: "V tomto modulu nejsou žádné pracovní položky k zobrazení", + description: "Vytvořte pracovní položky pro zahájení sledování tohoto modulu.", + cta_primary: "Vytvořit pracovní položku", + cta_secondary: "Přidat existující pracovní položku", + }, + views: { + title: "Uložte vlastní pohledy pro váš projekt", + description: + "Pohledy jsou uložené filtry, které vám pomáhají rychle přistupovat k informacím, které používáte nejčastěji. Spolupracujte bez námahy, zatímco spolupracovníci sdílejí a přizpůsobují pohledy svým specifickým potřebám.", + cta_primary: "Vytvořit pohled", + }, + no_work_items_in_project: { + title: "V projektu zatím nejsou žádné pracovní položky", + description: + "Přidejte pracovní položky do svého projektu a rozdělte svou práci na sledovatelné části pomocí pohledů.", + cta_primary: "Přidat pracovní položku", + }, + work_item_filter: { + title: "Nebyly nalezeny žádné pracovní položky", + description: "Váš aktuální filtr nevrátil žádné výsledky. Zkuste změnit filtry.", + cta_primary: "Přidat pracovní položku", + }, + pages: { + title: "Dokumentujte vše — od poznámek po PRD", + description: + "Stránky vám umožňují zachytit a organizovat informace na jednom místě. Pište poznámky ze schůzek, projektovou dokumentaci a PRD, vkládejte pracovní položky a strukturujte je pomocí připravených komponent.", + cta_primary: "Vytvořte svou první stránku", + }, + archive_pages: { + title: "Zatím žádné archivované stránky", + description: "Archivujte stránky, které nejsou na vašem radaru. Přistupte k nim zde, když budete potřebovat.", + }, + intake_sidebar: { + title: "Zaznamenejte příchozí požadavky", + description: + "Odesílejte nové požadavky k přezkoumání, stanovení priorit a sledování v rámci pracovního postupu vašeho projektu.", + cta_primary: "Vytvořit příchozí požadavek", + }, + intake_main: { + title: "Vyberte příchozí pracovní položku pro zobrazení jejích podrobností", + }, + }, + workspace: { + archive_work_items: { + title: "Zatím žádné archivované pracovní položky", + description: + "Ručně nebo pomocí automatizace můžete archivovat dokončené nebo zrušené pracovní položky. Najdete je zde, jakmile budou archivovány.", + cta_primary: "Nastavit automatizaci", + }, + archive_cycles: { + title: "Zatím žádné archivované cykly", + description: "Pro úklid vašeho projektu archivujte dokončené cykly. Najdete je zde, jakmile budou archivovány.", + }, + archive_modules: { + title: "Zatím žádné archivované moduly", + description: + "Pro úklid vašeho projektu archivujte dokončené nebo zrušené moduly. Najdete je zde, jakmile budou archivovány.", + }, + home_widget_quick_links: { + title: "Mějte po ruce důležité odkazy, zdroje nebo dokumenty pro vaši práci", + }, + inbox_sidebar_all: { + title: "Aktualizace pro vaše odebírané pracovní položky se zobrazí zde", + }, + inbox_sidebar_mentions: { + title: "Zmínky o vašich pracovních položkách se zobrazí zde", + }, + your_work_by_priority: { + title: "Zatím není přiřazena žádná pracovní položka", + }, + your_work_by_state: { + title: "Zatím není přiřazena žádná pracovní položka", + }, + views: { + title: "Zatím žádné pohledy", + description: + "Přidejte pracovní položky do svého projektu a používejte pohledy pro snadné filtrování, třídění a sledování pokroku.", + cta_primary: "Přidat pracovní položku", + }, + drafts: { + title: "Napůl napsané pracovní položky", + description: + "Chcete-li to vyzkoušet, začněte přidávat pracovní položku a nechte ji nedokončenou nebo vytvořte svůj první koncept níže. 😉", + cta_primary: "Vytvořit koncept pracovní položky", + }, + projects_archived: { + title: "Žádné archivované projekty", + description: "Vypadá to, že všechny vaše projekty jsou stále aktivní—skvělá práce!", + }, + analytics_projects: { + title: "Vytvořte projekty pro vizualizaci metrik projektu zde.", + }, + analytics_work_items: { + title: + "Vytvořte projekty s pracovními položkami a přiřazenými osobami pro zahájení sledování výkonu, pokroku a dopadu týmu zde.", + }, + analytics_no_cycle: { + title: "Vytvořte cykly pro organizaci práce do časově omezených fází a sledování pokroku napříč sprinty.", + }, + analytics_no_module: { + title: "Vytvořte moduly pro organizaci své práce a sledování pokroku napříč různými fázemi.", + }, + analytics_no_intake: { + title: "Nastavte příjem pro správu příchozích požadavků a sledování, jak jsou přijímány a odmítány", + }, + }, + settings: { + estimates: { + title: "Zatím žádné odhady", + description: "Definujte, jak váš tým měří úsilí, a sledujte to konzistentně napříč všemi pracovními položkami.", + cta_primary: "Přidat systém odhadů", + }, + labels: { + title: "Zatím žádné štítky", + description: "Vytvořte personalizované štítky pro efektivní kategorizaci a správu vašich pracovních položek.", + cta_primary: "Vytvořte svůj první štítek", + }, + exports: { + title: "Zatím žádné exporty", + description: "Momentálně nemáte žádné záznamy exportu. Jakmile exportujete data, všechny záznamy se zobrazí zde.", + }, + tokens: { + title: "Zatím žádný osobní token", + description: + "Generujte bezpečné API tokeny pro připojení vašeho pracovního prostoru s externími systémy a aplikacemi.", + cta_primary: "Přidat API token", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/de/empty-state.ts b/packages/i18n/src/locales/de/empty-state.ts new file mode 100644 index 0000000000..0c7a27eb7e --- /dev/null +++ b/packages/i18n/src/locales/de/empty-state.ts @@ -0,0 +1,190 @@ +export default { + common: { + progress: { + title: "Es gibt noch keine Fortschrittsmetriken anzuzeigen.", + description: + "Beginnen Sie mit dem Festlegen von Eigenschaftswerten in Arbeitselementen, um hier Fortschrittsmetriken zu sehen.", + }, + updates: { + title: "Noch keine Updates.", + description: "Sobald Projektmitglieder Updates hinzufügen, werden sie hier angezeigt", + }, + search: { + title: "Keine passenden Ergebnisse.", + description: "Keine Ergebnisse gefunden. Versuchen Sie, Ihre Suchbegriffe anzupassen.", + }, + not_found: { + title: "Hoppla! Etwas scheint nicht zu stimmen", + description: "Wir können Ihr Plane-Konto derzeit nicht abrufen. Dies könnte ein Netzwerkfehler sein.", + cta_primary: "Versuchen Sie neu zu laden", + }, + server_error: { + title: "Serverfehler", + description: + "Wir können keine Verbindung herstellen und Daten von unserem Server abrufen. Keine Sorge, wir arbeiten daran.", + cta_primary: "Versuchen Sie neu zu laden", + }, + }, + project: { + work_items: { + title: "Beginnen Sie mit Ihrem ersten Arbeitselement.", + description: + "Arbeitselemente sind die Bausteine Ihres Projekts — weisen Sie Eigentümer zu, setzen Sie Prioritäten und verfolgen Sie den Fortschritt einfach.", + cta_primary: "Erstellen Sie Ihr erstes Arbeitselement", + }, + cycles: { + title: "Gruppieren und zeitlich begrenzen Sie Ihre Arbeit in Zyklen.", + description: + "Teilen Sie die Arbeit in zeitlich begrenzte Blöcke auf, arbeiten Sie rückwärts von Ihrer Projektfrist, um Termine festzulegen, und machen Sie greifbare Fortschritte als Team.", + cta_primary: "Legen Sie Ihren ersten Zyklus fest", + }, + cycle_work_items: { + title: "Keine Arbeitselemente in diesem Zyklus anzuzeigen", + description: + "Erstellen Sie Arbeitselemente, um den Fortschritt Ihres Teams in diesem Zyklus zu überwachen und Ihre Ziele rechtzeitig zu erreichen.", + cta_primary: "Arbeitselement erstellen", + cta_secondary: "Bestehendes Arbeitselement hinzufügen", + }, + modules: { + title: "Ordnen Sie Ihre Projektziele Modulen zu und verfolgen Sie sie einfach.", + description: + "Module bestehen aus miteinander verbundenen Arbeitselementen. Sie helfen bei der Überwachung des Fortschritts durch Projektphasen, jede mit spezifischen Fristen und Analysen, um anzuzeigen, wie nahe Sie dem Erreichen dieser Phasen sind.", + cta_primary: "Legen Sie Ihr erstes Modul fest", + }, + module_work_items: { + title: "Keine Arbeitselemente in diesem Modul anzuzeigen", + description: "Erstellen Sie Arbeitselemente, um dieses Modul zu überwachen.", + cta_primary: "Arbeitselement erstellen", + cta_secondary: "Bestehendes Arbeitselement hinzufügen", + }, + views: { + title: "Speichern Sie benutzerdefinierte Ansichten für Ihr Projekt", + description: + "Ansichten sind gespeicherte Filter, die Ihnen helfen, schnell auf die Informationen zuzugreifen, die Sie am häufigsten verwenden. Arbeiten Sie mühelos zusammen, während Teammitglieder Ansichten teilen und an ihre spezifischen Bedürfnisse anpassen.", + cta_primary: "Ansicht erstellen", + }, + no_work_items_in_project: { + title: "Noch keine Arbeitselemente im Projekt", + description: + "Fügen Sie Arbeitselemente zu Ihrem Projekt hinzu und unterteilen Sie Ihre Arbeit in nachverfolgbare Teile mit Ansichten.", + cta_primary: "Arbeitselement hinzufügen", + }, + work_item_filter: { + title: "Keine Arbeitselemente gefunden", + description: "Ihr aktueller Filter hat keine Ergebnisse zurückgegeben. Versuchen Sie, die Filter zu ändern.", + cta_primary: "Arbeitselement hinzufügen", + }, + pages: { + title: "Dokumentieren Sie alles — von Notizen bis PRDs", + description: + "Seiten ermöglichen es Ihnen, Informationen an einem Ort zu erfassen und zu organisieren. Schreiben Sie Besprechungsnotizen, Projektdokumentationen und PRDs, betten Sie Arbeitselemente ein und strukturieren Sie sie mit gebrauchsfertigen Komponenten.", + cta_primary: "Erstellen Sie Ihre erste Seite", + }, + archive_pages: { + title: "Noch keine archivierten Seiten", + description: "Archivieren Sie Seiten, die nicht auf Ihrem Radar sind. Greifen Sie bei Bedarf hier darauf zu.", + }, + intake_sidebar: { + title: "Intake-Anfragen protokollieren", + description: + "Senden Sie neue Anfragen zur Überprüfung, Priorisierung und Verfolgung innerhalb Ihres Projekt-Workflows.", + cta_primary: "Intake-Anfrage erstellen", + }, + intake_main: { + title: "Wählen Sie ein Intake-Arbeitselement aus, um seine Details anzuzeigen", + }, + }, + workspace: { + archive_work_items: { + title: "Noch keine archivierten Arbeitselemente", + description: + "Manuell oder durch Automatisierung können Sie abgeschlossene oder stornierte Arbeitselemente archivieren. Finden Sie sie hier, sobald sie archiviert sind.", + cta_primary: "Automatisierung einrichten", + }, + archive_cycles: { + title: "Noch keine archivierten Zyklen", + description: + "Um Ihr Projekt aufzuräumen, archivieren Sie abgeschlossene Zyklen. Finden Sie sie hier, sobald sie archiviert sind.", + }, + archive_modules: { + title: "Noch keine archivierten Module", + description: + "Um Ihr Projekt aufzuräumen, archivieren Sie abgeschlossene oder stornierte Module. Finden Sie sie hier, sobald sie archiviert sind.", + }, + home_widget_quick_links: { + title: "Halten Sie wichtige Referenzen, Ressourcen oder Dokumente für Ihre Arbeit griffbereit", + }, + inbox_sidebar_all: { + title: "Updates für Ihre abonnierten Arbeitselemente werden hier angezeigt", + }, + inbox_sidebar_mentions: { + title: "Erwähnungen für Ihre Arbeitselemente werden hier angezeigt", + }, + your_work_by_priority: { + title: "Noch kein Arbeitselement zugewiesen", + }, + your_work_by_state: { + title: "Noch kein Arbeitselement zugewiesen", + }, + views: { + title: "Noch keine Ansichten", + description: + "Fügen Sie Arbeitselemente zu Ihrem Projekt hinzu und verwenden Sie Ansichten, um mühelos zu filtern, zu sortieren und den Fortschritt zu überwachen.", + cta_primary: "Arbeitselement hinzufügen", + }, + drafts: { + title: "Halb geschriebene Arbeitselemente", + description: + "Um dies auszuprobieren, beginnen Sie ein Arbeitselement hinzuzufügen und lassen Sie es auf halbem Weg liegen oder erstellen Sie unten Ihren ersten Entwurf. 😉", + cta_primary: "Entwurf-Arbeitselement erstellen", + }, + projects_archived: { + title: "Keine Projekte archiviert", + description: "Es sieht so aus, als wären alle Ihre Projekte noch aktiv—gute Arbeit!", + }, + analytics_projects: { + title: "Erstellen Sie Projekte, um hier Projektmetriken zu visualisieren.", + }, + analytics_work_items: { + title: + "Erstellen Sie Projekte mit Arbeitselementen und Zugewiesenen, um hier Leistung, Fortschritt und Teameinfluss zu verfolgen.", + }, + analytics_no_cycle: { + title: + "Erstellen Sie Zyklen, um Arbeit in zeitlich begrenzte Phasen zu organisieren und Fortschritte über Sprints hinweg zu verfolgen.", + }, + analytics_no_module: { + title: + "Erstellen Sie Module, um Ihre Arbeit zu organisieren und Fortschritte über verschiedene Phasen hinweg zu verfolgen.", + }, + analytics_no_intake: { + title: + "Richten Sie Intake ein, um eingehende Anfragen zu verwalten und zu verfolgen, wie sie akzeptiert und abgelehnt werden", + }, + }, + settings: { + estimates: { + title: "Noch keine Schätzungen", + description: + "Definieren Sie, wie Ihr Team den Aufwand misst, und verfolgen Sie ihn konsistent über alle Arbeitselemente hinweg.", + cta_primary: "Schätzsystem hinzufügen", + }, + labels: { + title: "Noch keine Labels", + description: + "Erstellen Sie personalisierte Labels, um Ihre Arbeitselemente effektiv zu kategorisieren und zu verwalten.", + cta_primary: "Erstellen Sie Ihr erstes Label", + }, + exports: { + title: "Noch keine Exporte", + description: + "Sie haben derzeit keine Exportaufzeichnungen. Sobald Sie Daten exportieren, werden alle Aufzeichnungen hier angezeigt.", + }, + tokens: { + title: "Noch kein persönliches Token", + description: + "Generieren Sie sichere API-Tokens, um Ihren Workspace mit externen Systemen und Anwendungen zu verbinden.", + cta_primary: "API-Token hinzufügen", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/en/empty-state.ts b/packages/i18n/src/locales/en/empty-state.ts new file mode 100644 index 0000000000..ef8265b121 --- /dev/null +++ b/packages/i18n/src/locales/en/empty-state.ts @@ -0,0 +1,176 @@ +export default { + common: { + progress: { + title: "There're no progress metrics to show yet.", + description: "Start setting property values in work items to see progress metrics here.", + }, + updates: { + title: "No updates yet.", + description: "Once project members add updates it will appear here", + }, + search: { + title: "No matching results.", + description: "No results found. Try adjusting your search terms.", + }, + not_found: { + title: "Oops! Something seems wrong", + description: "We are unable to fetch your plane account currently. This might be a network error.", + cta_primary: "Try reloading", + }, + server_error: { + title: "Server error", + description: "We are unable to connect and fetch data from our server. Don't worry, we are working on it.", + cta_primary: "Try reloading", + }, + }, + project: { + work_items: { + title: "Start with your first work item.", + description: + "Work items are the building blocks of your project — assign owners, set priorities, and track progress easily.", + cta_primary: "Create your first work item", + }, + cycles: { + title: "Group and timebox your work in Cycles.", + description: + "Break work down by timeboxed chunks, work backwards from your project deadline to set dates, and make tangible progress as a team.", + cta_primary: "Set your first cycle", + }, + cycle_work_items: { + title: "No work items to show in this cycle", + description: + "Create work items to begin monitoring your team's progress this cycle and achieve your goals on time.", + cta_primary: "Create work item", + cta_secondary: "Add existing work item", + }, + modules: { + title: "Map your project goals to Modules and track easily.", + description: + "Modules are made up of interconnected work items. They assist in monitoring progress through project phases, each with specific deadlines and analytics to indicate how close you are to achieving those phases.", + cta_primary: "Set your first module", + }, + module_work_items: { + title: "No work items to show in this Module", + description: "Create work items to begin monitoring this module.", + cta_primary: "Create work item", + cta_secondary: "Add existing work item", + }, + views: { + title: "Save custom views for your project", + description: + "Views are saved filters that help you quickly access the information you use most. Collaborate effortlessly as teammates share and tailor views to their specific needs.", + cta_primary: "Create view", + }, + no_work_items_in_project: { + title: "No work items in the project yet", + description: "Add work items to your project and slice your work into trackable pieces with views.", + cta_primary: "Add work item", + }, + work_item_filter: { + title: "No work items found", + description: "Your current filter didn't return any results. Try changing the filters.", + cta_primary: "Add work item", + }, + pages: { + title: "Document everything — from notes to PRDs", + description: + "Pages let you capture and organize information in one place. Write meeting notes, project documentation, and PRDs, embed work items, and structure them with ready-to-use components.", + cta_primary: "Create your first Page", + }, + archive_pages: { + title: "No archived pages yet", + description: "Archive pages not on your radar. Access them here when needed.", + }, + intake_sidebar: { + title: "Log Intake requests", + description: "Submit new requests to be reviewed, prioritized, and tracked within your project's workflow.", + cta_primary: "Create Intake request", + }, + intake_main: { + title: "Select an Intake work item to view its details", + }, + }, + workspace: { + archive_work_items: { + title: "No archived work items yet", + description: + "Manually or through automation, you can archive work items that are completed or cancelled. Find them here once archived.", + cta_primary: "Set automation", + }, + archive_cycles: { + title: "No archived cycles yet", + description: "To tidy up your project, archive completed cycles. Find them here once archived.", + }, + archive_modules: { + title: "No archived Modules yet", + description: "To tidy up your project, archive completed or cancelled modules. Find them here once archived.", + }, + home_widget_quick_links: { + title: "Keep important references, resources, or docs handy for your work", + }, + inbox_sidebar_all: { + title: "Updates for your subscribed work items will appear here", + }, + inbox_sidebar_mentions: { + title: "Mentions for your work items will appear here", + }, + your_work_by_priority: { + title: "No work item assigned yet", + }, + your_work_by_state: { + title: "No work item assigned yet", + }, + views: { + title: "No Views yet", + description: "Add work items to your project and use views to filter, sort, and monitor progress effortlessly.", + cta_primary: "Add work item", + }, + drafts: { + title: "Half-written work items", + description: + "To try this out, start adding a work item and leave it mid-way or create your first draft below. 😉", + cta_primary: "Create draft work item", + }, + projects_archived: { + title: "No projects archived", + description: "Looks like all your projects are still active—great job!", + }, + analytics_projects: { + title: "Create projects to visualize project metrics here.", + }, + analytics_work_items: { + title: + "Create projects with work items and assignees to start tracking performance, progress, and team impact here.", + }, + analytics_no_cycle: { + title: "Create cycles to organise work into time-bound phases and track progress across sprints.", + }, + analytics_no_module: { + title: "Create modules to organize your work and track progress across different stages.", + }, + analytics_no_intake: { + title: "Set up intake to manage incoming requests and track how they're accepted and rejected", + }, + }, + settings: { + estimates: { + title: "No estimates yet", + description: "Define how your team measures effort and track it consistently across all work items.", + cta_primary: "Add estimate system", + }, + labels: { + title: "No labels yet", + description: "Create personalized labels to effectively categorize and manage your work items.", + cta_primary: "Create your first label", + }, + exports: { + title: "No exports yet", + description: "You don't have any export records right now. Once you export data, all records will appear here.", + }, + tokens: { + title: "No Personal token yet", + description: "Generate secure API tokens to connect your workspace with external systems and applications.", + cta_primary: "Add API token", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/es/empty-state.ts b/packages/i18n/src/locales/es/empty-state.ts new file mode 100644 index 0000000000..3ee97c54f9 --- /dev/null +++ b/packages/i18n/src/locales/es/empty-state.ts @@ -0,0 +1,185 @@ +export default { + common: { + progress: { + title: "Todavía no hay métricas de progreso para mostrar.", + description: + "Comienza a establecer valores de propiedades en los elementos de trabajo para ver las métricas de progreso aquí.", + }, + updates: { + title: "Aún no hay actualizaciones.", + description: "Una vez que los miembros del proyecto agreguen actualizaciones, aparecerán aquí", + }, + search: { + title: "No se encontraron resultados coincidentes.", + description: "No se encontraron resultados. Intenta ajustar tus términos de búsqueda.", + }, + not_found: { + title: "¡Ups! Algo parece estar mal", + description: "No podemos obtener tu cuenta de Plane actualmente. Esto podría ser un error de red.", + cta_primary: "Intentar recargar", + }, + server_error: { + title: "Error del servidor", + description: + "No podemos conectarnos y obtener datos de nuestro servidor. No te preocupes, estamos trabajando en ello.", + cta_primary: "Intentar recargar", + }, + }, + project: { + work_items: { + title: "Comienza con tu primer elemento de trabajo.", + description: + "Los elementos de trabajo son los bloques de construcción de tu proyecto — asigna responsables, establece prioridades y realiza un seguimiento del progreso fácilmente.", + cta_primary: "Crea tu primer elemento de trabajo", + }, + cycles: { + title: "Agrupa y delimita tu trabajo en Ciclos.", + description: + "Divide el trabajo en bloques con tiempo definido, trabaja hacia atrás desde la fecha límite de tu proyecto para establecer fechas y haz un progreso tangible como equipo.", + cta_primary: "Establece tu primer ciclo", + }, + cycle_work_items: { + title: "No hay elementos de trabajo para mostrar en este ciclo", + description: + "Crea elementos de trabajo para comenzar a monitorear el progreso de tu equipo en este ciclo y alcanzar tus objetivos a tiempo.", + cta_primary: "Crear elemento de trabajo", + cta_secondary: "Agregar elemento de trabajo existente", + }, + modules: { + title: "Asigna los objetivos de tu proyecto a Módulos y rastrea fácilmente.", + description: + "Los módulos están compuestos de elementos de trabajo interconectados. Ayudan a monitorear el progreso a través de las fases del proyecto, cada una con fechas límite específicas y análisis para indicar qué tan cerca estás de alcanzar esas fases.", + cta_primary: "Establece tu primer módulo", + }, + module_work_items: { + title: "No hay elementos de trabajo para mostrar en este Módulo", + description: "Crea elementos de trabajo para comenzar a monitorear este módulo.", + cta_primary: "Crear elemento de trabajo", + cta_secondary: "Agregar elemento de trabajo existente", + }, + views: { + title: "Guarda vistas personalizadas para tu proyecto", + description: + "Las vistas son filtros guardados que te ayudan a acceder rápidamente a la información que más usas. Colabora sin esfuerzo mientras los compañeros de equipo comparten y adaptan las vistas a sus necesidades específicas.", + cta_primary: "Crear vista", + }, + no_work_items_in_project: { + title: "Aún no hay elementos de trabajo en el proyecto", + description: "Agrega elementos de trabajo a tu proyecto y divide tu trabajo en piezas rastreables con vistas.", + cta_primary: "Agregar elemento de trabajo", + }, + work_item_filter: { + title: "No se encontraron elementos de trabajo", + description: "Tu filtro actual no devolvió ningún resultado. Intenta cambiar los filtros.", + cta_primary: "Agregar elemento de trabajo", + }, + pages: { + title: "Documenta todo — desde notas hasta PRDs", + description: + "Las páginas te permiten capturar y organizar información en un solo lugar. Escribe notas de reuniones, documentación de proyectos y PRDs, incrusta elementos de trabajo y estructúralos con componentes listos para usar.", + cta_primary: "Crea tu primera Página", + }, + archive_pages: { + title: "Aún no hay páginas archivadas", + description: "Archiva las páginas que no están en tu radar. Accede a ellas aquí cuando las necesites.", + }, + intake_sidebar: { + title: "Registra solicitudes de Entrada", + description: + "Envía nuevas solicitudes para ser revisadas, priorizadas y rastreadas dentro del flujo de trabajo de tu proyecto.", + cta_primary: "Crear solicitud de Entrada", + }, + intake_main: { + title: "Selecciona un elemento de trabajo de Entrada para ver sus detalles", + }, + }, + workspace: { + archive_work_items: { + title: "Aún no hay elementos de trabajo archivados", + description: + "Manualmente o mediante automatización, puedes archivar elementos de trabajo que estén completados o cancelados. Encuéntralos aquí una vez archivados.", + cta_primary: "Configurar automatización", + }, + archive_cycles: { + title: "Aún no hay ciclos archivados", + description: "Para ordenar tu proyecto, archiva los ciclos completados. Encuéntralos aquí una vez archivados.", + }, + archive_modules: { + title: "Aún no hay Módulos archivados", + description: + "Para ordenar tu proyecto, archiva los módulos completados o cancelados. Encuéntralos aquí una vez archivados.", + }, + home_widget_quick_links: { + title: "Mantén a mano referencias importantes, recursos o documentos para tu trabajo", + }, + inbox_sidebar_all: { + title: "Las actualizaciones de tus elementos de trabajo suscritos aparecerán aquí", + }, + inbox_sidebar_mentions: { + title: "Las menciones a tus elementos de trabajo aparecerán aquí", + }, + your_work_by_priority: { + title: "Aún no hay elementos de trabajo asignados", + }, + your_work_by_state: { + title: "Aún no hay elementos de trabajo asignados", + }, + views: { + title: "Aún no hay Vistas", + description: + "Agrega elementos de trabajo a tu proyecto y usa vistas para filtrar, ordenar y monitorear el progreso sin esfuerzo.", + cta_primary: "Agregar elemento de trabajo", + }, + drafts: { + title: "Elementos de trabajo a medio escribir", + description: + "Para probarlo, comienza a agregar un elemento de trabajo y déjalo a medias o crea tu primer borrador a continuación. 😉", + cta_primary: "Crear borrador de elemento de trabajo", + }, + projects_archived: { + title: "No hay proyectos archivados", + description: "Parece que todos tus proyectos siguen activos — ¡buen trabajo!", + }, + analytics_projects: { + title: "Crea proyectos para visualizar las métricas del proyecto aquí.", + }, + analytics_work_items: { + title: + "Crea proyectos con elementos de trabajo y responsables para comenzar a rastrear el rendimiento, progreso e impacto del equipo aquí.", + }, + analytics_no_cycle: { + title: + "Crea ciclos para organizar el trabajo en fases con límite de tiempo y rastrear el progreso en los sprints.", + }, + analytics_no_module: { + title: "Crea módulos para organizar tu trabajo y rastrear el progreso en diferentes etapas.", + }, + analytics_no_intake: { + title: "Configura la entrada para gestionar las solicitudes entrantes y rastrear cómo se aceptan y rechazan", + }, + }, + settings: { + estimates: { + title: "Aún no hay estimaciones", + description: + "Define cómo tu equipo mide el esfuerzo y rastréalo de manera consistente en todos los elementos de trabajo.", + cta_primary: "Agregar sistema de estimación", + }, + labels: { + title: "Aún no hay etiquetas", + description: "Crea etiquetas personalizadas para categorizar y gestionar efectivamente tus elementos de trabajo.", + cta_primary: "Crea tu primera etiqueta", + }, + exports: { + title: "Aún no hay exportaciones", + description: + "No tienes ningún registro de exportación en este momento. Una vez que exportes datos, todos los registros aparecerán aquí.", + }, + tokens: { + title: "Aún no hay tokens Personales", + description: + "Genera tokens API seguros para conectar tu espacio de trabajo con sistemas y aplicaciones externos.", + cta_primary: "Agregar token API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/fr/empty-state.ts b/packages/i18n/src/locales/fr/empty-state.ts new file mode 100644 index 0000000000..cf86b413cb --- /dev/null +++ b/packages/i18n/src/locales/fr/empty-state.ts @@ -0,0 +1,188 @@ +export default { + common: { + progress: { + title: "Il n'y a pas encore de métriques de progression à afficher.", + description: + "Commencez à définir des valeurs de propriété dans les éléments de travail pour voir les métriques de progression ici.", + }, + updates: { + title: "Pas encore de mises à jour.", + description: "Une fois que les membres du projet ajoutent des mises à jour, elles apparaîtront ici", + }, + search: { + title: "Aucun résultat correspondant.", + description: "Aucun résultat trouvé. Essayez d'ajuster vos termes de recherche.", + }, + not_found: { + title: "Oups ! Quelque chose semble incorrect", + description: + "Nous ne sommes actuellement pas en mesure de récupérer votre compte plane. Il pourrait s'agir d'une erreur réseau.", + cta_primary: "Essayer de recharger", + }, + server_error: { + title: "Erreur du serveur", + description: + "Nous ne sommes pas en mesure de nous connecter et de récupérer les données de notre serveur. Ne vous inquiétez pas, nous y travaillons.", + cta_primary: "Essayer de recharger", + }, + }, + project: { + work_items: { + title: "Commencez avec votre premier élément de travail.", + description: + "Les éléments de travail sont les éléments constitutifs de votre projet — attribuez des propriétaires, définissez des priorités et suivez facilement les progrès.", + cta_primary: "Créer votre premier élément de travail", + }, + cycles: { + title: "Regroupez et définissez des délais pour votre travail dans les Cycles.", + description: + "Décomposez le travail en morceaux délimités dans le temps, travaillez à rebours à partir de la date limite de votre projet pour définir des dates, et faites des progrès tangibles en équipe.", + cta_primary: "Définir votre premier cycle", + }, + cycle_work_items: { + title: "Aucun élément de travail à afficher dans ce cycle", + description: + "Créez des éléments de travail pour commencer à surveiller la progression de votre équipe ce cycle et atteindre vos objectifs à temps.", + cta_primary: "Créer un élément de travail", + cta_secondary: "Ajouter un élément de travail existant", + }, + modules: { + title: "Associez vos objectifs de projet aux Modules et suivez facilement.", + description: + "Les modules sont composés d'éléments de travail interconnectés. Ils aident à surveiller les progrès à travers les phases du projet, chacune avec des délais spécifiques et des analyses pour indiquer à quel point vous êtes proche de la réalisation de ces phases.", + cta_primary: "Définir votre premier module", + }, + module_work_items: { + title: "Aucun élément de travail à afficher dans ce Module", + description: "Créez des éléments de travail pour commencer à surveiller ce module.", + cta_primary: "Créer un élément de travail", + cta_secondary: "Ajouter un élément de travail existant", + }, + views: { + title: "Enregistrez des vues personnalisées pour votre projet", + description: + "Les vues sont des filtres enregistrés qui vous aident à accéder rapidement aux informations que vous utilisez le plus. Collaborez sans effort pendant que les coéquipiers partagent et adaptent les vues à leurs besoins spécifiques.", + cta_primary: "Créer une vue", + }, + no_work_items_in_project: { + title: "Aucun élément de travail dans le projet pour le moment", + description: + "Ajoutez des éléments de travail à votre projet et découpez votre travail en éléments traçables avec des vues.", + cta_primary: "Ajouter un élément de travail", + }, + work_item_filter: { + title: "Aucun élément de travail trouvé", + description: "Votre filtre actuel n'a renvoyé aucun résultat. Essayez de modifier les filtres.", + cta_primary: "Ajouter un élément de travail", + }, + pages: { + title: "Documentez tout — des notes aux PRD", + description: + "Les pages vous permettent de capturer et d'organiser des informations en un seul endroit. Rédigez des notes de réunion, de la documentation de projet et des PRD, intégrez des éléments de travail et structurez-les avec des composants prêts à l'emploi.", + cta_primary: "Créer votre première Page", + }, + archive_pages: { + title: "Aucune page archivée pour le moment", + description: "Archivez les pages qui ne sont pas sur votre radar. Accédez-y ici si nécessaire.", + }, + intake_sidebar: { + title: "Enregistrer les demandes d'Intake", + description: + "Soumettez de nouvelles demandes à examiner, prioriser et suivre dans le flux de travail de votre projet.", + cta_primary: "Créer une demande d'Intake", + }, + intake_main: { + title: "Sélectionnez un élément de travail Intake pour voir ses détails", + }, + }, + workspace: { + archive_work_items: { + title: "Aucun élément de travail archivé pour le moment", + description: + "Manuellement ou par automatisation, vous pouvez archiver des éléments de travail qui sont terminés ou annulés. Retrouvez-les ici une fois archivés.", + cta_primary: "Définir l'automatisation", + }, + archive_cycles: { + title: "Aucun cycle archivé pour le moment", + description: "Pour organiser votre projet, archivez les cycles terminés. Retrouvez-les ici une fois archivés.", + }, + archive_modules: { + title: "Aucun Module archivé pour le moment", + description: + "Pour organiser votre projet, archivez les modules terminés ou annulés. Retrouvez-les ici une fois archivés.", + }, + home_widget_quick_links: { + title: "Gardez les références, ressources ou documents importants à portée de main pour votre travail", + }, + inbox_sidebar_all: { + title: "Les mises à jour pour vos éléments de travail auxquels vous êtes abonné apparaîtront ici", + }, + inbox_sidebar_mentions: { + title: "Les mentions pour vos éléments de travail apparaîtront ici", + }, + your_work_by_priority: { + title: "Aucun élément de travail attribué pour le moment", + }, + your_work_by_state: { + title: "Aucun élément de travail attribué pour le moment", + }, + views: { + title: "Aucune vue pour le moment", + description: + "Ajoutez des éléments de travail à votre projet et utilisez les vues pour filtrer, trier et surveiller les progrès sans effort.", + cta_primary: "Ajouter un élément de travail", + }, + drafts: { + title: "Éléments de travail à moitié écrits", + description: + "Pour l'essayer, commencez à ajouter un élément de travail et laissez-le à mi-chemin ou créez votre premier brouillon ci-dessous. 😉", + cta_primary: "Créer un brouillon d'élément de travail", + }, + projects_archived: { + title: "Aucun projet archivé", + description: "On dirait que tous vos projets sont toujours actifs—excellent travail !", + }, + analytics_projects: { + title: "Créez des projets pour visualiser les métriques de projet ici.", + }, + analytics_work_items: { + title: + "Créez des projets avec des éléments de travail et des assignés pour commencer à suivre les performances, les progrès et l'impact de l'équipe ici.", + }, + analytics_no_cycle: { + title: + "Créez des cycles pour organiser le travail en phases délimitées dans le temps et suivre les progrès à travers les sprints.", + }, + analytics_no_module: { + title: "Créez des modules pour organiser votre travail et suivre les progrès à travers différentes étapes.", + }, + analytics_no_intake: { + title: "Configurez l'intake pour gérer les demandes entrantes et suivre comment elles sont acceptées et rejetées", + }, + }, + settings: { + estimates: { + title: "Aucune estimation pour le moment", + description: + "Définissez comment votre équipe mesure l'effort et suivez-le de manière cohérente sur tous les éléments de travail.", + cta_primary: "Ajouter un système d'estimation", + }, + labels: { + title: "Aucune étiquette pour le moment", + description: + "Créez des étiquettes personnalisées pour catégoriser et gérer efficacement vos éléments de travail.", + cta_primary: "Créer votre première étiquette", + }, + exports: { + title: "Aucune exportation pour le moment", + description: + "Vous n'avez aucun enregistrement d'exportation pour le moment. Une fois que vous exportez des données, tous les enregistrements apparaîtront ici.", + }, + tokens: { + title: "Aucun jeton personnel pour le moment", + description: + "Générez des jetons API sécurisés pour connecter votre espace de travail avec des systèmes et applications externes.", + cta_primary: "Ajouter un jeton API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/id/empty-state.ts b/packages/i18n/src/locales/id/empty-state.ts new file mode 100644 index 0000000000..c6238e184c --- /dev/null +++ b/packages/i18n/src/locales/id/empty-state.ts @@ -0,0 +1,185 @@ +export default { + common: { + progress: { + title: "Belum ada metrik progres untuk ditampilkan.", + description: "Mulai mengatur nilai properti dalam item kerja untuk melihat metrik progres di sini.", + }, + updates: { + title: "Belum ada pembaruan.", + description: "Setelah anggota proyek menambahkan pembaruan, itu akan muncul di sini", + }, + search: { + title: "Tidak ada hasil yang cocok.", + description: "Tidak ada hasil yang ditemukan. Coba sesuaikan istilah pencarian Anda.", + }, + not_found: { + title: "Ups! Ada yang salah", + description: "Kami tidak dapat mengambil akun Plane Anda saat ini. Ini mungkin kesalahan jaringan.", + cta_primary: "Coba muat ulang", + }, + server_error: { + title: "Kesalahan server", + description: + "Kami tidak dapat terhubung dan mengambil data dari server kami. Jangan khawatir, kami sedang menanganinya.", + cta_primary: "Coba muat ulang", + }, + }, + project: { + work_items: { + title: "Mulai dengan item kerja pertama Anda.", + description: + "Item kerja adalah blok bangunan proyek Anda — tetapkan pemilik, atur prioritas, dan lacak kemajuan dengan mudah.", + cta_primary: "Buat item kerja pertama Anda", + }, + cycles: { + title: "Kelompokkan dan batasi waktu pekerjaan Anda dalam Siklus.", + description: + "Pecah pekerjaan menjadi potongan dengan batas waktu, bekerja mundur dari tenggat proyek Anda untuk menetapkan tanggal, dan buat kemajuan nyata sebagai tim.", + cta_primary: "Atur siklus pertama Anda", + }, + cycle_work_items: { + title: "Tidak ada item kerja untuk ditampilkan dalam siklus ini", + description: + "Buat item kerja untuk mulai memantau kemajuan tim Anda dalam siklus ini dan capai tujuan Anda tepat waktu.", + cta_primary: "Buat item kerja", + cta_secondary: "Tambahkan item kerja yang ada", + }, + modules: { + title: "Petakan tujuan proyek Anda ke Modul dan lacak dengan mudah.", + description: + "Modul terdiri dari item kerja yang saling berhubungan. Mereka membantu dalam memantau kemajuan melalui fase proyek, masing-masing dengan tenggat waktu dan analitik khusus untuk menunjukkan seberapa dekat Anda dengan mencapai fase tersebut.", + cta_primary: "Atur modul pertama Anda", + }, + module_work_items: { + title: "Tidak ada item kerja untuk ditampilkan dalam Modul ini", + description: "Buat item kerja untuk mulai memantau modul ini.", + cta_primary: "Buat item kerja", + cta_secondary: "Tambahkan item kerja yang ada", + }, + views: { + title: "Simpan tampilan kustom untuk proyek Anda", + description: + "Tampilan adalah filter yang disimpan yang membantu Anda mengakses informasi yang paling sering Anda gunakan dengan cepat. Berkolaborasi dengan mudah saat rekan tim berbagi dan menyesuaikan tampilan dengan kebutuhan spesifik mereka.", + cta_primary: "Buat tampilan", + }, + no_work_items_in_project: { + title: "Belum ada item kerja dalam proyek", + description: + "Tambahkan item kerja ke proyek Anda dan potong pekerjaan Anda menjadi bagian yang dapat dilacak dengan tampilan.", + cta_primary: "Tambahkan item kerja", + }, + work_item_filter: { + title: "Tidak ada item kerja yang ditemukan", + description: "Filter Anda saat ini tidak mengembalikan hasil apapun. Coba ubah filter.", + cta_primary: "Tambahkan item kerja", + }, + pages: { + title: "Dokumentasikan segalanya — dari catatan hingga PRD", + description: + "Halaman memungkinkan Anda menangkap dan mengorganisir informasi di satu tempat. Tulis catatan rapat, dokumentasi proyek, dan PRD, sematkan item kerja, dan strukturkan dengan komponen siap pakai.", + cta_primary: "Buat Halaman pertama Anda", + }, + archive_pages: { + title: "Belum ada halaman yang diarsipkan", + description: "Arsipkan halaman yang tidak ada dalam radar Anda. Akses di sini saat dibutuhkan.", + }, + intake_sidebar: { + title: "Catat permintaan Masuk", + description: "Kirim permintaan baru untuk ditinjau, diprioritaskan, dan dilacak dalam alur kerja proyek Anda.", + cta_primary: "Buat permintaan Masuk", + }, + intake_main: { + title: "Pilih item kerja Masuk untuk melihat detailnya", + }, + }, + workspace: { + archive_work_items: { + title: "Belum ada item kerja yang diarsipkan", + description: + "Secara manual atau melalui otomasi, Anda dapat mengarsipkan item kerja yang selesai atau dibatalkan. Temukan di sini setelah diarsipkan.", + cta_primary: "Atur otomasi", + }, + archive_cycles: { + title: "Belum ada siklus yang diarsipkan", + description: + "Untuk merapikan proyek Anda, arsipkan siklus yang telah selesai. Temukan di sini setelah diarsipkan.", + }, + archive_modules: { + title: "Belum ada Modul yang diarsipkan", + description: + "Untuk merapikan proyek Anda, arsipkan modul yang selesai atau dibatalkan. Temukan di sini setelah diarsipkan.", + }, + home_widget_quick_links: { + title: "Simpan referensi penting, sumber daya, atau dokumen untuk pekerjaan Anda", + }, + inbox_sidebar_all: { + title: "Pembaruan untuk item kerja yang Anda langgani akan muncul di sini", + }, + inbox_sidebar_mentions: { + title: "Penyebutan untuk item kerja Anda akan muncul di sini", + }, + your_work_by_priority: { + title: "Belum ada item kerja yang ditugaskan", + }, + your_work_by_state: { + title: "Belum ada item kerja yang ditugaskan", + }, + views: { + title: "Belum ada Tampilan", + description: + "Tambahkan item kerja ke proyek Anda dan gunakan tampilan untuk memfilter, mengurutkan, dan memantau kemajuan dengan mudah.", + cta_primary: "Tambahkan item kerja", + }, + drafts: { + title: "Item kerja setengah jadi", + description: + "Untuk mencoba ini, mulai menambahkan item kerja dan tinggalkan di tengah jalan atau buat draf pertama Anda di bawah ini. 😉", + cta_primary: "Buat item kerja draf", + }, + projects_archived: { + title: "Tidak ada proyek yang diarsipkan", + description: "Sepertinya semua proyek Anda masih aktif—kerja bagus!", + }, + analytics_projects: { + title: "Buat proyek untuk memvisualisasikan metrik proyek di sini.", + }, + analytics_work_items: { + title: + "Buat proyek dengan item kerja dan penerima tugas untuk mulai melacak kinerja, kemajuan, dan dampak tim di sini.", + }, + analytics_no_cycle: { + title: + "Buat siklus untuk mengorganisir pekerjaan ke dalam fase berbatas waktu dan melacak kemajuan di seluruh sprint.", + }, + analytics_no_module: { + title: "Buat modul untuk mengorganisir pekerjaan Anda dan melacak kemajuan di berbagai tahap.", + }, + analytics_no_intake: { + title: "Siapkan masukan untuk mengelola permintaan masuk dan melacak bagaimana mereka diterima dan ditolak", + }, + }, + settings: { + estimates: { + title: "Belum ada estimasi", + description: "Tentukan bagaimana tim Anda mengukur upaya dan lacak secara konsisten di semua item kerja.", + cta_primary: "Tambahkan sistem estimasi", + }, + labels: { + title: "Belum ada label", + description: + "Buat label yang dipersonalisasi untuk mengkategorikan dan mengelola item kerja Anda secara efektif.", + cta_primary: "Buat label pertama Anda", + }, + exports: { + title: "Belum ada ekspor", + description: + "Anda tidak memiliki catatan ekspor saat ini. Setelah Anda mengekspor data, semua catatan akan muncul di sini.", + }, + tokens: { + title: "Belum ada token Pribadi", + description: + "Hasilkan token API yang aman untuk menghubungkan ruang kerja Anda dengan sistem dan aplikasi eksternal.", + cta_primary: "Tambahkan token API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/index.ts b/packages/i18n/src/locales/index.ts index 0bdf18a64b..50188889ef 100644 --- a/packages/i18n/src/locales/index.ts +++ b/packages/i18n/src/locales/index.ts @@ -3,6 +3,7 @@ export { default as enCore } from "./en/core"; export { default as enTranslations } from "./en/translations"; export { default as enAccessibility } from "./en/accessibility"; export { default as enEditor } from "./en/editor"; +export { default as enEmptyState } from "./en/empty-state"; // Export locale data for all supported languages export const locales = { @@ -11,95 +12,114 @@ export const locales = { translations: () => import("./en/translations"), accessibility: () => import("./en/accessibility"), editor: () => import("./en/editor"), + emptyState: () => import("./en/empty-state"), }, fr: { translations: () => import("./fr/translations"), accessibility: () => import("./fr/accessibility"), editor: () => import("./fr/editor"), + emptyState: () => import("./fr/empty-state"), }, es: { translations: () => import("./es/translations"), accessibility: () => import("./es/accessibility"), editor: () => import("./es/editor"), + emptyState: () => import("./es/empty-state"), }, ja: { translations: () => import("./ja/translations"), accessibility: () => import("./ja/accessibility"), editor: () => import("./ja/editor"), + emptyState: () => import("./ja/empty-state"), }, "zh-CN": { translations: () => import("./zh-CN/translations"), accessibility: () => import("./zh-CN/accessibility"), editor: () => import("./zh-CN/editor"), + emptyState: () => import("./zh-CN/empty-state"), }, "zh-TW": { translations: () => import("./zh-TW/translations"), accessibility: () => import("./zh-TW/accessibility"), editor: () => import("./zh-TW/editor"), + emptyState: () => import("./zh-TW/empty-state"), }, ru: { translations: () => import("./ru/translations"), accessibility: () => import("./ru/accessibility"), editor: () => import("./ru/editor"), + emptyState: () => import("./ru/empty-state"), }, it: { translations: () => import("./it/translations"), accessibility: () => import("./it/accessibility"), editor: () => import("./it/editor"), + emptyState: () => import("./it/empty-state"), }, cs: { translations: () => import("./cs/translations"), accessibility: () => import("./cs/accessibility"), editor: () => import("./cs/editor"), + emptyState: () => import("./cs/empty-state"), }, sk: { translations: () => import("./sk/translations"), accessibility: () => import("./sk/accessibility"), editor: () => import("./sk/editor"), + emptyState: () => import("./sk/empty-state"), }, de: { translations: () => import("./de/translations"), accessibility: () => import("./de/accessibility"), editor: () => import("./de/editor"), + emptyState: () => import("./de/empty-state"), }, ua: { translations: () => import("./ua/translations"), accessibility: () => import("./ua/accessibility"), editor: () => import("./ua/editor"), + emptyState: () => import("./ua/empty-state"), }, pl: { translations: () => import("./pl/translations"), accessibility: () => import("./pl/accessibility"), editor: () => import("./pl/editor"), + emptyState: () => import("./pl/empty-state"), }, ko: { translations: () => import("./ko/translations"), accessibility: () => import("./ko/accessibility"), editor: () => import("./ko/editor"), + emptyState: () => import("./ko/empty-state"), }, "pt-BR": { translations: () => import("./pt-BR/translations"), accessibility: () => import("./pt-BR/accessibility"), editor: () => import("./pt-BR/editor"), + emptyState: () => import("./pt-BR/empty-state"), }, id: { translations: () => import("./id/translations"), accessibility: () => import("./id/accessibility"), editor: () => import("./id/editor"), + emptyState: () => import("./id/empty-state"), }, ro: { translations: () => import("./ro/translations"), accessibility: () => import("./ro/accessibility"), editor: () => import("./ro/editor"), + emptyState: () => import("./ro/empty-state"), }, "vi-VN": { translations: () => import("./vi-VN/translations"), accessibility: () => import("./vi-VN/accessibility"), editor: () => import("./vi-VN/editor"), + emptyState: () => import("./vi-VN/empty-state"), }, "tr-TR": { translations: () => import("./tr-TR/translations"), accessibility: () => import("./tr-TR/accessibility"), editor: () => import("./tr-TR/editor"), + emptyState: () => import("./tr-TR/empty-state"), }, }; diff --git a/packages/i18n/src/locales/it/empty-state.ts b/packages/i18n/src/locales/it/empty-state.ts new file mode 100644 index 0000000000..3417eab8d9 --- /dev/null +++ b/packages/i18n/src/locales/it/empty-state.ts @@ -0,0 +1,185 @@ +export default { + common: { + progress: { + title: "Non ci sono ancora metriche di progresso da mostrare.", + description: + "Inizia a impostare i valori delle proprietà negli elementi di lavoro per vedere qui le metriche di progresso.", + }, + updates: { + title: "Nessun aggiornamento ancora.", + description: "Una volta che i membri del progetto aggiungono aggiornamenti, appariranno qui", + }, + search: { + title: "Nessun risultato corrispondente.", + description: "Nessun risultato trovato. Prova a modificare i termini di ricerca.", + }, + not_found: { + title: "Oops! Qualcosa sembra andare storto", + description: + "Al momento non riusciamo a recuperare il tuo account plane. Potrebbe trattarsi di un errore di rete.", + cta_primary: "Prova a ricaricare", + }, + server_error: { + title: "Errore del server", + description: + "Non riusciamo a connetterci e recuperare dati dal nostro server. Non preoccuparti, ci stiamo lavorando.", + cta_primary: "Prova a ricaricare", + }, + }, + project: { + work_items: { + title: "Inizia con il tuo primo elemento di lavoro.", + description: + "Gli elementi di lavoro sono i mattoni del tuo progetto — assegna proprietari, imposta priorità e traccia facilmente i progressi.", + cta_primary: "Crea il tuo primo elemento di lavoro", + }, + cycles: { + title: "Raggruppa e delimita temporalmente il tuo lavoro in Cicli.", + description: + "Suddividi il lavoro in blocchi temporali, lavora a ritroso dalla scadenza del progetto per impostare le date e fai progressi tangibili come team.", + cta_primary: "Imposta il tuo primo ciclo", + }, + cycle_work_items: { + title: "Nessun elemento di lavoro da mostrare in questo ciclo", + description: + "Crea elementi di lavoro per iniziare a monitorare il progresso del tuo team in questo ciclo e raggiungere i tuoi obiettivi in tempo.", + cta_primary: "Crea elemento di lavoro", + cta_secondary: "Aggiungi elemento di lavoro esistente", + }, + modules: { + title: "Mappa gli obiettivi del tuo progetto ai Moduli e traccia facilmente.", + description: + "I moduli sono costituiti da elementi di lavoro interconnessi. Aiutano a monitorare i progressi attraverso le fasi del progetto, ciascuna con scadenze specifiche e analitiche per indicare quanto sei vicino al raggiungimento di quelle fasi.", + cta_primary: "Imposta il tuo primo modulo", + }, + module_work_items: { + title: "Nessun elemento di lavoro da mostrare in questo Modulo", + description: "Crea elementi di lavoro per iniziare a monitorare questo modulo.", + cta_primary: "Crea elemento di lavoro", + cta_secondary: "Aggiungi elemento di lavoro esistente", + }, + views: { + title: "Salva viste personalizzate per il tuo progetto", + description: + "Le viste sono filtri salvati che ti aiutano ad accedere rapidamente alle informazioni che usi di più. Collabora senza sforzo mentre i colleghi condividono e personalizzano le viste secondo le loro esigenze specifiche.", + cta_primary: "Crea vista", + }, + no_work_items_in_project: { + title: "Nessun elemento di lavoro nel progetto ancora", + description: + "Aggiungi elementi di lavoro al tuo progetto e suddividi il lavoro in pezzi tracciabili con le viste.", + cta_primary: "Aggiungi elemento di lavoro", + }, + work_item_filter: { + title: "Nessun elemento di lavoro trovato", + description: "Il filtro attuale non ha restituito risultati. Prova a modificare i filtri.", + cta_primary: "Aggiungi elemento di lavoro", + }, + pages: { + title: "Documenta tutto — dalle note ai PRD", + description: + "Le pagine ti permettono di catturare e organizzare informazioni in un unico posto. Scrivi note di riunioni, documentazione di progetto e PRD, incorpora elementi di lavoro e strutturali con componenti pronti all'uso.", + cta_primary: "Crea la tua prima Pagina", + }, + archive_pages: { + title: "Nessuna pagina archiviata ancora", + description: "Archivia le pagine non nel tuo radar. Accedi a esse qui quando necessario.", + }, + intake_sidebar: { + title: "Registra richieste di Intake", + description: + "Invia nuove richieste da rivedere, dare priorità e tracciare all'interno del flusso di lavoro del tuo progetto.", + cta_primary: "Crea richiesta di Intake", + }, + intake_main: { + title: "Seleziona un elemento di lavoro di Intake per visualizzarne i dettagli", + }, + }, + workspace: { + archive_work_items: { + title: "Nessun elemento di lavoro archiviato ancora", + description: + "Manualmente o tramite automazione, puoi archiviare elementi di lavoro completati o annullati. Trovali qui una volta archiviati.", + cta_primary: "Imposta automazione", + }, + archive_cycles: { + title: "Nessun ciclo archiviato ancora", + description: "Per riordinare il tuo progetto, archivia i cicli completati. Trovali qui una volta archiviati.", + }, + archive_modules: { + title: "Nessun Modulo archiviato ancora", + description: + "Per riordinare il tuo progetto, archivia i moduli completati o annullati. Trovali qui una volta archiviati.", + }, + home_widget_quick_links: { + title: "Mantieni a portata di mano riferimenti importanti, risorse o documenti per il tuo lavoro", + }, + inbox_sidebar_all: { + title: "Gli aggiornamenti per i tuoi elementi di lavoro sottoscritti appariranno qui", + }, + inbox_sidebar_mentions: { + title: "Le menzioni per i tuoi elementi di lavoro appariranno qui", + }, + your_work_by_priority: { + title: "Nessun elemento di lavoro assegnato ancora", + }, + your_work_by_state: { + title: "Nessun elemento di lavoro assegnato ancora", + }, + views: { + title: "Nessuna Vista ancora", + description: + "Aggiungi elementi di lavoro al tuo progetto e usa le viste per filtrare, ordinare e monitorare i progressi senza sforzo.", + cta_primary: "Aggiungi elemento di lavoro", + }, + drafts: { + title: "Elementi di lavoro semi-scritti", + description: + "Per provare questo, inizia ad aggiungere un elemento di lavoro e lascialo a metà o crea la tua prima bozza qui sotto. 😉", + cta_primary: "Crea elemento di lavoro bozza", + }, + projects_archived: { + title: "Nessun progetto archiviato", + description: "Sembra che tutti i tuoi progetti siano ancora attivi—ottimo lavoro!", + }, + analytics_projects: { + title: "Crea progetti per visualizzare qui le metriche del progetto.", + }, + analytics_work_items: { + title: + "Crea progetti con elementi di lavoro e assegnatari per iniziare a tracciare prestazioni, progressi e impatto del team qui.", + }, + analytics_no_cycle: { + title: "Crea cicli per organizzare il lavoro in fasi temporali e tracciare i progressi attraverso gli sprint.", + }, + analytics_no_module: { + title: "Crea moduli per organizzare il tuo lavoro e tracciare i progressi attraverso diverse fasi.", + }, + analytics_no_intake: { + title: "Imposta intake per gestire le richieste in arrivo e tracciare come vengono accettate e rifiutate", + }, + }, + settings: { + estimates: { + title: "Nessuna stima ancora", + description: + "Definisci come il tuo team misura lo sforzo e traccialo in modo coerente su tutti gli elementi di lavoro.", + cta_primary: "Aggiungi sistema di stima", + }, + labels: { + title: "Nessuna etichetta ancora", + description: "Crea etichette personalizzate per categorizzare e gestire efficacemente i tuoi elementi di lavoro.", + cta_primary: "Crea la tua prima etichetta", + }, + exports: { + title: "Nessuna esportazione ancora", + description: + "Al momento non hai record di esportazione. Una volta esportati i dati, tutti i record appariranno qui.", + }, + tokens: { + title: "Nessun token personale ancora", + description: "Genera token API sicuri per connettere il tuo workspace con sistemi e applicazioni esterne.", + cta_primary: "Aggiungi token API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/ja/empty-state.ts b/packages/i18n/src/locales/ja/empty-state.ts new file mode 100644 index 0000000000..90a3af7e1f --- /dev/null +++ b/packages/i18n/src/locales/ja/empty-state.ts @@ -0,0 +1,175 @@ +export default { + common: { + progress: { + title: "表示する進捗メトリクスがまだありません。", + description: "作業項目にプロパティ値を設定して、ここに進捗メトリクスを表示します。", + }, + updates: { + title: "更新はまだありません。", + description: "プロジェクトメンバーが更新を追加すると、ここに表示されます", + }, + search: { + title: "一致する結果が見つかりません。", + description: "結果が見つかりませんでした。検索条件を調整してください。", + }, + not_found: { + title: "おっと!何か問題があるようです", + description: "現在、Planeアカウントを取得できません。ネットワークエラーの可能性があります。", + cta_primary: "再読み込みを試す", + }, + server_error: { + title: "サーバーエラー", + description: "サーバーに接続してデータを取得できません。ご心配なく、対応中です。", + cta_primary: "再読み込みを試す", + }, + }, + project: { + work_items: { + title: "最初の作業項目から始めましょう。", + description: + "作業項目はプロジェクトの構成要素です — 担当者の割り当て、優先度の設定、進捗の追跡が簡単に行えます。", + cta_primary: "最初の作業項目を作成", + }, + cycles: { + title: "サイクルで作業をグループ化してタイムボックス化します。", + description: + "作業をタイムボックスで区切り、プロジェクトの締め切りから逆算して日付を設定し、チームとして具体的な進捗を達成します。", + cta_primary: "最初のサイクルを設定", + }, + cycle_work_items: { + title: "このサイクルに表示する作業項目はありません", + description: "作業項目を作成して、このサイクルでチームの進捗を監視し、目標を時間内に達成しましょう。", + cta_primary: "作業項目を作成", + cta_secondary: "既存の作業項目を追加", + }, + modules: { + title: "プロジェクトの目標をモジュールにマッピングして簡単に追跡します。", + description: + "モジュールは相互接続された作業項目で構成されています。プロジェクトフェーズを通じた進捗の監視を支援し、それぞれに特定の締め切りと分析があり、それらのフェーズをどれだけ達成に近づいているかを示します。", + cta_primary: "最初のモジュールを設定", + }, + module_work_items: { + title: "このモジュールに表示する作業項目はありません", + description: "作業項目を作成して、このモジュールの監視を開始します。", + cta_primary: "作業項目を作成", + cta_secondary: "既存の作業項目を追加", + }, + views: { + title: "プロジェクトのカスタムビューを保存", + description: + "ビューは保存されたフィルターで、最も頻繁に使用する情報に素早くアクセスできます。チームメイトがビューを共有し、それぞれのニーズに合わせて調整することで、簡単に協力できます。", + cta_primary: "ビューを作成", + }, + no_work_items_in_project: { + title: "プロジェクトにはまだ作業項目がありません", + description: "プロジェクトに作業項目を追加し、ビューを使用して作業を追跡可能な部分に分割します。", + cta_primary: "作業項目を追加", + }, + work_item_filter: { + title: "作業項目が見つかりません", + description: "現在のフィルターでは結果が返されませんでした。フィルターを変更してみてください。", + cta_primary: "作業項目を追加", + }, + pages: { + title: "メモからPRDまで、すべてを文書化", + description: + "ページを使用すると、情報を1か所でキャプチャして整理できます。会議のメモ、プロジェクトドキュメント、PRDを作成し、作業項目を埋め込み、すぐに使えるコンポーネントで構造化します。", + cta_primary: "最初のページを作成", + }, + archive_pages: { + title: "アーカイブされたページはまだありません", + description: "注目していないページをアーカイブします。必要に応じてここでアクセスできます。", + }, + intake_sidebar: { + title: "インテークリクエストを記録", + description: "新しいリクエストを送信して、プロジェクトのワークフロー内でレビュー、優先順位付け、追跡を行います。", + cta_primary: "インテークリクエストを作成", + }, + intake_main: { + title: "インテーク作業項目を選択して詳細を表示", + }, + }, + workspace: { + archive_work_items: { + title: "アーカイブされた作業項目はまだありません", + description: + "手動または自動化により、完了またはキャンセルされた作業項目をアーカイブできます。アーカイブされると、ここで見つけられます。", + cta_primary: "自動化を設定", + }, + archive_cycles: { + title: "アーカイブされたサイクルはまだありません", + description: + "プロジェクトを整理するために、完了したサイクルをアーカイブします。アーカイブされると、ここで見つけられます。", + }, + archive_modules: { + title: "アーカイブされたモジュールはまだありません", + description: + "プロジェクトを整理するために、完了またはキャンセルされたモジュールをアーカイブします。アーカイブされると、ここで見つけられます。", + }, + home_widget_quick_links: { + title: "作業に重要な参照、リソース、またはドキュメントを手元に保管", + }, + inbox_sidebar_all: { + title: "購読している作業項目の更新がここに表示されます", + }, + inbox_sidebar_mentions: { + title: "作業項目でのメンションがここに表示されます", + }, + your_work_by_priority: { + title: "割り当てられた作業項目はまだありません", + }, + your_work_by_state: { + title: "割り当てられた作業項目はまだありません", + }, + views: { + title: "ビューはまだありません", + description: "プロジェクトに作業項目を追加し、ビューを使用してフィルター、ソート、進捗の監視を簡単に行います。", + cta_primary: "作業項目を追加", + }, + drafts: { + title: "途中の作業項目", + description: "これを試すには、作業項目の追加を開始して途中で離れるか、以下で最初の下書きを作成してください。😉", + cta_primary: "下書き作業項目を作成", + }, + projects_archived: { + title: "アーカイブされたプロジェクトはありません", + description: "すべてのプロジェクトがまだアクティブです — 素晴らしい!", + }, + analytics_projects: { + title: "プロジェクトを作成して、ここでプロジェクトメトリクスを視覚化します。", + }, + analytics_work_items: { + title: "作業項目と担当者を含むプロジェクトを作成して、パフォーマンス、進捗、チームの影響をここで追跡開始します。", + }, + analytics_no_cycle: { + title: "サイクルを作成して、作業を期限付きフェーズに整理し、スプリント全体の進捗を追跡します。", + }, + analytics_no_module: { + title: "モジュールを作成して、作業を整理し、さまざまな段階での進捗を追跡します。", + }, + analytics_no_intake: { + title: "インテークを設定して、受信リクエストを管理し、承認と拒否を追跡します", + }, + }, + settings: { + estimates: { + title: "まだ見積もりはありません", + description: "チームが労力をどのように測定するかを定義し、すべての作業項目で一貫して追跡します。", + cta_primary: "見積もりシステムを追加", + }, + labels: { + title: "まだラベルはありません", + description: "作業項目を効果的に分類および管理するためのパーソナライズされたラベルを作成します。", + cta_primary: "最初のラベルを作成", + }, + exports: { + title: "まだエクスポートはありません", + description: "現在、エクスポート記録はありません。データをエクスポートすると、すべての記録がここに表示されます。", + }, + tokens: { + title: "まだ個人トークンはありません", + description: "ワークスペースを外部システムおよびアプリケーションと接続するための安全なAPIトークンを生成します。", + cta_primary: "APIトークンを追加", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/ko/empty-state.ts b/packages/i18n/src/locales/ko/empty-state.ts new file mode 100644 index 0000000000..c85b87e2fa --- /dev/null +++ b/packages/i18n/src/locales/ko/empty-state.ts @@ -0,0 +1,174 @@ +export default { + common: { + progress: { + title: "아직 표시할 진행 지표가 없습니다.", + description: "작업 항목에서 속성 값을 설정하여 여기에서 진행 지표를 확인하세요.", + }, + updates: { + title: "아직 업데이트가 없습니다.", + description: "프로젝트 멤버가 업데이트를 추가하면 여기에 표시됩니다", + }, + search: { + title: "일치하는 결과가 없습니다.", + description: "결과를 찾을 수 없습니다. 검색어를 조정해 보세요.", + }, + not_found: { + title: "앗! 문제가 발생한 것 같습니다", + description: "현재 Plane 계정을 가져올 수 없습니다. 네트워크 오류일 수 있습니다.", + cta_primary: "다시 로드 시도", + }, + server_error: { + title: "서버 오류", + description: "서버에 연결하여 데이터를 가져올 수 없습니다. 걱정하지 마세요, 작업 중입니다.", + cta_primary: "다시 로드 시도", + }, + }, + project: { + work_items: { + title: "첫 번째 작업 항목으로 시작하세요.", + description: + "작업 항목은 프로젝트의 구성 요소입니다. 소유자를 할당하고 우선순위를 설정하며 진행 상황을 쉽게 추적할 수 있습니다.", + cta_primary: "첫 번째 작업 항목 생성", + }, + cycles: { + title: "사이클로 작업을 그룹화하고 시간을 정하세요.", + description: + "시간 제한이 있는 단위로 작업을 나누고, 프로젝트 마감일로부터 역으로 날짜를 설정하며, 팀으로서 구체적인 진전을 이루세요.", + cta_primary: "첫 번째 사이클 설정", + }, + cycle_work_items: { + title: "이 사이클에 표시할 작업 항목이 없습니다", + description: "작업 항목을 생성하여 이 사이클 동안 팀의 진행 상황을 모니터링하고 제시간에 목표를 달성하세요.", + cta_primary: "작업 항목 생성", + cta_secondary: "기존 작업 항목 추가", + }, + modules: { + title: "프로젝트 목표를 모듈에 매핑하고 쉽게 추적하세요.", + description: + "모듈은 상호 연결된 작업 항목으로 구성됩니다. 특정 기한과 분석을 통해 프로젝트 단계를 통한 진행 상황을 모니터링하여 해당 단계 달성에 얼마나 가까운지 나타냅니다.", + cta_primary: "첫 번째 모듈 설정", + }, + module_work_items: { + title: "이 모듈에 표시할 작업 항목이 없습니다", + description: "작업 항목을 생성하여 이 모듈을 모니터링하기 시작하세요.", + cta_primary: "작업 항목 생성", + cta_secondary: "기존 작업 항목 추가", + }, + views: { + title: "프로젝트를 위한 사용자 정의 보기 저장", + description: + "보기는 가장 자주 사용하는 정보에 빠르게 액세스하는 데 도움이 되는 저장된 필터입니다. 팀원들이 특정 요구 사항에 맞게 보기를 공유하고 조정하면서 손쉽게 협업하세요.", + cta_primary: "보기 생성", + }, + no_work_items_in_project: { + title: "프로젝트에 아직 작업 항목이 없습니다", + description: "프로젝트에 작업 항목을 추가하고 보기를 사용하여 작업을 추적 가능한 조각으로 나누세요.", + cta_primary: "작업 항목 추가", + }, + work_item_filter: { + title: "작업 항목을 찾을 수 없습니다", + description: "현재 필터가 결과를 반환하지 않았습니다. 필터를 변경해 보세요.", + cta_primary: "작업 항목 추가", + }, + pages: { + title: "메모부터 PRD까지 모든 것을 문서화하세요", + description: + "페이지를 사용하면 정보를 한 곳에서 캡처하고 구성할 수 있습니다. 회의록, 프로젝트 문서 및 PRD를 작성하고, 작업 항목을 삽입하며, 바로 사용할 수 있는 구성 요소로 구조화하세요.", + cta_primary: "첫 번째 페이지 생성", + }, + archive_pages: { + title: "아직 보관된 페이지가 없습니다", + description: "주목하지 않는 페이지를 보관하세요. 필요할 때 여기에서 액세스하세요.", + }, + intake_sidebar: { + title: "접수 요청 기록", + description: "프로젝트 워크플로우 내에서 검토, 우선순위 지정 및 추적할 새로운 요청을 제출하세요.", + cta_primary: "접수 요청 생성", + }, + intake_main: { + title: "접수 작업 항목을 선택하여 세부 정보 보기", + }, + }, + workspace: { + archive_work_items: { + title: "아직 보관된 작업 항목이 없습니다", + description: + "수동으로 또는 자동화를 통해 완료되거나 취소된 작업 항목을 보관할 수 있습니다. 보관되면 여기에서 찾을 수 있습니다.", + cta_primary: "자동화 설정", + }, + archive_cycles: { + title: "아직 보관된 사이클이 없습니다", + description: "프로젝트를 정리하려면 완료된 사이클을 보관하세요. 보관되면 여기에서 찾을 수 있습니다.", + }, + archive_modules: { + title: "아직 보관된 모듈이 없습니다", + description: "프로젝트를 정리하려면 완료되거나 취소된 모듈을 보관하세요. 보관되면 여기에서 찾을 수 있습니다.", + }, + home_widget_quick_links: { + title: "작업에 편리한 중요한 참조 자료, 리소스 또는 문서 보관", + }, + inbox_sidebar_all: { + title: "구독한 작업 항목에 대한 업데이트가 여기에 표시됩니다", + }, + inbox_sidebar_mentions: { + title: "작업 항목에 대한 언급이 여기에 표시됩니다", + }, + your_work_by_priority: { + title: "아직 할당된 작업 항목이 없습니다", + }, + your_work_by_state: { + title: "아직 할당된 작업 항목이 없습니다", + }, + views: { + title: "아직 보기가 없습니다", + description: "프로젝트에 작업 항목을 추가하고 보기를 사용하여 쉽게 필터링, 정렬 및 진행 상황을 모니터링하세요.", + cta_primary: "작업 항목 추가", + }, + drafts: { + title: "작성 중인 작업 항목", + description: "이를 시도하려면 작업 항목 추가를 시작하고 중간에 남겨두거나 아래에 첫 번째 초안을 만드세요. 😉", + cta_primary: "초안 작업 항목 생성", + }, + projects_archived: { + title: "보관된 프로젝트가 없습니다", + description: "모든 프로젝트가 여전히 활성 상태인 것 같습니다. 잘하셨습니다!", + }, + analytics_projects: { + title: "여기에서 프로젝트 지표를 시각화하려면 프로젝트를 생성하세요.", + }, + analytics_work_items: { + title: + "작업 항목 및 담당자가 있는 프로젝트를 생성하여 여기에서 성과, 진행 상황 및 팀 영향을 추적하기 시작하세요.", + }, + analytics_no_cycle: { + title: "사이클을 생성하여 작업을 시간 제한 단계로 구성하고 스프린트 전반에 걸쳐 진행 상황을 추적하세요.", + }, + analytics_no_module: { + title: "모듈을 생성하여 작업을 구성하고 다양한 단계에서 진행 상황을 추적하세요.", + }, + analytics_no_intake: { + title: "접수를 설정하여 들어오는 요청을 관리하고 승인 및 거부 방법을 추적하세요", + }, + }, + settings: { + estimates: { + title: "아직 추정치가 없습니다", + description: "팀이 노력을 측정하는 방법을 정의하고 모든 작업 항목에서 일관되게 추적하세요.", + cta_primary: "추정 시스템 추가", + }, + labels: { + title: "아직 레이블이 없습니다", + description: "작업 항목을 효과적으로 분류하고 관리하기 위한 개인화된 레이블을 만드세요.", + cta_primary: "첫 번째 레이블 생성", + }, + exports: { + title: "아직 내보내기가 없습니다", + description: "현재 내보내기 기록이 없습니다. 데이터를 내보내면 모든 기록이 여기에 표시됩니다.", + }, + tokens: { + title: "아직 개인 토큰이 없습니다", + description: "작업 공간을 외부 시스템 및 애플리케이션과 연결하기 위한 보안 API 토큰을 생성하세요.", + cta_primary: "API 토큰 추가", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/pl/empty-state.ts b/packages/i18n/src/locales/pl/empty-state.ts new file mode 100644 index 0000000000..0fe9c9fb49 --- /dev/null +++ b/packages/i18n/src/locales/pl/empty-state.ts @@ -0,0 +1,186 @@ +export default { + common: { + progress: { + title: "Nie ma jeszcze metryk postępu do wyświetlenia.", + description: "Zacznij ustawiać wartości właściwości w elementach roboczych, aby zobaczyć tutaj metryki postępu.", + }, + updates: { + title: "Jeszcze brak aktualizacji.", + description: "Gdy członkowie projektu dodadzą aktualizacje, pojawią się one tutaj", + }, + search: { + title: "Brak pasujących wyników.", + description: "Nie znaleziono wyników. Spróbuj dostosować wyszukiwane hasła.", + }, + not_found: { + title: "Ups! Coś wydaje się nie tak", + description: "Obecnie nie możemy pobrać Twojego konta plane. Może to być błąd sieci.", + cta_primary: "Spróbuj przeładować", + }, + server_error: { + title: "Błąd serwera", + description: "Nie możemy się połączyć i pobrać danych z naszego serwera. Nie martw się, pracujemy nad tym.", + cta_primary: "Spróbuj przeładować", + }, + }, + project: { + work_items: { + title: "Zacznij od swojego pierwszego elementu roboczego.", + description: + "Elementy robocze są podstawowymi elementami Twojego projektu — przypisuj właścicieli, ustalaj priorytety i łatwo śledź postęp.", + cta_primary: "Utwórz swój pierwszy element roboczy", + }, + cycles: { + title: "Grupuj i ograniczaj czasowo swoją pracę w Cyklach.", + description: + "Podziel pracę na bloki czasowe, pracuj wstecz od terminu projektu, aby ustalić daty, i osiągaj wymierny postęp jako zespół.", + cta_primary: "Ustaw swój pierwszy cykl", + }, + cycle_work_items: { + title: "Brak elementów roboczych do wyświetlenia w tym cyklu", + description: + "Utwórz elementy robocze, aby rozpocząć monitorowanie postępów Twojego zespołu w tym cyklu i osiągnąć swoje cele na czas.", + cta_primary: "Utwórz element roboczy", + cta_secondary: "Dodaj istniejący element roboczy", + }, + modules: { + title: "Mapuj cele swojego projektu na Moduły i łatwo śledź.", + description: + "Moduły składają się z połączonych elementów roboczych. Pomagają one monitorować postęp przez fazy projektu, każda z konkretnymi terminami i analityką, aby wskazać, jak blisko jesteś osiągnięcia tych faz.", + cta_primary: "Ustaw swój pierwszy moduł", + }, + module_work_items: { + title: "Brak elementów roboczych do wyświetlenia w tym Module", + description: "Utwórz elementy robocze, aby rozpocząć monitorowanie tego modułu.", + cta_primary: "Utwórz element roboczy", + cta_secondary: "Dodaj istniejący element roboczy", + }, + views: { + title: "Zapisz niestandardowe widoki dla swojego projektu", + description: + "Widoki to zapisane filtry, które pomagają szybko uzyskać dostęp do najczęściej używanych informacji. Współpracuj bez wysiłku, gdy członkowie zespołu udostępniają i dostosowują widoki do swoich konkretnych potrzeb.", + cta_primary: "Utwórz widok", + }, + no_work_items_in_project: { + title: "Brak elementów roboczych w projekcie jeszcze", + description: + "Dodaj elementy robocze do swojego projektu i podziel swoją pracę na śledzone części za pomocą widoków.", + cta_primary: "Dodaj element roboczy", + }, + work_item_filter: { + title: "Nie znaleziono elementów roboczych", + description: "Twój aktualny filtr nie zwrócił żadnych wyników. Spróbuj zmienić filtry.", + cta_primary: "Dodaj element roboczy", + }, + pages: { + title: "Dokumentuj wszystko — od notatek po PRD", + description: + "Strony pozwalają przechwytywać i organizować informacje w jednym miejscu. Pisz notatki ze spotkań, dokumentację projektu i PRD, osadzaj elementy robocze i strukturyzuj je za pomocą gotowych komponentów.", + cta_primary: "Utwórz swoją pierwszą Stronę", + }, + archive_pages: { + title: "Jeszcze brak zarchiwizowanych stron", + description: + "Archiwizuj strony, które nie są na Twoim radarze. Uzyskaj do nich dostęp tutaj, gdy będzie to potrzebne.", + }, + intake_sidebar: { + title: "Rejestruj zgłoszenia przyjmowane", + description: + "Przesyłaj nowe zgłoszenia do przeglądu, ustalania priorytetów i śledzenia w ramach przepływu pracy Twojego projektu.", + cta_primary: "Utwórz zgłoszenie przyjmowane", + }, + intake_main: { + title: "Wybierz element roboczy Intake, aby wyświetlić jego szczegóły", + }, + }, + workspace: { + archive_work_items: { + title: "Jeszcze brak zarchiwizowanych elementów roboczych", + description: + "Ręcznie lub za pomocą automatyzacji możesz archiwizować ukończone lub anulowane elementy robocze. Znajdź je tutaj po zarchiwizowaniu.", + cta_primary: "Ustaw automatyzację", + }, + archive_cycles: { + title: "Jeszcze brak zarchiwizowanych cykli", + description: "Aby uporządkować swój projekt, archiwizuj ukończone cykle. Znajdź je tutaj po zarchiwizowaniu.", + }, + archive_modules: { + title: "Jeszcze brak zarchiwizowanych Modułów", + description: + "Aby uporządkować swój projekt, archiwizuj ukończone lub anulowane moduły. Znajdź je tutaj po zarchiwizowaniu.", + }, + home_widget_quick_links: { + title: "Miej pod ręką ważne odniesienia, zasoby lub dokumenty do swojej pracy", + }, + inbox_sidebar_all: { + title: "Aktualizacje dla Twoich subskrybowanych elementów roboczych pojawią się tutaj", + }, + inbox_sidebar_mentions: { + title: "Wzmianki dotyczące Twoich elementów roboczych pojawią się tutaj", + }, + your_work_by_priority: { + title: "Jeszcze nie przypisano elementu roboczego", + }, + your_work_by_state: { + title: "Jeszcze nie przypisano elementu roboczego", + }, + views: { + title: "Jeszcze brak Widoków", + description: + "Dodaj elementy robocze do swojego projektu i używaj widoków do filtrowania, sortowania i monitorowania postępów bez wysiłku.", + cta_primary: "Dodaj element roboczy", + }, + drafts: { + title: "Półnapisane elementy robocze", + description: + "Aby to wypróbować, zacznij dodawać element roboczy i zostaw go w połowie lub utwórz swój pierwszy szkic poniżej. 😉", + cta_primary: "Utwórz szkic elementu roboczego", + }, + projects_archived: { + title: "Brak zarchiwizowanych projektów", + description: "Wygląda na to, że wszystkie Twoje projekty są nadal aktywne—świetna robota!", + }, + analytics_projects: { + title: "Utwórz projekty, aby wizualizować metryki projektu tutaj.", + }, + analytics_work_items: { + title: + "Utwórz projekty z elementami roboczymi i osobami przypisanymi, aby rozpocząć śledzenie wydajności, postępów i wpływu zespołu tutaj.", + }, + analytics_no_cycle: { + title: "Utwórz cykle, aby organizować pracę w fazy czasowe i śledzić postępy przez sprinty.", + }, + analytics_no_module: { + title: "Utwórz moduły, aby organizować swoją pracę i śledzić postępy przez różne fazy.", + }, + analytics_no_intake: { + title: + "Skonfiguruj przyjmowanie, aby zarządzać przychodzącymi zgłoszeniami i śledzić, jak są akceptowane i odrzucane", + }, + }, + settings: { + estimates: { + title: "Jeszcze brak szacunków", + description: + "Zdefiniuj, jak Twój zespół mierzy wysiłek i śledź to konsekwentnie we wszystkich elementach roboczych.", + cta_primary: "Dodaj system szacowania", + }, + labels: { + title: "Jeszcze brak etykiet", + description: + "Twórz spersonalizowane etykiety, aby skutecznie kategoryzować i zarządzać swoimi elementami roboczymi.", + cta_primary: "Utwórz swoją pierwszą etykietę", + }, + exports: { + title: "Jeszcze brak eksportów", + description: + "Obecnie nie masz żadnych rekordów eksportu. Po wyeksportowaniu danych wszystkie rekordy pojawią się tutaj.", + }, + tokens: { + title: "Jeszcze brak Tokenu osobistego", + description: + "Generuj bezpieczne tokeny API, aby połączyć swój obszar roboczy z zewnętrznymi systemami i aplikacjami.", + cta_primary: "Dodaj token API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/pt-BR/empty-state.ts b/packages/i18n/src/locales/pt-BR/empty-state.ts new file mode 100644 index 0000000000..6c3ebc94ad --- /dev/null +++ b/packages/i18n/src/locales/pt-BR/empty-state.ts @@ -0,0 +1,185 @@ +export default { + common: { + progress: { + title: "Ainda não há métricas de progresso para mostrar.", + description: + "Comece definindo valores de propriedades em itens de trabalho para ver as métricas de progresso aqui.", + }, + updates: { + title: "Ainda não há atualizações.", + description: "Quando os membros do projeto adicionarem atualizações, elas aparecerão aqui", + }, + search: { + title: "Nenhum resultado correspondente.", + description: "Nenhum resultado encontrado. Tente ajustar seus termos de pesquisa.", + }, + not_found: { + title: "Ops! Algo parece errado", + description: "Não conseguimos buscar sua conta Plane no momento. Pode ser um erro de rede.", + cta_primary: "Tentar recarregar", + }, + server_error: { + title: "Erro do servidor", + description: + "Não conseguimos conectar e buscar dados do nosso servidor. Não se preocupe, estamos trabalhando nisso.", + cta_primary: "Tentar recarregar", + }, + }, + project: { + work_items: { + title: "Comece com seu primeiro item de trabalho.", + description: + "Os itens de trabalho são os blocos de construção do seu projeto — atribua proprietários, defina prioridades e acompanhe o progresso facilmente.", + cta_primary: "Criar seu primeiro item de trabalho", + }, + cycles: { + title: "Agrupe e defina prazos para seu trabalho em Ciclos.", + description: + "Divida o trabalho em blocos com prazo definido, trabalhe de trás para frente a partir do prazo do projeto para definir datas e faça progresso tangível como equipe.", + cta_primary: "Definir seu primeiro ciclo", + }, + cycle_work_items: { + title: "Nenhum item de trabalho para mostrar neste ciclo", + description: + "Crie itens de trabalho para começar a monitorar o progresso da sua equipe neste ciclo e atingir seus objetivos no prazo.", + cta_primary: "Criar item de trabalho", + cta_secondary: "Adicionar item de trabalho existente", + }, + modules: { + title: "Mapeie as metas do seu projeto para Módulos e acompanhe facilmente.", + description: + "Os módulos são compostos por itens de trabalho interconectados. Eles auxiliam no monitoramento do progresso através das fases do projeto, cada uma com prazos e análises específicas para indicar o quão perto você está de alcançar essas fases.", + cta_primary: "Definir seu primeiro módulo", + }, + module_work_items: { + title: "Nenhum item de trabalho para mostrar neste Módulo", + description: "Crie itens de trabalho para começar a monitorar este módulo.", + cta_primary: "Criar item de trabalho", + cta_secondary: "Adicionar item de trabalho existente", + }, + views: { + title: "Salve visualizações personalizadas para seu projeto", + description: + "As visualizações são filtros salvos que ajudam você a acessar rapidamente as informações que mais usa. Colabore sem esforço enquanto os colegas de equipe compartilham e adaptam as visualizações às suas necessidades específicas.", + cta_primary: "Criar visualização", + }, + no_work_items_in_project: { + title: "Ainda não há itens de trabalho no projeto", + description: + "Adicione itens de trabalho ao seu projeto e divida seu trabalho em partes rastreáveis com visualizações.", + cta_primary: "Adicionar item de trabalho", + }, + work_item_filter: { + title: "Nenhum item de trabalho encontrado", + description: "Seu filtro atual não retornou nenhum resultado. Tente alterar os filtros.", + cta_primary: "Adicionar item de trabalho", + }, + pages: { + title: "Documente tudo — de notas a PRDs", + description: + "As páginas permitem que você capture e organize informações em um só lugar. Escreva notas de reuniões, documentação de projetos e PRDs, incorpore itens de trabalho e estruture-os com componentes prontos para uso.", + cta_primary: "Criar sua primeira Página", + }, + archive_pages: { + title: "Ainda não há páginas arquivadas", + description: "Arquive páginas que não estão no seu radar. Acesse-as aqui quando necessário.", + }, + intake_sidebar: { + title: "Registrar solicitações de Entrada", + description: + "Envie novas solicitações para serem revisadas, priorizadas e rastreadas dentro do fluxo de trabalho do seu projeto.", + cta_primary: "Criar solicitação de Entrada", + }, + intake_main: { + title: "Selecione um item de trabalho de Entrada para ver seus detalhes", + }, + }, + workspace: { + archive_work_items: { + title: "Ainda não há itens de trabalho arquivados", + description: + "Manualmente ou por meio de automação, você pode arquivar itens de trabalho concluídos ou cancelados. Encontre-os aqui uma vez arquivados.", + cta_primary: "Configurar automação", + }, + archive_cycles: { + title: "Ainda não há ciclos arquivados", + description: "Para organizar seu projeto, arquive ciclos concluídos. Encontre-os aqui uma vez arquivados.", + }, + archive_modules: { + title: "Ainda não há Módulos arquivados", + description: + "Para organizar seu projeto, arquive módulos concluídos ou cancelados. Encontre-os aqui uma vez arquivados.", + }, + home_widget_quick_links: { + title: "Mantenha referências, recursos ou documentos importantes à mão para o seu trabalho", + }, + inbox_sidebar_all: { + title: "As atualizações dos seus itens de trabalho inscritos aparecerão aqui", + }, + inbox_sidebar_mentions: { + title: "As menções aos seus itens de trabalho aparecerão aqui", + }, + your_work_by_priority: { + title: "Ainda não há item de trabalho atribuído", + }, + your_work_by_state: { + title: "Ainda não há item de trabalho atribuído", + }, + views: { + title: "Ainda não há Visualizações", + description: + "Adicione itens de trabalho ao seu projeto e use visualizações para filtrar, classificar e monitorar o progresso sem esforço.", + cta_primary: "Adicionar item de trabalho", + }, + drafts: { + title: "Itens de trabalho semi-escritos", + description: + "Para experimentar isso, comece a adicionar um item de trabalho e deixe-o no meio do caminho ou crie seu primeiro rascunho abaixo. 😉", + cta_primary: "Criar item de trabalho de rascunho", + }, + projects_archived: { + title: "Nenhum projeto arquivado", + description: "Parece que todos os seus projetos ainda estão ativos — ótimo trabalho!", + }, + analytics_projects: { + title: "Crie projetos para visualizar as métricas do projeto aqui.", + }, + analytics_work_items: { + title: + "Crie projetos com itens de trabalho e responsáveis para começar a rastrear desempenho, progresso e impacto da equipe aqui.", + }, + analytics_no_cycle: { + title: "Crie ciclos para organizar o trabalho em fases com prazo definido e acompanhar o progresso em sprints.", + }, + analytics_no_module: { + title: "Crie módulos para organizar seu trabalho e acompanhar o progresso em diferentes estágios.", + }, + analytics_no_intake: { + title: "Configure a entrada para gerenciar solicitações recebidas e rastrear como elas são aceitas e rejeitadas", + }, + }, + settings: { + estimates: { + title: "Ainda não há estimativas", + description: + "Defina como sua equipe mede o esforço e acompanhe-o consistentemente em todos os itens de trabalho.", + cta_primary: "Adicionar sistema de estimativas", + }, + labels: { + title: "Ainda não há etiquetas", + description: "Crie etiquetas personalizadas para categorizar e gerenciar efetivamente seus itens de trabalho.", + cta_primary: "Criar sua primeira etiqueta", + }, + exports: { + title: "Ainda não há exportações", + description: + "Você não tem nenhum registro de exportação no momento. Depois de exportar dados, todos os registros aparecerão aqui.", + }, + tokens: { + title: "Ainda não há token Pessoal", + description: + "Gere tokens de API seguros para conectar seu espaço de trabalho com sistemas e aplicativos externos.", + cta_primary: "Adicionar token de API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/ro/empty-state.ts b/packages/i18n/src/locales/ro/empty-state.ts new file mode 100644 index 0000000000..71d2c30317 --- /dev/null +++ b/packages/i18n/src/locales/ro/empty-state.ts @@ -0,0 +1,184 @@ +export default { + common: { + progress: { + title: "Nu există încă metrici de progres de afișat.", + description: + "Începeți să setați valori de proprietăți în elementele de lucru pentru a vedea metricile de progres aici.", + }, + updates: { + title: "Încă nu există actualizări.", + description: "Odată ce membrii proiectului adaugă actualizări, acestea vor apărea aici", + }, + search: { + title: "Niciun rezultat corespunzător.", + description: "Nu s-au găsit rezultate. Încercați să ajustați termenii de căutare.", + }, + not_found: { + title: "Hopa! Se pare că ceva nu este în regulă", + description: "Nu putem accesa contul dvs. Plane în prezent. Aceasta ar putea fi o eroare de rețea.", + cta_primary: "Încercați reîncărcarea", + }, + server_error: { + title: "Eroare de server", + description: "Nu ne putem conecta și accesa datele de pe serverul nostru. Nu vă faceți griji, lucrăm la asta.", + cta_primary: "Încercați reîncărcarea", + }, + }, + project: { + work_items: { + title: "Începeți cu primul dvs. element de lucru.", + description: + "Elementele de lucru sunt blocurile de construcție ale proiectului dvs. — alocați proprietari, stabiliți priorități și urmăriți progresul cu ușurință.", + cta_primary: "Creați primul dvs. element de lucru", + }, + cycles: { + title: "Grupați și limitați în timp munca dvs. în Cicluri.", + description: + "Împărțiți munca în bucăți limitate în timp, lucrați înapoi de la termenul limită al proiectului pentru a stabili datele și faceți progrese tangibile ca echipă.", + cta_primary: "Setați primul dvs. ciclu", + }, + cycle_work_items: { + title: "Niciun element de lucru de afișat în acest ciclu", + description: + "Creați elemente de lucru pentru a începe monitorizarea progresului echipei dvs. în acest ciclu și pentru a-vă atinge obiectivele la timp.", + cta_primary: "Creați element de lucru", + cta_secondary: "Adăugați element de lucru existent", + }, + modules: { + title: "Mapați obiectivele proiectului dvs. la Module și urmăriți cu ușurință.", + description: + "Modulele sunt compuse din elemente de lucru interconectate. Acestea ajută la monitorizarea progresului prin fazele proiectului, fiecare cu termene limită și analize specifice pentru a indica cât de aproape sunteți de atingerea acelor faze.", + cta_primary: "Setați primul dvs. modul", + }, + module_work_items: { + title: "Niciun element de lucru de afișat în acest Modul", + description: "Creați elemente de lucru pentru a începe monitorizarea acestui modul.", + cta_primary: "Creați element de lucru", + cta_secondary: "Adăugați element de lucru existent", + }, + views: { + title: "Salvați vizualizări personalizate pentru proiectul dvs.", + description: + "Vizualizările sunt filtre salvate care vă ajută să accesați rapid informațiile pe care le utilizați cel mai mult. Colaborați fără efort pe măsură ce colegii de echipă partajează și personalizează vizualizările conform nevoilor lor specifice.", + cta_primary: "Creați vizualizare", + }, + no_work_items_in_project: { + title: "Încă nu există elemente de lucru în proiect", + description: + "Adăugați elemente de lucru la proiectul dvs. și împărțiți munca în bucăți urmăribile cu vizualizări.", + cta_primary: "Adăugați element de lucru", + }, + work_item_filter: { + title: "Nu s-au găsit elemente de lucru", + description: "Filtrul dvs. curent nu a returnat niciun rezultat. Încercați să modificați filtrele.", + cta_primary: "Adăugați element de lucru", + }, + pages: { + title: "Documentați totul — de la notițe la PRD-uri", + description: + "Paginile vă permit să capturați și să organizați informații într-un singur loc. Scrieți note de întâlnire, documentație de proiect și PRD-uri, încorporați elemente de lucru și structurați-le cu componente gata de utilizat.", + cta_primary: "Creați prima dvs. Pagină", + }, + archive_pages: { + title: "Încă nu există pagini arhivate", + description: "Arhivați paginile care nu sunt în radar-ul dvs. Accesați-le aici când este necesar.", + }, + intake_sidebar: { + title: "Înregistrați solicitări de Admitere", + description: + "Trimiteți solicitări noi pentru a fi revizuite, prioritizate și urmărite în cadrul fluxului de lucru al proiectului dvs.", + cta_primary: "Creați solicitare de Admitere", + }, + intake_main: { + title: "Selectați un element de lucru de Admitere pentru a vedea detaliile", + }, + }, + workspace: { + archive_work_items: { + title: "Încă nu există elemente de lucru arhivate", + description: + "Manual sau prin automatizare, puteți arhiva elemente de lucru finalizate sau anulate. Găsiți-le aici odată arhivate.", + cta_primary: "Configurați automatizarea", + }, + archive_cycles: { + title: "Încă nu există cicluri arhivate", + description: "Pentru a vă aranja proiectul, arhivați ciclurile finalizate. Găsiți-le aici odată arhivate.", + }, + archive_modules: { + title: "Încă nu există Module arhivate", + description: + "Pentru a vă aranja proiectul, arhivați modulele finalizate sau anulate. Găsiți-le aici odată arhivate.", + }, + home_widget_quick_links: { + title: "Păstrați referințe importante, resurse sau documente la îndemână pentru munca dvs.", + }, + inbox_sidebar_all: { + title: "Actualizările pentru elementele dvs. de lucru la care sunteți abonat vor apărea aici", + }, + inbox_sidebar_mentions: { + title: "Mențiunile pentru elementele dvs. de lucru vor apărea aici", + }, + your_work_by_priority: { + title: "Încă nu există elemente de lucru atribuite", + }, + your_work_by_state: { + title: "Încă nu există elemente de lucru atribuite", + }, + views: { + title: "Încă nu există Vizualizări", + description: + "Adăugați elemente de lucru la proiectul dvs. și utilizați vizualizări pentru a filtra, sorta și monitoriza progresul fără efort.", + cta_primary: "Adăugați element de lucru", + }, + drafts: { + title: "Elemente de lucru semi-scrise", + description: + "Pentru a încerca acest lucru, începeți să adăugați un element de lucru și lăsați-l nefinalizat sau creați prima dvs. schiță mai jos. 😉", + cta_primary: "Creați element de lucru schiță", + }, + projects_archived: { + title: "Niciun proiect arhivat", + description: "Se pare că toate proiectele dvs. sunt încă active — bună treabă!", + }, + analytics_projects: { + title: "Creați proiecte pentru a vizualiza metricile proiectului aici.", + }, + analytics_work_items: { + title: + "Creați proiecte cu elemente de lucru și responsabili pentru a începe urmărirea performanței, progresului și impactului echipei aici.", + }, + analytics_no_cycle: { + title: "Creați cicluri pentru a organiza munca în faze limitate în timp și a urmări progresul în sprint-uri.", + }, + analytics_no_module: { + title: "Creați module pentru a vă organiza munca și a urmări progresul în diferite etape.", + }, + analytics_no_intake: { + title: "Configurați admiterea pentru a gestiona solicitările primite și a urmări cum sunt acceptate și respinse", + }, + }, + settings: { + estimates: { + title: "Încă nu există estimări", + description: + "Definiți modul în care echipa dvs. măsoară efortul și urmăriți-l consecvent în toate elementele de lucru.", + cta_primary: "Adăugați sistem de estimări", + }, + labels: { + title: "Încă nu există etichete", + description: "Creați etichete personalizate pentru a categorisi și gestiona eficient elementele dvs. de lucru.", + cta_primary: "Creați prima dvs. etichetă", + }, + exports: { + title: "Încă nu există exporturi", + description: + "Nu aveți nicio înregistrare de export în acest moment. Odată ce exportați date, toate înregistrările vor apărea aici.", + }, + tokens: { + title: "Încă nu există token Personal", + description: + "Generați token-uri API sigure pentru a conecta spațiul dvs. de lucru cu sisteme și aplicații externe.", + cta_primary: "Adăugați token API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/ru/empty-state.ts b/packages/i18n/src/locales/ru/empty-state.ts new file mode 100644 index 0000000000..3bdc6d3931 --- /dev/null +++ b/packages/i18n/src/locales/ru/empty-state.ts @@ -0,0 +1,187 @@ +export default { + common: { + progress: { + title: "Пока нет показателей прогресса для отображения.", + description: + "Начните устанавливать значения свойств в рабочих элементах, чтобы видеть показатели прогресса здесь.", + }, + updates: { + title: "Пока нет обновлений.", + description: "Когда участники проекта добавят обновления, они появятся здесь", + }, + search: { + title: "Не найдено совпадающих результатов.", + description: "Результаты не найдены. Попробуйте изменить условия поиска.", + }, + not_found: { + title: "Упс! Что-то пошло не так", + description: "Мы не можем получить вашу учетную запись Plane в данный момент. Возможно, это ошибка сети.", + cta_primary: "Попробовать перезагрузить", + }, + server_error: { + title: "Ошибка сервера", + description: "Мы не можем подключиться и получить данные с нашего сервера. Не волнуйтесь, мы работаем над этим.", + cta_primary: "Попробовать перезагрузить", + }, + }, + project: { + work_items: { + title: "Начните с вашего первого рабочего элемента.", + description: + "Рабочие элементы — это строительные блоки вашего проекта — назначайте ответственных, устанавливайте приоритеты и легко отслеживайте прогресс.", + cta_primary: "Создайте свой первый рабочий элемент", + }, + cycles: { + title: "Группируйте и ограничивайте по времени свою работу в Циклах.", + description: + "Разбивайте работу на временные блоки, работайте в обратном направлении от крайнего срока проекта для установки дат и добивайтесь ощутимого прогресса как команда.", + cta_primary: "Установите свой первый цикл", + }, + cycle_work_items: { + title: "Нет рабочих элементов для отображения в этом цикле", + description: + "Создайте рабочие элементы, чтобы начать отслеживать прогресс вашей команды в этом цикле и достичь целей вовремя.", + cta_primary: "Создать рабочий элемент", + cta_secondary: "Добавить существующий рабочий элемент", + }, + modules: { + title: "Сопоставьте цели проекта с Модулями и легко отслеживайте.", + description: + "Модули состоят из взаимосвязанных рабочих элементов. Они помогают отслеживать прогресс через фазы проекта, каждая из которых имеет конкретные сроки и аналитику, указывающую, насколько близко вы к достижению этих фаз.", + cta_primary: "Установите свой первый модуль", + }, + module_work_items: { + title: "Нет рабочих элементов для отображения в этом Модуле", + description: "Создайте рабочие элементы, чтобы начать отслеживать этот модуль.", + cta_primary: "Создать рабочий элемент", + cta_secondary: "Добавить существующий рабочий элемент", + }, + views: { + title: "Сохраните пользовательские представления для вашего проекта", + description: + "Представления — это сохраненные фильтры, которые помогают вам быстро получить доступ к информации, которую вы используете чаще всего. Сотрудничайте легко, когда товарищи по команде делятся и адаптируют представления к своим конкретным потребностям.", + cta_primary: "Создать представление", + }, + no_work_items_in_project: { + title: "Пока нет рабочих элементов в проекте", + description: + "Добавьте рабочие элементы в свой проект и разделите работу на отслеживаемые части с помощью представлений.", + cta_primary: "Добавить рабочий элемент", + }, + work_item_filter: { + title: "Рабочие элементы не найдены", + description: "Ваш текущий фильтр не вернул результатов. Попробуйте изменить фильтры.", + cta_primary: "Добавить рабочий элемент", + }, + pages: { + title: "Документируйте все — от заметок до PRD", + description: + "Страницы позволяют захватывать и организовывать информацию в одном месте. Пишите заметки о встречах, документацию проекта и PRD, встраивайте рабочие элементы и структурируйте их с помощью готовых компонентов.", + cta_primary: "Создайте свою первую Страницу", + }, + archive_pages: { + title: "Пока нет архивированных страниц", + description: + "Архивируйте страницы, которые не находятся в поле вашего зрения. Получите доступ к ним здесь при необходимости.", + }, + intake_sidebar: { + title: "Регистрируйте запросы на прием", + description: + "Отправляйте новые запросы для рассмотрения, приоритизации и отслеживания в рамках рабочего процесса вашего проекта.", + cta_primary: "Создать запрос на прием", + }, + intake_main: { + title: "Выберите рабочий элемент приема, чтобы просмотреть его детали", + }, + }, + workspace: { + archive_work_items: { + title: "Пока нет архивированных рабочих элементов", + description: + "Вручную или через автоматизацию вы можете архивировать завершенные или отмененные рабочие элементы. Найдите их здесь после архивирования.", + cta_primary: "Настроить автоматизацию", + }, + archive_cycles: { + title: "Пока нет архивированных циклов", + description: + "Чтобы привести в порядок ваш проект, архивируйте завершенные циклы. Найдите их здесь после архивирования.", + }, + archive_modules: { + title: "Пока нет архивированных Модулей", + description: + "Чтобы привести в порядок ваш проект, архивируйте завершенные или отмененные модули. Найдите их здесь после архивирования.", + }, + home_widget_quick_links: { + title: "Держите под рукой важные ссылки, ресурсы или документы для вашей работы", + }, + inbox_sidebar_all: { + title: "Обновления для ваших подписанных рабочих элементов появятся здесь", + }, + inbox_sidebar_mentions: { + title: "Упоминания ваших рабочих элементов появятся здесь", + }, + your_work_by_priority: { + title: "Пока не назначен рабочий элемент", + }, + your_work_by_state: { + title: "Пока не назначен рабочий элемент", + }, + views: { + title: "Пока нет Представлений", + description: + "Добавьте рабочие элементы в свой проект и используйте представления для фильтрации, сортировки и отслеживания прогресса без усилий.", + cta_primary: "Добавить рабочий элемент", + }, + drafts: { + title: "Недописанные рабочие элементы", + description: + "Чтобы попробовать это, начните добавлять рабочий элемент и оставьте его на полпути или создайте свой первый черновик ниже. 😉", + cta_primary: "Создать черновик рабочего элемента", + }, + projects_archived: { + title: "Нет архивированных проектов", + description: "Похоже, все ваши проекты все еще активны — отличная работа!", + }, + analytics_projects: { + title: "Создайте проекты для визуализации метрик проекта здесь.", + }, + analytics_work_items: { + title: + "Создайте проекты с рабочими элементами и ответственными, чтобы начать отслеживать производительность, прогресс и влияние команды здесь.", + }, + analytics_no_cycle: { + title: + "Создайте циклы для организации работы в ограниченные по времени фазы и отслеживания прогресса в спринтах.", + }, + analytics_no_module: { + title: "Создайте модули для организации работы и отслеживания прогресса на разных этапах.", + }, + analytics_no_intake: { + title: "Настройте прием для управления входящими запросами и отслеживания их принятия и отклонения", + }, + }, + settings: { + estimates: { + title: "Пока нет оценок", + description: + "Определите, как ваша команда измеряет усилия, и отслеживайте это последовательно во всех рабочих элементах.", + cta_primary: "Добавить систему оценок", + }, + labels: { + title: "Пока нет меток", + description: + "Создавайте персонализированные метки для эффективной категоризации и управления рабочими элементами.", + cta_primary: "Создайте свою первую метку", + }, + exports: { + title: "Пока нет экспортов", + description: "У вас пока нет записей экспорта. После экспорта данных все записи появятся здесь.", + }, + tokens: { + title: "Пока нет Личного токена", + description: + "Генерируйте безопасные API-токены для подключения вашего рабочего пространства к внешним системам и приложениям.", + cta_primary: "Добавить API-токен", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/sk/empty-state.ts b/packages/i18n/src/locales/sk/empty-state.ts new file mode 100644 index 0000000000..8478fde4a2 --- /dev/null +++ b/packages/i18n/src/locales/sk/empty-state.ts @@ -0,0 +1,184 @@ +export default { + common: { + progress: { + title: "Zatiaľ nie sú k dispozícii žiadne metriky pokroku.", + description: "Začnite nastavovať hodnoty vlastností v pracovných položkách, aby ste tu videli metriky pokroku.", + }, + updates: { + title: "Zatiaľ žiadne aktualizácie.", + description: "Akonáhle členovia projektu pridajú aktualizácie, zobrazia sa tu", + }, + search: { + title: "Žiadne zodpovedajúce výsledky.", + description: "Neboli nájdené žiadne výsledky. Skúste upraviť vyhľadávacie výrazy.", + }, + not_found: { + title: "Ojej! Niečo sa zdá byť v neporiadku", + description: "Momentálne sa nám nedarí načítať váš účet plane. Môže ísť o chybu siete.", + cta_primary: "Skúste znovu načítať", + }, + server_error: { + title: "Chyba servera", + description: "Nemôžeme sa pripojiť a načítať údaje z nášho servera. Nebojte sa, pracujeme na tom.", + cta_primary: "Skúste znovu načítať", + }, + }, + project: { + work_items: { + title: "Začnite s vašou prvou pracovnou položkou.", + description: + "Pracovné položky sú stavebnými kameňmi vášho projektu — priraďujte vlastníkov, nastavujte priority a jednoducho sledujte pokrok.", + cta_primary: "Vytvorte svoju prvú pracovnú položku", + }, + cycles: { + title: "Zoskupujte a časovo obmedzte svoju prácu v cykloch.", + description: + "Rozdeľte prácu do časovo obmedzených blokov, pracujte spätne od termínu projektu na nastavenie dátumov a dosahujte hmatateľný pokrok ako tým.", + cta_primary: "Nastavte svoj prvý cyklus", + }, + cycle_work_items: { + title: "V tomto cykle nie sú žiadne pracovné položky na zobrazenie", + description: + "Vytvorte pracovné položky na začatie sledovania pokroku vášho tímu v tomto cykle a dosiahnutie vašich cieľov včas.", + cta_primary: "Vytvoriť pracovnú položku", + cta_secondary: "Pridať existujúcu pracovnú položku", + }, + modules: { + title: "Namapujte ciele vášho projektu na moduly a jednoducho sledujte.", + description: + "Moduly sa skladajú z prepojených pracovných položiek. Pomáhajú sledovať pokrok prostredníctvom fáz projektu, z ktorých každá má špecifické termíny a analytiku, ktorá ukazuje, ako blízko ste dosiahnutiu týchto fáz.", + cta_primary: "Nastavte svoj prvý modul", + }, + module_work_items: { + title: "V tomto module nie sú žiadne pracovné položky na zobrazenie", + description: "Vytvorte pracovné položky na začatie sledovania tohto modulu.", + cta_primary: "Vytvoriť pracovnú položku", + cta_secondary: "Pridať existujúcu pracovnú položku", + }, + views: { + title: "Uložte vlastné pohľady pre váš projekt", + description: + "Pohľady sú uložené filtre, ktoré vám pomáhajú rýchlo pristupovať k informáciám, ktoré používate najčastejšie. Spolupracujte bez námahy, zatiaľ čo spolupracovníci zdieľajú a prispôsobujú pohľady svojim špecifickým potrebám.", + cta_primary: "Vytvoriť pohľad", + }, + no_work_items_in_project: { + title: "V projekte zatiaľ nie sú žiadne pracovné položky", + description: + "Pridajte pracovné položky do svojho projektu a rozdeľte svoju prácu na sledovateľné časti pomocou pohľadov.", + cta_primary: "Pridať pracovnú položku", + }, + work_item_filter: { + title: "Neboli nájdené žiadne pracovné položky", + description: "Váš aktuálny filter nevrátil žiadne výsledky. Skúste zmeniť filtre.", + cta_primary: "Pridať pracovnú položku", + }, + pages: { + title: "Dokumentujte všetko — od poznámok po PRD", + description: + "Stránky vám umožňujú zachytiť a organizovať informácie na jednom mieste. Píšte poznámky zo stretnutí, projektovú dokumentáciu a PRD, vkladajte pracovné položky a štruktúrujte ich pomocou pripravených komponentov.", + cta_primary: "Vytvorte svoju prvú stránku", + }, + archive_pages: { + title: "Zatiaľ žiadne archivované stránky", + description: "Archivujte stránky, ktoré nie sú na vašom radare. Pristúpte k nim tu, keď budete potrebovať.", + }, + intake_sidebar: { + title: "Zaznamenajte príchodzí požiadavky", + description: + "Odosielajte nové požiadavky na preskúmanie, stanovenie priorít a sledovanie v rámci pracovného postupu vášho projektu.", + cta_primary: "Vytvoriť príchodzí požiadavku", + }, + intake_main: { + title: "Vyberte príchodzí pracovnú položku na zobrazenie jej podrobností", + }, + }, + workspace: { + archive_work_items: { + title: "Zatiaľ žiadne archivované pracovné položky", + description: + "Ručne alebo pomocou automatizácie môžete archivovať dokončené alebo zrušené pracovné položky. Nájdete ich tu, akonáhle budú archivované.", + cta_primary: "Nastaviť automatizáciu", + }, + archive_cycles: { + title: "Zatiaľ žiadne archivované cykly", + description: + "Pre upratanie vášho projektu archivujte dokončené cykly. Nájdete ich tu, akonáhle budú archivované.", + }, + archive_modules: { + title: "Zatiaľ žiadne archivované moduly", + description: + "Pre upratanie vášho projektu archivujte dokončené alebo zrušené moduly. Nájdete ich tu, akonáhle budú archivované.", + }, + home_widget_quick_links: { + title: "Majte po ruke dôležité odkazy, zdroje alebo dokumenty pre vašu prácu", + }, + inbox_sidebar_all: { + title: "Aktualizácie pre vaše odoberané pracovné položky sa zobrazia tu", + }, + inbox_sidebar_mentions: { + title: "Zmienky o vašich pracovných položkách sa zobrazia tu", + }, + your_work_by_priority: { + title: "Zatiaľ nie je priradená žiadna pracovná položka", + }, + your_work_by_state: { + title: "Zatiaľ nie je priradená žiadna pracovná položka", + }, + views: { + title: "Zatiaľ žiadne pohľady", + description: + "Pridajte pracovné položky do svojho projektu a používajte pohľady na jednoduché filtrovanie, triedenie a sledovanie pokroku.", + cta_primary: "Pridať pracovnú položku", + }, + drafts: { + title: "Napoly napísané pracovné položky", + description: + "Ak to chcete vyskúšať, začnite pridávať pracovnú položku a nechajte ju nedokončenú alebo vytvorte svoj prvý koncept nižšie. 😉", + cta_primary: "Vytvoriť koncept pracovnej položky", + }, + projects_archived: { + title: "Žiadne archivované projekty", + description: "Vyzerá to, že všetky vaše projekty sú stále aktívne—skvelá práca!", + }, + analytics_projects: { + title: "Vytvorte projekty na vizualizáciu metrík projektu tu.", + }, + analytics_work_items: { + title: + "Vytvorte projekty s pracovnými položkami a priradenými osobami na začatie sledovania výkonu, pokroku a dopadu tímu tu.", + }, + analytics_no_cycle: { + title: "Vytvorte cykly na organizáciu práce do časovo obmedzených fáz a sledovanie pokroku naprieč šprintmi.", + }, + analytics_no_module: { + title: "Vytvorte moduly na organizáciu svojej práce a sledovanie pokroku naprieč rôznymi fázami.", + }, + analytics_no_intake: { + title: "Nastavte príjem na správu prichádzajúcich požiadaviek a sledovanie, ako sú prijímané a odmietané", + }, + }, + settings: { + estimates: { + title: "Zatiaľ žiadne odhady", + description: + "Definujte, ako váš tím meria úsilie, a sledujte to konzistentne naprieč všetkými pracovnými položkami.", + cta_primary: "Pridať systém odhadov", + }, + labels: { + title: "Zatiaľ žiadne štítky", + description: "Vytvorte personalizované štítky na efektívnu kategorizáciu a správu vašich pracovných položiek.", + cta_primary: "Vytvorte svoj prvý štítok", + }, + exports: { + title: "Zatiaľ žiadne exporty", + description: + "Momentálne nemáte žiadne záznamy exportu. Akonáhle exportujete údaje, všetky záznamy sa zobrazia tu.", + }, + tokens: { + title: "Zatiaľ žiadny osobný token", + description: + "Generujte bezpečné API tokeny na pripojenie vášho pracovného priestoru s externými systémami a aplikáciami.", + cta_primary: "Pridať API token", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/tr-TR/empty-state.ts b/packages/i18n/src/locales/tr-TR/empty-state.ts new file mode 100644 index 0000000000..a1cb6296d3 --- /dev/null +++ b/packages/i18n/src/locales/tr-TR/empty-state.ts @@ -0,0 +1,183 @@ +export default { + common: { + progress: { + title: "Henüz gösterilecek ilerleme metriği yok.", + description: "İlerleme metriklerini burada görmek için iş öğelerinde özellik değerleri belirlemeye başlayın.", + }, + updates: { + title: "Henüz güncelleme yok.", + description: "Proje üyeleri güncelleme eklediğinde burada görünecek", + }, + search: { + title: "Eşleşen sonuç yok.", + description: "Sonuç bulunamadı. Arama terimlerinizi ayarlamayı deneyin.", + }, + not_found: { + title: "Hata! Bir şeyler ters gitti", + description: "Şu anda Plane hesabınızı alamıyoruz. Bu bir ağ hatası olabilir.", + cta_primary: "Yeniden yüklemeyi dene", + }, + server_error: { + title: "Sunucu hatası", + description: "Sunucumuza bağlanamıyor ve veri alamıyoruz. Endişelenmeyin, üzerinde çalışıyoruz.", + cta_primary: "Yeniden yüklemeyi dene", + }, + }, + project: { + work_items: { + title: "İlk iş öğenizle başlayın.", + description: + "İş öğeleri projenizin yapı taşlarıdır — sahipler atayın, öncelikleri belirleyin ve ilerlemeyi kolayca takip edin.", + cta_primary: "İlk iş öğenizi oluşturun", + }, + cycles: { + title: "Çalışmanızı Döngülerde gruplayın ve zaman sınırlayın.", + description: + "Çalışmayı zaman sınırlı parçalara bölün, tarihleri belirlemek için proje son tarihinden geriye doğru çalışın ve bir ekip olarak somut ilerleme kaydedin.", + cta_primary: "İlk döngünüzü ayarlayın", + }, + cycle_work_items: { + title: "Bu döngüde gösterilecek iş öğesi yok", + description: + "Ekibinizin bu döngüdeki ilerlemesini izlemeye başlamak ve hedeflerinize zamanında ulaşmak için iş öğeleri oluşturun.", + cta_primary: "İş öğesi oluştur", + cta_secondary: "Mevcut iş öğesini ekle", + }, + modules: { + title: "Proje hedeflerinizi Modüllere eşleyin ve kolayca takip edin.", + description: + "Modüller birbirine bağlı iş öğelerinden oluşur. Proje aşamalarındaki ilerlemeyi izlemeye yardımcı olurlar, her biri bu aşamalara ne kadar yakın olduğunuzu göstermek için belirli son tarihler ve analizlerle.", + cta_primary: "İlk modülünüzü ayarlayın", + }, + module_work_items: { + title: "Bu Modülde gösterilecek iş öğesi yok", + description: "Bu modülü izlemeye başlamak için iş öğeleri oluşturun.", + cta_primary: "İş öğesi oluştur", + cta_secondary: "Mevcut iş öğesini ekle", + }, + views: { + title: "Projeniz için özel görünümler kaydedin", + description: + "Görünümler, en çok kullandığınız bilgilere hızlı erişmenize yardımcı olan kaydedilmiş filtrelerdir. Ekip arkadaşları görünümleri paylaşıp kendi özel ihtiyaçlarına göre uyarladıkça zahmetsizce işbirliği yapın.", + cta_primary: "Görünüm oluştur", + }, + no_work_items_in_project: { + title: "Projede henüz iş öğesi yok", + description: "Projenize iş öğeleri ekleyin ve çalışmanızı görünümlerle takip edilebilir parçalara ayırın.", + cta_primary: "İş öğesi ekle", + }, + work_item_filter: { + title: "İş öğesi bulunamadı", + description: "Mevcut filtreniz hiçbir sonuç döndürmedi. Filtreleri değiştirmeyi deneyin.", + cta_primary: "İş öğesi ekle", + }, + pages: { + title: "Her şeyi belgeleyin — notlardan PRD'lere", + description: + "Sayfalar bilgileri tek bir yerde yakalamanıza ve düzenlemenize olanak tanır. Toplantı notları, proje belgeleri ve PRD'ler yazın, iş öğelerini yerleştirin ve kullanıma hazır bileşenlerle yapılandırın.", + cta_primary: "İlk Sayfanızı oluşturun", + }, + archive_pages: { + title: "Henüz arşivlenmiş sayfa yok", + description: "Radarınızda olmayan sayfaları arşivleyin. Gerektiğinde buradan erişin.", + }, + intake_sidebar: { + title: "Giriş isteklerini kaydedin", + description: + "Projenizin iş akışı içinde incelenmek, önceliklendirilmek ve takip edilmek üzere yeni istekler gönderin.", + cta_primary: "Giriş isteği oluştur", + }, + intake_main: { + title: "Ayrıntılarını görmek için bir Giriş iş öğesi seçin", + }, + }, + workspace: { + archive_work_items: { + title: "Henüz arşivlenmiş iş öğesi yok", + description: + "Manuel veya otomasyon yoluyla tamamlanmış veya iptal edilmiş iş öğelerini arşivleyebilirsiniz. Arşivlendikten sonra burada bulun.", + cta_primary: "Otomasyonu ayarla", + }, + archive_cycles: { + title: "Henüz arşivlenmiş döngü yok", + description: "Projenizi düzenlemek için tamamlanmış döngüleri arşivleyin. Arşivlendikten sonra burada bulun.", + }, + archive_modules: { + title: "Henüz arşivlenmiş Modül yok", + description: + "Projenizi düzenlemek için tamamlanmış veya iptal edilmiş modülleri arşivleyin. Arşivlendikten sonra burada bulun.", + }, + home_widget_quick_links: { + title: "Çalışmanız için önemli referansları, kaynakları veya belgeleri elinizin altında tutun", + }, + inbox_sidebar_all: { + title: "Abone olduğunuz iş öğeleri için güncellemeler burada görünecek", + }, + inbox_sidebar_mentions: { + title: "İş öğeleriniz için bahsetmeler burada görünecek", + }, + your_work_by_priority: { + title: "Henüz atanmış iş öğesi yok", + }, + your_work_by_state: { + title: "Henüz atanmış iş öğesi yok", + }, + views: { + title: "Henüz Görünüm yok", + description: + "Projenize iş öğeleri ekleyin ve zahmetsizce filtrelemek, sıralamak ve ilerlemeyi izlemek için görünümleri kullanın.", + cta_primary: "İş öğesi ekle", + }, + drafts: { + title: "Yarım yazılmış iş öğeleri", + description: + "Bunu denemek için bir iş öğesi eklemeye başlayın ve yarıda bırakın veya aşağıda ilk taslağınızı oluşturun. 😉", + cta_primary: "Taslak iş öğesi oluştur", + }, + projects_archived: { + title: "Arşivlenmiş proje yok", + description: "Görünüşe göre tüm projeleriniz hala aktif—harika iş!", + }, + analytics_projects: { + title: "Proje metriklerini burada görselleştirmek için projeler oluşturun.", + }, + analytics_work_items: { + title: + "Performansı, ilerlemeyi ve ekip etkisini burada izlemeye başlamak için iş öğeleri ve atananlar içeren projeler oluşturun.", + }, + analytics_no_cycle: { + title: + "Çalışmayı zaman sınırlı aşamalara organize etmek ve sprintler boyunca ilerlemeyi takip etmek için döngüler oluşturun.", + }, + analytics_no_module: { + title: "Çalışmanızı organize etmek ve farklı aşamalarda ilerlemeyi takip etmek için modüller oluşturun.", + }, + analytics_no_intake: { + title: + "Gelen istekleri yönetmek ve bunların nasıl kabul edildiğini ve reddedildiğini izlemek için giriş ayarlayın", + }, + }, + settings: { + estimates: { + title: "Henüz tahmin yok", + description: "Ekibinizin çabayı nasıl ölçtüğünü tanımlayın ve tüm iş öğelerinde tutarlı bir şekilde takip edin.", + cta_primary: "Tahmin sistemi ekle", + }, + labels: { + title: "Henüz etiket yok", + description: + "İş öğelerinizi etkili bir şekilde kategorize etmek ve yönetmek için kişiselleştirilmiş etiketler oluşturun.", + cta_primary: "İlk etiketinizi oluşturun", + }, + exports: { + title: "Henüz dışa aktarma yok", + description: "Şu anda hiç dışa aktarma kaydınız yok. Verileri dışa aktardığınızda tüm kayıtlar burada görünecek.", + }, + tokens: { + title: "Henüz Kişisel token yok", + description: + "Çalışma alanınızı harici sistemler ve uygulamalarla bağlamak için güvenli API token'ları oluşturun.", + cta_primary: "API token'ı ekle", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/ua/empty-state.ts b/packages/i18n/src/locales/ua/empty-state.ts new file mode 100644 index 0000000000..12cc622e22 --- /dev/null +++ b/packages/i18n/src/locales/ua/empty-state.ts @@ -0,0 +1,186 @@ +export default { + common: { + progress: { + title: "Ще немає метрик прогресу для відображення.", + description: + "Почніть встановлювати значення властивостей у робочих елементах, щоб побачити тут метрики прогресу.", + }, + updates: { + title: "Ще немає оновлень.", + description: "Як тільки учасники проєкту додадуть оновлення, вони з'являться тут", + }, + search: { + title: "Немає відповідних результатів.", + description: "Результатів не знайдено. Спробуйте змінити пошукові терміни.", + }, + not_found: { + title: "Ой! Щось здається не так", + description: "Ми не можемо отримати ваш обліковий запис plane зараз. Це може бути помилка мережі.", + cta_primary: "Спробуйте перезавантажити", + }, + server_error: { + title: "Помилка сервера", + description: "Ми не можемо підключитися та отримати дані з нашого сервера. Не хвилюйтеся, ми працюємо над цим.", + cta_primary: "Спробуйте перезавантажити", + }, + }, + project: { + work_items: { + title: "Почніть з вашого першого робочого елемента.", + description: + "Робочі елементи є будівельними блоками вашого проєкту — призначайте власників, встановлюйте пріоритети та легко відстежуйте прогрес.", + cta_primary: "Створіть свій перший робочий елемент", + }, + cycles: { + title: "Групуйте та обмежуйте за часом вашу роботу в Циклах.", + description: + "Розділіть роботу на часові блоки, працюйте назад від кінцевого терміну проєкту для встановлення дат і робіть відчутний прогрес як команда.", + cta_primary: "Встановіть свій перший цикл", + }, + cycle_work_items: { + title: "Немає робочих елементів для відображення в цьому циклі", + description: + "Створіть робочі елементи, щоб почати моніторинг прогресу вашої команди в цьому циклі та досягти своїх цілей вчасно.", + cta_primary: "Створити робочий елемент", + cta_secondary: "Додати існуючий робочий елемент", + }, + modules: { + title: "Відобразіть цілі вашого проєкту на Модулі та легко відстежуйте.", + description: + "Модулі складаються з взаємопов'язаних робочих елементів. Вони допомагають моніторити прогрес через фази проєкту, кожна з конкретними термінами та аналітикою, щоб показати, наскільки ви близькі до досягнення цих фаз.", + cta_primary: "Встановіть свій перший модуль", + }, + module_work_items: { + title: "Немає робочих елементів для відображення в цьому Модулі", + description: "Створіть робочі елементи, щоб почати моніторинг цього модуля.", + cta_primary: "Створити робочий елемент", + cta_secondary: "Додати існуючий робочий елемент", + }, + views: { + title: "Зберігайте власні подання для вашого проєкту", + description: + "Подання є збереженими фільтрами, які допомагають вам швидко отримувати доступ до інформації, яку ви використовуєте найчастіше. Співпрацюйте без зусиль, оскільки члени команди діляться та адаптують подання до своїх конкретних потреб.", + cta_primary: "Створити подання", + }, + no_work_items_in_project: { + title: "У проєкті ще немає робочих елементів", + description: + "Додайте робочі елементи до свого проєкту та розділіть свою роботу на відстежувані частини з поданнями.", + cta_primary: "Додати робочий елемент", + }, + work_item_filter: { + title: "Робочих елементів не знайдено", + description: "Ваш поточний фільтр не повернув результатів. Спробуйте змінити фільтри.", + cta_primary: "Додати робочий елемент", + }, + pages: { + title: "Документуйте все — від нотаток до PRD", + description: + "Сторінки дозволяють вам захоплювати та організовувати інформацію в одному місці. Пишіть нотатки зустрічей, проєктну документацію та PRD, вбудовуйте робочі елементи та структуруйте їх за допомогою готових компонентів.", + cta_primary: "Створіть свою першу Сторінку", + }, + archive_pages: { + title: "Ще немає архівованих сторінок", + description: "Архівуйте сторінки, які не на вашому радарі. Отримуйте до них доступ тут, коли потрібно.", + }, + intake_sidebar: { + title: "Реєструйте запити на вхід", + description: + "Надсилайте нові запити для перегляду, встановлення пріоритетів та відстеження в рамках робочого процесу вашого проєкту.", + cta_primary: "Створити запит на вхід", + }, + intake_main: { + title: "Виберіть робочий елемент Intake, щоб переглянути його деталі", + }, + }, + workspace: { + archive_work_items: { + title: "Ще немає архівованих робочих елементів", + description: + "Вручну або через автоматизацію ви можете архівувати завершені або скасовані робочі елементи. Знайдіть їх тут після архівування.", + cta_primary: "Налаштувати автоматизацію", + }, + archive_cycles: { + title: "Ще немає архівованих циклів", + description: "Щоб упорядкувати свій проєкт, архівуйте завершені цикли. Знайдіть їх тут після архівування.", + }, + archive_modules: { + title: "Ще немає архівованих Модулів", + description: + "Щоб упорядкувати свій проєкт, архівуйте завершені або скасовані модулі. Знайдіть їх тут після архівування.", + }, + home_widget_quick_links: { + title: "Тримайте під рукою важливі посилання, ресурси або документи для вашої роботи", + }, + inbox_sidebar_all: { + title: "Оновлення для ваших підписаних робочих елементів з'являться тут", + }, + inbox_sidebar_mentions: { + title: "Згадки для ваших робочих елементів з'являться тут", + }, + your_work_by_priority: { + title: "Ще не призначено робочого елемента", + }, + your_work_by_state: { + title: "Ще не призначено робочого елемента", + }, + views: { + title: "Ще немає Поданнь", + description: + "Додайте робочі елементи до свого проєкту та використовуйте подання для фільтрування, сортування та моніторингу прогресу без зусиль.", + cta_primary: "Додати робочий елемент", + }, + drafts: { + title: "Напівнаписані робочі елементи", + description: + "Щоб спробувати це, почніть додавати робочий елемент і залиште його на половині або створіть свій перший чернетка нижче. 😉", + cta_primary: "Створити чернетковий робочий елемент", + }, + projects_archived: { + title: "Немає архівованих проєктів", + description: "Схоже, всі ваші проєкти все ще активні—чудова робота!", + }, + analytics_projects: { + title: "Створіть проєкти для візуалізації метрик проєкту тут.", + }, + analytics_work_items: { + title: + "Створіть проєкти з робочими елементами та призначеними особами, щоб почати відстежувати ефективність, прогрес та вплив команди тут.", + }, + analytics_no_cycle: { + title: "Створіть цикли для організації роботи в часові фази та відстеження прогресу через спринти.", + }, + analytics_no_module: { + title: "Створіть модулі для організації вашої роботи та відстеження прогресу через різні фази.", + }, + analytics_no_intake: { + title: + "Налаштуйте вхід для управління вхідними запитами та відстеження того, як вони приймаються та відхиляються", + }, + }, + settings: { + estimates: { + title: "Ще немає оцінок", + description: + "Визначте, як ваша команда вимірює зусилля, та відстежуйте це послідовно для всіх робочих елементів.", + cta_primary: "Додати систему оцінок", + }, + labels: { + title: "Ще немає міток", + description: + "Створіть персоналізовані мітки для ефективної категоризації та управління вашими робочими елементами.", + cta_primary: "Створіть свою першу мітку", + }, + exports: { + title: "Ще немає експортів", + description: + "Ви зараз не маєте жодних записів експорту. Як тільки ви експортуєте дані, усі записи з'являться тут.", + }, + tokens: { + title: "Ще немає Персонального токена", + description: + "Генеруйте безпечні API токени для підключення вашого робочого простору до зовнішніх систем та додатків.", + cta_primary: "Додати API токен", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/vi-VN/empty-state.ts b/packages/i18n/src/locales/vi-VN/empty-state.ts new file mode 100644 index 0000000000..6899c509e6 --- /dev/null +++ b/packages/i18n/src/locales/vi-VN/empty-state.ts @@ -0,0 +1,184 @@ +export default { + common: { + progress: { + title: "Chưa có số liệu tiến độ để hiển thị.", + description: "Bắt đầu đặt giá trị thuộc tính trong các mục công việc để xem số liệu tiến độ ở đây.", + }, + updates: { + title: "Chưa có cập nhật.", + description: "Khi thành viên dự án thêm cập nhật, nó sẽ xuất hiện ở đây", + }, + search: { + title: "Không có kết quả phù hợp.", + description: "Không tìm thấy kết quả. Hãy thử điều chỉnh các từ khóa tìm kiếm.", + }, + not_found: { + title: "Rất tiếc! Có vẻ như có gì đó không ổn", + description: "Chúng tôi không thể tải tài khoản Plane của bạn hiện tại. Đây có thể là lỗi mạng.", + cta_primary: "Thử tải lại", + }, + server_error: { + title: "Lỗi máy chủ", + description: + "Chúng tôi không thể kết nối và lấy dữ liệu từ máy chủ của chúng tôi. Đừng lo lắng, chúng tôi đang khắc phục.", + cta_primary: "Thử tải lại", + }, + }, + project: { + work_items: { + title: "Bắt đầu với mục công việc đầu tiên của bạn.", + description: + "Các mục công việc là những khối xây dựng của dự án của bạn — chỉ định người sở hữu, đặt mức độ ưu tiên và theo dõi tiến độ dễ dàng.", + cta_primary: "Tạo mục công việc đầu tiên của bạn", + }, + cycles: { + title: "Nhóm và giới hạn thời gian công việc của bạn trong Chu kỳ.", + description: + "Chia nhỏ công việc thành các phần có giới hạn thời gian, làm ngược từ thời hạn dự án để đặt ngày và tạo tiến triển cụ thể như một đội.", + cta_primary: "Đặt chu kỳ đầu tiên của bạn", + }, + cycle_work_items: { + title: "Không có mục công việc để hiển thị trong chu kỳ này", + description: + "Tạo các mục công việc để bắt đầu giám sát tiến độ của đội bạn trong chu kỳ này và đạt được mục tiêu đúng hạn.", + cta_primary: "Tạo mục công việc", + cta_secondary: "Thêm mục công việc hiện có", + }, + modules: { + title: "Ánh xạ mục tiêu dự án của bạn vào Mô-đun và theo dõi dễ dàng.", + description: + "Các mô-đun được tạo thành từ các mục công việc kết nối với nhau. Chúng hỗ trợ theo dõi tiến độ qua các giai đoạn dự án, mỗi giai đoạn có thời hạn và phân tích cụ thể để chỉ ra bạn gần đạt được các giai đoạn đó như thế nào.", + cta_primary: "Đặt mô-đun đầu tiên của bạn", + }, + module_work_items: { + title: "Không có mục công việc để hiển thị trong Mô-đun này", + description: "Tạo các mục công việc để bắt đầu giám sát mô-đun này.", + cta_primary: "Tạo mục công việc", + cta_secondary: "Thêm mục công việc hiện có", + }, + views: { + title: "Lưu chế độ xem tùy chỉnh cho dự án của bạn", + description: + "Chế độ xem là các bộ lọc đã lưu giúp bạn truy cập nhanh chóng thông tin bạn sử dụng nhiều nhất. Cộng tác dễ dàng khi các đồng đội chia sẻ và điều chỉnh chế độ xem theo nhu cầu cụ thể của họ.", + cta_primary: "Tạo chế độ xem", + }, + no_work_items_in_project: { + title: "Chưa có mục công việc trong dự án", + description: + "Thêm các mục công việc vào dự án của bạn và chia nhỏ công việc thành các phần có thể theo dõi với chế độ xem.", + cta_primary: "Thêm mục công việc", + }, + work_item_filter: { + title: "Không tìm thấy mục công việc", + description: "Bộ lọc hiện tại của bạn không trả về kết quả nào. Hãy thử thay đổi bộ lọc.", + cta_primary: "Thêm mục công việc", + }, + pages: { + title: "Ghi chép mọi thứ — từ ghi chú đến PRD", + description: + "Các trang cho phép bạn ghi lại và tổ chức thông tin ở một nơi. Viết ghi chú cuộc họp, tài liệu dự án và PRD, nhúng các mục công việc và cấu trúc chúng với các thành phần sẵn sàng sử dụng.", + cta_primary: "Tạo Trang đầu tiên của bạn", + }, + archive_pages: { + title: "Chưa có trang được lưu trữ", + description: "Lưu trữ các trang không nằm trong tầm quan sát của bạn. Truy cập chúng ở đây khi cần.", + }, + intake_sidebar: { + title: "Ghi lại yêu cầu Tiếp nhận", + description: "Gửi các yêu cầu mới để được xem xét, ưu tiên và theo dõi trong quy trình làm việc của dự án.", + cta_primary: "Tạo yêu cầu Tiếp nhận", + }, + intake_main: { + title: "Chọn một mục công việc Tiếp nhận để xem chi tiết của nó", + }, + }, + workspace: { + archive_work_items: { + title: "Chưa có mục công việc được lưu trữ", + description: + "Thủ công hoặc thông qua tự động hóa, bạn có thể lưu trữ các mục công việc đã hoàn thành hoặc bị hủy. Tìm chúng ở đây sau khi lưu trữ.", + cta_primary: "Thiết lập tự động hóa", + }, + archive_cycles: { + title: "Chưa có chu kỳ được lưu trữ", + description: "Để sắp xếp dự án của bạn, hãy lưu trữ các chu kỳ đã hoàn thành. Tìm chúng ở đây sau khi lưu trữ.", + }, + archive_modules: { + title: "Chưa có Mô-đun được lưu trữ", + description: + "Để sắp xếp dự án của bạn, hãy lưu trữ các mô-đun đã hoàn thành hoặc bị hủy. Tìm chúng ở đây sau khi lưu trữ.", + }, + home_widget_quick_links: { + title: "Giữ các tài liệu tham khảo, tài nguyên hoặc tài liệu quan trọng tiện lợi cho công việc của bạn", + }, + inbox_sidebar_all: { + title: "Cập nhật cho các mục công việc bạn đăng ký sẽ xuất hiện ở đây", + }, + inbox_sidebar_mentions: { + title: "Đề cập cho các mục công việc của bạn sẽ xuất hiện ở đây", + }, + your_work_by_priority: { + title: "Chưa có mục công việc được giao", + }, + your_work_by_state: { + title: "Chưa có mục công việc được giao", + }, + views: { + title: "Chưa có Chế độ xem", + description: + "Thêm các mục công việc vào dự án của bạn và sử dụng chế độ xem để lọc, sắp xếp và giám sát tiến độ dễ dàng.", + cta_primary: "Thêm mục công việc", + }, + drafts: { + title: "Các mục công việc viết dở", + description: + "Để thử điều này, hãy bắt đầu thêm một mục công việc và để nó ở giữa chừng hoặc tạo bản nháp đầu tiên của bạn bên dưới. 😉", + cta_primary: "Tạo mục công việc nháp", + }, + projects_archived: { + title: "Không có dự án được lưu trữ", + description: "Có vẻ như tất cả các dự án của bạn vẫn đang hoạt động—làm tốt lắm!", + }, + analytics_projects: { + title: "Tạo dự án để trực quan hóa số liệu dự án ở đây.", + }, + analytics_work_items: { + title: + "Tạo dự án với các mục công việc và người được giao để bắt đầu theo dõi hiệu suất, tiến độ và tác động của đội ở đây.", + }, + analytics_no_cycle: { + title: + "Tạo chu kỳ để tổ chức công việc thành các giai đoạn có giới hạn thời gian và theo dõi tiến độ qua các sprint.", + }, + analytics_no_module: { + title: "Tạo mô-đun để tổ chức công việc của bạn và theo dõi tiến độ qua các giai đoạn khác nhau.", + }, + analytics_no_intake: { + title: "Thiết lập tiếp nhận để quản lý các yêu cầu đến và theo dõi cách chúng được chấp nhận và từ chối", + }, + }, + settings: { + estimates: { + title: "Chưa có ước tính", + description: + "Xác định cách đội của bạn đo lường nỗ lực và theo dõi nó một cách nhất quán trên tất cả các mục công việc.", + cta_primary: "Thêm hệ thống ước tính", + }, + labels: { + title: "Chưa có nhãn", + description: "Tạo nhãn cá nhân hóa để phân loại và quản lý các mục công việc của bạn một cách hiệu quả.", + cta_primary: "Tạo nhãn đầu tiên của bạn", + }, + exports: { + title: "Chưa có xuất khẩu", + description: + "Bạn chưa có bản ghi xuất khẩu nào ngay bây giờ. Sau khi bạn xuất dữ liệu, tất cả các bản ghi sẽ xuất hiện ở đây.", + }, + tokens: { + title: "Chưa có token Cá nhân", + description: + "Tạo token API an toàn để kết nối không gian làm việc của bạn với các hệ thống và ứng dụng bên ngoài.", + cta_primary: "Thêm token API", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/zh-CN/empty-state.ts b/packages/i18n/src/locales/zh-CN/empty-state.ts new file mode 100644 index 0000000000..7d0cfb5311 --- /dev/null +++ b/packages/i18n/src/locales/zh-CN/empty-state.ts @@ -0,0 +1,170 @@ +export default { + common: { + progress: { + title: "暂无进度指标可显示。", + description: "开始在工作项中设置属性值以在此查看进度指标。", + }, + updates: { + title: "暂无更新。", + description: "项目成员添加更新后将显示在此处", + }, + search: { + title: "未找到匹配结果。", + description: "未找到结果。请尝试调整搜索条件。", + }, + not_found: { + title: "糟糕!似乎出了点问题", + description: "我们目前无法获取您的 Plane 账户。这可能是网络错误。", + cta_primary: "尝试重新加载", + }, + server_error: { + title: "服务器错误", + description: "我们无法连接并从服务器获取数据。请放心,我们正在处理。", + cta_primary: "尝试重新加载", + }, + }, + project: { + work_items: { + title: "从您的第一个工作项开始。", + description: "工作项是项目的构建块 — 分配负责人、设置优先级并轻松跟踪进度。", + cta_primary: "创建您的第一个工作项", + }, + cycles: { + title: "在周期中分组和限时您的工作。", + description: "将工作分解为限时块,从项目截止日期倒推设置日期,并作为团队取得实质性进展。", + cta_primary: "设置您的第一个周期", + }, + cycle_work_items: { + title: "此周期中没有要显示的工作项", + description: "创建工作项以开始监控团队在此周期中的进度并按时实现目标。", + cta_primary: "创建工作项", + cta_secondary: "添加现有工作项", + }, + modules: { + title: "将项目目标映射到模块并轻松跟踪。", + description: + "模块由相互关联的工作项组成。它们有助于监控项目阶段的进度,每个阶段都有特定的截止日期和分析,以指示您离实现这些阶段有多近。", + cta_primary: "设置您的第一个模块", + }, + module_work_items: { + title: "此模块中没有要显示的工作项", + description: "创建工作项以开始监控此模块。", + cta_primary: "创建工作项", + cta_secondary: "添加现有工作项", + }, + views: { + title: "为项目保存自定义视图", + description: + "视图是保存的过滤器,可帮助您快速访问最常用的信息。团队成员可以轻松协作,共享视图并根据特定需求进行调整。", + cta_primary: "创建视图", + }, + no_work_items_in_project: { + title: "项目中暂无工作项", + description: "将工作项添加到项目中,并使用视图将工作切分为可跟踪的部分。", + cta_primary: "添加工作项", + }, + work_item_filter: { + title: "未找到工作项", + description: "您当前的过滤器未返回任何结果。请尝试更改过滤器。", + cta_primary: "添加工作项", + }, + pages: { + title: "记录一切 — 从笔记到 PRD", + description: + "页面让您在一个地方捕获和组织信息。编写会议笔记、项目文档和 PRD,嵌入工作项,并使用现成的组件进行结构化。", + cta_primary: "创建您的第一个页面", + }, + archive_pages: { + title: "暂无已归档页面", + description: "归档不在您关注范围内的页面。需要时在此处访问它们。", + }, + intake_sidebar: { + title: "记录接收请求", + description: "提交新请求以在项目工作流程中进行审查、优先排序和跟踪。", + cta_primary: "创建接收请求", + }, + intake_main: { + title: "选择一个接收工作项以查看其详细信息", + }, + }, + workspace: { + archive_work_items: { + title: "暂无已归档工作项", + description: "通过手动或自动化,您可以归档已完成或已取消的工作项。归档后在此处查找它们。", + cta_primary: "设置自动化", + }, + archive_cycles: { + title: "暂无已归档周期", + description: "为了整理项目,请归档已完成的周期。归档后在此处查找它们。", + }, + archive_modules: { + title: "暂无已归档模块", + description: "为了整理项目,请归档已完成或已取消的模块。归档后在此处查找它们。", + }, + home_widget_quick_links: { + title: "为您的工作保留重要的参考、资源或文档", + }, + inbox_sidebar_all: { + title: "您订阅的工作项的更新将显示在此处", + }, + inbox_sidebar_mentions: { + title: "您的工作项的提及将显示在此处", + }, + your_work_by_priority: { + title: "尚未分配工作项", + }, + your_work_by_state: { + title: "尚未分配工作项", + }, + views: { + title: "暂无视图", + description: "将工作项添加到项目中并使用视图轻松过滤、排序和监控进度。", + cta_primary: "添加工作项", + }, + drafts: { + title: "半成品工作项", + description: "要试用此功能,请开始添加工作项并在中途离开,或在下方创建您的第一个草稿。😉", + cta_primary: "创建草稿工作项", + }, + projects_archived: { + title: "没有已归档项目", + description: "看起来您的所有项目仍然活跃 — 做得好!", + }, + analytics_projects: { + title: "创建项目以在此处可视化项目指标。", + }, + analytics_work_items: { + title: "创建包含工作项和受理人的项目,以开始在此处跟踪绩效、进度和团队影响。", + }, + analytics_no_cycle: { + title: "创建周期以将工作组织成有时限的阶段并跟踪冲刺进度。", + }, + analytics_no_module: { + title: "创建模块以组织工作并跟踪不同阶段的进度。", + }, + analytics_no_intake: { + title: "设置接收以管理传入请求并跟踪它们的接受和拒绝情况", + }, + }, + settings: { + estimates: { + title: "暂无估算", + description: "定义团队如何衡量工作量,并在所有工作项中一致地跟踪它。", + cta_primary: "添加估算系统", + }, + labels: { + title: "暂无标签", + description: "创建个性化标签以有效分类和管理工作项。", + cta_primary: "创建您的第一个标签", + }, + exports: { + title: "暂无导出", + description: "您目前没有任何导出记录。导出数据后,所有记录将显示在此处。", + }, + tokens: { + title: "暂无个人令牌", + description: "生成安全的 API 令牌以将工作空间与外部系统和应用程序连接。", + cta_primary: "添加 API 令牌", + }, + }, +} as const; diff --git a/packages/i18n/src/locales/zh-TW/empty-state.ts b/packages/i18n/src/locales/zh-TW/empty-state.ts new file mode 100644 index 0000000000..b7c3f4bdc0 --- /dev/null +++ b/packages/i18n/src/locales/zh-TW/empty-state.ts @@ -0,0 +1,170 @@ +export default { + common: { + progress: { + title: "暫無進度指標可顯示。", + description: "開始在工作項中設定屬性值以在此查看進度指標。", + }, + updates: { + title: "暫無更新。", + description: "專案成員新增更新後將顯示在此處", + }, + search: { + title: "未找到符合結果。", + description: "未找到結果。請嘗試調整搜尋條件。", + }, + not_found: { + title: "糟糕!似乎出了點問題", + description: "我們目前無法取得您的 Plane 帳戶。這可能是網路錯誤。", + cta_primary: "嘗試重新載入", + }, + server_error: { + title: "伺服器錯誤", + description: "我們無法連線並從伺服器取得資料。請放心,我們正在處理。", + cta_primary: "嘗試重新載入", + }, + }, + project: { + work_items: { + title: "從您的第一個工作項開始。", + description: "工作項是專案的建構模組 — 指派負責人、設定優先順序並輕鬆追蹤進度。", + cta_primary: "建立您的第一個工作項", + }, + cycles: { + title: "在週期中分組和限時您的工作。", + description: "將工作分解為限時區塊,從專案截止日期倒推設定日期,並作為團隊取得實質性進展。", + cta_primary: "設定您的第一個週期", + }, + cycle_work_items: { + title: "此週期中沒有要顯示的工作項", + description: "建立工作項以開始監控團隊在此週期中的進度並按時實現目標。", + cta_primary: "建立工作項", + cta_secondary: "新增現有工作項", + }, + modules: { + title: "將專案目標對應到模組並輕鬆追蹤。", + description: + "模組由相互關聯的工作項組成。它們有助於監控專案階段的進度,每個階段都有特定的截止日期和分析,以指示您離實現這些階段有多近。", + cta_primary: "設定您的第一個模組", + }, + module_work_items: { + title: "此模組中沒有要顯示的工作項", + description: "建立工作項以開始監控此模組。", + cta_primary: "建立工作項", + cta_secondary: "新增現有工作項", + }, + views: { + title: "為專案儲存自訂檢視", + description: + "檢視是已儲存的篩選器,可協助您快速存取最常用的資訊。團隊成員可以輕鬆協作,共用檢視並根據特定需求進行調整。", + cta_primary: "建立檢視", + }, + no_work_items_in_project: { + title: "專案中暫無工作項", + description: "將工作項新增至專案中,並使用檢視將工作切分為可追蹤的部分。", + cta_primary: "新增工作項", + }, + work_item_filter: { + title: "未找到工作項", + description: "您目前的篩選器未傳回任何結果。請嘗試變更篩選器。", + cta_primary: "新增工作項", + }, + pages: { + title: "記錄一切 — 從筆記到 PRD", + description: + "頁面讓您在一個地方擷取和組織資訊。撰寫會議筆記、專案文件和 PRD,嵌入工作項,並使用現成的元件進行結構化。", + cta_primary: "建立您的第一個頁面", + }, + archive_pages: { + title: "暫無已封存頁面", + description: "封存不在您關注範圍內的頁面。需要時在此處存取它們。", + }, + intake_sidebar: { + title: "記錄接收請求", + description: "提交新請求以在專案工作流程中進行審查、優先順序排序和追蹤。", + cta_primary: "建立接收請求", + }, + intake_main: { + title: "選擇一個接收工作項以查看其詳細資訊", + }, + }, + workspace: { + archive_work_items: { + title: "暫無已封存工作項", + description: "透過手動或自動化,您可以封存已完成或已取消的工作項。封存後在此處尋找它們。", + cta_primary: "設定自動化", + }, + archive_cycles: { + title: "暫無已封存週期", + description: "為了整理專案,請封存已完成的週期。封存後在此處尋找它們。", + }, + archive_modules: { + title: "暫無已封存模組", + description: "為了整理專案,請封存已完成或已取消的模組。封存後在此處尋找它們。", + }, + home_widget_quick_links: { + title: "為您的工作保留重要的參考、資源或文件", + }, + inbox_sidebar_all: { + title: "您訂閱的工作項的更新將顯示在此處", + }, + inbox_sidebar_mentions: { + title: "您的工作項的提及將顯示在此處", + }, + your_work_by_priority: { + title: "尚未分配工作項", + }, + your_work_by_state: { + title: "尚未分配工作項", + }, + views: { + title: "暫無檢視", + description: "將工作項新增至專案中並使用檢視輕鬆篩選、排序和監控進度。", + cta_primary: "新增工作項", + }, + drafts: { + title: "半成品工作項", + description: "要試用此功能,請開始新增工作項並在中途離開,或在下方建立您的第一個草稿。😉", + cta_primary: "建立草稿工作項", + }, + projects_archived: { + title: "沒有已封存專案", + description: "看起來您的所有專案仍然活躍 — 做得好!", + }, + analytics_projects: { + title: "建立專案以在此處視覺化專案指標。", + }, + analytics_work_items: { + title: "建立包含工作項和受託人的專案,以開始在此處追蹤績效、進度和團隊影響。", + }, + analytics_no_cycle: { + title: "建立週期以將工作組織成有時限的階段並追蹤衝刺進度。", + }, + analytics_no_module: { + title: "建立模組以組織工作並追蹤不同階段的進度。", + }, + analytics_no_intake: { + title: "設定接收以管理傳入請求並追蹤它們的接受和拒絕情況", + }, + }, + settings: { + estimates: { + title: "暫無估算", + description: "定義團隊如何衡量工作量,並在所有工作項中一致地追蹤它。", + cta_primary: "新增估算系統", + }, + labels: { + title: "暫無標籤", + description: "建立個人化標籤以有效分類和管理工作項。", + cta_primary: "建立您的第一個標籤", + }, + exports: { + title: "暫無匯出", + description: "您目前沒有任何匯出記錄。匯出資料後,所有記錄將顯示在此處。", + }, + tokens: { + title: "暫無個人權杖", + description: "產生安全的 API 權杖以將工作區與外部系統和應用程式連線。", + cta_primary: "新增 API 權杖", + }, + }, +} as const; diff --git a/packages/propel/src/empty-state/assets-showcase.stories.tsx b/packages/propel/src/empty-state/assets-showcase.stories.tsx new file mode 100644 index 0000000000..da35189fc5 --- /dev/null +++ b/packages/propel/src/empty-state/assets-showcase.stories.tsx @@ -0,0 +1,204 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { HorizontalStackAssetsMap } from "./assets/horizontal-stack/constant"; +import { IllustrationMap } from "./assets/illustration/constant"; +import { VerticalStackAssetsMap } from "./assets/vertical-stack/constant"; + +// Meta for asset showcase +const meta: Meta = { + title: "Components/EmptyState/Assets Showcase", + parameters: { + layout: "fullscreen", + docs: { + description: { + component: "Visual catalog of all available empty state assets organized by type.", + }, + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const HorizontalStackAssets: Story = { + parameters: { + docs: { + description: { + story: + "Horizontal stack assets designed for compact empty states. These are optimized for smaller, inline empty state scenarios.", + }, + }, + }, + render: () => ( +
+
+

Horizontal Stack Assets

+

Used primarily in EmptyStateCompact component

+
+
+ {HorizontalStackAssetsMap.map((item) => ( +
+
{item.asset}
+

{item.title}

+ + {item.title.toLowerCase().replace(/\s+/g, "-")} + +
+ ))} +
+
+ ), +}; + +export const VerticalStackAssets: Story = { + parameters: { + docs: { + description: { + story: + "Vertical stack assets designed for detailed empty states. These are larger and more prominent, suitable for feature-specific empty states.", + }, + }, + }, + render: () => ( +
+
+

Vertical Stack Assets

+

Used primarily in EmptyStateDetailed component

+
+
+ {VerticalStackAssetsMap.map((item) => ( +
+
{item.asset}
+

+ {item.title.replace(/VerticalStackIllustration$/, "")} +

+ + {item.title + .replace(/VerticalStackIllustration$/, "") + .replace(/([A-Z])/g, "-$1") + .toLowerCase() + .slice(1)} + +
+ ))} +
+
+ ), +}; + +export const IllustrationAssets: Story = { + parameters: { + docs: { + description: { + story: "Illustration assets available for both compact and detailed empty states.", + }, + }, + }, + render: () => ( +
+
+

Illustration Assets

+

Available in both EmptyStateCompact and EmptyStateDetailed

+
+
+ {IllustrationMap.map((item) => ( +
+
{item.asset}
+

{item.title}

+ + {item.title.toLowerCase()} + +
+ ))} +
+
+ ), +}; + +export const AllAssets: Story = { + parameters: { + docs: { + description: { + story: "Complete catalog of all available empty state assets.", + }, + }, + }, + render: () => ( +
+ {/* Horizontal Stack */} +
+
+

Horizontal Stack Assets

+

+ For EmptyStateCompact - {HorizontalStackAssetsMap.length} assets +

+
+
+ {HorizontalStackAssetsMap.map((item) => ( +
+
{item.asset}
+ {item.title.toLowerCase().replace(/\s+/g, "-")} +
+ ))} +
+
+ + {/* Vertical Stack */} +
+
+

Vertical Stack Assets

+

+ For EmptyStateDetailed - {VerticalStackAssetsMap.length} assets +

+
+
+ {VerticalStackAssetsMap.map((item) => ( +
+
{item.asset}
+ + {item.title + .replace(/VerticalStackIllustration$/, "") + .replace(/([A-Z])/g, "-$1") + .toLowerCase() + .slice(1)} + +
+ ))} +
+
+ + {/* Illustrations */} +
+
+

Illustration Assets

+

For both components - {IllustrationMap.length} assets

+
+
+ {IllustrationMap.map((item) => ( +
+
{item.asset}
+ {item.title.toLowerCase()} +
+ ))} +
+
+
+ ), +}; diff --git a/packages/propel/src/empty-state/assets/asset-registry.tsx b/packages/propel/src/empty-state/assets/asset-registry.tsx new file mode 100644 index 0000000000..42ac821e6d --- /dev/null +++ b/packages/propel/src/empty-state/assets/asset-registry.tsx @@ -0,0 +1,130 @@ +import React from "react"; +import type { + CompactAssetType, + DetailedAssetType, + HorizontalStackAssetType, + IllustrationAssetType, + VerticalStackAssetType, +} from "./asset-types"; +import { + CustomerHorizontalStackIllustration, + EpicHorizontalStackIllustration, + EstimateHorizontalStackIllustration, + ExportHorizontalStackIllustration, + IntakeHorizontalStackIllustration, + LabelHorizontalStackIllustration, + LinkHorizontalStackIllustration, + MembersHorizontalStackIllustration, + NoteHorizontalStackIllustration, + PriorityHorizontalStackIllustration, + ProjectHorizontalStackIllustration, + SettingsHorizontalStackIllustration, + StateHorizontalStackIllustration, + TemplateHorizontalStackIllustration, + TokenHorizontalStackIllustration, + UnknownHorizontalStackIllustration, + UpdateHorizontalStackIllustration, + WebhookHorizontalStackIllustration, + WorkItemHorizontalStackIllustration, + WorklogHorizontalStackIllustration, +} from "./horizontal-stack"; +import { InboxIllustration, SearchIllustration } from "./illustration"; +import { + ArchivedCycleVerticalStackIllustration, + ArchivedModuleVerticalStackIllustration, + ArchivedWorkItemVerticalStackIllustration, + CustomerVerticalStackIllustration, + CycleVerticalStackIllustration, + DashboardVerticalStackIllustration, + DraftVerticalStackIllustration, + EpicVerticalStackIllustration, + Error404VerticalStackIllustration, + InvalidLinkVerticalStackIllustration, + ModuleVerticalStackIllustration, + NoAccessVerticalStackIllustration, + PageVerticalStackIllustration, + ProjectVerticalStackIllustration, + ServerErrorVerticalStackIllustration, + TeamspaceVerticalStackIllustration, + ViewVerticalStackIllustration, + WorkItemVerticalStackIllustration, +} from "./vertical-stack"; + +// Horizontal Stack Asset Registry +export const HORIZONTAL_STACK_ASSETS: Record> = { + customer: CustomerHorizontalStackIllustration, + epic: EpicHorizontalStackIllustration, + estimate: EstimateHorizontalStackIllustration, + export: ExportHorizontalStackIllustration, + intake: IntakeHorizontalStackIllustration, + label: LabelHorizontalStackIllustration, + link: LinkHorizontalStackIllustration, + members: MembersHorizontalStackIllustration, + note: NoteHorizontalStackIllustration, + priority: PriorityHorizontalStackIllustration, + project: ProjectHorizontalStackIllustration, + settings: SettingsHorizontalStackIllustration, + state: StateHorizontalStackIllustration, + template: TemplateHorizontalStackIllustration, + token: TokenHorizontalStackIllustration, + unknown: UnknownHorizontalStackIllustration, + update: UpdateHorizontalStackIllustration, + webhook: WebhookHorizontalStackIllustration, + "work-item": WorkItemHorizontalStackIllustration, + worklog: WorklogHorizontalStackIllustration, +}; + +// Vertical Stack Asset Registry +export const VERTICAL_STACK_ASSETS: Record> = { + "archived-cycle": ArchivedCycleVerticalStackIllustration, + "archived-module": ArchivedModuleVerticalStackIllustration, + "archived-work-item": ArchivedWorkItemVerticalStackIllustration, + customer: CustomerVerticalStackIllustration, + cycle: CycleVerticalStackIllustration, + dashboard: DashboardVerticalStackIllustration, + draft: DraftVerticalStackIllustration, + epic: EpicVerticalStackIllustration, + "error-404": Error404VerticalStackIllustration, + "invalid-link": InvalidLinkVerticalStackIllustration, + module: ModuleVerticalStackIllustration, + "no-access": NoAccessVerticalStackIllustration, + page: PageVerticalStackIllustration, + project: ProjectVerticalStackIllustration, + "server-error": ServerErrorVerticalStackIllustration, + teamspace: TeamspaceVerticalStackIllustration, + view: ViewVerticalStackIllustration, + "work-item": WorkItemVerticalStackIllustration, +}; + +// Illustration Asset Registry +export const ILLUSTRATION_ASSETS: Record> = { + inbox: InboxIllustration, + search: SearchIllustration, +}; + +// Helper functions to get assets +export const getCompactAsset = (assetKey: CompactAssetType, className?: string): React.ReactNode => { + const AssetComponent = + (HORIZONTAL_STACK_ASSETS[assetKey as HorizontalStackAssetType] as React.ComponentType<{ className?: string }>) || + ILLUSTRATION_ASSETS[assetKey as IllustrationAssetType]; + + if (!AssetComponent) { + console.warn(`Asset "${assetKey}" not found in compact asset registry`); + return null; + } + + return ; +}; + +export const getDetailedAsset = (assetKey: DetailedAssetType, className?: string): React.ReactNode => { + const AssetComponent = + (VERTICAL_STACK_ASSETS[assetKey as VerticalStackAssetType] as React.ComponentType<{ className?: string }>) || + ILLUSTRATION_ASSETS[assetKey as IllustrationAssetType]; + + if (!AssetComponent) { + console.warn(`Asset "${assetKey}" not found in detailed asset registry`); + return null; + } + + return ; +}; diff --git a/packages/propel/src/empty-state/assets/asset-types.ts b/packages/propel/src/empty-state/assets/asset-types.ts new file mode 100644 index 0000000000..af8e48e087 --- /dev/null +++ b/packages/propel/src/empty-state/assets/asset-types.ts @@ -0,0 +1,52 @@ +// Horizontal Stack Asset Types +export type HorizontalStackAssetType = + | "customer" + | "epic" + | "estimate" + | "export" + | "intake" + | "label" + | "link" + | "members" + | "note" + | "priority" + | "project" + | "settings" + | "state" + | "template" + | "token" + | "unknown" + | "update" + | "webhook" + | "work-item" + | "worklog"; + +// Vertical Stack Asset Types +export type VerticalStackAssetType = + | "archived-cycle" + | "archived-module" + | "archived-work-item" + | "customer" + | "cycle" + | "dashboard" + | "draft" + | "epic" + | "error-404" + | "invalid-link" + | "module" + | "no-access" + | "page" + | "project" + | "server-error" + | "teamspace" + | "view" + | "work-item"; + +// Illustration Asset Types +export type IllustrationAssetType = "inbox" | "search"; + +// Combined Asset Types for Compact (uses horizontal + illustration) +export type CompactAssetType = HorizontalStackAssetType | IllustrationAssetType; + +// Combined Asset Types for Detailed (uses vertical + illustration) +export type DetailedAssetType = VerticalStackAssetType | IllustrationAssetType; diff --git a/packages/propel/src/empty-state/assets/horizontal-stack/constant.tsx b/packages/propel/src/empty-state/assets/horizontal-stack/constant.tsx index ebaa89b450..2328b58e58 100644 --- a/packages/propel/src/empty-state/assets/horizontal-stack/constant.tsx +++ b/packages/propel/src/empty-state/assets/horizontal-stack/constant.tsx @@ -9,6 +9,7 @@ import { MembersHorizontalStackIllustration, NoteHorizontalStackIllustration, PriorityHorizontalStackIllustration, + ProjectHorizontalStackIllustration, SettingsHorizontalStackIllustration, StateHorizontalStackIllustration, TemplateHorizontalStackIllustration, @@ -61,6 +62,10 @@ export const HorizontalStackAssetsMap = [ asset: , title: "Priority", }, + { + asset: , + title: "Project", + }, { asset: , title: "Settings", diff --git a/packages/propel/src/empty-state/assets/horizontal-stack/index.ts b/packages/propel/src/empty-state/assets/horizontal-stack/index.ts index 049eb54385..35bda744d5 100644 --- a/packages/propel/src/empty-state/assets/horizontal-stack/index.ts +++ b/packages/propel/src/empty-state/assets/horizontal-stack/index.ts @@ -8,6 +8,7 @@ export * from "./link"; export * from "./members"; export * from "./note"; export * from "./priority"; +export * from "./project"; export * from "./settings"; export * from "./state"; export * from "./template"; diff --git a/packages/propel/src/empty-state/assets/horizontal-stack/project.tsx b/packages/propel/src/empty-state/assets/horizontal-stack/project.tsx new file mode 100644 index 0000000000..2417d68305 --- /dev/null +++ b/packages/propel/src/empty-state/assets/horizontal-stack/project.tsx @@ -0,0 +1,69 @@ +import { type TIllustrationAssetProps, ILLUSTRATION_COLOR_TOKEN_MAP } from "../helper"; + +export const ProjectHorizontalStackIllustration = ({ className }: TIllustrationAssetProps) => ( + + + + + + + + + + + + + +); diff --git a/packages/propel/src/empty-state/assets/illustration/constant.tsx b/packages/propel/src/empty-state/assets/illustration/constant.tsx new file mode 100644 index 0000000000..31da2e49eb --- /dev/null +++ b/packages/propel/src/empty-state/assets/illustration/constant.tsx @@ -0,0 +1,12 @@ +import { InboxIllustration, SearchIllustration } from "./"; + +export const IllustrationMap = [ + { + asset: , + title: "Inbox", + }, + { + asset: , + title: "Search", + }, +]; diff --git a/packages/propel/src/empty-state/assets/illustration/inbox.tsx b/packages/propel/src/empty-state/assets/illustration/inbox.tsx new file mode 100644 index 0000000000..93aa614f9e --- /dev/null +++ b/packages/propel/src/empty-state/assets/illustration/inbox.tsx @@ -0,0 +1,134 @@ +import { type TIllustrationAssetProps, ILLUSTRATION_COLOR_TOKEN_MAP } from "../helper"; + +export const InboxIllustration = ({ className, ...rest }: TIllustrationAssetProps) => ( + + + + + + + + + + + + + + + + + + + +); diff --git a/packages/propel/src/empty-state/assets/illustration/index.ts b/packages/propel/src/empty-state/assets/illustration/index.ts new file mode 100644 index 0000000000..0a9791fe4d --- /dev/null +++ b/packages/propel/src/empty-state/assets/illustration/index.ts @@ -0,0 +1,2 @@ +export * from "./inbox"; +export * from "./search"; diff --git a/packages/propel/src/empty-state/assets/illustration/search.tsx b/packages/propel/src/empty-state/assets/illustration/search.tsx new file mode 100644 index 0000000000..a9057f98f2 --- /dev/null +++ b/packages/propel/src/empty-state/assets/illustration/search.tsx @@ -0,0 +1,58 @@ +import { type TIllustrationAssetProps, ILLUSTRATION_COLOR_TOKEN_MAP } from "../helper"; + +export const SearchIllustration = ({ className, ...rest }: TIllustrationAssetProps) => ( + + + + + + + + + +); diff --git a/packages/propel/src/empty-state/assets/index.ts b/packages/propel/src/empty-state/assets/index.ts index 3791a83f5f..c5431d8049 100644 --- a/packages/propel/src/empty-state/assets/index.ts +++ b/packages/propel/src/empty-state/assets/index.ts @@ -1,3 +1,6 @@ -export * from "./horizontal-stack"; -export * from "./vertical-stack"; +export * from "./asset-registry"; +export * from "./asset-types"; export * from "./helper"; +export * from "./horizontal-stack"; +export * from "./illustration"; +export * from "./vertical-stack"; diff --git a/packages/propel/src/empty-state/compact-empty-state.stories.tsx b/packages/propel/src/empty-state/compact-empty-state.stories.tsx new file mode 100644 index 0000000000..d49d5f10b1 --- /dev/null +++ b/packages/propel/src/empty-state/compact-empty-state.stories.tsx @@ -0,0 +1,142 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { EmptyStateCompact } from "./compact-empty-state"; +import type { BaseEmptyStateCommonProps } from "./types"; + +const meta: Meta = { + title: "Components/EmptyState/Compact", + component: EmptyStateCompact, + parameters: { + layout: "centered", + docs: { + description: { + component: + "A compact empty state component with centered title, asset, and action buttons. Best used for simple, space-constrained empty states. Supports horizontal stack and illustration assets via `assetKey`.", + }, + }, + }, + argTypes: { + title: { + control: "text", + description: "The main title text for the empty state", + }, + assetKey: { + control: "select", + options: [ + "customer", + "epic", + "estimate", + "export", + "intake", + "label", + "link", + "members", + "note", + "priority", + "project", + "settings", + "state", + "template", + "token", + "unknown", + "update", + "webhook", + "work-item", + "worklog", + "inbox", + ], + description: "Predefined asset key (horizontal-stack or illustration)", + }, + className: { + control: "text", + description: "Additional CSS classes to apply to the content wrapper", + }, + rootClassName: { + control: "text", + description: "Additional CSS classes to apply to the root container", + }, + assetClassName: { + control: "text", + description: "Additional CSS classes to apply to the asset", + }, + asset: { + control: false, + description: "Custom React node to display as the visual asset (use this for full control instead of assetKey)", + }, + actions: { + control: false, + description: "Array of action buttons to display", + }, + }, +}; + +export default meta; +type Story = StoryObj; + +// Using assetKey (recommended approach) +export const WithAssetKey: Story = { + args: { + assetKey: "work-item", + assetClassName: "size-20", + title: "There're no progress metrics to show yet.", + }, +}; + +export const WithAssetKeyAndAction: Story = { + args: { + assetKey: "project", + assetClassName: "size-20", + title: "No projects found", + actions: [ + { + label: "Create Project", + onClick: () => console.log("create-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const WithAssetKeyAndMultipleActions: Story = { + args: { + assetKey: "members", + assetClassName: "size-20", + title: "Get started with your workspace", + actions: [ + { + label: "Create Project", + onClick: () => console.log("create-clicked"), + variant: "primary", + }, + { + label: "Import", + onClick: () => console.log("import-clicked"), + variant: "outline-primary", + }, + ], + }, +}; + +// Using custom asset (legacy approach) +export const WithCustomAsset: Story = { + args: { + asset: ( + + + + ), + title: "No items found", + actions: [ + { + label: "Create Item", + onClick: () => console.log("create-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const TitleOnly: Story = { + args: { + title: "No results found", + }, +}; diff --git a/packages/propel/src/empty-state/compact-empty-state.tsx b/packages/propel/src/empty-state/compact-empty-state.tsx new file mode 100644 index 0000000000..33f135d97c --- /dev/null +++ b/packages/propel/src/empty-state/compact-empty-state.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { Button } from "../button/button"; +import { cn } from "../utils/classname"; +import { getCompactAsset } from "./assets/asset-registry"; +import type { CompactAssetType } from "./assets/asset-types"; +import type { BaseEmptyStateCommonProps } from "./types"; + +export const EmptyStateCompact: React.FC = ({ + asset, + assetKey, + title, + description, + actions, + className, + rootClassName, + assetClassName, + align = "center", +}) => { + // Determine which asset to use: assetKey takes precedence, fallback to custom asset + const resolvedAsset = assetKey ? getCompactAsset(assetKey as CompactAssetType, assetClassName) : asset; + + const rootAlignClasses = align === "center" ? "items-center" : "items-start"; + const containerAlignClasses = align === "center" ? "items-center text-center" : "items-start text-left"; + + return ( +
+
+ {resolvedAsset &&
{resolvedAsset}
} + +
+ {title && description ? ( +
+ {title &&

{title}

} + {description &&

{description}

} +
+ ) : ( + title &&

{title}

+ )} + + {actions && actions.length > 0 && ( +
+ {actions.map((action, index) => { + const { label, variant, ...rest } = action; + return ( + + ); + })} +
+ )} +
+
+
+ ); +}; + +EmptyStateCompact.displayName = "EmptyStateCompact"; diff --git a/packages/propel/src/empty-state/detailed-empty-state.stories.tsx b/packages/propel/src/empty-state/detailed-empty-state.stories.tsx new file mode 100644 index 0000000000..a06d2cbca8 --- /dev/null +++ b/packages/propel/src/empty-state/detailed-empty-state.stories.tsx @@ -0,0 +1,295 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { EmptyStateDetailed } from "./detailed-empty-state"; +import type { BaseEmptyStateCommonProps } from "./types"; + +const meta: Meta = { + title: "Components/EmptyState/Detailed", + component: EmptyStateDetailed, + parameters: { + layout: "centered", + docs: { + description: { + component: + "A detailed empty state component with title, description, asset, and action buttons. Best used for feature-specific empty states that need more context. Supports vertical stack and illustration assets via `assetKey`.", + }, + }, + }, + argTypes: { + title: { + control: "text", + description: "The main title text for the empty state", + }, + description: { + control: "text", + description: "Optional description text that appears below the title", + }, + assetKey: { + control: "select", + options: [ + "archived-cycle", + "archived-module", + "archived-work-item", + "customer", + "cycle", + "dashboard", + "draft", + "epic", + "error-404", + "invalid-link", + "module", + "no-access", + "page", + "project", + "server-error", + "teamspace", + "view", + "work-item", + "inbox", + ], + description: "Predefined asset key (vertical-stack or illustration)", + }, + className: { + control: "text", + description: "Additional CSS classes to apply to the content wrapper", + }, + rootClassName: { + control: "text", + description: "Additional CSS classes to apply to the root container", + }, + assetClassName: { + control: "text", + description: "Additional CSS classes to apply to the asset", + }, + asset: { + control: false, + description: "Custom React node to display as the visual asset (use this for full control instead of assetKey)", + }, + actions: { + control: false, + description: "Array of action buttons to display", + }, + }, +}; + +export default meta; +type Story = StoryObj; + +// Primary story - showcases the most common usage +export const Default: Story = { + args: { + assetKey: "epic", + assetClassName: "w-40 h-45", + title: "Create an epic and split work into smaller goals", + description: "For larger bodies of work that span several cycles and can live across modules, create an epic.", + actions: [ + { + label: "Create an Epic", + onClick: () => console.log("primary-action-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const WithSingleAction: Story = { + args: { + assetKey: "project", + assetClassName: "w-40 h-45", + title: "No projects found", + description: "Get started by creating your first project to organize your work.", + actions: [ + { + label: "Create Project", + onClick: () => console.log("create-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const WithMultipleActions: Story = { + args: { + assetKey: "module", + assetClassName: "w-40 h-45", + title: "No modules found", + description: "Get started by creating your first module or import existing ones.", + actions: [ + { + label: "Create Module", + onClick: () => console.log("create-clicked"), + variant: "primary", + }, + { + label: "Import Modules", + onClick: () => console.log("import-clicked"), + variant: "outline-primary", + }, + ], + }, +}; + +export const WithoutActions: Story = { + args: { + assetKey: "dashboard", + assetClassName: "w-40 h-45", + title: "No activity yet", + description: "Your activity feed will show up here once you start using the platform.", + }, +}; + +export const ErrorState: Story = { + args: { + assetKey: "error-404", + assetClassName: "w-40 h-45", + title: "Page not found", + description: "The page you're looking for doesn't exist or has been moved.", + actions: [ + { + label: "Go to Home", + onClick: () => console.log("home-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const ServerErrorState: Story = { + name: "Error - Server", + args: { + assetKey: "server-error", + assetClassName: "w-40 h-45", + title: "Something went wrong", + description: "We're experiencing technical difficulties. Please try again later.", + actions: [ + { + label: "Retry", + onClick: () => console.log("retry-clicked"), + variant: "primary", + }, + { + label: "Contact Support", + onClick: () => console.log("support-clicked"), + variant: "outline-primary", + }, + ], + }, +}; + +export const NoAccessState: Story = { + name: "Access Denied", + args: { + assetKey: "no-access", + assetClassName: "w-40 h-45", + title: "You don't have access", + description: "Contact your workspace admin to request access to this resource.", + }, +}; + +export const ArchivedState: Story = { + name: "Archived Content", + args: { + assetKey: "archived-work-item", + assetClassName: "w-40 h-45", + title: "No archived items", + description: "Archived items will appear here when you archive them.", + }, +}; + +export const CycleState: Story = { + name: "Cycles", + args: { + assetKey: "cycle", + assetClassName: "w-40 h-45", + title: "No cycles found", + description: "Create cycles to organize your work into time-boxed iterations.", + actions: [ + { + label: "Create Cycle", + onClick: () => console.log("create-cycle-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const ModuleState: Story = { + name: "Modules", + args: { + assetKey: "module", + assetClassName: "w-40 h-45", + title: "No modules found", + description: "Modules help you organize related work items into logical groups.", + actions: [ + { + label: "Create Module", + onClick: () => console.log("create-module-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const ViewState: Story = { + name: "Views", + args: { + assetKey: "view", + assetClassName: "w-40 h-45", + title: "No saved views", + description: "Create custom views to filter and organize your work items.", + actions: [ + { + label: "Create View", + onClick: () => console.log("create-view-clicked"), + variant: "primary", + }, + ], + }, +}; + +export const PageState: Story = { + name: "Pages", + args: { + assetKey: "page", + assetClassName: "w-40 h-45", + title: "No pages found", + description: "Create pages to document your project, share knowledge, and collaborate.", + actions: [ + { + label: "Create Page", + onClick: () => console.log("create-page-clicked"), + variant: "primary", + }, + ], + }, +}; + +// Using custom asset (for special cases) +export const WithCustomAsset: Story = { + name: "Custom Asset", + args: { + asset: ( + + + + + ), + title: "Custom asset example", + description: "This example uses a custom SVG asset instead of predefined assetKey.", + actions: [ + { + label: "Get Started", + onClick: () => console.log("action-clicked"), + variant: "primary", + }, + ], + }, +}; + +// Minimal example +export const Minimal: Story = { + name: "Minimal - Text Only", + args: { + title: "No data available", + description: "Data will appear here once available.", + }, +}; diff --git a/packages/propel/src/empty-state/detailed-empty-state.tsx b/packages/propel/src/empty-state/detailed-empty-state.tsx new file mode 100644 index 0000000000..b6fd4af0c8 --- /dev/null +++ b/packages/propel/src/empty-state/detailed-empty-state.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { Button } from "../button/button"; +import { cn } from "../utils/classname"; +import { getDetailedAsset } from "./assets/asset-registry"; +import type { DetailedAssetType } from "./assets/asset-types"; +import type { BaseEmptyStateCommonProps } from "./types"; + +export const EmptyStateDetailed: React.FC = ({ + asset, + assetKey, + title, + description, + actions, + className, + rootClassName, + assetClassName, +}) => { + // Determine which asset to use: assetKey takes precedence, fallback to custom asset + const resolvedAsset = assetKey ? getDetailedAsset(assetKey as DetailedAssetType, assetClassName) : asset; + + return ( +
+
+ {resolvedAsset &&
{resolvedAsset}
} + +
+ {(title || description) && ( +
+ {title &&

{title}

} + {description &&

{description}

} +
+ )} + + {actions && actions.length > 0 && ( +
+ {actions.map((action, index) => { + const { label, variant, ...rest } = action; + return ( + + ); + })} +
+ )} +
+
+
+ ); +}; + +EmptyStateDetailed.displayName = "EmptyStateDetailed"; diff --git a/packages/propel/src/empty-state/empty-state.stories.tsx b/packages/propel/src/empty-state/empty-state.stories.tsx deleted file mode 100644 index 095bbb7115..0000000000 --- a/packages/propel/src/empty-state/empty-state.stories.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react-vite"; -import { WorkItemHorizontalStackIllustration } from "./assets/horizontal-stack"; -import { HorizontalStackAssetsMap } from "./assets/horizontal-stack/constant"; -import { WorkItemVerticalStackIllustration } from "./assets/vertical-stack"; -import { VerticalStackAssetsMap } from "./assets/vertical-stack/constant"; -import { EmptyState, type EmptyStateProps } from "./empty-state"; - -const meta: Meta = { - title: "Components/EmptyState", - component: EmptyState, - parameters: { - layout: "centered", - docs: { - description: { - component: - "A flexible empty state component that can display an asset, title, description, and action buttons.", - }, - }, - }, - argTypes: { - title: { - control: "text", - description: "The main title text for the empty state", - }, - description: { - control: "text", - description: "Optional description text that appears below the title", - }, - className: { - control: "text", - description: "Additional CSS classes to apply to the root element", - }, - type: { - control: "select", - options: ["detailed", "simple"], - description: "The layout type of the empty state", - }, - asset: { - control: false, - description: "React node to display as the visual asset (icon, illustration, etc.)", - }, - actions: { - control: false, - description: "Array of action buttons to display", - }, - }, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - asset: , - title: "Create an epic and split work into smaller goals", - description: "For larger bodies of work that span several cycles and can live across modules, create an epic.", - actions: [ - { - label: "Create an Epic", - onClick: () => console.log("primary-action-clicked"), - variant: "primary", - }, - ], - }, -}; - -export const Simple: Story = { - args: { - asset: , - title: "There're no progress metrics to show yet.", - description: "For larger bodies of work that span several cycles and can live across modules, create an epic.", - type: "simple", - }, -}; - -export const HorizontalStackAssets: Story = { - render: () => ( -
- {HorizontalStackAssetsMap.map((item) => ( -
- {item.asset} -

{item.title}

-
- ))} -
- ), -}; - -export const VerticalStackAssets: Story = { - render: () => ( -
- {VerticalStackAssetsMap.map((item) => ( -
- {item.asset} -

{item.title}

-
- ))} -
- ), -}; diff --git a/packages/propel/src/empty-state/empty-state.tsx b/packages/propel/src/empty-state/empty-state.tsx index d1dc8823be..a1304d08d4 100644 --- a/packages/propel/src/empty-state/empty-state.tsx +++ b/packages/propel/src/empty-state/empty-state.tsx @@ -1,62 +1,71 @@ import React from "react"; -import { Button } from "../button/button"; -import { TButtonVariant } from "../button/helper"; +import { CompactAssetType, DetailedAssetType } from "./assets/asset-types"; +import { EmptyStateCompact } from "./compact-empty-state"; +import { EmptyStateDetailed } from "./detailed-empty-state"; +import type { BaseEmptyStateCommonProps } from "./types"; -export interface ActionButton { - label: string; - onClick: () => void; - variant?: TButtonVariant; - disabled?: boolean; -} +/** + * @deprecated Use EmptyStateCompact or EmptyStateDetailed directly with assetKey for better type safety + * + * This wrapper component maintains backward compatibility for existing code. + * For new code, prefer: + * - EmptyStateCompact with assetKey for simple states + * - EmptyStateDetailed with assetKey for detailed states + */ -type TEmptyStateType = "detailed" | "simple"; +type EmptyStateType = "detailed" | "simple"; export interface EmptyStateProps { + /** @deprecated Use assetKey instead */ asset?: React.ReactNode; - title: string; + title?: string; description?: string; - actions?: ActionButton[]; + actions?: BaseEmptyStateCommonProps["actions"]; className?: string; - type?: TEmptyStateType; + rootClassName?: string; + assetClassName?: string; + type?: EmptyStateType; + /** Type-safe asset key (use instead of asset) */ + assetKey?: CompactAssetType | DetailedAssetType; } -const EmptyStateContent: React.FC<{ - title: string; - description?: string; - actions?: ActionButton[]; -}> = ({ title, description, actions }) => ( -
-
-

{title}

- {description &&

{description}

} -
- - {actions && actions.length > 0 && ( -
- {actions.map((action, index) => ( - - ))} -
- )} -
-); - export const EmptyState: React.FC = ({ + type = "detailed", asset, + assetKey, title, description, actions, - className = "", - type = "detailed", + className, + rootClassName, + assetClassName, }) => { - const alignmentClass = type === "simple" ? "items-center text-center" : "text-left"; + if (type === "simple") { + return ( + + ); + } return ( -
- {asset &&
{asset}
} - -
+ ); }; + +EmptyState.displayName = "EmptyState"; diff --git a/packages/propel/src/empty-state/index.ts b/packages/propel/src/empty-state/index.ts index ce215b7c3b..b38181d5e1 100644 --- a/packages/propel/src/empty-state/index.ts +++ b/packages/propel/src/empty-state/index.ts @@ -1 +1,5 @@ +export * from "./assets"; +export * from "./compact-empty-state"; +export * from "./detailed-empty-state"; export * from "./empty-state"; +export * from "./types"; diff --git a/packages/propel/src/empty-state/types.ts b/packages/propel/src/empty-state/types.ts new file mode 100644 index 0000000000..8c28867992 --- /dev/null +++ b/packages/propel/src/empty-state/types.ts @@ -0,0 +1,24 @@ +import type { TButtonVariant } from "../button/helper"; +import type { TAlign } from "../utils/placement"; +import type { CompactAssetType, DetailedAssetType } from "./assets/asset-types"; + +export interface ActionButton extends Omit, "children"> { + label: string; + variant?: TButtonVariant; + [key: `data-${string}`]: string | undefined; +} + +export interface BaseEmptyStateCommonProps { + title?: string; + actions?: ActionButton[]; + /** CSS classes for the content wrapper */ + className?: string; + /** CSS classes for the root container */ + rootClassName?: string; + /** CSS classes for the asset wrapper */ + assetClassName?: string; + description?: string; + assetKey?: CompactAssetType | DetailedAssetType; + asset?: React.ReactNode; + align?: TAlign; +}