diff --git a/packages/constants/src/index.ts b/packages/constants/src/index.ts index e2546a2003a..75e25cf91e0 100644 --- a/packages/constants/src/index.ts +++ b/packages/constants/src/index.ts @@ -15,6 +15,7 @@ export * from "./tab-indices"; export * from "./user"; export * from "./workspace"; export * from "./stickies"; +export * from "./project"; export * from "./views"; export * from "./inbox"; export * from "./profile"; diff --git a/web/core/constants/project.ts b/packages/constants/src/project.ts similarity index 66% rename from web/core/constants/project.ts rename to packages/constants/src/project.ts index e984cb968a3..6c70afcc902 100644 --- a/web/core/constants/project.ts +++ b/packages/constants/src/project.ts @@ -1,41 +1,59 @@ // icons import { Globe2, Lock, LucideIcon } from "lucide-react"; -import { TProjectAppliedDisplayFilterKeys, TProjectOrderByOptions } from "@plane/types"; +import { + TProjectAppliedDisplayFilterKeys, + TProjectOrderByOptions, +} from "@plane/types"; export const NETWORK_CHOICES: { key: 0 | 2; - label: string; + i18n_label: string; description: string; icon: LucideIcon; }[] = [ { key: 0, - label: "Private", - description: "Accessible only by invite", + i18n_label: "workspace_projects.network.private.title", + description: "workspace_projects.network.private.description", //"Accessible only by invite", icon: Lock, }, { key: 2, - label: "Public", - description: "Anyone in the workspace except Guests can join", + i18n_label: "workspace_projects.network.public.title", + description: "workspace_projects.network.public.description", //"Anyone in the workspace except Guests can join", icon: Globe2, }, ]; export const GROUP_CHOICES = { - backlog: "Backlog", - unstarted: "Unstarted", - started: "Started", - completed: "Completed", - cancelled: "Cancelled", + backlog: { + key: "backlog", + i18n_label: "workspace_projects.state.backlog", + }, + unstarted: { + key: "unstarted", + i18n_label: "workspace_projects.state.unstarted", + }, + started: { + key: "started", + i18n_label: "workspace_projects.state.started", + }, + completed: { + key: "completed", + i18n_label: "workspace_projects.state.completed", + }, + cancelled: { + key: "cancelled", + i18n_label: "workspace_projects.state.cancelled", + }, }; export const PROJECT_AUTOMATION_MONTHS = [ - { label: "1 month", value: 1 }, - { label: "3 months", value: 3 }, - { label: "6 months", value: 6 }, - { label: "9 months", value: 9 }, - { label: "12 months", value: 12 }, + { i18n_label: "common.months_count", value: 1 }, + { i18n_label: "common.months_count", value: 3 }, + { i18n_label: "common.months_count", value: 6 }, + { i18n_label: "common.months_count", value: 9 }, + { i18n_label: "common.months_count", value: 12 }, ]; export const PROJECT_UNSPLASH_COVERS = [ @@ -59,55 +77,55 @@ export const PROJECT_UNSPLASH_COVERS = [ export const PROJECT_ORDER_BY_OPTIONS: { key: TProjectOrderByOptions; - label: string; + i18n_label: string; }[] = [ { key: "sort_order", - label: "Manual", + i18n_label: "workspace_projects.sort.manual", }, { key: "name", - label: "Name", + i18n_label: "workspace_projects.sort.name", }, { key: "created_at", - label: "Created date", + i18n_label: "workspace_projects.sort.created_at", }, { key: "members_length", - label: "Number of members", + i18n_label: "workspace_projects.sort.members_length", }, ]; export const PROJECT_DISPLAY_FILTER_OPTIONS: { key: TProjectAppliedDisplayFilterKeys; - label: string; + i18n_label: string; }[] = [ { key: "my_projects", - label: "My projects", + i18n_label: "workspace_projects.scope.my_projects", }, { key: "archived_projects", - label: "Archived", + i18n_label: "workspace_projects.scope.archived_projects", }, ]; export const PROJECT_ERROR_MESSAGES = { permissionError: { - title: "You don't have permission to perform this action.", - message: undefined, + i18n_title: "workspace_projects.error.permission", + i18n_message: undefined, }, cycleDeleteError: { - title: "Error", - message: "Failed to delete cycle", + i18n_title: "error", + i18n_message: "workspace_projects.error.cycle_delete", }, moduleDeleteError: { - title: "Error", - message: "Failed to delete module", + i18n_title: "error", + i18n_message: "workspace_projects.error.module_delete", }, issueDeleteError: { - title: "Error", - message: "Failed to delete issue", + i18n_title: "error", + i18n_message: "workspace_projects.error.issue_delete", }, }; diff --git a/packages/i18n/src/locales/en/translations.json b/packages/i18n/src/locales/en/translations.json index 04a23f07b91..8391ac01ab6 100644 --- a/packages/i18n/src/locales/en/translations.json +++ b/packages/i18n/src/locales/en/translations.json @@ -312,7 +312,7 @@ "change_parent_issue": "Change parent issue", "remove_parent_issue": "Remove parent issue", "add_parent": "Add parent", - "loading_members": "Loading members...", + "loading_members": "Loading members...", "view_link_copied_to_clipboard": "View link copied to clipboard.", "required": "Required", "optional": "Optional", @@ -669,6 +669,42 @@ }, "workspace_projects": { + "network": { + "private": { + "title": "Private", + "description": "Accessible only by invite" + }, + "public": { + "title": "Public", + "description": "Anyone in the workspace except Guests can join" + } + }, + "error": { + "permission": "You don't have permission to perform this action.", + "cycle_delete": "Failed to delete cycle", + "module_delete": "Failed to delete module", + "issue_delete": "Failed to delete issue" + }, + "state": { + "backlog": "Backlog", + "unstarted": "Unstarted", + "started": "Started", + "completed": "Completed", + "cancelled": "Cancelled" + }, + "sort": { + "manual": "Manual", + "name": "Name", + "created_at": "Created date", + "members_length": "Number of members" + }, + "scope": { + "my_projects": "My projects", + "archived_projects": "Archived" + }, + "common": { + "months_count": "{months, plural, one{# month} other{# months}}" + }, "empty_state": { "general": { "title": "No active projects", diff --git a/packages/i18n/src/locales/es/translations.json b/packages/i18n/src/locales/es/translations.json index e3a66d10626..a4baa482bab 100644 --- a/packages/i18n/src/locales/es/translations.json +++ b/packages/i18n/src/locales/es/translations.json @@ -672,6 +672,42 @@ }, "workspace_projects": { + "network": { + "private": { + "title": "Privado", + "description": "Accesible solo por invitación" + }, + "public": { + "title": "Público", + "description": "Cualquiera en el espacio de trabajo excepto invitados puede unirse" + } + }, + "error": { + "permission": "No tienes permiso para realizar esta acción.", + "cycle_delete": "Error al eliminar el ciclo", + "module_delete": "Error al eliminar el módulo", + "issue_delete": "Error al eliminar la incidencia" + }, + "state": { + "backlog": "Pendientes", + "unstarted": "Sin comenzar", + "started": "Iniciado", + "completed": "Completado", + "cancelled": "Cancelado" + }, + "sort": { + "manual": "Manual", + "name": "Nombre", + "created_at": "Fecha de creación", + "members_length": "Número de miembros" + }, + "scope": { + "my_projects": "Mis proyectos", + "archived_projects": "Archivados" + }, + "common": { + "months_count": "{months, plural, one{# mes} other{# meses}}" + }, "empty_state": { "general": { "title": "No hay proyectos activos", diff --git a/packages/i18n/src/locales/fr/translations.json b/packages/i18n/src/locales/fr/translations.json index c1b951cb747..2c5847e4b93 100644 --- a/packages/i18n/src/locales/fr/translations.json +++ b/packages/i18n/src/locales/fr/translations.json @@ -667,6 +667,42 @@ }, "workspace_projects": { + "network": { + "private": { + "title": "Privé", + "description": "Accessible uniquement sur invitation" + }, + "public": { + "title": "Public", + "description": "Tout le monde dans l'espace de travail sauf les invités peut rejoindre" + } + }, + "error": { + "permission": "Vous n'avez pas la permission d'effectuer cette action.", + "cycle_delete": "Échec de la suppression du cycle", + "module_delete": "Échec de la suppression du module", + "issue_delete": "Échec de la suppression du problème" + }, + "state": { + "backlog": "Backlog", + "unstarted": "Non démarré", + "started": "Démarré", + "completed": "Terminé", + "cancelled": "Annulé" + }, + "sort": { + "manual": "Manuel", + "name": "Nom", + "created_at": "Date de création", + "members_length": "Nombre de membres" + }, + "scope": { + "my_projects": "Mes projets", + "archived_projects": "Archivés" + }, + "common": { + "months_count": "{months, plural, one{# mois} other{# mois}}" + }, "empty_state": { "general": { "title": "Aucun projet actif", diff --git a/packages/i18n/src/locales/ja/translations.json b/packages/i18n/src/locales/ja/translations.json index 8e6d6e8c7a0..7f727c34964 100644 --- a/packages/i18n/src/locales/ja/translations.json +++ b/packages/i18n/src/locales/ja/translations.json @@ -312,7 +312,7 @@ "change_parent_issue": "親問題を変更", "remove_parent_issue": "親問題を削除", "add_parent": "親問題を追加", - "loading_members": "メンバーを読み込んでいます...", + "loading_members": "メンバーを読み込んでいます...", "view_link_copied_to_clipboard": "表示リンクがクリップボードにコピーされました。", "required": "必須", "optional": "任意", @@ -670,6 +670,42 @@ }, "workspace_projects": { + "network": { + "private": { + "title": "プライベート", + "description": "招待のみでアクセス可能" + }, + "public": { + "title": "パブリック", + "description": "ゲスト以外のワークスペースのメンバーが参加可能" + } + }, + "error": { + "permission": "この操作を実行する権限がありません。", + "cycle_delete": "サイクルの削除に失敗しました", + "module_delete": "モジュールの削除に失敗しました", + "issue_delete": "課題の削除に失敗しました" + }, + "state": { + "backlog": "バックログ", + "unstarted": "未着手", + "started": "開始済み", + "completed": "完了", + "cancelled": "キャンセル" + }, + "sort": { + "manual": "手動", + "name": "名前", + "created_at": "作成日", + "members_length": "メンバー数" + }, + "scope": { + "my_projects": "自分のプロジェクト", + "archived_projects": "アーカイブ済み" + }, + "common": { + "months_count": "{months, plural, other{#ヶ月}}" + }, "empty_state": { "general": { "title": "アクティブなプロジェクトがありません", diff --git a/packages/i18n/src/locales/zh-CN/translations.json b/packages/i18n/src/locales/zh-CN/translations.json index dd99d22a90d..e75371244a2 100644 --- a/packages/i18n/src/locales/zh-CN/translations.json +++ b/packages/i18n/src/locales/zh-CN/translations.json @@ -354,7 +354,6 @@ "add_parent": "添加父问题", "loading_members": "正在加载成员...", "inbox": "收件箱", - "show_all": "显示全部", "show_less": "显示较少", "no_data_yet": "暂无数据", @@ -815,5 +814,43 @@ "message": "无法删除便签" } } + }, + "workspace_projects": { + "network": { + "private": { + "title": "私有", + "description": "仅限邀请访问" + }, + "public": { + "title": "公开", + "description": "除访客外的工作区所有成员都可加入" + } + }, + "error": { + "permission": "您没有执行此操作的权限。", + "cycle_delete": "删除周期失败", + "module_delete": "删除模块失败", + "issue_delete": "删除问题失败" + }, + "state": { + "backlog": "待办", + "unstarted": "未开始", + "started": "进行中", + "completed": "已完成", + "cancelled": "已取消" + }, + "sort": { + "manual": "手动", + "name": "名称", + "created_at": "创建日期", + "members_length": "成员数量" + }, + "scope": { + "my_projects": "我的项目", + "archived_projects": "已归档" + }, + "common": { + "months_count": "{months, plural, one{#个月} other{#个月}}" + } } } diff --git a/web/app/[workspaceSlug]/(projects)/profile/[userId]/page.tsx b/web/app/[workspaceSlug]/(projects)/profile/[userId]/page.tsx index aaacff0d7ed..0db37129c27 100644 --- a/web/app/[workspaceSlug]/(projects)/profile/[userId]/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/profile/[userId]/page.tsx @@ -3,6 +3,7 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; // types +import { GROUP_CHOICES } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IUserStateDistribution, TStateGroups } from "@plane/types"; // components @@ -17,7 +18,6 @@ import { } from "@/components/profile"; // constants import { USER_PROFILE_DATA } from "@/constants/fetch-keys"; -import { GROUP_CHOICES } from "@/constants/project"; // services import { UserService } from "@/services/user.service"; diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/page.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/page.tsx index e21532c643a..49b09693203 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/page.tsx @@ -43,8 +43,6 @@ const GeneralSettingsPage = observer(() => { ); const pageTitle = currentProjectDetails?.name ? `${currentProjectDetails?.name} - General Settings` : undefined; - // const currentNetwork = NETWORK_CHOICES.find((n) => n.key === projectDetails?.network); - // const selectedNetwork = NETWORK_CHOICES.find((n) => n.key === watch("network")); return ( <> diff --git a/web/ce/components/projects/create/attributes.tsx b/web/ce/components/projects/create/attributes.tsx index c40d45b6d41..ec20671a121 100644 --- a/web/ce/components/projects/create/attributes.tsx +++ b/web/ce/components/projects/create/attributes.tsx @@ -1,15 +1,13 @@ "use client"; import { FC } from "react"; import { Controller, useFormContext } from "react-hook-form"; -import { ETabIndices } from "@plane/constants"; +import { NETWORK_CHOICES, ETabIndices } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IProject } from "@plane/types"; // ui import { CustomSelect } from "@plane/ui"; // components import { MemberDropdown } from "@/components/dropdowns"; -// constants -import { NETWORK_CHOICES } from "@/constants/project"; // helpers import { getTabIndex } from "@/helpers/tab-indices.helper"; @@ -40,7 +38,7 @@ const ProjectAttributes: FC = (props) => { {currentNetwork ? ( <> - {currentNetwork.label} + {t(currentNetwork.i18n_label)} ) : ( {t("select_network")} @@ -58,8 +56,8 @@ const ProjectAttributes: FC = (props) => {
-

