diff --git a/packages/constants/src/workspace.ts b/packages/constants/src/workspace.ts index 8fd77cb572b..3bbb5b1f31f 100644 --- a/packages/constants/src/workspace.ts +++ b/packages/constants/src/workspace.ts @@ -121,7 +121,7 @@ export const WORKSPACE_SETTINGS = { }, "api-tokens": { key: "api-tokens", - i18n_label: "workspace_settings.settings.webhooks.title", + i18n_label: "workspace_settings.settings.api_tokens.title", href: `/settings/api-tokens`, access: [EUserWorkspaceRoles.ADMIN], highlight: (pathname: string, baseUrl: string) => diff --git a/packages/i18n/src/locales/en/translations.json b/packages/i18n/src/locales/en/translations.json index cab40f4fec0..6fc3f296aae 100644 --- a/packages/i18n/src/locales/en/translations.json +++ b/packages/i18n/src/locales/en/translations.json @@ -352,6 +352,17 @@ "no_labels_yet": "No labels yet", "ideal": "Ideal", "current": "Current", + "no_matching_members": "No matching members", + "leaving": "Leaving", + "removing": "Removing", + "leave": "Leave", + "refreshing": "Refreshing", + "refresh_status": "Refresh status", + "prev": "Prev", + "next": "Next", + "re_generating": "Re-generating", + "re_generate": "Re-generate", + "re_generate_key": "Re-generate key", "project_view": { "sort_by": { @@ -895,24 +906,124 @@ "workspace_settings": { "label": "Workspace settings", + "key_created": "Key created", + "copy_key": "Copy and save this secret key in Plane Pages. You can't see this key after you hit Close. A CSV file containing the key has been downloaded.", + "token_copied": "Token copied to clipboard.", "settings": { "general": { - "title": "General" + "title": "General", + "upload_logo": "Upload logo", + "edit_logo": "Edit logo", + "name": "Workspace name", + "company_size": "Company size", + "url": "Workspace URL", + "update_workspace" : "Update workspace", + "delete_workspace" : "Delete workspace", + "delete_workspace_description" : "When deleting a workspace, all of the data and resources within that workspace will be permanently removed and cannot be recovered.", + "delete_btn": "Delete my workspace", + "errors": { + "name": { + "required": "Name is required", + "max_length": "Workspace name should not exceed 80 characters" + }, + "company_size": { + "required": "Company size is required" + } + } }, "members": { - "title": "Members" + "title": "Members", + "add_member": "Add member", + "invitations_sent_successfully": "Invitations sent successfully", + "leave_confirmation": "Are you sure you want to leave the workspace? You will no longer have access to this workspace. This action cannot be undone.", + "details":{ + "full_name":"Full name", + "display_name":"Display name", + "email_address":"Email address", + "account_type":"Account type", + "authentication":"Authentication", + "joining_date":"Joining date" + } }, - "billing-and-plans": { - "title": "Billing & Plans" + "billing_and_plans": { + "title": "Billing & Plans", + "current_plan":"Current plan", + "free_plan":"You are currently using the free plan", + "view_plans":"View plans" }, "exports": { - "title": "Exports" + "title": "Exports", + "exporting": "Exporting", + "previous_exports": "Previous exports", + "export_separate_files" : "Export the data into separate files", + "modal": { + "title": "Export to", + "toasts": { + "success": { + "title": "Export successful", + "message": "You will be able to download the exported {entity} from the previous export." + }, + "error": { + "title": "Export failed", + "message": "Export was unsuccessful. Please try again." + } + } + } }, "webhooks": { - "title": "Webhooks" + "title": "Webhooks", + "add_webhook": "Add webhook", + "modal": { + "title": "Create webhook", + "details": "Webhook details", + "payload": "Payload URL", + "question": "Which events would you like to trigger this webhook?" , + "error": "URL is required" + }, + "secret_key": { + "title": "Secret key", + "message": "Generate a token to sign-in to the webhook payload" + }, + "toasts": { + "created": { + "title": "Webhook created", + "message": "The webhook has been successfully created" + }, + "not_created": { + "title": "Webhook not created", + "message": "The webhook could not be created" + }, + "updated": { + "title": "Webhook updated", + "message": "The webhook has been successfully updated" + }, + "not_updated": { + "title": "Webhook not updated", + "message": "The webhook could not be updated" + }, + "removed": { + "title": "Webhook removed", + "message": "The webhook has been successfully removed" + }, + "not_removed": { + "title": "Webhook not removed", + "message": "The webhook could not be removed" + }, + "secret_key_copied": { + "message": "Secret key copied to clipboard." + }, + "secret_key_not_copied": { + "message": "Error occurred while copying secret key." + } + } }, - "api-tokens": { - "title": "API Tokens" + "api_tokens": { + "title": "API Tokens", + "add_token": "Add API token", + "create_token": "Create token", + "never_expires": "Never expires", + "generate_token": "Generate token", + "generating": "Generating" } }, "empty_state": { diff --git a/web/app/[workspaceSlug]/(projects)/settings/api-tokens/page.tsx b/web/app/[workspaceSlug]/(projects)/settings/api-tokens/page.tsx index 03bb1fa6cbe..6c46a1d812a 100644 --- a/web/app/[workspaceSlug]/(projects)/settings/api-tokens/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/settings/api-tokens/page.tsx @@ -43,7 +43,9 @@ const ApiTokensPage = observer(() => { workspaceSlug && canPerformWorkspaceAdminActions ? apiTokenService.getApiTokens(workspaceSlug.toString()) : null ); - const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - API Tokens` : undefined; + const pageTitle = currentWorkspace?.name + ? `${currentWorkspace.name} - ${t("workspace_settings.settings.api_tokens.title")}` + : undefined; if (workspaceUserInfo && !canPerformWorkspaceAdminActions) { return ; @@ -61,9 +63,9 @@ const ApiTokensPage = observer(() => { {tokens.length > 0 ? ( <>
-

API tokens

+

{t("workspace_settings.settings.api_tokens.title")}

@@ -75,9 +77,9 @@ const ApiTokensPage = observer(() => { ) : (
-

API tokens

+

{t("workspace_settings.settings.api_tokens.title")}

diff --git a/web/app/[workspaceSlug]/(projects)/settings/exports/page.tsx b/web/app/[workspaceSlug]/(projects)/settings/exports/page.tsx index dc3f3aafce7..0c6c26b377f 100644 --- a/web/app/[workspaceSlug]/(projects)/settings/exports/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/settings/exports/page.tsx @@ -2,6 +2,7 @@ import { observer } from "mobx-react"; // components +import { useTranslation } from "@plane/i18n"; import { NotAuthorizedView } from "@/components/auth-screens"; import { PageHead } from "@/components/core"; import ExportGuide from "@/components/exporter/guide"; @@ -15,13 +16,16 @@ const ExportsPage = observer(() => { // store hooks const { workspaceUserInfo, allowPermissions } = useUserPermissions(); const { currentWorkspace } = useWorkspace(); + const { t } = useTranslation(); // derived values const canPerformWorkspaceMemberActions = allowPermissions( [EUserPermissions.ADMIN, EUserPermissions.MEMBER], EUserPermissionsLevel.WORKSPACE ); - const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Exports` : undefined; + const pageTitle = currentWorkspace?.name + ? `${currentWorkspace.name} - ${t("workspace_settings.settings.exports.title")}` + : undefined; // if user is not authorized to view this page if (workspaceUserInfo && !canPerformWorkspaceMemberActions) { @@ -37,7 +41,7 @@ const ExportsPage = observer(() => { })} >
-

Exports

+

{t("workspace_settings.settings.exports.title")}

diff --git a/web/app/[workspaceSlug]/(projects)/settings/members/page.tsx b/web/app/[workspaceSlug]/(projects)/settings/members/page.tsx index 2b869612773..861548d23c7 100644 --- a/web/app/[workspaceSlug]/(projects)/settings/members/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/settings/members/page.tsx @@ -6,6 +6,7 @@ import { useParams } from "next/navigation"; import { Search } from "lucide-react"; // types import { MEMBER_INVITED } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { IWorkspaceBulkInviteFormData } from "@plane/types"; // ui import { Button, TOAST_TYPE, setToast } from "@plane/ui"; @@ -34,6 +35,7 @@ const WorkspaceMembersSettingsPage = observer(() => { workspace: { inviteMembersToWorkspace }, } = useMember(); const { currentWorkspace } = useWorkspace(); + const { t } = useTranslation(); // derived values const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE); @@ -62,7 +64,7 @@ const WorkspaceMembersSettingsPage = observer(() => { setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", - message: "Invitations sent successfully.", + message: t("workspace_settings.settings.members.invitations_sent_successfully"), }); }) .catch((err) => { @@ -80,7 +82,7 @@ const WorkspaceMembersSettingsPage = observer(() => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", - message: `${err.error ?? "Something went wrong. Please try again."}`, + message: `${err.error ?? t("something_went_wrong_please_try_again")}`, }); }); }; @@ -107,12 +109,12 @@ const WorkspaceMembersSettingsPage = observer(() => { })} >
-

Members

+

{t("workspace_settings.settings.members.title")}

setSearchQuery(e.target.value)} @@ -120,7 +122,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
{canPerformWorkspaceAdminActions && ( )}
diff --git a/web/app/[workspaceSlug]/(projects)/settings/sidebar.tsx b/web/app/[workspaceSlug]/(projects)/settings/sidebar.tsx index 8dfe7437938..c071622e601 100644 --- a/web/app/[workspaceSlug]/(projects)/settings/sidebar.tsx +++ b/web/app/[workspaceSlug]/(projects)/settings/sidebar.tsx @@ -26,7 +26,7 @@ export const WorkspaceSettingsSidebar = observer(() => { return (
- SETTINGS + {t("settings")}
{WORKSPACE_SETTINGS_LINKS.map( (link) => diff --git a/web/app/[workspaceSlug]/(projects)/settings/webhooks/page.tsx b/web/app/[workspaceSlug]/(projects)/settings/webhooks/page.tsx index 412c29f5dd2..0b300928c5c 100644 --- a/web/app/[workspaceSlug]/(projects)/settings/webhooks/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/settings/webhooks/page.tsx @@ -38,7 +38,9 @@ const WebhooksListPage = observer(() => { workspaceSlug && canPerformWorkspaceAdminActions ? () => fetchWebhooks(workspaceSlug.toString()) : null ); - const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Webhooks` : undefined; + const pageTitle = currentWorkspace?.name + ? `${currentWorkspace.name} - ${t("workspace_settings.settings.webhooks.title")}` + : undefined; // clear secret key when modal is closed. useEffect(() => { @@ -67,9 +69,9 @@ const WebhooksListPage = observer(() => { {Object.keys(webhooks).length > 0 ? (
-
Webhooks
+
{t("workspace_settings.settings.webhooks.title")}
@@ -77,9 +79,9 @@ const WebhooksListPage = observer(() => { ) : (
-
Webhooks
+
{t("workspace_settings.settings.webhooks.title")}
diff --git a/web/ce/components/workspace/billing/root.tsx b/web/ce/components/workspace/billing/root.tsx index 4acba0af06d..e9c6bd8f7c0 100644 --- a/web/ce/components/workspace/billing/root.tsx +++ b/web/ce/components/workspace/billing/root.tsx @@ -1,21 +1,27 @@ import { MARKETING_PRICING_PAGE_LINK } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/ui"; -export const BillingRoot = () => ( -
-
-
-

Billing and Plans

-
-
-
+export const BillingRoot = () => { + const { t } = useTranslation(); + return ( +
-

Current plan

-

You are currently using the free plan

- - - +
+

{t("workspace_settings.settings.billing_and_plans.title")}

+
+
+
+
+

{t("workspace_settings.settings.billing_and_plans.current_plan")}

+

+ {t("workspace_settings.settings.billing_and_plans.free_plan")} +

+ + + +
-
-
-); + + ); +}; diff --git a/web/ce/components/workspace/delete-workspace-section.tsx b/web/ce/components/workspace/delete-workspace-section.tsx index 93836284f8f..81fc754593f 100644 --- a/web/ce/components/workspace/delete-workspace-section.tsx +++ b/web/ce/components/workspace/delete-workspace-section.tsx @@ -2,6 +2,7 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; import { ChevronDown, ChevronUp } from "lucide-react"; // types +import { useTranslation } from "@plane/i18n"; import { IWorkspace } from "@plane/types"; // ui import { Button, Collapsible } from "@plane/ui"; @@ -17,6 +18,7 @@ export const DeleteWorkspaceSection: FC = observer((props) => // states const [isOpen, setIsOpen] = useState(false); const [deleteWorkspaceModal, setDeleteWorkspaceModal] = useState(false); + const { t } = useTranslation(); return ( <> @@ -34,19 +36,20 @@ export const DeleteWorkspaceSection: FC = observer((props) => buttonClassName="flex w-full items-center justify-between py-4" title={ <> - Delete workspace + + {t("workspace_settings.settings.general.delete_workspace")} + {isOpen ? : } } >
- When deleting a workspace, all of the data and resources within that workspace will be permanently - removed and cannot be recovered. + {t("workspace_settings.settings.general.delete_workspace_description")}
diff --git a/web/ce/components/workspace/settings/useMemberColumns.tsx b/web/ce/components/workspace/settings/useMemberColumns.tsx index 64c92cf52ab..f58a1ea9297 100644 --- a/web/ce/components/workspace/settings/useMemberColumns.tsx +++ b/web/ce/components/workspace/settings/useMemberColumns.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; import { useParams } from "next/navigation"; +import { useTranslation } from "@plane/i18n"; import { AccountTypeColumn, NameColumn, RowData } from "@/components/workspace/settings/member-columns"; import { useUser, useUserPermissions } from "@/hooks/store"; import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; @@ -12,6 +13,7 @@ export const useMemberColumns = () => { const { data: currentUser } = useUser(); const { allowPermissions } = useUserPermissions(); + const { t } = useTranslation(); const getFormattedDate = (dateStr: string) => { const date = new Date(dateStr); @@ -26,7 +28,7 @@ export const useMemberColumns = () => { const columns = [ { key: "Full name", - content: "Full name", + content: t("workspace_settings.settings.members.details.full_name"), thClassName: "text-left", tdRender: (rowData: RowData) => ( { { key: "Display name", - content: "Display name", + content: t("workspace_settings.settings.members.details.display_name"), tdRender: (rowData: RowData) =>
{rowData.member.display_name}
, }, { key: "Email address", - content: "Email address", + content: t("workspace_settings.settings.members.details.email_address"), tdRender: (rowData: RowData) =>
{rowData.member.email}
, }, { key: "Account type", - content: "Account type", + content: t("workspace_settings.settings.members.details.account_type"), tdRender: (rowData: RowData) => , }, { key: "Authentication", - content: "Authentication", + content: t("workspace_settings.settings.members.details.authentication"), tdRender: (rowData: RowData) => (
{rowData.member.last_login_medium?.replace("-", " ")}
), @@ -67,7 +69,7 @@ export const useMemberColumns = () => { { key: "Joining date", - content: "Joining date", + content: t("workspace_settings.settings.members.details.joining_date"), tdRender: (rowData: RowData) =>
{getFormattedDate(rowData?.member?.joining_date || "")}
, }, ]; diff --git a/web/core/components/api-token/modal/form.tsx b/web/core/components/api-token/modal/form.tsx index 18ade7f2af7..17e14ae563c 100644 --- a/web/core/components/api-token/modal/form.tsx +++ b/web/core/components/api-token/modal/form.tsx @@ -5,6 +5,7 @@ import { add } from "date-fns"; import { Controller, useForm } from "react-hook-form"; import { Calendar } from "lucide-react"; // types +import { useTranslation } from "@plane/i18n"; import { IApiToken } from "@plane/types"; // ui import { Button, CustomSelect, Input, TextArea, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui"; @@ -76,6 +77,8 @@ export const CreateApiTokenForm: React.FC = (props) => { reset, watch, } = useForm({ defaultValues }); + // hooks + const { t } = useTranslation(); const handleFormSubmit = async (data: IApiToken) => { // if never expires is toggled off, and the user has not selected a custom date or a predefined date, show an error @@ -115,19 +118,21 @@ export const CreateApiTokenForm: React.FC = (props) => { return (
-

Create token

+

+ {t("workspace_settings.settings.api_tokens.create_token")} +

val.trim() !== "" || "Title is required", + validate: (val) => val.trim() !== "" || t("title_is_required"), }} render={({ field: { value, onChange } }) => ( = (props) => { value={value} onChange={onChange} hasError={Boolean(errors.label)} - placeholder="Title" + placeholder={t("title")} className="w-full text-base" /> )} @@ -150,7 +155,7 @@ export const CreateApiTokenForm: React.FC = (props) => { value={value} onChange={onChange} hasError={Boolean(errors.description)} - placeholder="Description" + placeholder={t("description")} className="w-full text-base resize-none min-h-24" /> )} @@ -229,14 +234,16 @@ export const CreateApiTokenForm: React.FC = (props) => {
{}} size="sm" />
- Never expires + {t("workspace_settings.settings.api_tokens.never_expires")}
diff --git a/web/core/components/api-token/modal/generated-token-details.tsx b/web/core/components/api-token/modal/generated-token-details.tsx index 8f0a62c3ac8..da833cefb3e 100644 --- a/web/core/components/api-token/modal/generated-token-details.tsx +++ b/web/core/components/api-token/modal/generated-token-details.tsx @@ -1,6 +1,7 @@ "use client"; import { Copy } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; import { IApiToken } from "@plane/types"; // ui import { Button, Tooltip, TOAST_TYPE, setToast } from "@plane/ui"; @@ -19,12 +20,13 @@ type Props = { export const GeneratedTokenDetails: React.FC = (props) => { const { handleClose, tokenDetails } = props; const { isMobile } = usePlatformOS(); + const { t } = useTranslation(); const copyApiToken = (token: string) => { copyTextToClipboard(token).then(() => setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: "Token copied to clipboard.", + title: `${t("success")}!`, + message: t("workspace_setting.token_copied"), }) ); }; @@ -32,11 +34,8 @@ export const GeneratedTokenDetails: React.FC = (props) => { return (
-

Key created

-

- Copy and save this secret key in Plane Pages. You can{"'"}t see this key after you hit Close. A CSV file - containing the key has been downloaded. -

+

{t("workspace_settings.key_created")}

+

{t("workspace_settings.copy_key")}

diff --git a/web/core/components/exporter/export-modal.tsx b/web/core/components/exporter/export-modal.tsx index 0c3d6cf0ba5..b54ea7d8cfe 100644 --- a/web/core/components/exporter/export-modal.tsx +++ b/web/core/components/exporter/export-modal.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Dialog, Transition } from "@headlessui/react"; // types +import { useTranslation } from "@plane/i18n"; import { IUser, IImporterService } from "@plane/types"; // ui import { Button, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui"; @@ -36,6 +37,7 @@ export const Exporter: React.FC = observer((props) => { // store hooks const { workspaceProjectIds, getProjectById } = useProject(); const { projectsWithCreatePermissions } = useUser(); + const { t } = useTranslation(); const wsProjectIdsWithCreatePermisisons = projectsWithCreatePermissions ? intersection(workspaceProjectIds, Object.keys(projectsWithCreatePermissions)) @@ -77,18 +79,18 @@ export const Exporter: React.FC = observer((props) => { setExportLoading(false); setToast({ type: TOAST_TYPE.SUCCESS, - title: "Export Successful", - message: `You will be able to download the exported ${ - provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : "" - } from the previous export.`, + title: t("workspace_settings.settings.exports.modal.success.title"), + message: t("workspace_settings.settings.exports.modal.success.message", { + entity: provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : "", + }), }); }) .catch(() => { setExportLoading(false); setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Export was unsuccessful. Please try again.", + title: t("error"), + message: t("workspace_settings.settings.exports.modal.error.message"), }); }); } @@ -131,7 +133,7 @@ export const Exporter: React.FC = observer((props) => {

- Export to{" "} + {t("workspace_settings.settings.exports.modal.title")}{" "} {provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : ""}

@@ -165,11 +167,13 @@ export const Exporter: React.FC = observer((props) => { className="flex max-w-min cursor-pointer items-center gap-2" > setMultiple(!multiple)} /> -
Export the data into separate files
+
+ {t("workspace_settings.settings.exports.export_separate_files")} +
diff --git a/web/core/components/exporter/guide.tsx b/web/core/components/exporter/guide.tsx index 828afab0c1c..7e53cf93c1e 100644 --- a/web/core/components/exporter/guide.tsx +++ b/web/core/components/exporter/guide.tsx @@ -140,7 +140,9 @@ const IntegrationGuide = observer(() => {
-

Previous exports

+

+ {t("workspace_settings.settings.exports.previous_exports")} +

@@ -162,7 +164,7 @@ const IntegrationGuide = observer(() => { }`} > -
Prev
+
{t("prev")}
diff --git a/web/core/components/web-hooks/create-webhook-modal.tsx b/web/core/components/web-hooks/create-webhook-modal.tsx index 87a564cba4a..d5eecbe9c7a 100644 --- a/web/core/components/web-hooks/create-webhook-modal.tsx +++ b/web/core/components/web-hooks/create-webhook-modal.tsx @@ -3,6 +3,7 @@ import React, { useState } from "react"; import { useParams } from "next/navigation"; // types +import { useTranslation } from "@plane/i18n"; import { IWebhook, IWorkspace, TWebhookEventTypes } from "@plane/types"; // ui import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; @@ -34,6 +35,7 @@ export const CreateWebhookModal: React.FC = (props) => { const [generatedWebhook, setGeneratedKey] = useState(null); // router const { workspaceSlug } = useParams(); + const { t } = useTranslation(); const handleCreateWebhook = async (formData: IWebhook, webhookEventType: TWebhookEventTypes) => { if (!workspaceSlug) return; @@ -65,8 +67,8 @@ export const CreateWebhookModal: React.FC = (props) => { .then(({ webHook, secretKey }) => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: "Webhook created successfully.", + title: t("workspace_settings.settings.webhooks.toasts.created.title"), + message: t("workspace_settings.settings.webhooks.toasts.created.message"), }); setGeneratedKey(webHook); @@ -77,8 +79,8 @@ export const CreateWebhookModal: React.FC = (props) => { .catch((error) => { setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", - message: error?.error ?? "Something went wrong. Please try again.", + title: t("workspace_settings.settings.webhooks.toasts.not_created.title"), + message: error?.error ?? t("workspace_settings.settings.webhooks.toasts.not_created.message"), }); }); }; diff --git a/web/core/components/web-hooks/form/event-types.tsx b/web/core/components/web-hooks/form/event-types.tsx index c90500a7405..dd69dbf8953 100644 --- a/web/core/components/web-hooks/form/event-types.tsx +++ b/web/core/components/web-hooks/form/event-types.tsx @@ -1,4 +1,5 @@ // types +import { useTranslation } from "@plane/i18n"; import { TWebhookEventTypes } from "@plane/types"; type Props = { @@ -19,10 +20,11 @@ const WEBHOOK_EVENT_TYPES: { key: TWebhookEventTypes; label: string }[] = [ export const WebhookOptions: React.FC = (props) => { const { value, onChange } = props; + const { t } = useTranslation(); return ( <> -
Which events would you like to trigger this webhook?
+
{t("workspace_settings.settings.webhooks.modal.question")}
{WEBHOOK_EVENT_TYPES.map((option) => (
diff --git a/web/core/components/web-hooks/form/form.tsx b/web/core/components/web-hooks/form/form.tsx index bbb953cb382..ba55a75b302 100644 --- a/web/core/components/web-hooks/form/form.tsx +++ b/web/core/components/web-hooks/form/form.tsx @@ -3,6 +3,7 @@ import React, { FC, useEffect, useState } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; +import { useTranslation } from "@plane/i18n"; import { IWebhook, TWebhookEventTypes } from "@plane/types"; // hooks import { Button } from "@plane/ui"; @@ -39,6 +40,7 @@ export const WebhookForm: FC = observer((props) => { const [webhookEventType, setWebhookEventType] = useState("all"); // store hooks const { webhookSecretKey } = useWebhook(); + const { t } = useTranslation(); // use form const { handleSubmit, @@ -62,14 +64,18 @@ export const WebhookForm: FC = observer((props) => { return (
-
{data ? "Webhook details" : "Create webhook"}
+
+ {data + ? t("workspace_settings.settings.webhooks.modal.details") + : t("workspace_settings.settings.webhooks.modal.title")} +
( @@ -88,17 +94,17 @@ export const WebhookForm: FC = observer((props) => {
) : (
{!webhookSecretKey && ( - )}
diff --git a/web/core/components/web-hooks/form/input.tsx b/web/core/components/web-hooks/form/input.tsx index 997e97e7974..c5ee281aa6b 100644 --- a/web/core/components/web-hooks/form/input.tsx +++ b/web/core/components/web-hooks/form/input.tsx @@ -1,5 +1,6 @@ "use client"; +import { useTranslation } from "@plane/i18n"; import { Input } from "@plane/ui"; type Props = { @@ -9,10 +10,11 @@ type Props = { }; export const WebhookInput: React.FC = (props) => { const { value, onChange, hasError } = props; + const { t } = useTranslation(); return ( <> -
Payload URL
+
{t("workspace_settings.settings.webhooks.modal.payload")}
= observer((props) => { const { currentWorkspace } = useWorkspace(); const { currentWebhook, regenerateSecretKey, webhookSecretKey } = useWebhook(); const { isMobile } = usePlatformOS(); + const { t } = useTranslation(); const handleCopySecretKey = () => { if (!webhookSecretKey) return; @@ -42,15 +44,15 @@ export const WebhookSecretKey: FC = observer((props) => { .then(() => setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: "Secret key copied to clipboard.", + title: `${t("success")!}`, + message: t("workspace_settings.settings.webhooks.toasts.secret_key_copied.message"), }) ) .catch(() => setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Error occurred while copying secret key.", + title: `${t("error")}!`, + message: t("workspace_settings.settings.webhooks.toasts.secret_key_not_copied.message"), }) ); }; @@ -64,7 +66,7 @@ export const WebhookSecretKey: FC = observer((props) => { .then(() => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success!", + title: `${t("success")!}`, message: "New key regenerated successfully.", }); @@ -76,8 +78,8 @@ export const WebhookSecretKey: FC = observer((props) => { .catch((err) => setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", - message: err?.error ?? "Something went wrong. Please try again.", + title: `${t("error")}!`, + message: err?.error ?? t("something_went_wrong_please_try_again"), }) ) .finally(() => setIsRegenerating(false)); @@ -94,8 +96,14 @@ export const WebhookSecretKey: FC = observer((props) => { <> {(data || webhookSecretKey) && (
- {webhookId &&
Secret key
} -
Generate a token to sign-in to the webhook payload
+ {webhookId && ( +
+ {t("workspace_settings.settings.webhooks.modal.secret_key.title")} +
+ )} +
+ {t("workspace_settings.settings.webhooks.modal.secret_key.message")} +
@@ -125,7 +133,7 @@ export const WebhookSecretKey: FC = observer((props) => {
)} diff --git a/web/core/components/web-hooks/generated-hook-details.tsx b/web/core/components/web-hooks/generated-hook-details.tsx index 2db0bcc79ff..bf616e88005 100644 --- a/web/core/components/web-hooks/generated-hook-details.tsx +++ b/web/core/components/web-hooks/generated-hook-details.tsx @@ -2,6 +2,7 @@ // components // ui +import { useTranslation } from "@plane/i18n"; import { IWebhook } from "@plane/types"; import { Button } from "@plane/ui"; // types @@ -14,15 +15,17 @@ type Props = { export const GeneratedHookDetails: React.FC = (props) => { const { handleClose, webhookDetails } = props; + const { t } = useTranslation(); return ( <>
-

Key created

+

+ {t("workspace_settings.settings.webhooks.modal.secret_key.created")} +

- Copy and save this secret key in Plane Pages. You can{"'"}t see this key after you hit Close. A CSV file - containing the key has been downloaded. + {t("workspace_settings.settings.webhooks.modal.secret_key.copy_message")}

diff --git a/web/core/components/workspace/confirm-workspace-member-remove.tsx b/web/core/components/workspace/confirm-workspace-member-remove.tsx index 51408d1ee86..07bd56a129d 100644 --- a/web/core/components/workspace/confirm-workspace-member-remove.tsx +++ b/web/core/components/workspace/confirm-workspace-member-remove.tsx @@ -5,6 +5,7 @@ import { observer } from "mobx-react"; import { AlertTriangle } from "lucide-react"; import { Dialog, Transition } from "@headlessui/react"; // ui +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/ui"; // hooks import { useUser } from "@/hooks/store"; @@ -25,6 +26,7 @@ export const ConfirmWorkspaceMemberRemove: React.FC = observer((props) => const [isRemoving, setIsRemoving] = useState(false); // store hooks const { data: currentUser } = useUser(); + const { t } = useTranslation(); const handleClose = () => { onClose(); @@ -80,11 +82,11 @@ export const ConfirmWorkspaceMemberRemove: React.FC = observer((props) =>
{currentUser?.id === userDetails.id ? (

- Are you sure you want to leave the workspace? You will no longer have access to this - workspace. This action cannot be undone. + {t("workspace_settings.settings.members.leave_confirmation")}

) : (

+ {/* TODO: Add translation here */} Are you sure you want to remove member-{" "} {userDetails?.display_name}? They will no longer have access to this workspace. This action cannot be undone. @@ -96,16 +98,16 @@ export const ConfirmWorkspaceMemberRemove: React.FC = observer((props) =>

diff --git a/web/core/components/workspace/settings/invitations-list-item.tsx b/web/core/components/workspace/settings/invitations-list-item.tsx index 60a7402cccc..ef531f79ab3 100644 --- a/web/core/components/workspace/settings/invitations-list-item.tsx +++ b/web/core/components/workspace/settings/invitations-list-item.tsx @@ -7,6 +7,7 @@ import { ChevronDown, XCircle } from "lucide-react"; // plane imports import { ROLE } from "@plane/constants"; // ui +import { useTranslation } from "@plane/i18n"; import { CustomSelect, Tooltip, TOAST_TYPE, setToast } from "@plane/ui"; // components import { ConfirmWorkspaceMemberRemove } from "@/components/workspace"; @@ -28,6 +29,7 @@ export const WorkspaceInvitationsListItem: FC = observer((props) => { const { workspaceSlug } = useParams(); // store hooks const { allowPermissions, workspaceInfoBySlug } = useUserPermissions(); + const { t } = useTranslation(); const { workspace: { updateMemberInvitation, deleteMemberInvitation, getWorkspaceInvitationDetails }, @@ -96,7 +98,7 @@ export const WorkspaceInvitationsListItem: FC = observer((props) => {
-

Pending

+

{t("pending")}

= observer((props) => { } = useMember(); const { leaveWorkspace } = useUserPermissions(); const { captureEvent } = useEventTracker(); + const { t } = useTranslation(); // derived values const handleLeaveWorkspace = async () => { @@ -49,7 +51,7 @@ export const WorkspaceMembersListItem: FC = observer((props) => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", - message: err?.error || "Something went wrong. Please try again.", + message: err?.error || t("something_went_wrong_please_try_again"), }) ); }; @@ -61,7 +63,7 @@ export const WorkspaceMembersListItem: FC = observer((props) => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", - message: err?.error || "Something went wrong. Please try again.", + message: err?.error || t("something_went_wrong_please_try_again"), }) ); }; diff --git a/web/core/components/workspace/settings/members-list.tsx b/web/core/components/workspace/settings/members-list.tsx index 9c19d2f8fe6..5b5bd0983a1 100644 --- a/web/core/components/workspace/settings/members-list.tsx +++ b/web/core/components/workspace/settings/members-list.tsx @@ -4,6 +4,7 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; import { ChevronDown } from "lucide-react"; import { Disclosure } from "@headlessui/react"; +import { useTranslation } from "@plane/i18n"; import { Collapsible } from "@plane/ui"; import { CountChip } from "@/components/common"; import { MembersSettingsLoader } from "@/components/ui"; @@ -29,6 +30,7 @@ export const WorkspaceMembersList: FC<{ searchQuery: string; isAdmin: boolean }> getWorkspaceMemberDetails, }, } = useMember(); + const { t } = useTranslation(); // fetching workspace invitations useSWR( workspaceSlug ? `WORKSPACE_MEMBERS_AND_MEMBER_INVITATIONS_${workspaceSlug.toString()}` : null, @@ -52,7 +54,7 @@ export const WorkspaceMembersList: FC<{ searchQuery: string; isAdmin: boolean }>
{searchedMemberIds?.length !== 0 && } {searchedInvitationsIds?.length === 0 && searchedMemberIds?.length === 0 && ( -

No matching members

+

{t("no_matching_members")}

)}
{isAdmin && searchedInvitationsIds && searchedInvitationsIds.length > 0 && ( @@ -63,7 +65,7 @@ export const WorkspaceMembersList: FC<{ searchQuery: string; isAdmin: boolean }> title={
-

Pending invites

+

{t("pending_invites")}

{searchedInvitationsIds && ( )} diff --git a/web/core/components/workspace/settings/workspace-details.tsx b/web/core/components/workspace/settings/workspace-details.tsx index 28a2167e3d6..083e76c7e55 100644 --- a/web/core/components/workspace/settings/workspace-details.tsx +++ b/web/core/components/workspace/settings/workspace-details.tsx @@ -7,6 +7,7 @@ import { Pencil } from "lucide-react"; // constants import { ORGANIZATION_SIZE, WORKSPACE_UPDATED } from "@plane/constants"; // types +import { useTranslation } from "@plane/i18n"; import { IWorkspace } from "@plane/types"; // ui import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui"; @@ -37,6 +38,7 @@ export const WorkspaceDetails: FC = observer(() => { const { captureWorkspaceEvent } = useEventTracker(); const { currentWorkspace, updateWorkspace } = useWorkspace(); const { allowPermissions } = useUserPermissions(); + const { t } = useTranslation(); // form info const { @@ -188,10 +190,10 @@ export const WorkspaceDetails: FC = observer(() => { {workspaceLogo && workspaceLogo !== "" ? ( <> - Edit logo + {t("workspace_settings.settings.general.edit_logo")} ) : ( - "Upload logo" + t("workspace_settings.settings.general.upload_logo") )} )} @@ -201,15 +203,15 @@ export const WorkspaceDetails: FC = observer(() => {
-

Workspace name

+

{t("workspace_settings.settings.general.name")}

( @@ -221,7 +223,7 @@ export const WorkspaceDetails: FC = observer(() => { onChange={onChange} ref={ref} hasError={Boolean(errors.name)} - placeholder="Name" + placeholder={t("workspace_settings.settings.general.name")} className="w-full rounded-md font-medium" disabled={!isAdmin} /> @@ -230,7 +232,7 @@ export const WorkspaceDetails: FC = observer(() => {
-

Company size

+

{t("workspace_settings.settings.general.company_size")}

{ c === value) ?? "Select organization size"} + label={ + ORGANIZATION_SIZE.find((c) => c === value) ?? + t("workspace_settings.settings.general.errors.company_size.select_a_range") + } optionsClassName="w-full" buttonClassName="!border-[0.5px] !border-custom-border-200 !shadow-none" input @@ -255,7 +260,7 @@ export const WorkspaceDetails: FC = observer(() => {
-

Workspace URL

+

{t("workspace_settings.settings.general.url")}

{ {isAdmin && (
)}