{network.label}

-

{network.description}

+

{t(network.i18n_label)}

+

{t(network.description)}

diff --git a/web/ce/components/projects/create/root.tsx b/web/ce/components/projects/create/root.tsx index 8d77d2c0150..95c509a4f7f 100644 --- a/web/ce/components/projects/create/root.tsx +++ b/web/ce/components/projects/create/root.tsx @@ -3,6 +3,7 @@ import { useState, FC } from "react"; import { observer } from "mobx-react"; import { FormProvider, useForm } from "react-hook-form"; +import { PROJECT_UNSPLASH_COVERS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // ui import { setToast, TOAST_TYPE } from "@plane/ui"; @@ -11,7 +12,6 @@ import ProjectCommonAttributes from "@/components/project/create/common-attribut import ProjectCreateHeader from "@/components/project/create/header"; import ProjectCreateButtons from "@/components/project/create/project-create-buttons"; import { PROJECT_CREATED } from "@/constants/event-tracker"; -import { PROJECT_UNSPLASH_COVERS } from "@/constants/project"; // helpers import { getRandomEmoji } from "@/helpers/emoji.helper"; // hooks diff --git a/web/core/components/analytics/custom-analytics/sidebar/sidebar-header.tsx b/web/core/components/analytics/custom-analytics/sidebar/sidebar-header.tsx index 9873d08a879..707a149221b 100644 --- a/web/core/components/analytics/custom-analytics/sidebar/sidebar-header.tsx +++ b/web/core/components/analytics/custom-analytics/sidebar/sidebar-header.tsx @@ -1,9 +1,10 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // components +import { NETWORK_CHOICES } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Logo } from "@/components/common"; // constants -import { NETWORK_CHOICES } from "@/constants/project"; // helpers import { renderFormattedDate } from "@/helpers/date-time.helper"; // hooks @@ -16,6 +17,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => { const { getCycleById } = useCycle(); const { getModuleById } = useModule(); const { getUserDetails } = useMember(); + const { t } = useTranslation(); const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined; const moduleDetails = moduleId ? getModuleById(moduleId.toString()) : undefined; @@ -91,7 +93,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
Network
- {NETWORK_CHOICES.find((n) => n.key === projectDetails?.network)?.label ?? ""} + {t(NETWORK_CHOICES.find((n) => n.key === projectDetails?.network)?.i18n_label ?? "")}
diff --git a/web/core/components/automation/auto-archive-automation.tsx b/web/core/components/automation/auto-archive-automation.tsx index 8ef488da599..800c94e8215 100644 --- a/web/core/components/automation/auto-archive-automation.tsx +++ b/web/core/components/automation/auto-archive-automation.tsx @@ -4,13 +4,14 @@ import React, { useState } from "react"; import { observer } from "mobx-react"; import { ArchiveRestore } from "lucide-react"; // types +import { PROJECT_AUTOMATION_MONTHS } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { IProject } from "@plane/types"; // ui import { CustomSelect, Loader, ToggleSwitch } from "@plane/ui"; // component import { SelectMonthModal } from "@/components/automation"; // constants -import { PROJECT_AUTOMATION_MONTHS } from "@/constants/project"; // hooks import { useProject, useUserPermissions } from "@/hooks/store"; import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; @@ -27,6 +28,7 @@ export const AutoArchiveAutomation: React.FC = observer((props) => { const [monthModal, setmonthModal] = useState(false); // store hooks const { allowPermissions } = useUserPermissions(); + const { t } = useTranslation(); const { currentProjectDetails } = useProject(); @@ -90,8 +92,8 @@ export const AutoArchiveAutomation: React.FC = observer((props) => { > <> {PROJECT_AUTOMATION_MONTHS.map((month) => ( - - {month.label} + + {t(month.i18n_label, { month: month.value })} ))} diff --git a/web/core/components/automation/auto-close-automation.tsx b/web/core/components/automation/auto-close-automation.tsx index dce5764d420..9dfd8fcaa68 100644 --- a/web/core/components/automation/auto-close-automation.tsx +++ b/web/core/components/automation/auto-close-automation.tsx @@ -5,13 +5,14 @@ import { observer } from "mobx-react"; // icons import { ArchiveX } from "lucide-react"; // types +import { PROJECT_AUTOMATION_MONTHS } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { IProject } from "@plane/types"; // ui import { CustomSelect, CustomSearchSelect, ToggleSwitch, StateGroupIcon, DoubleCircleIcon, Loader } from "@plane/ui"; // component import { SelectMonthModal } from "@/components/automation"; // constants -import { PROJECT_AUTOMATION_MONTHS } from "@/constants/project"; // hooks import { useProject, useProjectState, useUserPermissions } from "@/hooks/store"; import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; @@ -28,6 +29,7 @@ export const AutoCloseAutomation: React.FC = observer((props) => { const { currentProjectDetails } = useProject(); const { projectStates } = useProjectState(); const { allowPermissions } = useUserPermissions(); + const { t } = useTranslation(); // const stateGroups = projectStateStore.groupedProjectStates ?? undefined; @@ -117,8 +119,8 @@ export const AutoCloseAutomation: React.FC = observer((props) => { > <> {PROJECT_AUTOMATION_MONTHS.map((month) => ( - - {month.label} + + {t(month.i18n_label, { month: month.value })} ))}