diff --git a/apps/space/app/error.tsx b/apps/space/app/error.tsx index 87aa8dc1992..340ae517322 100644 --- a/apps/space/app/error.tsx +++ b/apps/space/app/error.tsx @@ -5,34 +5,36 @@ */ // ui +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; +const handleRetry = () => { + window.location.reload(); +}; + function ErrorPage() { - const handleRetry = () => { - window.location.reload(); - }; + const { t } = useTranslation(); return (
-

Yikes! That doesn{"'"}t look good.

+

{t("localized_ui.space_public.error_title")}

- That crashed Plane, pun intended. No worries, though. Our engineers have been notified. If you have more - details, please write to{" "} + {t("localized_ui.space_public.error_description_prefix")}{" "} support@plane.so {" "} - or on our{" "} + {t("localized_ui.space_public.error_description_middle")}{" "} - Forum + {t("localized_ui.space_public.forum")} .

{/*
); diff --git a/apps/space/components/account/auth-forms/email.tsx b/apps/space/components/account/auth-forms/email.tsx index 303f9038e60..7a97cc940b3 100644 --- a/apps/space/components/account/auth-forms/email.tsx +++ b/apps/space/components/account/auth-forms/email.tsx @@ -5,12 +5,13 @@ */ import type { FormEvent } from "react"; -import { useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { observer } from "mobx-react"; // icons import { CircleAlert, XCircle } from "lucide-react"; // types import { Button } from "@plane/propel/button"; +import { useTranslation } from "@plane/i18n"; import type { IEmailCheckData } from "@plane/types"; // ui import { Input, Spinner } from "@plane/ui"; @@ -25,13 +26,14 @@ type TAuthEmailForm = { export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailForm) { const { onSubmit, defaultEmail } = props; + const { t } = useTranslation(); // states const [isSubmitting, setIsSubmitting] = useState(false); const [email, setEmail] = useState(defaultEmail); const emailError = useMemo( - () => (email && !checkEmailValidity(email) ? { email: "Email is invalid" } : undefined), - [email] + () => (email && !checkEmailValidity(email) ? { email: t("localized_ui.space_auth.email_invalid") } : undefined), + [email, t] ); const handleFormSubmit = async (event: FormEvent) => { @@ -49,11 +51,15 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo const [isFocused, setIsFocused] = useState(true); const inputRef = useRef(null); + useEffect(() => { + inputRef.current?.focus(); + }, []); + return (
{email.length > 0 && (
); diff --git a/apps/space/components/account/auth-forms/password.tsx b/apps/space/components/account/auth-forms/password.tsx index 7bf8971fa4a..972bd83921a 100644 --- a/apps/space/components/account/auth-forms/password.tsx +++ b/apps/space/components/account/auth-forms/password.tsx @@ -9,6 +9,7 @@ import { observer } from "mobx-react"; import { Eye, EyeOff, XCircle } from "lucide-react"; // plane imports import { API_BASE_URL, E_PASSWORD_STRENGTH } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { AuthService } from "@plane/services"; import { Input, Spinner, PasswordStrengthIndicator } from "@plane/ui"; @@ -41,6 +42,7 @@ const authService = new AuthService(); export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props) { const { email, nextPath, isSMTPConfigured, handleAuthStep, handleEmailClear, mode } = props; + const { t } = useTranslation(); // ref const formRef = useRef(null); // states @@ -79,14 +81,11 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props) const isButtonDisabled = useMemo( () => - !isSubmitting && - !!passwordFormData.password && - (mode === EAuthModes.SIGN_UP - ? getPasswordStrength(passwordFormData.password) === E_PASSWORD_STRENGTH.STRENGTH_VALID && - passwordFormData.password === passwordFormData.confirm_password - : true) - ? false - : true, + isSubmitting || + !passwordFormData.password || + (mode === EAuthModes.SIGN_UP && + (getPasswordStrength(passwordFormData.password) !== E_PASSWORD_STRENGTH.STRENGTH_VALID || + passwordFormData.password !== passwordFormData.confirm_password)), [isSubmitting, mode, passwordFormData.confirm_password, passwordFormData.password] ); @@ -123,7 +122,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
handleFormChange("password", e.target.value)} - placeholder="Enter password" + placeholder={t("localized_ui.space_auth.enter_password")} className="h-10 w-full border border-subtle !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder" onFocus={() => setIsPasswordInputFocused(true)} onBlur={() => setIsPasswordInputFocused(false)} autoComplete="off" - autoFocus /> {showPassword?.password ? (
handleFormChange("confirm_password", e.target.value)} - placeholder="Confirm password" + placeholder={t("localized_ui.space_auth.confirm_password")} className="h-10 w-full border border-subtle !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder" onFocus={() => setIsRetryPasswordInputFocused(true)} onBlur={() => setIsRetryPasswordInputFocused(false)} @@ -208,7 +208,9 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
{!!passwordFormData.confirm_password && passwordFormData.password !== passwordFormData.confirm_password && - renderPasswordMatchError && Passwords don{"'"}t match} + renderPasswordMatchError && ( + {t("localized_ui.space_auth.passwords_dont_match")} + )}
)} @@ -219,9 +221,9 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props) {isSubmitting ? ( ) : isSMTPConfigured ? ( - "Continue" + t("localized_ui.space_auth.continue") ) : ( - "Go to workspace" + t("localized_ui.space_auth.go_to_workspace") )} {isSMTPConfigured && ( @@ -232,13 +234,13 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props) className="w-full" size="xl" > - Sign in with unique code + {t("localized_ui.space_auth.sign_in_with_unique_code")} )} ) : ( )}
diff --git a/apps/space/components/account/auth-forms/unique-code.tsx b/apps/space/components/account/auth-forms/unique-code.tsx index c1dd21278b6..973eed7c5fb 100644 --- a/apps/space/components/account/auth-forms/unique-code.tsx +++ b/apps/space/components/account/auth-forms/unique-code.tsx @@ -8,6 +8,7 @@ import React, { useEffect, useState } from "react"; import { CircleCheck, XCircle } from "lucide-react"; // plane imports import { API_BASE_URL } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { AuthService } from "@plane/services"; import { Input, Spinner } from "@plane/ui"; @@ -39,6 +40,7 @@ const defaultValues: TUniqueCodeFormValues = { export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) { const { mode, email, nextPath, handleEmailClear, generateEmailUniqueCode } = props; + const { t } = useTranslation(); // derived values const defaultResetTimerValue = 5; // states @@ -52,10 +54,10 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) { const handleFormChange = (key: keyof TUniqueCodeFormValues, value: string) => setUniqueCodeFormData((prev) => ({ ...prev, [key]: value })); - const generateNewCode = async (email: string) => { + const generateNewCode = async (targetEmail: string) => { try { setIsRequestingNewCode(true); - const uniqueCode = await generateEmailUniqueCode(email); + const uniqueCode = await generateEmailUniqueCode(targetEmail); setResendCodeTimer(defaultResetTimerValue); handleFormChange("code", uniqueCode?.code || ""); setIsRequestingNewCode(false); @@ -87,7 +89,7 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {

- Paste the code sent to your email + {t("localized_ui.space_auth.paste_code_sent")}

diff --git a/apps/space/components/account/terms-and-conditions.tsx b/apps/space/components/account/terms-and-conditions.tsx index 1e9a71a6ee0..bb31207e382 100644 --- a/apps/space/components/account/terms-and-conditions.tsx +++ b/apps/space/components/account/terms-and-conditions.tsx @@ -4,22 +4,31 @@ * See the LICENSE file for details. */ +import { useTranslation } from "@plane/i18n"; + type Props = { isSignUp?: boolean; }; export function TermsAndConditions(props: Props) { const { isSignUp = false } = props; + const { t } = useTranslation(); return (

- {isSignUp ? "By creating an account" : "By signing in"}, you agree to our{" \n"} + {isSignUp ? t("localized_ui.space_public.by_creating_account") : t("localized_ui.space_public.by_signing_in")},{" "} + {t("localized_ui.space_public.you_agree_to_our")} + {" \n"} - Terms of Service + + {t("localized_ui.space_public.terms_of_service")} + {" "} - and{" "} + {t("localized_ui.space_public.and")}{" "} - Privacy Policy + + {t("localized_ui.space_public.privacy_policy")} + {"."}

diff --git a/apps/space/components/account/user-logged-in.tsx b/apps/space/components/account/user-logged-in.tsx index 42815b013b4..9c294349064 100644 --- a/apps/space/components/account/user-logged-in.tsx +++ b/apps/space/components/account/user-logged-in.tsx @@ -5,6 +5,7 @@ */ import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; import { PlaneLockup } from "@plane/propel/icons"; // assets import UserLoggedInImage from "@/app/assets/user-logged-in.svg?url"; @@ -17,6 +18,7 @@ import { useUser } from "@/hooks/store/use-user"; export const UserLoggedIn = observer(function UserLoggedIn() { // store hooks const { data: user } = useUser(); + const { t } = useTranslation(); if (!user) return null; @@ -31,14 +33,17 @@ export const UserLoggedIn = observer(function UserLoggedIn() {
- User already logged in + {t("localized_ui.space_public.user_already_logged_in")}
-

Nice! Just one more step.

-

- Enter the public-share URL or link of the view or Page you are trying to see in the browser{"'"}s address - bar. -

+

+ {t("localized_ui.space_public.logged_in_title")} +

+

{t("localized_ui.space_public.logged_in_hint")}

diff --git a/apps/space/components/common/powered-by.tsx b/apps/space/components/common/powered-by.tsx index 05da512100b..73cfd472735 100644 --- a/apps/space/components/common/powered-by.tsx +++ b/apps/space/components/common/powered-by.tsx @@ -5,6 +5,7 @@ */ import { WEBSITE_URL } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; // assets import { PlaneLogo } from "@plane/propel/icons"; @@ -15,6 +16,7 @@ type TPoweredBy = { export function PoweredBy(props: TPoweredBy) { // props const { disabled = false } = props; + const { t } = useTranslation(); if (disabled || !WEBSITE_URL) return null; @@ -27,7 +29,7 @@ export function PoweredBy(props: TPoweredBy) { >
- Powered by Plane Publish + {t("localized_ui.space_public.powered_by")} Plane Publish
); diff --git a/apps/space/components/instance/instance-failure-view.tsx b/apps/space/components/instance/instance-failure-view.tsx index 2bf810e9d01..c52654ba466 100644 --- a/apps/space/components/instance/instance-failure-view.tsx +++ b/apps/space/components/instance/instance-failure-view.tsx @@ -5,34 +5,36 @@ */ import { useTheme } from "next-themes"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; // assets import InstanceFailureDarkImage from "@/app/assets/instance/instance-failure-dark.svg?url"; import InstanceFailureImage from "@/app/assets/instance/instance-failure.svg?url"; +const handleRetry = () => { + window.location.reload(); +}; + export function InstanceFailureView() { const { resolvedTheme } = useTheme(); + const { t } = useTranslation(); const instanceImage = resolvedTheme === "dark" ? InstanceFailureDarkImage : InstanceFailureImage; - const handleRetry = () => { - window.location.reload(); - }; - return (
- Plane instance failure image -

Unable to fetch instance details.

+ {t("localized_ui.space_public.instance_failure_image_alt")} +

{t("localized_ui.space_public.instance_failure_title")}

- We were unable to fetch the details of the instance.
- Fret not, it might just be a connectivity work items. + {t("localized_ui.space_public.instance_failure_description")}
+ {t("localized_ui.space_public.instance_failure_hint")}

diff --git a/apps/space/components/issues/filters/labels.tsx b/apps/space/components/issues/filters/labels.tsx index db235c5b798..0d60a7e689f 100644 --- a/apps/space/components/issues/filters/labels.tsx +++ b/apps/space/components/issues/filters/labels.tsx @@ -6,6 +6,7 @@ import React, { useState } from "react"; // plane imports +import { useTranslation } from "@plane/i18n"; import { Loader } from "@plane/ui"; // types import type { IIssueLabel } from "@/types/issue"; @@ -26,6 +27,7 @@ type Props = { export function FilterLabels(props: Props) { const { appliedFilters, handleUpdate, labels, searchQuery } = props; + const { t } = useTranslation(); const [itemsToRender, setItemsToRender] = useState(5); const [previewEnabled, setPreviewEnabled] = useState(true); @@ -44,7 +46,7 @@ export function FilterLabels(props: Props) { return ( <> 0 ? ` (${appliedFiltersCount})` : ""}`} + title={`${t("labels")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`} isPreviewEnabled={previewEnabled} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} /> @@ -56,7 +58,7 @@ export function FilterLabels(props: Props) { {filteredOptions.slice(0, itemsToRender).map((label) => ( handleUpdate(label?.id)} icon={} title={label.name} @@ -68,12 +70,14 @@ export function FilterLabels(props: Props) { className="ml-8 text-11 font-medium text-accent-primary" onClick={handleViewToggle} > - {itemsToRender === filteredOptions.length ? "View less" : "View all"} + {itemsToRender === filteredOptions.length + ? t("localized_ui.space_public.view_less") + : t("localized_ui.space_public.view_all")} )} ) : ( -

No matches found

+

{t("localized_ui.space_public.no_matches_found")}

) ) : ( diff --git a/apps/space/components/issues/filters/root.tsx b/apps/space/components/issues/filters/root.tsx index 983f00ad4ba..434aede1113 100644 --- a/apps/space/components/issues/filters/root.tsx +++ b/apps/space/components/issues/filters/root.tsx @@ -10,6 +10,7 @@ import { observer } from "mobx-react"; import { useRouter } from "next/navigation"; // constants import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; // components import { FiltersDropdown } from "@/components/issues/filters/helpers/dropdown"; import { FilterSelection } from "@/components/issues/filters/selection"; @@ -26,6 +27,7 @@ type IssueFiltersDropdownProps = { export const IssueFiltersDropdown = observer(function IssueFiltersDropdown(props: IssueFiltersDropdownProps) { const { anchor } = props; + const { t } = useTranslation(); // router const router = useRouter(); // hooks @@ -63,7 +65,7 @@ export const IssueFiltersDropdown = observer(function IssueFiltersDropdown(props return (
- + setFiltersSearchQuery(e.target.value)} - autoFocus /> {filtersSearchQuery !== "" && ( )} ) : ( -

No matches found

+

{t("localized_ui.space_public.no_matches_found")}

) ) : ( diff --git a/apps/space/components/issues/issue-layouts/error.tsx b/apps/space/components/issues/issue-layouts/error.tsx index 40e4f554038..25652299e41 100644 --- a/apps/space/components/issues/issue-layouts/error.tsx +++ b/apps/space/components/issues/issue-layouts/error.tsx @@ -5,9 +5,12 @@ */ // assets +import { useTranslation } from "@plane/i18n"; import SomethingWentWrongImage from "@/app/assets/something-went-wrong.svg?url"; export function SomethingWentWrongError() { + const { t } = useTranslation(); + return (
@@ -15,13 +18,13 @@ export function SomethingWentWrongError() {
Oops! Something went wrong
-

Oops! Something went wrong.

-

The public board does not exist. Please check the URL.

+

{t("localized_ui.space_public.something_went_wrong")}

+

{t("localized_ui.space_public.public_board_not_found")}

); diff --git a/apps/space/components/issues/issue-layouts/issue-layout-HOC.tsx b/apps/space/components/issues/issue-layouts/issue-layout-HOC.tsx index 6a9a719bcd3..8e41ed87a33 100644 --- a/apps/space/components/issues/issue-layouts/issue-layout-HOC.tsx +++ b/apps/space/components/issues/issue-layouts/issue-layout-HOC.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; // plane imports +import { useTranslation } from "@plane/i18n"; import type { TLoader } from "@plane/types"; // components import { LogoSpinner } from "@/components/common/logo-spinner"; @@ -22,6 +23,7 @@ interface Props { export const IssueLayoutHOC = observer(function IssueLayoutHOC(props: Props) { const { getIssueLoader, getGroupIssueCount } = props; + const { t } = useTranslation(); const issueCount = getGroupIssueCount(undefined, undefined, false); @@ -34,7 +36,11 @@ export const IssueLayoutHOC = observer(function IssueLayoutHOC(props: Props) { } if (getGroupIssueCount(undefined, undefined, false) === 0) { - return
No work items found
; + return ( +
+ {t("localized_ui.space_public.no_work_items_found")} +
+ ); } return <>{props.children}; diff --git a/apps/space/components/issues/issue-layouts/kanban/default.tsx b/apps/space/components/issues/issue-layouts/kanban/default.tsx index fa934aeb995..693b6ae9a2f 100644 --- a/apps/space/components/issues/issue-layouts/kanban/default.tsx +++ b/apps/space/components/issues/issue-layouts/kanban/default.tsx @@ -7,6 +7,7 @@ import type { MutableRefObject } from "react"; import { isNil } from "lodash-es"; import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; // types import type { GroupByColumnTypes, @@ -68,8 +69,12 @@ export const KanBan = observer(function KanBan(props: IKanBan) { const cycle = useCycle(); const modules = useModule(); const state = useStates(); + const { t } = useTranslation(); - const groupList = getGroupByColumns(groupBy as GroupByColumnTypes, cycle, modules, label, state, member); + const groupList = getGroupByColumns(groupBy as GroupByColumnTypes, cycle, modules, label, state, member, false, { + allWorkItems: `${t("common.all")} ${t("work_items")}`, + none: t("common.none"), + }); if (!groupList) return null; diff --git a/apps/space/components/issues/issue-layouts/kanban/swimlanes.tsx b/apps/space/components/issues/issue-layouts/kanban/swimlanes.tsx index 977bf5bb0a2..f68528c6076 100644 --- a/apps/space/components/issues/issue-layouts/kanban/swimlanes.tsx +++ b/apps/space/components/issues/issue-layouts/kanban/swimlanes.tsx @@ -7,6 +7,7 @@ import type { MutableRefObject } from "react"; import { useState } from "react"; import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; // types import type { GroupByColumnTypes, @@ -69,9 +70,33 @@ export const KanBanSwimLanes = observer(function KanBanSwimLanes(props: IKanBanS const cycle = useCycle(); const modules = useModule(); const state = useStates(); + const { t } = useTranslation(); - const groupByList = getGroupByColumns(groupBy as GroupByColumnTypes, cycle, modules, label, state, member); - const subGroupByList = getGroupByColumns(subGroupBy as GroupByColumnTypes, cycle, modules, label, state, member); + const localizedLabels = { + allWorkItems: `${t("common.all")} ${t("work_items")}`, + none: t("common.none"), + }; + + const groupByList = getGroupByColumns( + groupBy as GroupByColumnTypes, + cycle, + modules, + label, + state, + member, + false, + localizedLabels + ); + const subGroupByList = getGroupByColumns( + subGroupBy as GroupByColumnTypes, + cycle, + modules, + label, + state, + member, + false, + localizedLabels + ); if (!groupByList || !subGroupByList) return null; diff --git a/apps/space/components/issues/issue-layouts/list/default.tsx b/apps/space/components/issues/issue-layouts/list/default.tsx index f8f545b47ee..f5645156be3 100644 --- a/apps/space/components/issues/issue-layouts/list/default.tsx +++ b/apps/space/components/issues/issue-layouts/list/default.tsx @@ -6,6 +6,7 @@ import { useRef } from "react"; import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; // types import type { GroupByColumnTypes, @@ -59,8 +60,12 @@ export const List = observer(function List(props: IList) { const cycle = useCycle(); const modules = useModule(); const state = useStates(); + const { t } = useTranslation(); - const groupList = getGroupByColumns(groupBy as GroupByColumnTypes, cycle, modules, label, state, member, true); + const groupList = getGroupByColumns(groupBy as GroupByColumnTypes, cycle, modules, label, state, member, true, { + allWorkItems: `${t("common.all")} ${t("work_items")}`, + none: t("common.none"), + }); if (!groupList) return null; diff --git a/apps/space/components/issues/issue-layouts/properties/all-properties.tsx b/apps/space/components/issues/issue-layouts/properties/all-properties.tsx index 9d9c9dace58..47d6e0b1a3b 100644 --- a/apps/space/components/issues/issue-layouts/properties/all-properties.tsx +++ b/apps/space/components/issues/issue-layouts/properties/all-properties.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import { Paperclip } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; import { LinkIcon, ViewsIcon } from "@plane/propel/icons"; // plane imports import { Tooltip } from "@plane/propel/tooltip"; @@ -33,6 +34,7 @@ export interface IIssueProperties { export const IssueProperties = observer(function IssueProperties(props: IIssueProperties) { const { issue, displayProperties, className } = props; + const { t } = useTranslation(); if (!displayProperties || !issue.project_id) return null; @@ -138,7 +140,7 @@ export const IssueProperties = observer(function IssueProperties(props: IIssuePr displayPropertyKey="sub_issue_count" shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!issue.sub_issues_count} > - +
!!properties.attachment_count && !!issue.attachment_count} > - +
{issue.attachment_count}
@@ -173,7 +175,7 @@ export const IssueProperties = observer(function IssueProperties(props: IIssuePr displayPropertyKey="link" shouldRenderProperty={(properties) => !!properties.link && !!issue.link_count} > - +
{issue.link_count}
diff --git a/apps/space/components/issues/issue-layouts/properties/cycle.tsx b/apps/space/components/issues/issue-layouts/properties/cycle.tsx index 4f70bac2a5b..690d982b2ab 100644 --- a/apps/space/components/issues/issue-layouts/properties/cycle.tsx +++ b/apps/space/components/issues/issue-layouts/properties/cycle.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; // plane ui +import { useTranslation } from "@plane/i18n"; import { CycleIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; // plane utils @@ -19,12 +20,16 @@ type Props = { }; export const IssueBlockCycle = observer(function IssueBlockCycle({ cycleId, shouldShowBorder = true }: Props) { + const { t } = useTranslation(); const { getCycleById } = useCycle(); const cycle = getCycleById(cycleId); return ( - +
-
{cycle?.name ?? "No Cycle"}
+
{cycle?.name ?? t("localized_ui.space_public.no_cycle")}
diff --git a/apps/space/components/issues/issue-layouts/properties/due-date.tsx b/apps/space/components/issues/issue-layouts/properties/due-date.tsx index 7fa853b4489..8448a139335 100644 --- a/apps/space/components/issues/issue-layouts/properties/due-date.tsx +++ b/apps/space/components/issues/issue-layouts/properties/due-date.tsx @@ -5,6 +5,7 @@ */ import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; import { DueDatePropertyIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; import { cn } from "@plane/utils"; @@ -23,6 +24,7 @@ type Props = { export const IssueBlockDate = observer(function IssueBlockDate(props: Props) { const { due_date, stateId, shouldHighLight = true, shouldShowBorder = true } = props; + const { t } = useTranslation(); const { getStateById } = useStates(); const state = getStateById(stateId); @@ -30,7 +32,7 @@ export const IssueBlockDate = observer(function IssueBlockDate(props: Props) { const formattedDate = renderFormattedDate(due_date); return ( - +
- {formattedDate ? formattedDate : "No Date"} + {formattedDate ? formattedDate : t("localized_ui.space_public.no_date")}
); diff --git a/apps/space/components/issues/issue-layouts/properties/labels.tsx b/apps/space/components/issues/issue-layouts/properties/labels.tsx index 4a6d1ab0a03..69efd2a1527 100644 --- a/apps/space/components/issues/issue-layouts/properties/labels.tsx +++ b/apps/space/components/issues/issue-layouts/properties/labels.tsx @@ -5,6 +5,7 @@ */ import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; import { LabelPropertyIcon } from "@plane/propel/icons"; // plane imports import { Tooltip } from "@plane/propel/tooltip"; @@ -17,20 +18,22 @@ type Props = { }; export const IssueBlockLabels = observer(function IssueBlockLabels({ labelIds, shouldShowLabel = false }: Props) { + const { t } = useTranslation(); const { getLabelsByIds } = useLabel(); const labels = getLabelsByIds(labelIds); - const labelsString = labels.length > 0 ? labels.map((label) => label.name).join(", ") : "No Labels"; + const labelsString = + labels.length > 0 ? labels.map((label) => label.name).join(", ") : t("localized_ui.space_public.no_labels"); if (labels.length <= 0) return ( - +
- {shouldShowLabel && No Labels} + {shouldShowLabel && {t("localized_ui.space_public.no_labels")}}
); @@ -40,7 +43,7 @@ export const IssueBlockLabels = observer(function IssueBlockLabels({ labelIds, s {labels.length <= 2 ? ( <> {labels.map((label) => ( - +
- +
- {`${labels.length} Labels`} + {t("localized_ui.space_public.labels_count", { count: labels.length })}
diff --git a/apps/space/components/issues/issue-layouts/properties/member.tsx b/apps/space/components/issues/issue-layouts/properties/member.tsx index c24f115932e..e288b29097d 100644 --- a/apps/space/components/issues/issue-layouts/properties/member.tsx +++ b/apps/space/components/issues/issue-layouts/properties/member.tsx @@ -7,6 +7,7 @@ import { observer } from "mobx-react"; // icons import type { LucideIcon } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; import { MembersPropertyIcon } from "@plane/propel/icons"; // plane ui import { Avatar, AvatarGroup } from "@plane/ui"; @@ -61,6 +62,7 @@ export const ButtonAvatars = observer(function ButtonAvatars(props: AvatarProps) }); export const IssueBlockMembers = observer(function IssueBlockMembers({ memberIds, shouldShowBorder = true }: Props) { + const { t } = useTranslation(); const { getMembersByIds } = useMember(); const members = getMembersByIds(memberIds); @@ -75,7 +77,7 @@ export const IssueBlockMembers = observer(function IssueBlockMembers({ memberIds
{!shouldShowBorder && members.length <= 1 && ( - {members?.[0]?.member__display_name ?? "No Assignees"} + {members?.[0]?.member__display_name ?? t("localized_ui.space_public.no_assignees")} )}
diff --git a/apps/space/components/issues/issue-layouts/properties/modules.tsx b/apps/space/components/issues/issue-layouts/properties/modules.tsx index 5e80222063b..1a5a30d28fc 100644 --- a/apps/space/components/issues/issue-layouts/properties/modules.tsx +++ b/apps/space/components/issues/issue-layouts/properties/modules.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; // plane ui +import { useTranslation } from "@plane/i18n"; import { ModuleIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; // plane utils @@ -19,6 +20,7 @@ type Props = { }; export const IssueBlockModules = observer(function IssueBlockModules({ moduleIds, shouldShowBorder = true }: Props) { + const { t } = useTranslation(); const { getModulesByIds } = useModule(); const modules = getModulesByIds(moduleIds ?? []); @@ -27,7 +29,7 @@ export const IssueBlockModules = observer(function IssueBlockModules({ moduleIds return (
- + {modules.length <= 1 ? (
-
{modules?.[0]?.name ?? "No Modules"}
+
{modules?.[0]?.name ?? t("localized_ui.space_public.no_modules")}
) : (
-
{modules.length} Modules
+
{t("localized_ui.space_public.modules_count", { count: modules.length })}
)} diff --git a/apps/space/components/issues/issue-layouts/properties/priority.tsx b/apps/space/components/issues/issue-layouts/properties/priority.tsx index 9b4dc3d0176..084c078ac6d 100644 --- a/apps/space/components/issues/issue-layouts/properties/priority.tsx +++ b/apps/space/components/issues/issue-layouts/properties/priority.tsx @@ -35,7 +35,7 @@ export function IssueBlockPriority({ if (priority_detail === null) return <>; return ( - +
+
{ switch (groupBy) { case "cycle": - return getCycleColumns(cycle); + return getCycleColumns(cycle, localizedLabels); case "module": - return getModuleColumns(module); + return getModuleColumns(module, localizedLabels); case "state": return getStateColumns(projectState); case "priority": return getPriorityColumns(); case "labels": - return getLabelsColumns(label) as any; + return getLabelsColumns(label, localizedLabels) as any; case "assignees": - return getAssigneeColumns(member); + return getAssigneeColumns(member, localizedLabels); case "created_by": return getCreatedByColumns(member) as any; default: - if (includeNone) return [{ id: `All Issues`, name: `All work items`, payload: {}, icon: undefined }]; + if (includeNone) + return [ + { id: `All Issues`, name: localizedLabels?.allWorkItems ?? `All work items`, payload: {}, icon: undefined }, + ]; } }; -const getCycleColumns = (cycleStore: ICycleStore): IGroupByColumn[] | undefined => { +const getCycleColumns = ( + cycleStore: ICycleStore, + localizedLabels?: TGroupByLocalizedLabels +): IGroupByColumn[] | undefined => { const { cycles } = cycleStore; if (!cycles) return; @@ -78,7 +90,7 @@ const getCycleColumns = (cycleStore: ICycleStore): IGroupByColumn[] | undefined }); cycleGroups.push({ id: "None", - name: "None", + name: localizedLabels?.none ?? "None", icon: , payload: { cycle_id: null }, }); @@ -86,7 +98,10 @@ const getCycleColumns = (cycleStore: ICycleStore): IGroupByColumn[] | undefined return cycleGroups; }; -const getModuleColumns = (moduleStore: IIssueModuleStore): IGroupByColumn[] | undefined => { +const getModuleColumns = ( + moduleStore: IIssueModuleStore, + localizedLabels?: TGroupByLocalizedLabels +): IGroupByColumn[] | undefined => { const { modules } = moduleStore; if (!modules) return; @@ -104,7 +119,7 @@ const getModuleColumns = (moduleStore: IIssueModuleStore): IGroupByColumn[] | un }) as any; moduleGroups.push({ id: "None", - name: "None", + name: localizedLabels?.none ?? "None", icon: , payload: { module_ids: [] }, }); @@ -139,49 +154,55 @@ const getPriorityColumns = () => { })); }; -const getLabelsColumns = (label: IIssueLabelStore) => { - const { labels: storeLabels } = label; +const getLabelsColumns = (labelStore: IIssueLabelStore, localizedLabels?: TGroupByLocalizedLabels) => { + const { labels: storeLabels } = labelStore; if (!storeLabels) return; - const labels = [...storeLabels, { id: "None", name: "None", color: "#666" }]; + const labels = [...storeLabels, { id: "None", name: localizedLabels?.none ?? "None", color: "#666" }]; - return labels.map((label) => ({ - id: label.id, - name: label.name, + return labels.map((labelInfo) => ({ + id: labelInfo.id, + name: labelInfo.name, icon: ( -
+
), - payload: label?.id === "None" ? {} : { label_ids: [label.id] }, + payload: labelInfo?.id === "None" ? {} : { label_ids: [labelInfo.id] }, })); }; -const getAssigneeColumns = (member: IIssueMemberStore) => { - const { members } = member; +const getAssigneeColumns = ( + memberStore: IIssueMemberStore, + localizedLabels?: TGroupByLocalizedLabels +): IGroupByColumn[] | undefined => { + const { members } = memberStore; if (!members) return; - const assigneeColumns: any = members.map((member) => ({ - id: member.id, - name: member?.member__display_name || "", - icon: , - payload: { assignee_ids: [member.id] }, + const assigneeColumns: IGroupByColumn[] = members.map((memberInfo) => ({ + id: memberInfo.id, + name: memberInfo?.member__display_name || "", + icon: , + payload: { assignee_ids: [memberInfo.id] }, })); - assigneeColumns.push({ id: "None", name: "None", icon: , payload: {} }); + assigneeColumns.push({ id: "None", name: localizedLabels?.none ?? "None", icon: , payload: {} }); return assigneeColumns; }; -const getCreatedByColumns = (member: IIssueMemberStore) => { - const { members } = member; +const getCreatedByColumns = (memberStore: IIssueMemberStore) => { + const { members } = memberStore; if (!members) return; - return members.map((member) => ({ - id: member.id, - name: member?.member__display_name || "", - icon: , + return members.map((memberInfo) => ({ + id: memberInfo.id, + name: memberInfo?.member__display_name || "", + icon: , payload: {}, })); }; diff --git a/apps/space/components/issues/navbar/user-avatar.tsx b/apps/space/components/issues/navbar/user-avatar.tsx index 595fe570db6..306c6ca368c 100644 --- a/apps/space/components/issues/navbar/user-avatar.tsx +++ b/apps/space/components/issues/navbar/user-avatar.tsx @@ -13,6 +13,7 @@ import { LogOut } from "lucide-react"; import { Popover, Transition } from "@headlessui/react"; // plane imports import { API_BASE_URL } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { AuthService } from "@plane/services"; import { Avatar } from "@plane/ui"; @@ -27,6 +28,7 @@ const authService = new AuthService(); export const UserAvatar = observer(function UserAvatar() { const pathName = usePathname(); const searchParams = useSearchParams(); + const { t } = useTranslation(); // query params const board = searchParams.get("board") || undefined; const labels = searchParams.get("labels") || undefined; @@ -78,7 +80,7 @@ export const UserAvatar = observer(function UserAvatar() { {currentUser?.display_name || `${currentUser?.first_name} ${currentUser?.first_name}` || currentUser?.email || - "User"} + t("localized_ui.space_public.user")} @@ -107,7 +109,7 @@ export const UserAvatar = observer(function UserAvatar() { className="flex min-w-36 cursor-pointer items-center gap-2 rounded-sm p-2 text-13 whitespace-nowrap hover:bg-layer-transparent-hover" > -
Sign out
+
{t("sign_out")}
)} @@ -119,7 +121,7 @@ export const UserAvatar = observer(function UserAvatar() { ) : (
- +
)} diff --git a/apps/space/components/issues/peek-overview/comment/add-comment.tsx b/apps/space/components/issues/peek-overview/comment/add-comment.tsx index acd86cdd5cf..f27769b6d2d 100644 --- a/apps/space/components/issues/peek-overview/comment/add-comment.tsx +++ b/apps/space/components/issues/peek-overview/comment/add-comment.tsx @@ -9,6 +9,7 @@ import { observer } from "mobx-react"; import { useForm, Controller } from "react-hook-form"; // plane imports import type { EditorRefApi } from "@plane/editor"; +import { useTranslation } from "@plane/i18n"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import { SitesFileService } from "@plane/services"; import type { TIssuePublicComment } from "@plane/types"; @@ -32,6 +33,7 @@ type Props = { export const AddComment = observer(function AddComment(props: Props) { const { anchor } = props; + const { t } = useTranslation(); // states const [uploadedAssetIds, setUploadAssetIds] = useState([]); // refs @@ -52,24 +54,23 @@ export const AddComment = observer(function AddComment(props: Props) { const onSubmit = async (formData: TIssuePublicComment) => { if (!anchor || !issueId || isSubmitting || !formData.comment_html) return; - await addIssueComment(anchor, issueId, formData) - .then(async (res) => { - reset(defaultValues); - editorRef.current?.clearEditor(); - if (uploadedAssetIds.length > 0) { - await fileService.updateBulkAssetsUploadStatus(anchor, res.id, { - asset_ids: uploadedAssetIds, - }); - setUploadAssetIds([]); - } - }) - .catch(() => - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Comment could not be posted. Please try again.", - }) - ); + try { + const res = await addIssueComment(anchor, issueId, formData); + reset(defaultValues); + editorRef.current?.clearEditor(); + if (uploadedAssetIds.length > 0) { + await fileService.updateBulkAssetsUploadStatus(anchor, res.id, { + asset_ids: uploadedAssetIds, + }); + setUploadAssetIds([]); + } + } catch { + setToast({ + type: TOAST_TYPE.ERROR, + title: t("error"), + message: t("localized_ui.space_public.comment_post_error"), + }); + } }; // TODO: on click if he user is not logged in redirect to login page @@ -96,7 +97,7 @@ export const AddComment = observer(function AddComment(props: Props) { } onChange={(comment_json, comment_html) => onChange(comment_html)} isSubmitting={isSubmitting} - placeholder="Add comment..." + placeholder={t("localized_ui.space_public.add_comment")} uploadFile={async (blockId, file) => { const { asset_id } = await uploadCommentAsset(file, anchor); setUploadAssetIds((prev) => [...prev, asset_id]); diff --git a/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx b/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx index 27506d837bb..5a9ac6dd964 100644 --- a/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx +++ b/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx @@ -11,6 +11,7 @@ import { MessageSquare, MoreVertical } from "lucide-react"; import { Menu, Transition } from "@headlessui/react"; // plane imports import type { EditorRefApi } from "@plane/editor"; +import { useTranslation } from "@plane/i18n"; import { CheckIcon, CloseIcon } from "@plane/propel/icons"; import type { TIssuePublicComment } from "@plane/types"; import { getFileURL } from "@plane/utils"; @@ -32,6 +33,7 @@ type Props = { export const CommentCard = observer(function CommentCard(props: Props) { const { anchor, comment } = props; + const { t } = useTranslation(); // store hooks const { peekId, deleteIssueComment, updateIssueComment, uploadCommentAsset } = useIssueDetails(); const { data: currentUser } = useUser(); @@ -72,7 +74,9 @@ export const CommentCard = observer(function CommentCard(props: Props) { {
- {comment.actor_detail.is_bot ? comment.actor_detail.first_name + " Bot" : comment.actor_detail.display_name} + {comment.actor_detail.is_bot + ? t("localized_ui.space_public.bot_name", { name: comment.actor_detail.first_name }) + : comment.actor_detail.display_name}

- <>commented {timeAgo(comment.created_at)} + <>{t("localized_ui.space_public.commented_time", { time: timeAgo(comment.created_at) })}

@@ -199,7 +205,7 @@ export const CommentCard = observer(function CommentCard(props: Props) { active ? "bg-layer-transparent-hover" : "" }`} > - Edit + {t("edit")}
)} @@ -214,7 +220,7 @@ export const CommentCard = observer(function CommentCard(props: Props) { active ? "bg-layer-transparent-hover" : "" }`} > - Delete + {t("delete")}
)} diff --git a/apps/space/components/issues/peek-overview/header.tsx b/apps/space/components/issues/peek-overview/header.tsx index 764ac4ebf87..9e0b61aae6d 100644 --- a/apps/space/components/issues/peek-overview/header.tsx +++ b/apps/space/components/issues/peek-overview/header.tsx @@ -9,6 +9,7 @@ import { observer } from "mobx-react"; import { MoveRight } from "lucide-react"; import { Listbox, Transition } from "@headlessui/react"; // ui +import { useTranslation } from "@plane/i18n"; import { LinkIcon, CenterPanelIcon, FullScreenPanelIcon, SidePanelIcon } from "@plane/propel/icons"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; // helpers @@ -27,23 +28,24 @@ type Props = { const PEEK_MODES: { key: IPeekMode; icon: any; - label: string; + labelKey: string; }[] = [ - { key: "side", icon: SidePanelIcon, label: "Side Peek" }, + { key: "side", icon: SidePanelIcon, labelKey: "localized_ui.space_public.peek.side" }, { key: "modal", icon: CenterPanelIcon, - label: "Modal", + labelKey: "localized_ui.space_public.peek.modal", }, { key: "full", icon: FullScreenPanelIcon, - label: "Full Screen", + labelKey: "localized_ui.space_public.peek.full_screen", }, ]; export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Props) { const { handleClose } = props; + const { t } = useTranslation(); const { peekMode, setPeekMode } = useIssueDetails(); const isClipboardWriteAllowed = useClipboardWritePermission(); @@ -54,9 +56,10 @@ export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Pr copyTextToClipboard(urlToCopy).then(() => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Link copied!", - message: "Work item link copied to clipboard.", + title: t("localized_ui.space_public.link_copied"), + message: t("localized_ui.space_public.work_item_link_copied"), }); + return undefined; }); }; @@ -106,7 +109,7 @@ export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Pr >
- {mode.label} + {t(mode.labelKey)}
))} @@ -120,7 +123,7 @@ export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Pr type="button" onClick={handleCopyLink} className="shrink-0 text-tertiary hover:text-secondary focus:outline-none" - tabIndex={1} + tabIndex={0} > diff --git a/apps/space/components/issues/peek-overview/issue-activity.tsx b/apps/space/components/issues/peek-overview/issue-activity.tsx index 4e725c2b8cd..9bbdbc8b175 100644 --- a/apps/space/components/issues/peek-overview/issue-activity.tsx +++ b/apps/space/components/issues/peek-overview/issue-activity.tsx @@ -9,6 +9,7 @@ import { Link } from "react-router"; import { usePathname } from "next/navigation"; import { Lock } from "lucide-react"; // plane imports +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; // components import { AddComment } from "@/components/issues/peek-overview/comment/add-comment"; @@ -28,6 +29,7 @@ type Props = { export const PeekOverviewIssueActivity = observer(function PeekOverviewIssueActivity(props: Props) { const { anchor } = props; + const { t } = useTranslation(); // router const pathname = usePathname(); // store hooks @@ -40,7 +42,7 @@ export const PeekOverviewIssueActivity = observer(function PeekOverviewIssueActi return (
-

Comments

+

{t("comments")}

{comments.map((comment) => ( @@ -60,10 +62,10 @@ export const PeekOverviewIssueActivity = observer(function PeekOverviewIssueActi

- Sign in to add your comment + {t("localized_ui.space_public.sign_in_to_add_comment")}

- +
))} diff --git a/apps/space/components/issues/peek-overview/issue-properties.tsx b/apps/space/components/issues/peek-overview/issue-properties.tsx index 1c010ddafaf..55cdb0f949f 100644 --- a/apps/space/components/issues/peek-overview/issue-properties.tsx +++ b/apps/space/components/issues/peek-overview/issue-properties.tsx @@ -54,9 +54,10 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr copyTextToClipboard(urlToCopy).then(() => { setToast({ type: TOAST_TYPE.INFO, - title: "Link copied!", - message: "Work item link copied to clipboard", + title: t("localized_ui.space_public.link_copied"), + message: t("localized_ui.space_public.work_item_link_copied"), }); + return undefined; }); }; @@ -78,7 +79,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr
- State + {t("state")}
@@ -89,7 +90,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr
- Priority + {t("priority")}
- Due date + {t("due_date")}
{issueDetails.target_date ? ( @@ -127,7 +128,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr {renderFormattedDate(issueDetails.target_date)}
) : ( - Empty + {t("common.none")} )}
diff --git a/apps/space/components/issues/reactions/issue-vote-reactions.tsx b/apps/space/components/issues/reactions/issue-vote-reactions.tsx index c41609317f0..f5c0a22342c 100644 --- a/apps/space/components/issues/reactions/issue-vote-reactions.tsx +++ b/apps/space/components/issues/reactions/issue-vote-reactions.tsx @@ -9,6 +9,7 @@ import { ArrowDown, ArrowUp } from "lucide-react"; import { observer } from "mobx-react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; // plane imports +import { useTranslation } from "@plane/i18n"; import { Tooltip } from "@plane/propel/tooltip"; import { cn } from "@plane/utils"; // helpers @@ -26,6 +27,7 @@ type TIssueVotes = { export const IssueVotes = observer(function IssueVotes(props: TIssueVotes) { const { anchor, issueIdFromProps, size = "md" } = props; + const { t } = useTranslation(); // states const [isSubmitting, setIsSubmitting] = useState(false); // router @@ -89,10 +91,11 @@ export const IssueVotes = observer(function IssueVotes(props: TIssueVotes) { .map((r) => r.actor_details?.display_name) .splice(0, VOTES_LIMIT) .join(", ")} - {allUpVotes.length > VOTES_LIMIT && " and " + (allUpVotes.length - VOTES_LIMIT) + " more"} + {allUpVotes.length > VOTES_LIMIT && + t("localized_ui.space_public.and_more", { count: allUpVotes.length - VOTES_LIMIT })} ) : ( - "No upvotes yet" + t("localized_ui.space_public.no_upvotes_yet") )}
} @@ -127,13 +130,14 @@ export const IssueVotes = observer(function IssueVotes(props: TIssueVotes) { {allDownVotes.length > 0 ? ( <> {allDownVotes - .map((r) => r.actor_details.display_name) + .map((r) => r.actor_details?.display_name) .splice(0, VOTES_LIMIT) .join(", ")} - {allDownVotes.length > VOTES_LIMIT && " and " + (allDownVotes.length - VOTES_LIMIT) + " more"} + {allDownVotes.length > VOTES_LIMIT && + t("localized_ui.space_public.and_more", { count: allDownVotes.length - VOTES_LIMIT })} ) : ( - "No downvotes yet" + t("localized_ui.space_public.no_downvotes_yet") )}
} diff --git a/apps/space/components/ui/not-found.tsx b/apps/space/components/ui/not-found.tsx index e3952f58c89..decfb41c1f4 100644 --- a/apps/space/components/ui/not-found.tsx +++ b/apps/space/components/ui/not-found.tsx @@ -5,22 +5,26 @@ */ // images +import { useTranslation } from "@plane/i18n"; import Image404 from "@/app/assets/404.svg?url"; export function PageNotFound() { + const { t } = useTranslation(); + return (
- 404- Page not found + {t("localized_ui.space_public.page_not_found_alt")}
-

Oops! Something went wrong.

-

- Sorry, the page you are looking for cannot be found. It may have been removed, had its name changed, or is - temporarily unavailable. -

+

{t("localized_ui.space_public.something_went_wrong")}

+

{t("localized_ui.space_public.page_not_found_description")}

diff --git a/apps/space/hooks/oauth/core.tsx b/apps/space/hooks/oauth/core.tsx index 63a18cc2e59..7d9f3ca1b61 100644 --- a/apps/space/hooks/oauth/core.tsx +++ b/apps/space/hooks/oauth/core.tsx @@ -8,6 +8,7 @@ import { useSearchParams } from "next/navigation"; import { useTheme } from "next-themes"; import { API_BASE_URL } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import type { TOAuthConfigs, TOAuthOption } from "@plane/types"; // assets import giteaLogo from "@/app/assets/logos/gitea-logo.svg?url"; @@ -27,6 +28,7 @@ export const useCoreOAuthConfig = (oauthActionText: string): TOAuthConfigs => { const { resolvedTheme } = useTheme(); // store hooks const { config } = useInstance(); + const { t } = useTranslation(); // derived values const isOAuthEnabled = (config && @@ -38,7 +40,7 @@ export const useCoreOAuthConfig = (oauthActionText: string): TOAuthConfigs => { const oAuthOptions: TOAuthOption[] = [ { id: "google", - text: `${oauthActionText} with Google`, + text: t("localized_ui.space_public.oauth_with_provider", { action: oauthActionText, provider: "Google" }), icon: Google Logo, onClick: () => { window.location.assign(`${API_BASE_URL}/auth/google/${next_path ? `?next_path=${next_path}` : ``}`); @@ -47,7 +49,7 @@ export const useCoreOAuthConfig = (oauthActionText: string): TOAuthConfigs => { }, { id: "github", - text: `${oauthActionText} with GitHub`, + text: t("localized_ui.space_public.oauth_with_provider", { action: oauthActionText, provider: "GitHub" }), icon: ( { }, { id: "gitlab", - text: `${oauthActionText} with GitLab`, + text: t("localized_ui.space_public.oauth_with_provider", { action: oauthActionText, provider: "GitLab" }), icon: GitLab Logo, onClick: () => { window.location.assign(`${API_BASE_URL}/auth/gitlab/${next_path ? `?next_path=${next_path}` : ``}`); @@ -72,7 +74,7 @@ export const useCoreOAuthConfig = (oauthActionText: string): TOAuthConfigs => { }, { id: "gitea", - text: `${oauthActionText} with Gitea`, + text: t("localized_ui.space_public.oauth_with_provider", { action: oauthActionText, provider: "Gitea" }), icon: Gitea Logo, onClick: () => { window.location.assign(`${API_BASE_URL}/auth/gitea/${next_path ? `?next_path=${next_path}` : ``}`); diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx index 69e02a43bc7..a224fcd27b7 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx @@ -54,7 +54,7 @@ function ProfileActivityPage() { return ( <> - +

{t("profile.stats.recent_activity.title")}

diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx index ec332bbe10d..6b063cd9230 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx @@ -9,6 +9,7 @@ import { observer } from "mobx-react"; import Link from "next/link"; import useSWR from "swr"; // plane types +import { useTranslation } from "@plane/i18n"; import { getButtonStyling } from "@plane/propel/button"; import type { TSearchEntityRequestPayload, TWebhookConnectionQueryParams } from "@plane/types"; import { EFileAssetType } from "@plane/types"; @@ -40,6 +41,7 @@ const projectPageVersionService = new ProjectPageVersionService(); const storeType = EPageStoreType.PROJECT; function PageDetailsPage({ params }: Route.ComponentProps) { + const { t } = useTranslation(); // router const router = useAppRouter(); const { workspaceSlug, projectId, pageId } = params; @@ -79,20 +81,20 @@ function PageDetailsPage({ params }: Route.ComponentProps) { const pageRootHandlers: TPageRootHandlers = useMemo( () => ({ create: createPage, - fetchAllVersions: async (pageId) => - await projectPageVersionService.fetchAllVersions(workspaceSlug, projectId, pageId), + fetchAllVersions: async (targetPageId) => + await projectPageVersionService.fetchAllVersions(workspaceSlug, projectId, targetPageId), fetchDescriptionBinary: async () => { if (!id) return; return await projectPageService.fetchDescriptionBinary(workspaceSlug, projectId, id); }, fetchEntity: fetchEntityCallback, - fetchVersionDetails: async (pageId, versionId) => - await projectPageVersionService.fetchVersionById(workspaceSlug, projectId, pageId, versionId), - restoreVersion: async (pageId, versionId) => - await projectPageVersionService.restoreVersion(workspaceSlug, projectId, pageId, versionId), - getRedirectionLink: (pageId) => { - if (pageId) { - return `/${workspaceSlug}/projects/${projectId}/pages/${pageId}`; + fetchVersionDetails: async (targetPageId, versionId) => + await projectPageVersionService.fetchVersionById(workspaceSlug, projectId, targetPageId, versionId), + restoreVersion: async (targetPageId, versionId) => + await projectPageVersionService.restoreVersion(workspaceSlug, projectId, targetPageId, versionId), + getRedirectionLink: (targetPageId) => { + if (targetPageId) { + return `/${workspaceSlug}/projects/${projectId}/pages/${targetPageId}`; } else { return `/${workspaceSlug}/projects/${projectId}/pages`; } @@ -161,15 +163,13 @@ function PageDetailsPage({ params }: Route.ComponentProps) { if (pageDetailsError || !canCurrentUserAccessPage) return (
-

Page not found

-

- The page you are trying to access doesn{"'"}t exist or you don{"'"}t have permission to view it. -

+

{t("localized_ui.pages.not_found_title")}

+

{t("localized_ui.pages.not_found_description")}

- View other Pages + {t("localized_ui.pages.view_other_pages")}
); diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx index c529c4efe9f..8acc3d6b667 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx @@ -8,6 +8,7 @@ import { isEmpty } from "lodash-es"; import { observer } from "mobx-react"; // plane helpers import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; // components import { SidebarWrapper } from "@/components/sidebar/sidebar-wrapper"; import { SidebarFavoritesMenu } from "@/components/workspace/sidebar/favorites/favorites-menu"; @@ -24,6 +25,7 @@ export const AppSidebar = observer(function AppSidebar() { // store hooks const { allowPermissions } = useUserPermissions(); const { groupedFavorites } = useFavorite(); + const { t } = useTranslation(); // derived values const canPerformWorkspaceMemberActions = allowPermissions( @@ -34,7 +36,7 @@ export const AppSidebar = observer(function AppSidebar() { const isFavoriteEmpty = isEmpty(groupedFavorites); return ( - }> + }> {/* Favorites Menu */} {canPerformWorkspaceMemberActions && !isFavoriteEmpty && } diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/stickies/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/stickies/page.tsx index d925b2ce4fe..633729a4d96 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/stickies/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/stickies/page.tsx @@ -5,13 +5,16 @@ */ // components +import { useTranslation } from "@plane/i18n"; import { PageHead } from "@/components/core/page-title"; import { StickiesInfinite } from "@/components/stickies/layout/stickies-infinite"; export default function WorkspaceStickiesPage() { + const { t } = useTranslation(); + return ( <> - +
diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx index 8043f47f8cb..01afc36cd47 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx @@ -24,7 +24,9 @@ function WorkspaceViewsPage() { const { currentWorkspace } = useWorkspace(); const { t } = useTranslation(); // derived values - const pageTitle = currentWorkspace?.name ? `${currentWorkspace?.name} - All Views` : undefined; + const pageTitle = currentWorkspace?.name + ? t("localized_ui.workspace_views.page_title", { workspaceName: currentWorkspace.name }) + : undefined; return ( <> @@ -36,7 +38,7 @@ function WorkspaceViewsPage() { className="w-full bg-transparent !p-0 text-11 leading-5 text-secondary placeholder:text-placeholder focus:outline-none" value={query} onChange={(e) => setQuery(e.target.value)} - placeholder="Search" + placeholder={t("search")} mode="true-transparent" />
diff --git a/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx index 86bd9f85f42..feed29ab12c 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx @@ -9,6 +9,7 @@ import Link from "next/link"; import { useTheme } from "next-themes"; // plane imports import { PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button, getButtonStyling } from "@plane/propel/button"; import { cn } from "@plane/utils"; // assets @@ -21,25 +22,25 @@ function ProjectSettingsPage() { // store hooks const { resolvedTheme } = useTheme(); const { toggleCreateProjectModal } = useCommandPalette(); + const { t } = useTranslation(); // derived values const resolvedPath = resolvedTheme === "dark" ? ProjectDarkEmptyState : ProjectLightEmptyState; return (
- No projects yet -
No projects yet
-
- Projects act as the foundation for goal-driven work. They let you manage your teams, tasks, and everything you - need to get things done. + {t("localized_ui.projects_empty_state.no_projects_yet")} +
+ {t("localized_ui.projects_empty_state.no_projects_yet")}
+
{t("localized_ui.projects_empty_state.description")}
- Learn more about projects + {t("localized_ui.projects_empty_state.learn_more")}
diff --git a/apps/web/app/(all)/workspace-invitations/page.tsx b/apps/web/app/(all)/workspace-invitations/page.tsx index 4ab9b02eb8e..ce91dc72790 100644 --- a/apps/web/app/(all)/workspace-invitations/page.tsx +++ b/apps/web/app/(all)/workspace-invitations/page.tsx @@ -9,6 +9,7 @@ import { useSearchParams } from "next/navigation"; import useSWR from "swr"; import { Boxes, Share2, Star, User2 } from "lucide-react"; import { CheckIcon, CloseIcon } from "@plane/propel/icons"; +import { useTranslation } from "@plane/i18n"; // components import { LogoSpinner } from "@/components/common/logo-spinner"; import { EmptySpace, EmptySpaceItem } from "@/components/ui/empty-space"; @@ -28,6 +29,7 @@ import { WorkspaceService } from "@/services/workspace.service"; const workspaceService = new WorkspaceService(); function WorkspaceInvitationPage() { + const { t } = useTranslation(); // router const router = useAppRouter(); // query params @@ -54,10 +56,9 @@ function WorkspaceInvitationPage() { }) .then(() => { if (invitationDetail.email === currentUser?.email) { - router.push(`/${invitationDetail.workspace.slug}`); - } else { - router.push("/"); + return router.push(`/${invitationDetail.workspace.slug}`); } + return router.push("/"); }) .catch((err: unknown) => console.error(err)); }; @@ -70,7 +71,7 @@ function WorkspaceInvitationPage() { token: token, }) .then(() => { - router.push("/"); + return router.push("/"); }) .catch((err: unknown) => console.error(err)); }; @@ -81,40 +82,60 @@ function WorkspaceInvitationPage() { {invitationDetail && !invitationDetail.responded_at ? ( error ? (
-

INVITATION NOT FOUND

+

{t("localized_ui.workspace_invitation.invitation_not_found")}

) : ( - - + + ) ) : error || invitationDetail?.responded_at ? ( invitationDetail?.accepted ? ( - + ) : ( {!currentUser ? ( - + ) : ( - + )} - + diff --git a/apps/web/app/not-found.tsx b/apps/web/app/not-found.tsx index 13763951ce1..112a0f4eca4 100644 --- a/apps/web/app/not-found.tsx +++ b/apps/web/app/not-found.tsx @@ -5,6 +5,7 @@ */ import Link from "next/link"; +import { useTranslation } from "@plane/i18n"; // ui import { Button } from "@plane/propel/button"; // images @@ -18,24 +19,23 @@ export const meta: Route.MetaFunction = () => [ ]; function PageNotFound() { + const { t } = useTranslation(); + return (
- 404- Page not found + {t("localized_ui.not_found.alt")}
-

Oops! Something went wrong.

-

- Sorry, the page you are looking for cannot be found. It may have been removed, had its name changed, or is - temporarily unavailable. -

+

{t("localized_ui.not_found.title")}

+

{t("localized_ui.not_found.description")}

diff --git a/apps/web/ce/components/projects/settings/intake/header.tsx b/apps/web/ce/components/projects/settings/intake/header.tsx index c60466e41a8..8456486aaf5 100644 --- a/apps/web/ce/components/projects/settings/intake/header.tsx +++ b/apps/web/ce/components/projects/settings/intake/header.tsx @@ -51,7 +51,7 @@ export const ProjectInboxHeader = observer(function ProjectInboxHeader() { } isLast diff --git a/apps/web/core/components/inbox/content/inbox-issue-header.tsx b/apps/web/core/components/inbox/content/inbox-issue-header.tsx index 5243521731e..2183f52702c 100644 --- a/apps/web/core/components/inbox/content/inbox-issue-header.tsx +++ b/apps/web/core/components/inbox/content/inbox-issue-header.tsx @@ -159,9 +159,8 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader const handleInboxIssueDelete = async () => { if (!inboxIssue || !currentInboxIssueId) return; - await deleteInboxIssue(workspaceSlug, projectId, currentInboxIssueId).then(() => { - if (!isNotificationEmbed) router.push(`/${workspaceSlug}/projects/${projectId}/intake`); - }); + await deleteInboxIssue(workspaceSlug, projectId, currentInboxIssueId); + if (!isNotificationEmbed) router.push(`/${workspaceSlug}/projects/${projectId}/intake`); }; const handleIssueSnoozeAction = async () => { @@ -217,7 +216,7 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader else { setToast({ type: TOAST_TYPE.ERROR, - title: "Permission denied", + title: t("localized_ui.inbox.errors.permission_denied"), message: errorMessage, }); } @@ -311,14 +310,14 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader variant="secondary" size="lg" icon={ChevronUpIcon} - aria-label="Previous work item" + aria-label={t("localized_ui.inbox.navigation.previous_work_item")} onClick={() => handleInboxIssueNavigation("prev")} /> handleInboxIssueNavigation("next")} />
@@ -407,7 +406,7 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader handleActionWithPermission( isProjectAdmin, () => setSelectDuplicateIssue(true), - "Only project admins can mark work item as duplicate" + t("localized_ui.inbox.errors.mark_duplicate_permission") ) } > diff --git a/apps/web/core/components/inbox/content/inbox-issue-mobile-header.tsx b/apps/web/core/components/inbox/content/inbox-issue-mobile-header.tsx index bde81665d54..24b2635d920 100644 --- a/apps/web/core/components/inbox/content/inbox-issue-mobile-header.tsx +++ b/apps/web/core/components/inbox/content/inbox-issue-mobile-header.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import { Clock, FileStack, MoreHorizontal, PanelLeft, MoveRight } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; import { IconButton, getIconButtonStyling } from "@plane/propel/icon-button"; import { LinkIcon, @@ -81,6 +82,7 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions } = props; const router = useAppRouter(); const { getProjectIdentifierById } = useProject(); + const { t } = useTranslation(); const issue = inboxIssue?.issue; const currentInboxIssueId = issue?.id; @@ -116,14 +118,14 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions variant="secondary" size="lg" icon={ChevronUpIcon} - aria-label="Previous work item" + aria-label={t("localized_ui.inbox.navigation.previous_work_item")} onClick={() => handleInboxIssueNavigation("prev")} /> handleInboxIssueNavigation("next")} />
@@ -143,7 +145,7 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions
- Copy work item link + {t("inbox_issue.actions.copy")}
)} @@ -151,7 +153,7 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions router.push(workItemLink)}>
- Open work item + {t("inbox_issue.actions.open")}
)} @@ -161,13 +163,15 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions handleActionWithPermission( isProjectAdmin, handleIssueSnoozeAction, - "Only project admins can snooze/Un-snooze work items" + t("inbox_issue.errors.snooze_permission") ) } >
- {inboxIssue?.snoozed_till && numberOfDaysLeft && numberOfDaysLeft > 0 ? "Un-snooze" : "Snooze"} + {inboxIssue?.snoozed_till && numberOfDaysLeft && numberOfDaysLeft > 0 + ? t("inbox_issue.actions.unsnooze") + : t("inbox_issue.actions.snooze")}
)} @@ -177,13 +181,13 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions handleActionWithPermission( isProjectAdmin, () => setSelectDuplicateIssue(true), - "Only project admins can mark work items as duplicate" + t("localized_ui.inbox.errors.mark_duplicate_permission_plural") ) } >
- Mark as duplicate + {t("inbox_issue.actions.mark_as_duplicate")}
)} @@ -193,13 +197,13 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions handleActionWithPermission( isProjectAdmin, () => setAcceptIssueModal(true), - "Only project admins can accept work items" + t("inbox_issue.errors.accept_permission") ) } >
- Accept + {t("inbox_issue.actions.accept")}
)} @@ -209,13 +213,13 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions handleActionWithPermission( isProjectAdmin, () => setDeclineIssueModal(true), - "Only project admins can deny work items" + t("inbox_issue.errors.decline_permission") ) } >
- Decline + {t("inbox_issue.actions.decline")}
)} @@ -223,7 +227,7 @@ export const InboxIssueActionsMobileHeader = observer(function InboxIssueActions setDeleteIssueModal(true)}>
- Delete + {t("inbox_issue.actions.delete")}
)} diff --git a/apps/web/core/components/inbox/content/issue-properties.tsx b/apps/web/core/components/inbox/content/issue-properties.tsx index f355e39e36c..96dc0378722 100644 --- a/apps/web/core/components/inbox/content/issue-properties.tsx +++ b/apps/web/core/components/inbox/content/issue-properties.tsx @@ -5,6 +5,7 @@ */ import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; import { StatePropertyIcon, MembersPropertyIcon, @@ -44,6 +45,7 @@ export const InboxIssueContentProperties = observer(function InboxIssueContentPr props; const router = useAppRouter(); + const { t } = useTranslation(); // store hooks const { currentProjectDetails } = useProject(); @@ -63,14 +65,14 @@ export const InboxIssueContentProperties = observer(function InboxIssueContentPr return (
-
Properties
+
{t("common.properties")}
{/* Intake State */}
- State + {t("common.state")}
{issue?.state_id && (
- Assignees + {t("common.assignees")}
0 ? "transparent-without-text" : "transparent-with-text" @@ -119,7 +121,7 @@ export const InboxIssueContentProperties = observer(function InboxIssueContentPr
- Priority + {t("common.priority")}
- Due date + {t("due_date")}
issue?.id && @@ -166,7 +168,7 @@ export const InboxIssueContentProperties = observer(function InboxIssueContentPr
- Labels + {t("common.labels")}
{issue?.id && ( @@ -189,7 +191,7 @@ export const InboxIssueContentProperties = observer(function InboxIssueContentPr
- Duplicate of + {t("localized_ui.inbox.properties.duplicate_of")}
{ + archive: async (_workspaceSlug: string, _projectId: string, issueId: string) => { try { - await archiveIssue(workspaceSlug, projectId, issueId); + await archiveIssue(_workspaceSlug, _projectId, issueId); } catch (error) { console.error("Error in archiving issue:", error); } }, }), - [inboxIssue] + [archiveIssue, inboxIssue, projectId, removeIssue, t, workspaceSlug] ); if (!issue) return <>; @@ -206,7 +208,7 @@ export const InboxIssueMainContent = observer(function InboxIssueMainContent(pro createdAt: issue.created_at ? new Date(issue.created_at) : new Date(), createdByDisplayName: inboxIssue.source === EInboxIssueSource.FORMS - ? "Intake Form user" + ? t("localized_ui.inbox.description_versions.intake_form_user") : (getUserDetails(issue.created_by ?? "")?.display_name ?? ""), id: issue.id, isRestoreDisabled: !isEditable, diff --git a/apps/web/core/components/inbox/inbox-filter/applied-filters/date.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/date.tsx index 53cf70989bd..f7902cb2279 100644 --- a/apps/web/core/components/inbox/inbox-filter/applied-filters/date.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/date.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import { PAST_DURATION_FILTER_OPTIONS } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { CloseIcon } from "@plane/propel/icons"; import type { TInboxIssueFilterDateKeys } from "@plane/types"; // helpers @@ -15,25 +16,43 @@ import { renderFormattedDate } from "@plane/utils"; // hooks import { useProjectInbox } from "@/hooks/store/use-project-inbox"; -type InboxIssueAppliedFiltersDate = { +type TInboxIssueAppliedFiltersDate = { filterKey: TInboxIssueFilterDateKeys; label: string; }; +const PAST_DURATION_FILTER_I18N_KEYS: Record = { + today: "localized_ui.inbox.filters.date_options.today", + yesterday: "localized_ui.inbox.filters.date_options.yesterday", + last_7_days: "localized_ui.inbox.filters.date_options.last_7_days", + last_30_days: "localized_ui.inbox.filters.date_options.last_30_days", +}; + +const CUSTOM_DATE_OPERATOR_I18N_KEYS: Record = { + after: "localized_ui.inbox.filters.date_operators.after", + before: "localized_ui.inbox.filters.date_operators.before", +}; + export const InboxIssueAppliedFiltersDate = observer(function InboxIssueAppliedFiltersDate( - props: InboxIssueAppliedFiltersDate + props: TInboxIssueAppliedFiltersDate ) { const { filterKey, label } = props; // hooks + const { t } = useTranslation(); const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); // derived values const filteredValues = inboxFilters?.[filterKey] || []; const currentOptionDetail = (date: string) => { const currentDate = PAST_DURATION_FILTER_OPTIONS.find((d) => d.value === date); - if (currentDate) return currentDate; + if (currentDate) + return { + ...currentDate, + name: t(PAST_DURATION_FILTER_I18N_KEYS[currentDate.value]), + }; const dateSplit = date.split(";"); + const operator = dateSplit[1]; return { - name: `${dateSplit[1].charAt(0).toUpperCase() + dateSplit[1].slice(1)} ${renderFormattedDate(dateSplit[0])}`, + name: `${t(CUSTOM_DATE_OPERATOR_I18N_KEYS[operator])} ${renderFormattedDate(dateSplit[0])}`, value: date, }; }; @@ -53,22 +72,24 @@ export const InboxIssueAppliedFiltersDate = observer(function InboxIssueAppliedF return (
{optionDetail?.name}
-
handleInboxIssueFilters(filterKey, handleFilterValue(optionDetail?.value))} > -
+
); })} -
-
+ ); }); diff --git a/apps/web/core/components/inbox/inbox-filter/applied-filters/label.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/label.tsx index 1fd33cbe80c..429738f5ca0 100644 --- a/apps/web/core/components/inbox/inbox-filter/applied-filters/label.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/label.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; // hooks +import { useTranslation } from "@plane/i18n"; import { CloseIcon } from "@plane/propel/icons"; import { Tag } from "@plane/ui"; import { useLabel } from "@/hooks/store/use-label"; @@ -19,6 +20,7 @@ export const InboxIssueAppliedFiltersLabel = observer(function InboxIssueApplied // hooks const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); const { getLabelById } = useLabel(); + const { t } = useTranslation(); // derived values const filteredValues = inboxFilters?.labels || []; const currentOptionDetail = (labelId: string) => getLabelById(labelId) || undefined; @@ -31,7 +33,7 @@ export const InboxIssueAppliedFiltersLabel = observer(function InboxIssueApplied if (filteredValues.length === 0) return <>; return ( -
Label
+
{t("common.label")}
{filteredValues.map((value) => { const optionDetail = currentOptionDetail(value); if (!optionDetail) return <>; @@ -41,22 +43,24 @@ export const InboxIssueAppliedFiltersLabel = observer(function InboxIssueApplied
{optionDetail?.name}
-
handleInboxIssueFilters("labels", handleFilterValue(value))} > -
+
); })} -
-
+ ); }); diff --git a/apps/web/core/components/inbox/inbox-filter/applied-filters/root.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/root.tsx index 99283e6c2c9..a13198f6b51 100644 --- a/apps/web/core/components/inbox/inbox-filter/applied-filters/root.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/root.tsx @@ -5,6 +5,7 @@ */ import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; // plane imports import { Header, EHeaderVariant } from "@plane/ui"; // hooks @@ -19,6 +20,7 @@ import { InboxIssueAppliedFiltersStatus } from "./status"; export const InboxIssueAppliedFilters = observer(function InboxIssueAppliedFilters() { const { getAppliedFiltersCount } = useProjectInbox(); + const { t } = useTranslation(); if (getAppliedFiltersCount === 0) return <>; return ( @@ -30,15 +32,15 @@ export const InboxIssueAppliedFilters = observer(function InboxIssueAppliedFilte {/* priority */} {/* assignees */} - + {/* created_by */} - + {/* label */} {/* created_at */} - + {/* updated_at */} - + ); }); diff --git a/apps/web/core/components/inbox/inbox-filter/applied-filters/state.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/state.tsx index f8b94c9bcf0..15331454ca8 100644 --- a/apps/web/core/components/inbox/inbox-filter/applied-filters/state.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/state.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import { EIconSize } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { StateGroupIcon, CloseIcon } from "@plane/propel/icons"; import { Tag } from "@plane/ui"; // hooks @@ -16,6 +17,7 @@ export const InboxIssueAppliedFiltersState = observer(function InboxIssueApplied // hooks const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); const { getStateById } = useProjectState(); + const { t } = useTranslation(); // derived values const filteredValues = inboxFilters?.state || []; const currentOptionDetail = (stateId: string) => getStateById(stateId) || undefined; @@ -28,7 +30,7 @@ export const InboxIssueAppliedFiltersState = observer(function InboxIssueApplied if (filteredValues.length === 0) return <>; return ( -
State
+
{t("common.state")}
{filteredValues.map((value) => { const optionDetail = currentOptionDetail(value); if (!optionDetail) return <>; @@ -38,22 +40,24 @@ export const InboxIssueAppliedFiltersState = observer(function InboxIssueApplied
{optionDetail?.name}
-
handleInboxIssueFilters("state", handleFilterValue(optionDetail?.id))} > -
+
); })} -
-
+ ); }); diff --git a/apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx index ccc7c31ae7a..d4d5df8d0e3 100644 --- a/apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx @@ -29,7 +29,7 @@ export const InboxIssueAppliedFiltersStatus = observer(function InboxIssueApplie if (filteredValues.length === 0) return <>; return ( -
Status
+
{t("localized_ui.inbox.filters.status")}
{filteredValues.map((value) => { const optionDetail = currentOptionDetail(value); if (!optionDetail) return <>; @@ -40,12 +40,13 @@ export const InboxIssueAppliedFiltersStatus = observer(function InboxIssueApplie
{t(optionDetail?.i18n_title)}
{handleFilterValue(optionDetail?.status).length >= 1 && ( -
handleInboxIssueFilters("status", handleFilterValue(optionDetail?.status))} > -
+ )}
); diff --git a/apps/web/core/components/inbox/inbox-filter/filters/date.tsx b/apps/web/core/components/inbox/inbox-filter/filters/date.tsx index 51fbbe6d495..93c8ce445a0 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/date.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/date.tsx @@ -8,6 +8,7 @@ import { useState } from "react"; import { concat, uniq } from "lodash-es"; import { observer } from "mobx-react"; import { PAST_DURATION_FILTER_OPTIONS } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import type { TInboxIssueFilterDateKeys } from "@plane/types"; // components import { DateFilterModal } from "@/components/core/filters/date-filter-modal"; @@ -27,9 +28,17 @@ const isDate = (date: string) => { return datePattern.test(date); }; +const PAST_DURATION_FILTER_I18N_KEYS: Record = { + today: "localized_ui.inbox.filters.date_options.today", + yesterday: "localized_ui.inbox.filters.date_options.yesterday", + last_7_days: "localized_ui.inbox.filters.date_options.last_7_days", + last_30_days: "localized_ui.inbox.filters.date_options.last_30_days", +}; + export const FilterDate = observer(function FilterDate(props: Props) { const { filterKey, label, searchQuery } = props; // hooks + const { t } = useTranslation(); const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); // state const [previewEnabled, setPreviewEnabled] = useState(true); @@ -38,14 +47,14 @@ export const FilterDate = observer(function FilterDate(props: Props) { const filterValue: string[] = inboxFilters?.[filterKey] || []; const appliedFiltersCount = filterValue?.length ?? 0; const filteredOptions = PAST_DURATION_FILTER_OPTIONS.filter((d) => - d.name.toLowerCase().includes(searchQuery.toLowerCase()) + t(PAST_DURATION_FILTER_I18N_KEYS[d.value]).toLowerCase().includes(searchQuery.toLowerCase()) ); const handleFilterValue = (value: string): string[] => (filterValue?.includes(value) ? [] : uniq(concat(value))); const isCustomDateSelected = () => { const isValidDateSelected = filterValue?.filter((f) => isDate(f.split(";")[0])) || []; - return isValidDateSelected.length > 0 ? true : false; + return isValidDateSelected.length > 0; }; const handleCustomDate = () => { @@ -64,11 +73,11 @@ export const FilterDate = observer(function FilterDate(props: Props) { handleClose={() => setIsDateFilterModalOpen(false)} isOpen={isDateFilterModalOpen} onSelect={(val) => handleInboxIssueFilters(filterKey, val)} - title="Created date" + title={t("localized_ui.inbox.filters.created_date")} /> )} 0 ? ` (${appliedFiltersCount})` : ""}`} + title={`${label || t("localized_ui.inbox.filters.created_date")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`} isPreviewEnabled={previewEnabled} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} /> @@ -79,21 +88,21 @@ export const FilterDate = observer(function FilterDate(props: Props) { {filteredOptions.map((option) => ( handleInboxIssueFilters(filterKey, handleFilterValue(option.value))} - title={option.name} + title={t(PAST_DURATION_FILTER_I18N_KEYS[option.value])} multiple={false} /> ))} ) : ( -

No matches found

+

{t("common.search.no_matches_found")}

)}
)} diff --git a/apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx b/apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx index 99ae144cd0c..8f10fe55bda 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx @@ -6,11 +6,11 @@ import { useState } from "react"; import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; import { SearchIcon, CloseIcon } from "@plane/propel/icons"; // hooks import { useLabel } from "@/hooks/store/use-label"; import { useMember } from "@/hooks/store/use-member"; -import { usePlatformOS } from "@/hooks/use-platform-os"; // local imports import { FilterDate } from "./date"; import { FilterLabels } from "./labels"; @@ -20,7 +20,7 @@ import { FilterStatus } from "./status"; export const InboxIssueFilterSelection = observer(function InboxIssueFilterSelection() { // hooks - const { isMobile } = usePlatformOS(); + const { t } = useTranslation(); const { project: { projectMemberIds }, } = useMember(); @@ -36,10 +36,9 @@ export const InboxIssueFilterSelection = observer(function InboxIssueFilterSelec setFiltersSearchQuery(e.target.value)} - autoFocus={!isMobile} /> {filtersSearchQuery !== "" && (
diff --git a/apps/web/core/components/inbox/inbox-filter/filters/labels.tsx b/apps/web/core/components/inbox/inbox-filter/filters/labels.tsx index 23e338b1d31..cc1f6c4b81a 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/labels.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/labels.tsx @@ -6,6 +6,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; import type { IIssueLabel } from "@plane/types"; import { Loader } from "@plane/ui"; // components @@ -28,6 +29,7 @@ export const FilterLabels = observer(function FilterLabels(props: Props) { const [itemsToRender, setItemsToRender] = useState(5); const [previewEnabled, setPreviewEnabled] = useState(true); + const { t } = useTranslation(); const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); const filterValue = inboxFilters?.labels || []; @@ -49,7 +51,7 @@ export const FilterLabels = observer(function FilterLabels(props: Props) { return ( <> 0 ? ` (${appliedFiltersCount})` : ""}`} + title={`${t("common.label")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`} isPreviewEnabled={previewEnabled} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} /> @@ -61,7 +63,7 @@ export const FilterLabels = observer(function FilterLabels(props: Props) { {filteredOptions.slice(0, itemsToRender).map((label) => ( handleInboxIssueFilters("labels", handleFilterValue(label.id))} icon={} title={label.name} @@ -73,12 +75,14 @@ export const FilterLabels = observer(function FilterLabels(props: Props) { className="ml-8 text-11 font-medium text-accent-primary" onClick={handleViewToggle} > - {itemsToRender === filteredOptions.length ? "View less" : "View all"} + {itemsToRender === filteredOptions.length + ? t("localized_ui.inbox.filters.view_less") + : t("localized_ui.inbox.filters.view_all")} )} ) : ( -

No matches found

+

{t("common.search.no_matches_found")}

) ) : ( diff --git a/apps/web/core/components/inbox/inbox-filter/filters/members.tsx b/apps/web/core/components/inbox/inbox-filter/filters/members.tsx index d555aa81b85..dc0b0cdedc1 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/members.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/members.tsx @@ -7,6 +7,7 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; +import { useTranslation } from "@plane/i18n"; // plane types import type { TInboxIssueFilterMemberKeys } from "@plane/types"; // plane ui @@ -28,8 +29,9 @@ type Props = { }; export const FilterMember = observer(function FilterMember(props: Props) { - const { filterKey, label = "Members", memberIds, searchQuery } = props; + const { filterKey, label, memberIds, searchQuery } = props; // hooks + const { t } = useTranslation(); const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); const { getUserDetails } = useMember(); const { data: currentUser } = useUser(); @@ -66,7 +68,7 @@ export const FilterMember = observer(function FilterMember(props: Props) { return ( <> 0 ? ` (${appliedFiltersCount})` : ""}`} + title={`${label ?? t("members")} ${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`} isPreviewEnabled={previewEnabled} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} /> @@ -82,7 +84,7 @@ export const FilterMember = observer(function FilterMember(props: Props) { return ( handleInboxIssueFilters(filterKey, handleFilterValue(member.id))} icon={ } - title={currentUser?.id === member.id ? "You" : member?.display_name} + title={currentUser?.id === member.id ? t("you") : member?.display_name} /> ); })} @@ -102,12 +104,14 @@ export const FilterMember = observer(function FilterMember(props: Props) { className="ml-8 text-11 font-medium text-accent-primary" onClick={handleViewToggle} > - {itemsToRender === sortedOptions.length ? "View less" : "View all"} + {itemsToRender === sortedOptions.length + ? t("localized_ui.inbox.filters.view_less") + : t("localized_ui.inbox.filters.view_all")} )} ) : ( -

No matches found

+

{t("common.search.no_matches_found")}

) ) : ( diff --git a/apps/web/core/components/inbox/inbox-filter/filters/state.tsx b/apps/web/core/components/inbox/inbox-filter/filters/state.tsx index 4a4af021fce..c5ff1e2484a 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/state.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/state.tsx @@ -7,6 +7,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { EIconSize } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { StateGroupIcon } from "@plane/propel/icons"; import type { IState } from "@plane/types"; import { Loader } from "@plane/ui"; @@ -26,6 +27,7 @@ export const FilterState = observer(function FilterState(props: Props) { const [itemsToRender, setItemsToRender] = useState(5); const [previewEnabled, setPreviewEnabled] = useState(true); + const { t } = useTranslation(); const { inboxFilters, handleInboxIssueFilters } = useProjectInbox(); const filterValue = inboxFilters?.state || []; @@ -47,7 +49,7 @@ export const FilterState = observer(function FilterState(props: Props) { return ( <> 0 ? ` (${appliedFiltersCount})` : ""}`} + title={`${t("common.state")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`} isPreviewEnabled={previewEnabled} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} /> @@ -59,7 +61,7 @@ export const FilterState = observer(function FilterState(props: Props) { {filteredOptions.slice(0, itemsToRender).map((state) => ( handleInboxIssueFilters("state", handleFilterValue(state.id))} icon={ - {itemsToRender === filteredOptions.length ? "View less" : "View all"} + {itemsToRender === filteredOptions.length + ? t("localized_ui.inbox.filters.view_less") + : t("localized_ui.inbox.filters.view_all")} )} ) : ( -

No matches found

+

{t("common.search.no_matches_found")}

) ) : ( diff --git a/apps/web/core/components/inbox/inbox-filter/filters/status.tsx b/apps/web/core/components/inbox/inbox-filter/filters/status.tsx index e08a71334ac..508bf1935c1 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/status.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/status.tsx @@ -49,7 +49,7 @@ export const FilterStatus = observer(function FilterStatus(props: Props) { return ( <> 0 ? ` (${appliedFiltersCount})` : ""}`} + title={`${t("localized_ui.inbox.filters.work_item_status")} ${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`} isPreviewEnabled={previewEnabled} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} /> @@ -59,14 +59,14 @@ export const FilterStatus = observer(function FilterStatus(props: Props) { filteredOptions.map((status) => ( handleStatusFilterSelect(status.status)} icon={} title={t(status.i18n_title)} /> )) ) : ( -

No matches found

+

{t("common.search.no_matches_found")}

)}
)} diff --git a/apps/web/core/components/inbox/inbox-filter/root.tsx b/apps/web/core/components/inbox/inbox-filter/root.tsx index 2413ccc382f..3fa02ff5650 100644 --- a/apps/web/core/components/inbox/inbox-filter/root.tsx +++ b/apps/web/core/components/inbox/inbox-filter/root.tsx @@ -5,6 +5,7 @@ */ import { ListFilter } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; import { getButtonStyling } from "@plane/propel/button"; // plane imports import { ChevronDownIcon } from "@plane/propel/icons"; @@ -19,15 +20,17 @@ import { InboxIssueOrderByDropdown } from "./sorting/order-by"; const smallButton = ; -const largeButton = ( -
- - Filters - -
-); export function FiltersRoot() { const windowSize = useSize(); + const { t } = useTranslation(); + + const largeButton = ( +
+ + {t("common.filters")} + +
+ ); return (
diff --git a/apps/web/core/components/inbox/modals/create-modal/create-root.tsx b/apps/web/core/components/inbox/modals/create-modal/create-root.tsx index e31e8da1270..430486ad727 100644 --- a/apps/web/core/components/inbox/modals/create-modal/create-root.tsx +++ b/apps/web/core/components/inbox/modals/create-modal/create-root.tsx @@ -110,8 +110,8 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props } else { setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Editor is still processing changes. Please wait before proceeding.", + title: t("common.error.label"), + message: t("localized_ui.inbox.toasts.editor_processing"), }); event.preventDefault(); // Prevent default action if editor is not ready to discard } @@ -142,8 +142,8 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props if (!descriptionEditorRef.current?.isEditorReadyToDiscard()) { setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Editor is still processing changes. Please wait before proceeding.", + title: t("common.error.label"), + message: t("localized_ui.inbox.toasts.editor_processing"), }); return; } @@ -159,35 +159,34 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props }; setFormSubmitting(true); - await createInboxIssue(workspaceSlug, projectId, payload) - .then(async (res) => { - if (uploadedAssetIds.length > 0) { - await fileService.updateBulkProjectAssetsUploadStatus(workspaceSlug, projectId, res?.issue.id ?? "", { - asset_ids: uploadedAssetIds, - }); - setUploadedAssetIds([]); - } - if (!createMore) { - router.push(`/${workspaceSlug}/projects/${projectId}/intake/?currentTab=open&inboxIssueId=${res?.issue?.id}`); - handleModalClose(); - } else { - descriptionEditorRef?.current?.clearEditor(); - setFormData(defaultIssueData); - } - setToast({ - type: TOAST_TYPE.SUCCESS, - title: `Success!`, - message: "Work item created successfully.", - }); - }) - .catch((error) => { - console.error(error); - setToast({ - type: TOAST_TYPE.ERROR, - title: `Error!`, - message: "Some error occurred. Please try again.", + try { + const res = await createInboxIssue(workspaceSlug, projectId, payload); + if (uploadedAssetIds.length > 0) { + await fileService.updateBulkProjectAssetsUploadStatus(workspaceSlug, projectId, res?.issue.id ?? "", { + asset_ids: uploadedAssetIds, }); + setUploadedAssetIds([]); + } + if (!createMore) { + router.push(`/${workspaceSlug}/projects/${projectId}/intake/?currentTab=open&inboxIssueId=${res?.issue?.id}`); + handleModalClose(); + } else { + descriptionEditorRef?.current?.clearEditor(); + setFormData(defaultIssueData); + } + setToast({ + type: TOAST_TYPE.SUCCESS, + title: t("common.success"), + message: t("localized_ui.inbox.toasts.create_success"), }); + } catch (error) { + console.error(error); + setToast({ + type: TOAST_TYPE.ERROR, + title: t("common.error.label"), + message: t("common.error.message"), + }); + } setFormSubmitting(false); }; @@ -207,7 +206,7 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props 1 ? "s" : ""} found!`} + label={t("localized_ui.inbox.duplicate_issues_found", { count: duplicateIssues.length })} handleOnClick={() => handleDuplicateIssueModal(!isDuplicateModalOpen)} /> )} @@ -233,15 +232,15 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props
-
setCreateMore((prevData) => !prevData)} - role="button" tabIndex={getIndex("create_more")} > {}} size="sm" /> {t("create_more")} -
+
@@ -122,7 +124,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props onChange={(date) => handleData("target_date", date ? renderFormattedPayloadDate(date) : "")} buttonVariant="border-with-text" minDate={minDate ?? undefined} - placeholder="Due date" + placeholder={t("due_date")} tabIndex={getIndex("target_date")} />
@@ -134,7 +136,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props value={data?.cycle_id || ""} onChange={(cycleId) => handleData("cycle_id", cycleId)} projectId={projectId} - placeholder="Cycle" + placeholder={t("common.cycle")} buttonVariant="border-with-text" tabIndex={getIndex("cycle_id")} /> @@ -148,7 +150,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props value={data?.module_ids || []} onChange={(moduleIds) => handleData("module_ids", moduleIds)} projectId={projectId} - placeholder="Modules" + placeholder={t("common.modules")} buttonVariant="border-with-text" multiple showCount @@ -165,7 +167,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props onChange={(estimatePoint) => handleData("estimate_point", estimatePoint)} projectId={projectId} buttonVariant="border-with-text" - placeholder="Estimate" + placeholder={t("estimate")} tabIndex={getIndex("estimate_point")} />
@@ -185,7 +187,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props {selectedParentIssue ? `${selectedParentIssue.project__identifier}-${selectedParentIssue.sequence_id}` - : `Add parent`} + : t("add_parent")} } @@ -196,7 +198,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props > <> setParentIssueModalOpen(true)}> - Change parent work item + {t("change_parent_issue")} - Remove parent work item + {t("remove_parent_issue")} @@ -216,7 +218,7 @@ export const InboxIssueProperties = observer(function InboxIssueProperties(props onClick={() => setParentIssueModalOpen(true)} > - Add parent + {t("add_parent")} )} diff --git a/apps/web/core/components/inbox/modals/select-duplicate.tsx b/apps/web/core/components/inbox/modals/select-duplicate.tsx index 7b6911830f1..93f3afd67e8 100644 --- a/apps/web/core/components/inbox/modals/select-duplicate.tsx +++ b/apps/web/core/components/inbox/modals/select-duplicate.tsx @@ -77,7 +77,7 @@ export function SelectDuplicateInboxIssueModal(props: Props) { const handleSubmit = (selectedItem: string) => { if (!selectedItem || selectedItem.length === 0) return setToast({ - title: "Error", + title: t("error"), type: TOAST_TYPE.ERROR, }); onSubmit(selectedItem); @@ -87,7 +87,11 @@ export function SelectDuplicateInboxIssueModal(props: Props) { const issueList = filteredIssues.length > 0 ? (
  • - {query === "" &&

    Select work item

    } + {query === "" && ( +

    + {t("localized_ui.inbox.select_duplicate.select_work_item")} +

    + )}
      {filteredIssues.map((issue) => { const stateColor = issue.state__color || ""; @@ -141,7 +145,7 @@ export function SelectDuplicateInboxIssueModal(props: Props) { setQuery(e.target.value)} />
  • diff --git a/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx b/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx index db8d4240f9f..cba60333cbb 100644 --- a/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx +++ b/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx @@ -9,6 +9,7 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; // plane imports +import { useTranslation } from "@plane/i18n"; import { PriorityIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; import { Row, Avatar } from "@plane/ui"; @@ -43,6 +44,7 @@ export const InboxIssueListItem = observer(function InboxIssueListItem(props: In const { projectLabels } = useLabel(); const { isMobile } = usePlatformOS(); const { getUserDetails } = useMember(); + const { t } = useTranslation(); const inboxIssue = getIssueInboxByIssueId(inboxIssueId); const issue = inboxIssue?.issue; @@ -85,7 +87,7 @@ export const InboxIssueListItem = observer(function InboxIssueListItem(props: In
    @@ -95,7 +97,7 @@ export const InboxIssueListItem = observer(function InboxIssueListItem(props: In
    {issue.priority && ( - + )} @@ -103,7 +105,9 @@ export const InboxIssueListItem = observer(function InboxIssueListItem(props: In {issue.label_ids && issue.label_ids.length > 3 ? (
    - {`${issue.label_ids.length} labels`} + + {t("localized_ui.inbox.sidebar.label_count", { count: issue.label_ids.length })} +
    ) : ( <> diff --git a/apps/web/core/components/inbox/sidebar/root.tsx b/apps/web/core/components/inbox/sidebar/root.tsx index e378c766d56..c4023d98e49 100644 --- a/apps/web/core/components/inbox/sidebar/root.tsx +++ b/apps/web/core/components/inbox/sidebar/root.tsx @@ -87,7 +87,8 @@ export const InboxSidebar = observer(function InboxSidebar(props: IInboxSidebarP
    {tabNavigationOptions.map((option) => ( -
    -
    + ))}
    @@ -161,11 +162,10 @@ export const InboxSidebar = observer(function InboxSidebar(props: IInboxSidebarP rootClassName="px-page-x" /> ) : ( - // TODO: Add translation diff --git a/apps/web/core/components/onboarding/invitations.tsx b/apps/web/core/components/onboarding/invitations.tsx index f8537b96245..0f7ad8c496d 100644 --- a/apps/web/core/components/onboarding/invitations.tsx +++ b/apps/web/core/components/onboarding/invitations.tsx @@ -7,6 +7,7 @@ import { useState } from "react"; // plane imports import { ROLE } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; // types import { Button } from "@plane/propel/button"; import type { IWorkspaceMemberInvitation } from "@plane/types"; @@ -31,6 +32,7 @@ const workspaceService = new WorkspaceService(); export function Invitations(props: Props) { const { invitations, handleNextStep, handleCurrentViewChange } = props; + const { t } = useTranslation(); // states const [isJoiningWorkspaces, setIsJoiningWorkspaces] = useState(false); const [invitationsRespond, setInvitationsRespond] = useState([]); @@ -47,8 +49,10 @@ export function Invitations(props: Props) { }; const submitInvitations = async () => { - const invitation = invitations?.find((invitation) => invitation.id === invitationsRespond[0]); - if (invitationsRespond.length <= 0 && !invitation?.role) return; + const selectedInvitation = invitations?.find( + (workspaceInvitation) => workspaceInvitation.id === invitationsRespond[0] + ); + if (invitationsRespond.length <= 0 && !selectedInvitation?.role) return; setIsJoiningWorkspaces(true); try { await workspaceService.joinWorkspaces({ invitations: invitationsRespond }); @@ -64,8 +68,8 @@ export function Invitations(props: Props) { return invitations && invitations.length > 0 ? (
    -

    You are invited!

    -

    Accept the invites to collaborate with your team.

    +

    {t("localized_ui.onboarding.you_are_invited")}

    +

    {t("localized_ui.onboarding.accept_invites")}

    {invitations && @@ -74,9 +78,10 @@ export function Invitations(props: Props) { const isSelected = invitationsRespond.includes(invitation.id); const invitedWorkspace = invitation.workspace; return ( -
    handleInvitation(invitation, isSelected ? "withdraw" : "accepted")} >
    @@ -93,7 +98,7 @@ export function Invitations(props: Props) { -
    + ); })}
    @@ -104,11 +109,15 @@ export function Invitations(props: Props) { onClick={submitInvitations} disabled={isJoiningWorkspaces || !invitationsRespond.length} > - {isJoiningWorkspaces ? : "Continue to workspace"} + {isJoiningWorkspaces ? ( + + ) : ( + t("localized_ui.onboarding.continue_to_workspace") + )}

    -

    or

    +

    {t("localized_ui.onboarding.or")}


    ) : ( -
    No Invitations found
    +
    {t("localized_ui.onboarding.no_invitations_found")}
    ); } diff --git a/apps/web/core/components/onboarding/invite-members.tsx b/apps/web/core/components/onboarding/invite-members.tsx index b73c87bb8b8..bc1bd92044e 100644 --- a/apps/web/core/components/onboarding/invite-members.tsx +++ b/apps/web/core/components/onboarding/invite-members.tsx @@ -213,7 +213,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe style={styles.popper} {...attributes.popper} > - {Object.entries(ROLE_DETAILS).map(([key, value]) => ( + {Object.entries(ROLE_DETAILS).map(([key, roleDetail]) => ( (
    -
    {t(value.i18n_title)}
    -
    {t(value.i18n_description)}
    +
    {t(roleDetail.i18n_title)}
    +
    {t(roleDetail.i18n_description)}
    {selected && }
    @@ -254,7 +254,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe {email && !emailRegex.test(email) && (
    🤥{" "} - That doesn{"'"}t look like an email address. + {t("localized_ui.onboarding.invalid_email")}
    )}
    @@ -263,6 +263,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe export function InviteMembers(props: Props) { const { finishOnboarding, workspace } = props; + const { t } = useTranslation(); const [isInvitationDisabled, setIsInvitationDisabled] = useState(true); @@ -297,18 +298,18 @@ export function InviteMembers(props: Props) { role: email.role, })), }) - .then(async () => { + .then(() => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: "Invitations sent successfully.", + title: t("localized_ui.onboarding.success"), + message: t("localized_ui.onboarding.invitations_sent"), }); - await nextStep(); + return nextStep(); }) .catch((err) => { setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", + title: t("localized_ui.onboarding.error"), message: err?.error, }); }); @@ -338,10 +339,8 @@ export function InviteMembers(props: Props) {
    -

    Invite your teammates

    -

    - Work in plane happens best with your team. Invite them now to use Plane to its potential. -

    +

    {t("localized_ui.onboarding.invite_team_title")}

    +

    {t("localized_ui.onboarding.invite_team_description")}

    -
    Email
    -
    Role
    +
    + {t("localized_ui.space_auth.email")} +
    +
    {t("role")}
    {fields.map((field, index) => ( @@ -379,7 +380,7 @@ export function InviteMembers(props: Props) { onClick={appendField} > - Add another + {t("localized_ui.onboarding.add_another")}
    @@ -390,10 +391,10 @@ export function InviteMembers(props: Props) { className="w-full" disabled={isInvitationDisabled || !isValid || isSubmitting} > - {isSubmitting ? : "Continue"} + {isSubmitting ? : t("localized_ui.onboarding.continue")}
    diff --git a/apps/web/core/components/onboarding/steps/profile/root.tsx b/apps/web/core/components/onboarding/steps/profile/root.tsx index 5e71c802f3b..27e76dc5db1 100644 --- a/apps/web/core/components/onboarding/steps/profile/root.tsx +++ b/apps/web/core/components/onboarding/steps/profile/root.tsx @@ -10,6 +10,7 @@ import { Controller, useForm } from "react-hook-form"; import { ImageIcon } from "lucide-react"; // plane imports import { E_PASSWORD_STRENGTH } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { IUser } from "@plane/types"; @@ -54,6 +55,7 @@ const defaultValues: Partial = { }; export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepChange }: Props) { + const { t } = useTranslation(); // states const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); // store hooks @@ -99,8 +101,8 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC } catch { setToast({ type: TOAST_TYPE.ERROR, - title: "Error", - message: "User details update failed. Please try again!", + title: t("localized_ui.onboarding.error"), + message: t("something_went_wrong_please_try_again"), }); } }; @@ -141,13 +143,15 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC // Check for all available fields validation and if password field is available, then checks for password validation (strength + confirmation). // Also handles the condition for optional password i.e if password field is optional it only checks for above validation if it's not empty. - const isButtonDisabled = - !isSubmitting && isValid ? (isPasswordAlreadySetup ? false : isValidPassword ? false : true) : true; + const isButtonDisabled = isSubmitting || !isValid || (!isPasswordAlreadySetup && !isValidPassword); return (
    {/* Header */} - + {/* Profile Picture Section */} setIsImageUploadModalOpen(true)} alt={user?.display_name} className="h-full w-full rounded-full object-cover" /> @@ -190,7 +193,9 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC onClick={() => setIsImageUploadModalOpen(true)} > - {userAvatar ? "Change image" : "Upload image"} + + {userAvatar ? t("localized_ui.onboarding.change_image") : t("localized_ui.onboarding.upload_image")} +
    @@ -201,17 +206,17 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC className="block text-13 font-medium text-tertiary after:ml-0.5 after:text-danger-primary after:content-['*']" htmlFor="first_name" > - Name + {t("localized_ui.onboarding.name")} ( @@ -222,7 +227,6 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC type="text" value={value} onChange={(e) => onChange(e.target.value)} - autoFocus className={cn( "w-full rounded-md border border-strong bg-surface-1 px-3 py-2 text-secondary transition-all duration-200 placeholder:text-placeholder focus:border-transparent focus:ring-2 focus:ring-accent-strong focus:outline-none", { @@ -230,7 +234,7 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC "border-danger-strong": errors.first_name, } )} - placeholder="Enter your full name" + placeholder={t("localized_ui.onboarding.enter_full_name")} autoComplete="on" /> )} @@ -248,7 +252,7 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC
    {/* Continue Button */} {/* Marketing Consent */} diff --git a/apps/web/core/components/onboarding/steps/profile/set-password.tsx b/apps/web/core/components/onboarding/steps/profile/set-password.tsx index 95421e2b391..1179cf653a9 100644 --- a/apps/web/core/components/onboarding/steps/profile/set-password.tsx +++ b/apps/web/core/components/onboarding/steps/profile/set-password.tsx @@ -5,6 +5,7 @@ */ import React, { useState, useCallback, useMemo } from "react"; +import { useTranslation } from "@plane/i18n"; import { LockIcon, ChevronDownIcon } from "@plane/propel/icons"; import { PasswordInput, PasswordStrengthIndicator } from "@plane/ui"; import { cn } from "@plane/utils"; @@ -21,6 +22,7 @@ interface SetPasswordRootProps { } export function SetPasswordRoot({ onPasswordChange, onConfirmPasswordChange, disabled = false }: SetPasswordRootProps) { + const { t } = useTranslation(); const [isExpanded, setIsExpanded] = useState(false); const [passwordState, setPasswordState] = useState({ password: "", @@ -77,7 +79,8 @@ export function SetPasswordRoot({ onPasswordChange, onConfirmPasswordChange, dis return (
    -
    - Set a password - {`(Optional)`} + {t("localized_ui.onboarding.set_password")} + ({t("localized_ui.onboarding.optional")})
    -
    +
    {/* Password input */} @@ -102,7 +105,7 @@ export function SetPasswordRoot({ onPasswordChange, onConfirmPasswordChange, dis id="password" value={passwordState.password} onChange={(value) => handlePasswordChange("password", value)} - placeholder="Set a password" + placeholder={t("localized_ui.onboarding.set_password")} className="transition-all duration-200" /> {passwordState.password.length > 0 && } @@ -111,7 +114,7 @@ export function SetPasswordRoot({ onPasswordChange, onConfirmPasswordChange, dis
    {/* Confirm password label */}
    - Confirm password + {t("localized_ui.space_auth.confirm_password")}
    {/* Confirm password input */} @@ -120,11 +123,15 @@ export function SetPasswordRoot({ onPasswordChange, onConfirmPasswordChange, dis id="confirm-password" value={passwordState.confirmPassword} onChange={(value) => handlePasswordChange("confirmPassword", value)} - placeholder="Confirm password" + placeholder={t("localized_ui.space_auth.confirm_password")} className="transition-all duration-200" /> - {hasPasswordMismatch &&

    Passwords do not match

    } - {isPasswordValid &&

    ✓ Passwords match

    } + {hasPasswordMismatch && ( +

    {t("localized_ui.onboarding.passwords_do_not_match")}

    + )} + {isPasswordValid && ( +

    ✓ {t("localized_ui.onboarding.passwords_match")}

    + )}
    diff --git a/apps/web/core/components/onboarding/steps/team/root.tsx b/apps/web/core/components/onboarding/steps/team/root.tsx index 536110fd03b..de84dc6310d 100644 --- a/apps/web/core/components/onboarding/steps/team/root.tsx +++ b/apps/web/core/components/onboarding/steps/team/root.tsx @@ -145,7 +145,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe rules={{ pattern: { value: emailRegex, - message: "Invalid Email ID", + message: t("localized_ui.onboarding.invalid_email"), }, }} render={({ field: { value, onChange, ref } }) => ( @@ -209,7 +209,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe style={styles.popper} {...attributes.popper} > - {Object.entries(ROLE_DETAILS).map(([key, value]) => ( + {Object.entries(ROLE_DETAILS).map(([key, roleDetail]) => ( (
    -
    {t(value.i18n_title)}
    -
    {t(value.i18n_description)}
    +
    {t(roleDetail.i18n_title)}
    +
    {t(roleDetail.i18n_description)}
    {selected && }
    @@ -250,7 +250,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe {email && !emailRegex.test(email) && (
    🤥{" "} - That doesn{"'"}t look like an email address. + {t("localized_ui.onboarding.invalid_email")}
    )}
    @@ -259,6 +259,7 @@ const InviteMemberInput = observer(function InviteMemberInput(props: InviteMembe export const InviteTeamStep = observer(function InviteTeamStep(props: Props) { const { handleStepChange } = props; + const { t } = useTranslation(); const [isInvitationDisabled, setIsInvitationDisabled] = useState(true); @@ -297,18 +298,18 @@ export const InviteTeamStep = observer(function InviteTeamStep(props: Props) { role: email.role, })), }) - .then(async () => { + .then(() => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: "Invitations sent successfully.", + title: t("localized_ui.onboarding.success"), + message: t("localized_ui.onboarding.invitations_sent"), }); - await nextStep(); + return nextStep(); }) .catch((err) => { setToast({ type: TOAST_TYPE.ERROR, - title: "Error!", + title: t("localized_ui.onboarding.error"), message: err?.error, }); }); @@ -342,13 +343,13 @@ export const InviteTeamStep = observer(function InviteTeamStep(props: Props) { }} >
    -
    Email
    -
    Role
    +
    {t("localized_ui.space_auth.email")}
    +
    {t("role")}
    {fields.map((field, index) => ( @@ -374,7 +375,7 @@ export const InviteTeamStep = observer(function InviteTeamStep(props: Props) { onClick={appendField} > - Add another + {t("localized_ui.onboarding.add_another")}
    @@ -385,10 +386,10 @@ export const InviteTeamStep = observer(function InviteTeamStep(props: Props) { className="w-full" disabled={isInvitationDisabled || !isValid || isSubmitting} > - {isSubmitting ? : "Continue"} + {isSubmitting ? : t("localized_ui.onboarding.continue")}
    diff --git a/apps/web/core/components/onboarding/steps/usecase/root.tsx b/apps/web/core/components/onboarding/steps/usecase/root.tsx index 8908adaf3b4..2918d16bcc4 100644 --- a/apps/web/core/components/onboarding/steps/usecase/root.tsx +++ b/apps/web/core/components/onboarding/steps/usecase/root.tsx @@ -8,6 +8,7 @@ import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; // plane imports import { USE_CASES } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { CheckIcon } from "@plane/propel/icons"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; @@ -29,6 +30,7 @@ const defaultValues = { }; export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepChange }: Props) { + const { t } = useTranslation(); // store hooks const { data: profile, updateUserProfile } = useUserProfile(); // form info @@ -50,20 +52,17 @@ export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepC use_case: formData.use_case && formData.use_case.length > 0 ? formData.use_case.join(". ") : undefined, }; try { - await Promise.all([ - updateUserProfile(profileUpdatePayload), - // totalSteps > 2 && stepChange({ profile_complete: true }), - ]); + await updateUserProfile(profileUpdatePayload); setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success", - message: "Profile setup completed!", + title: t("localized_ui.onboarding.success"), + message: t("localized_ui.onboarding.profile_setup_completed"), }); } catch { setToast({ type: TOAST_TYPE.ERROR, - title: "Error", - message: "Profile setup failed. Please try again!", + title: t("localized_ui.onboarding.error"), + message: t("localized_ui.onboarding.profile_setup_failed"), }); } }; @@ -81,23 +80,26 @@ export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepC }; // derived values - const isButtonDisabled = !isSubmitting && isValid ? false : true; + const isButtonDisabled = isSubmitting || !isValid; return (
    {/* Header */} - + {/* Use Case Selection */}
    -

    Select one or more

    +

    {t("localized_ui.onboarding.select_one_or_more")}

    (value && value.length > 0) || "Please select at least one option", + required: t("localized_ui.onboarding.select_at_least_one"), + validate: (value) => (value && value.length > 0) || t("localized_ui.onboarding.select_at_least_one"), }} render={({ field: { value, onChange } }) => (
    @@ -151,10 +153,10 @@ export const UseCaseSetupStep = observer(function UseCaseSetupStep({ handleStepC {/* Action Buttons */}
    diff --git a/apps/web/core/components/onboarding/steps/workspace/create.tsx b/apps/web/core/components/onboarding/steps/workspace/create.tsx index f9c32a91f26..884535c7db9 100644 --- a/apps/web/core/components/onboarding/steps/workspace/create.tsx +++ b/apps/web/core/components/onboarding/steps/workspace/create.tsx @@ -118,9 +118,7 @@ export const WorkspaceCreateStep = observer(function WorkspaceCreateStep({ return (
    - You don't seem to have any invites to a workspace and your instance admin has restricted creation of new - workspaces. Please ask a workspace owner or admin to invite you to a workspace first and come back to this - screen to join. + {t("localized_ui.onboarding.workspace_creation_disabled")}
    ); @@ -132,7 +130,10 @@ export const WorkspaceCreateStep = observer(function WorkspaceCreateStep({ void handleSubmit(handleCreateWorkspace)(e); }} > - +
    diff --git a/apps/web/core/components/onboarding/steps/workspace/join-invites.tsx b/apps/web/core/components/onboarding/steps/workspace/join-invites.tsx index c49c0d2aca2..49bd145abd8 100644 --- a/apps/web/core/components/onboarding/steps/workspace/join-invites.tsx +++ b/apps/web/core/components/onboarding/steps/workspace/join-invites.tsx @@ -7,6 +7,7 @@ import { useState } from "react"; // plane imports import { ROLE } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import type { IWorkspaceMemberInvitation } from "@plane/types"; import { Checkbox, Spinner } from "@plane/ui"; @@ -30,6 +31,7 @@ const workspaceService = new WorkspaceService(); export function WorkspaceJoinInvitesStep(props: Props) { const { invitations, handleNextStep, handleCurrentViewChange } = props; + const { t } = useTranslation(); // states const [isJoiningWorkspaces, setIsJoiningWorkspaces] = useState(false); const [invitationsRespond, setInvitationsRespond] = useState([]); @@ -48,9 +50,11 @@ export function WorkspaceJoinInvitesStep(props: Props) { // submit invitations const submitInvitations = async () => { - const invitation = invitations?.find((invitation) => invitation.id === invitationsRespond[0]); + const selectedInvitation = invitations?.find( + (workspaceInvitation) => workspaceInvitation.id === invitationsRespond[0] + ); - if (invitationsRespond.length <= 0 && !invitation?.role) return; + if (invitationsRespond.length <= 0 || !selectedInvitation?.role) return; setIsJoiningWorkspaces(true); @@ -67,7 +71,10 @@ export function WorkspaceJoinInvitesStep(props: Props) { return invitations && invitations.length > 0 ? (
    - +
    {invitations && invitations.length > 0 && @@ -75,9 +82,10 @@ export function WorkspaceJoinInvitesStep(props: Props) { const isSelected = invitationsRespond.includes(invitation.id); const invitedWorkspace = invitation.workspace; return ( -
    handleInvitation(invitation, isSelected ? "withdraw" : "accepted")} >
    @@ -94,7 +102,7 @@ export function WorkspaceJoinInvitesStep(props: Props) { -
    + ); })}
    @@ -106,7 +114,7 @@ export function WorkspaceJoinInvitesStep(props: Props) { onClick={submitInvitations} disabled={isJoiningWorkspaces || !invitationsRespond.length} > - {isJoiningWorkspaces ? : "Continue"} + {isJoiningWorkspaces ? : t("localized_ui.onboarding.continue")}
    ) : ( -
    No Invitations found
    +
    {t("localized_ui.onboarding.no_invitations_found")}
    ); } diff --git a/apps/web/core/components/stickies/modal/stickies.tsx b/apps/web/core/components/stickies/modal/stickies.tsx index 95746422ebc..4a5294aa837 100644 --- a/apps/web/core/components/stickies/modal/stickies.tsx +++ b/apps/web/core/components/stickies/modal/stickies.tsx @@ -8,6 +8,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane ui +import { useTranslation } from "@plane/i18n"; import { RecentStickyIcon, PlusIcon, CloseIcon } from "@plane/propel/icons"; // hooks import { useSticky } from "@/hooks/use-stickies"; @@ -22,6 +23,7 @@ type TProps = { export const Stickies = observer(function Stickies(props: TProps) { const { handleClose } = props; + const { t } = useTranslation(); // navigation const { workspaceSlug } = useParams(); // store hooks @@ -36,7 +38,7 @@ export const Stickies = observer(function Stickies(props: TProps) { {/* Title */}
    -

    Your stickies

    +

    {t("stickies.title")}

    {/* actions */}
    @@ -49,7 +51,7 @@ export const Stickies = observer(function Stickies(props: TProps) { className="my-auto flex gap-1 text-13 font-medium text-accent-primary" disabled={creatingSticky} > - Add sticky + {t("stickies.add")} {creatingSticky && (
    {currentUser?.email}
    -
    - + -
    +
    Plane logo
    -

    Workspace not found

    +

    {t("localized_ui.workspace_access.not_found_title")}

    - No workspace found with the URL. It may not exist or you lack authorization to view it. + {t("localized_ui.workspace_access.not_found_description")}

    {allWorkspaces && allWorkspaces.length > 0 && ( - Go Home + {t("go_home")} )} {allWorkspaces?.length > 0 && ( - Visit Profile + {t("localized_ui.workspace_access.visit_profile")} )} {allWorkspaces && allWorkspaces.length === 0 && ( - Create new workspace + {t("localized_ui.onboarding.create_new_workspace")} )}
    @@ -209,21 +213,20 @@ export const WorkspaceAuthWrapper = observer(function WorkspaceAuthWrapper(props
    -

    Not Authorized!

    +

    {t("localized_ui.workspace_access.not_authorized_title")}

    - You{"'"}re not a member of this workspace. Please contact the workspace admin to get an invitation or - check your pending invitations. + {t("localized_ui.workspace_access.not_authorized_description")}

    - + - +
    diff --git a/packages/editor/package.json b/packages/editor/package.json index ae4aa512d42..5de021008ab 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -39,6 +39,7 @@ "@hocuspocus/provider": "2.15.2", "@plane/constants": "workspace:*", "@plane/hooks": "workspace:*", + "@plane/i18n": "workspace:*", "@plane/propel": "workspace:*", "@plane/types": "workspace:*", "@plane/ui": "workspace:*", diff --git a/packages/editor/src/core/components/links/link-edit-view.tsx b/packages/editor/src/core/components/links/link-edit-view.tsx index 3adbefa27cd..195eca5c393 100644 --- a/packages/editor/src/core/components/links/link-edit-view.tsx +++ b/packages/editor/src/core/components/links/link-edit-view.tsx @@ -7,6 +7,7 @@ import type { Node } from "@tiptap/pm/model"; import { Link2Off } from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; +import { useTranslation } from "@plane/i18n"; // components import type { LinkViewProps, LinkViews } from "@/components/links"; // helpers @@ -17,10 +18,9 @@ type InputViewProps = { value: string; placeholder: string; onChange: (value: string) => void; - autoFocus?: boolean; }; -function InputView({ label, value, placeholder, onChange, autoFocus }: InputViewProps) { +function InputView({ label, value, placeholder, onChange }: InputViewProps) { return (
    @@ -30,7 +30,6 @@ function InputView({ label, value, placeholder, onChange, autoFocus }: InputView className="w-[280px] rounded-md border border-strong bg-layer-1 p-2 text-13 text-primary outline-none" value={value} onChange={(e) => onChange(e.target.value)} - autoFocus={autoFocus} />
    ); @@ -43,6 +42,7 @@ type LinkEditViewProps = { export function LinkEditView({ viewProps }: LinkEditViewProps) { const { editor, from, to, url: initialUrl, text: initialText, closeLinkView } = viewProps; + const { t } = useTranslation(); // State const [positionRef] = useState({ from, to }); @@ -139,18 +139,30 @@ export function LinkEditView({ viewProps }: LinkEditViewProps) {
    - - + +
    diff --git a/packages/i18n/src/locales/cs/translations.ts b/packages/i18n/src/locales/cs/translations.ts index d2a818f3b89..1246d0d777f 100644 --- a/packages/i18n/src/locales/cs/translations.ts +++ b/packages/i18n/src/locales/cs/translations.ts @@ -2657,4 +2657,312 @@ export default { close_button: "Zavřít navigační panel", outline_floating_button: "Otevřít osnovu", }, + localized_ui: { + not_found: { + alt: "404 - Stránka nenalezena", + title: "Jejda! Něco se pokazilo.", + description: + "Omlouváme se, stránku, kterou hledáte, nelze najít. Možná byla odstraněna, přejmenována nebo je dočasně nedostupná.", + go_to_home: "Přejít domů", + }, + workspace_views: { + page_title: "{workspaceName} - Všechna zobrazení", + }, + projects_empty_state: { + no_projects_yet: "Zatím žádné projekty", + description: + "Projekty jsou základem práce řízené cíli. Pomáhají spravovat týmy, úkoly a vše potřebné k dokončení práce.", + learn_more: "Další informace o projektech", + start_first_project: "Začít první projekt", + }, + profile_activity: { + page_title: "Profil - Aktivita", + }, + pages: { + not_found_title: "Stránka nenalezena", + not_found_description: "Stránka, ke které se pokoušíte přistoupit, neexistuje nebo k ní nemáte oprávnění.", + view_other_pages: "Zobrazit další stránky", + }, + workspace_access: { + not_found_title: "Pracovní prostor nenalezen", + not_found_description: + "Pro tuto adresu URL nebyl nalezen žádný pracovní prostor. Možná neexistuje nebo k němu nemáte oprávnění.", + visit_profile: "Navštívit profil", + not_authorized_title: "Bez oprávnění!", + not_authorized_description: + "Nejste členem tohoto pracovního prostoru. Požádejte správce pracovního prostoru o pozvánku nebo zkontrolujte čekající pozvánky.", + check_pending_invites: "Zkontrolovat čekající pozvánky", + }, + editor: { + url: "URL", + enter_or_paste_url: "Zadejte nebo vložte adresu URL", + text: "Text", + enter_text_to_display: "Zadejte text, který chcete zobrazit", + remove_link: "Odebrat odkaz", + edit_link: "Upravit odkaz", + color: "Barva", + text_colors: "Barvy textu", + background_colors: "Barvy pozadí", + link: "Odkaz", + enter_or_paste_link: "Zadejte nebo vložte odkaz", + please_enter_valid_url: "Zadejte prosím platné URL", + delete: "Vymazat", + duplicate: "Duplikát", + multiple: "Více", + loading: "Načítání", + no_results: "Žádné výsledky", + copy_code: "Kopírovat kód", + add_an_image: "Přidejte obrázek", + error_loading_image: "Chyba při načítání obrázku", + uploading: "Nahrávání", + drop_image_here: "Přetáhněte obrázek sem", + retry_duplication: "Opakovat duplikaci", + retry: "Zkuste to znovu", + no_emojis_found: "Nebyly nalezeny žádné emotikony", + fullscreen_image_viewer: "Prohlížeč obrázků na celou obrazovku", + close_image_viewer: "Zavřete prohlížeč obrázků", + zoom_out: "Oddálit", + zoom_in: "Přiblížit", + download_image: "Stáhnout obrázek", + open_image_in_new_tab: "Otevřít obrázek na nové kartě", + view_in_full_screen: "Zobrazit přes celou obrazovku", + view_image_in_full_screen: "Zobrazit obrázek na celé obrazovce", + align: "Zarovnat", + download: "Stáhnout", + clear_contents: "Přehledný obsah", + insert_above: "Vložte výše", + insert_below: "Vložte níže", + insert_left: "Vložte vlevo", + insert_right: "Vložte vpravo", + header_row: "Řádek záhlaví", + header_column: "Sloupec záhlaví", + alignment: { + left: "Vlevo", + center: "Centrum", + right: "Vpravo", + }, + menu_items: { + text: "Text", + h1: "Nadpis 1", + h2: "Nadpis 2", + h3: "Nadpis 3", + h4: "Nadpis 4", + h5: "Nadpis 5", + h6: "Nadpis 6", + "bulleted-list": "Seznam s odrážkami", + "numbered-list": "Číslovaný seznam", + "to-do-list": "Seznam úkolů", + quote: "Citovat", + code: "Kód", + table: "Tabulka", + image: "Obrázek", + divider: "Oddělovač", + link: "Odkaz", + bold: "Tučné", + italic: "kurzíva", + underline: "Podtržení", + strikethrough: "Přeškrtnutí", + "text-color": "Barva textu", + "background-color": "Barva pozadí", + "text-align": "Zarovnání textu", + }, + }, + workspace_invitation: { + invitation_not_found: "Pozvánka nenalezena", + invited_to_workspace: "Byli jste pozváni do {workspaceName}", + description: + "Váš pracovní prostor je místo, kde budete vytvářet projekty, spolupracovat na svých pracovních položkách a organizovat různé toky práce ve svém účtu Plane.", + accept: "Přijmout", + ignore: "Ignorovat", + already_member: "Již jste členem {workspaceName}", + continue_to_home: "Pokračujte domů", + inactive_title: "Tento odkaz na pozvánku již není aktivní.", + empty_project_link: "Nebo začněte z prázdného projektu", + sign_in_to_continue: "Chcete-li pokračovat, přihlaste se", + star_on_github: "Sledujte nás na GitHub", + join_community: "Připojte se k naší komunitě aktivních tvůrců", + }, + space_auth: { + email: "E-mail", + email_invalid: "E-mail je neplatný", + clear_email: "Vymazat e-mail", + password: "Heslo", + set_password: "Nastavte heslo", + enter_password: "Zadejte heslo", + confirm_password: "Potvrďte heslo", + passwords_dont_match: "Hesla se neshodují", + continue: "Pokračovat", + go_to_workspace: "Přejděte do pracovního prostoru", + sign_in_with_unique_code: "Přihlaste se pomocí jedinečného kódu", + create_account: "Vytvořit účet", + unique_code: "Unikátní kód", + paste_code_sent: "Vložte kód zaslaný na váš e-mail", + resend_in: "Znovu odeslat v {seconds}s", + requesting_new_code: "Požadavek na nový kód", + resend: "Odeslat znovu", + sending_code: "Odesílání kódu", + }, + onboarding: { + create_profile_title: "Vytvořte si svůj profil.", + create_profile_description: "Takto se objevíte v Plane.", + change_image: "Změnit obrázek", + upload_image: "Nahrajte obrázek", + name: "Jméno", + name_required: "Jméno je povinné", + name_within_50: "Název musí mít maximálně 50 znaků.", + enter_full_name: "Zadejte své celé jméno", + set_password: "Nastavte heslo", + optional: "Volitelný", + passwords_do_not_match: "Hesla se neshodují", + passwords_match: "Hesla se shodují", + continue: "Pokračovat", + invite_team_title: "Pozvěte své spoluhráče", + invite_team_description: "Práce v Plane probíhá nejlépe s vaším týmem. Pozvěte je, aby využili potenciál Plane.", + invalid_email: "To nevypadá jako e-mailová adresa.", + success: "Úspěch!", + invitations_sent: "Pozvánky byly úspěšně odeslány.", + error: "Chyba!", + add_another: "Přidejte další", + do_later: "Udělám to později", + join_invites_title: "Připojte se k pozvánkám nebo vytvořte pracovní prostor", + unified_description: "Veškerá vaše práce – jednotná.", + create_new_workspace: "Vytvořte nový pracovní prostor", + no_invitations_found: "Nebyly nalezeny žádné pozvánky", + you_are_invited: "Jste zváni!", + accept_invites: "Přijměte pozvání ke spolupráci se svým týmem.", + continue_to_workspace: "Pokračujte do pracovního prostoru", + or: "nebo", + create_own_workspace: "Vytvořte si vlastní pracovní prostor", + workspace_creation_disabled: + "Zdá se, že nemáte žádné pozvánky do pracovního prostoru a váš správce instance omezil vytváření nových pracovních prostorů. Požádejte vlastníka nebo správce pracovního prostoru, aby vás nejprve pozval do pracovního prostoru a vraťte se na tuto obrazovku a připojte se.", + create_workspace_title: "Vytvořte si svůj pracovní prostor", + enter_workspace_name: "Zadejte název pracovního prostoru", + join_existing_workspace: "Připojte se k existujícímu pracovnímu prostoru", + profile_setup_completed: "Nastavení profilu dokončeno.", + profile_setup_failed: "Nastavení profilu se nezdařilo.", + usecase_title: "Jak plánujete používat Plane?", + usecase_description: "Vyberte jednu nebo více možností, abychom mohli přizpůsobit váš zážitek.", + select_one_or_more: "Vyberte jednu nebo více", + select_at_least_one: "Vyberte alespoň jednu možnost.", + skip: "Přeskočit", + }, + inbox: { + duplicate_issues_found: "Nalezeno {count} duplicitních pracovních položek", + description_versions: { + intake_form_user: "Uživatel sběrného formuláře", + }, + errors: { + asset_upload_failed: "Nahrání podkladu se nezdařilo. Zkuste to znovu později.", + asset_duplication_failed: "Duplikace aktiv se nezdařila. Zkuste to znovu později.", + permission_denied: "Povolení odepřeno", + mark_duplicate_permission: "Pouze správci projektu mohou označit pracovní položku jako duplicitní", + mark_duplicate_permission_plural: "Pouze správci projektu mohou označit pracovní položky jako duplicitní", + }, + filters: { + created_date: "Datum vytvoření", + updated_date: "Aktualizováno datum", + last_updated_date: "Datum poslední aktualizace", + status: "Stav", + work_item_status: "Stav pracovní položky", + view_all: "Zobrazit vše", + view_less: "Zobrazit méně", + date_options: { + today: "Dnes", + yesterday: "Včera", + last_7_days: "Posledních 7 dní", + last_30_days: "Posledních 30 dní", + }, + date_operators: { + after: "Po", + before: "Před", + }, + }, + navigation: { + previous_work_item: "Předchozí pracovní položka", + next_work_item: "Další pracovní položka", + }, + properties: { + duplicate_of: "Duplikát", + }, + select_duplicate: { + select_work_item: "Vyberte pracovní položku", + }, + sidebar: { + label_count: "{count} štítky", + }, + toasts: { + editor_processing: "Editor stále zpracovává změny. Před pokračováním prosím počkejte.", + create_success: "Pracovní položka byla úspěšně vytvořena.", + delete_failed: "Smazání pracovní položky se nezdařilo", + update_failed: "Aktualizace pracovní položky se nezdařila", + }, + }, + space_public: { + error_title: "Jejda! Tohle nevypadá dobře.", + error_description_prefix: + "Plane spadl. Nemějte obavy, naši inženýři už byli upozorněni. Pokud máte další podrobnosti, napište na", + error_description_middle: "nebo na našem", + forum: "Fórum", + refresh: "Obnovit", + not_found_title: "Tohle nefungovalo", + not_found_hint: "Zkontrolujte URL v adresním řádku prohlížeče a zkuste to znovu.", + user_already_logged_in: "Uživatel je již přihlášen", + logged_in_title: "Skvělé! Ještě jeden krok.", + logged_in_hint: + "Zadejte do adresního řádku prohlížeče veřejně sdílenou URL nebo odkaz na zobrazení či stránku, kterou chcete otevřít.", + by_creating_account: "Vytvořením účtu", + by_signing_in: "Přihlášením", + you_agree_to_our: "souhlasíte s našimi", + terms_of_service: "Podmínkami služby", + and: "a", + privacy_policy: "Zásadami ochrany osobních údajů", + sign_up: "Zaregistrovat se", + oauth_with_provider: "{action} přes {provider}", + auth: { + sign_in_header: "Přihlaste se, abyste mohli hlasovat nebo komentovat", + sign_in_subheader: "Pomozte posunout funkce, které chcete mít vytvořené.", + sign_up_header: "Zobrazujte, komentujte a dělejte víc", + sign_up_subheader: + "Zaregistrujte se nebo přihlaste, abyste mohli pracovat s pracovními položkami a stránkami Plane.", + }, + peek: { + side: "Boční náhled", + modal: "Modální okno", + full_screen: "Celá obrazovka", + }, + bot_name: "Bot {name}", + commented_time: "komentováno {time}", + and_more: "a dalších {count}", + no_upvotes_yet: "Zatím žádné hlasy pro", + no_downvotes_yet: "Zatím žádné hlasy proti", + view_less: "Zobrazit méně", + view_all: "Zobrazit vše", + no_matches_found: "Nebyly nalezeny žádné shody", + no_date: "Bez data", + no_cycle: "Bez cyklu", + no_modules: "Bez modulů", + modules_count: "{count} modulů", + no_assignees: "Bez přiřazených osob", + labels_count: "{count} štítků", + page_not_found_alt: "Stránka nenalezena", + something_went_wrong: "Jejda! Něco se pokazilo.", + page_not_found_description: "Stránka, kterou hledáte, neexistuje nebo byla přesunuta.", + instance_failure_image_alt: "Nelze načíst podrobnosti instance", + instance_failure_title: "Nelze načíst podrobnosti instance.", + instance_failure_description: "Podrobnosti vaší instance se nepodařilo načíst.", + instance_failure_hint: "Zkontrolujte připojení a zkuste to znovu.", + retry: "Zkusit znovu", + powered_by: "Používá", + sign_in_to_add_comment: "Přihlaste se a přidejte komentář", + sign_in: "Přihlásit se", + link_copied: "Odkaz zkopírován!", + work_item_link_copied: "Odkaz na pracovní položku byl zkopírován do schránky.", + comment_post_error: "Komentář se nepodařilo odeslat. Zkuste to prosím znovu.", + add_comment: "Přidat komentář", + public_board_not_found: "Veřejná nástěnka neexistuje. Zkontrolujte URL.", + no_work_items_found: "Nebyly nalezeny žádné pracovní položky", + no_labels: "Žádné štítky", + user: "Uživatel", + }, + }, } as const; diff --git a/packages/i18n/src/locales/de/translations.ts b/packages/i18n/src/locales/de/translations.ts index db4925f1f92..539b8348489 100644 --- a/packages/i18n/src/locales/de/translations.ts +++ b/packages/i18n/src/locales/de/translations.ts @@ -2687,4 +2687,315 @@ export default { close_button: "Navigationsbereich schließen", outline_floating_button: "Gliederung öffnen", }, + localized_ui: { + not_found: { + alt: "404 - Seite nicht gefunden", + title: "Hoppla! Etwas ist schiefgelaufen.", + description: + "Die gesuchte Seite wurde nicht gefunden. Sie wurde möglicherweise entfernt, umbenannt oder ist vorübergehend nicht verfügbar.", + go_to_home: "Zur Startseite", + }, + workspace_views: { + page_title: "{workspaceName} - Alle Ansichten", + }, + projects_empty_state: { + no_projects_yet: "Noch keine Projekte", + description: + "Projekte bilden die Grundlage für zielorientierte Arbeit. Mit ihnen verwalten Sie Teams, Aufgaben und alles, was Sie zur Erledigung der Arbeit benötigen.", + learn_more: "Mehr über Projekte erfahren", + start_first_project: "Erstes Projekt starten", + }, + profile_activity: { + page_title: "Profil - Aktivität", + }, + pages: { + not_found_title: "Seite nicht gefunden", + not_found_description: + "Die Seite, auf die Sie zugreifen möchten, existiert nicht oder Sie haben keine Berechtigung, sie anzusehen.", + view_other_pages: "Andere Seiten anzeigen", + }, + workspace_access: { + not_found_title: "Arbeitsbereich nicht gefunden", + not_found_description: + "Für diese URL wurde kein Arbeitsbereich gefunden. Er existiert möglicherweise nicht oder Sie haben keine Berechtigung, ihn anzusehen.", + visit_profile: "Profil öffnen", + not_authorized_title: "Nicht autorisiert!", + not_authorized_description: + "Sie sind kein Mitglied dieses Arbeitsbereichs. Wenden Sie sich an den Administrator des Arbeitsbereichs, um eine Einladung zu erhalten, oder prüfen Sie Ihre ausstehenden Einladungen.", + check_pending_invites: "Ausstehende Einladungen prüfen", + }, + editor: { + url: "URL", + enter_or_paste_url: "Geben Sie die URL ein oder fügen Sie sie ein", + text: "Text", + enter_text_to_display: "Geben Sie den anzuzeigenden Text ein", + remove_link: "Link entfernen", + edit_link: "Link bearbeiten", + color: "Farbe", + text_colors: "Textfarben", + background_colors: "Hintergrundfarben", + link: "Link", + enter_or_paste_link: "Link eingeben oder einfügen", + please_enter_valid_url: "Bitte geben Sie eine gültige URL ein", + delete: "Löschen", + duplicate: "Duplikat", + multiple: "Mehrere", + loading: "Laden", + no_results: "Keine Ergebnisse", + copy_code: "Code kopieren", + add_an_image: "Fügen Sie ein Bild hinzu", + error_loading_image: "Fehler beim Laden des Bildes", + uploading: "Hochladen", + drop_image_here: "Bild hier einfügen", + retry_duplication: "Versuchen Sie es erneut", + retry: "Wiederholen", + no_emojis_found: "Keine Emojis gefunden", + fullscreen_image_viewer: "Vollbild-Bildbetrachter", + close_image_viewer: "Bildbetrachter schließen", + zoom_out: "Herauszoomen", + zoom_in: "Vergrößern", + download_image: "Bild herunterladen", + open_image_in_new_tab: "Bild in neuem Tab öffnen", + view_in_full_screen: "Im Vollbildmodus ansehen", + view_image_in_full_screen: "Bild im Vollbildmodus anzeigen", + align: "Ausrichten", + download: "Herunterladen", + clear_contents: "Klare Inhalte", + insert_above: "Oben einfügen", + insert_below: "Unten einfügen", + insert_left: "Links einfügen", + insert_right: "Rechts einfügen", + header_row: "Kopfzeile", + header_column: "Kopfspalte", + alignment: { + left: "Links", + center: "Zentriert", + right: "Rechts", + }, + menu_items: { + text: "Text", + h1: "Überschrift 1", + h2: "Überschrift 2", + h3: "Überschrift 3", + h4: "Überschrift 4", + h5: "Überschrift 5", + h6: "Überschrift 6", + "bulleted-list": "Liste mit Aufzählungszeichen", + "numbered-list": "Nummerierte Liste", + "to-do-list": "To-Do-Liste", + quote: "Zitat", + code: "Code", + table: "Tabelle", + image: "Bild", + divider: "Teiler", + link: "Link", + bold: "Fett", + italic: "Kursiv", + underline: "Unterstreichen", + strikethrough: "Durchgestrichen", + "text-color": "Textfarbe", + "background-color": "Hintergrundfarbe", + "text-align": "Text ausrichten", + }, + }, + workspace_invitation: { + invitation_not_found: "Einladung nicht gefunden", + invited_to_workspace: "Sie wurden zu {workspaceName} eingeladen", + description: + "In Ihrem Arbeitsbereich erstellen Sie Projekte, arbeiten gemeinsam an Ihren Arbeitselementen und organisieren verschiedene Arbeitsströme in Ihrem Plane-Konto.", + accept: "Akzeptieren", + ignore: "Ignorieren", + already_member: "Sie sind bereits Mitglied von {workspaceName}", + continue_to_home: "Weiter nach Hause", + inactive_title: "Dieser Einladungslink ist nicht mehr aktiv.", + empty_project_link: "Oder beginnen Sie mit einem leeren Projekt", + sign_in_to_continue: "Melden Sie sich an, um fortzufahren", + star_on_github: "Star uns auf GitHub", + join_community: "Treten Sie unserer Community aktiver YouTuber bei", + }, + space_auth: { + email: "E-Mail", + email_invalid: "E-Mail ist ungültig", + clear_email: "Klare E-Mail", + password: "Passwort", + set_password: "Legen Sie ein Passwort fest", + enter_password: "Passwort eingeben", + confirm_password: "Passwort bestätigen", + passwords_dont_match: "Passwörter stimmen nicht überein", + continue: "Weitermachen", + go_to_workspace: "Gehen Sie zum Arbeitsbereich", + sign_in_with_unique_code: "Melden Sie sich mit einem eindeutigen Code an", + create_account: "Benutzerkonto erstellen", + unique_code: "Eindeutiger Code", + paste_code_sent: "Fügen Sie den an Ihre E-Mail gesendeten Code ein", + resend_in: "In {seconds}s erneut senden", + requesting_new_code: "Fordern Sie neuen Code an", + resend: "Erneut senden", + sending_code: "Code senden", + }, + onboarding: { + create_profile_title: "Erstellen Sie Ihr Profil.", + create_profile_description: "So werden Sie in Plane angezeigt.", + change_image: "Bild ändern", + upload_image: "Bild hochladen", + name: "Name", + name_required: "Name ist erforderlich", + name_within_50: "Der Name muss maximal 50 Zeichen lang sein.", + enter_full_name: "Geben Sie Ihren vollständigen Namen ein", + set_password: "Legen Sie ein Passwort fest", + optional: "Optional", + passwords_do_not_match: "Passwörter stimmen nicht überein", + passwords_match: "Passwörter stimmen überein", + continue: "Weitermachen", + invite_team_title: "Laden Sie Ihre Teamkollegen ein", + invite_team_description: + "Die Arbeit in Plane gelingt am besten mit Ihrem Team. Laden Sie sie jetzt ein, Plane voll auszuschöpfen.", + invalid_email: "Das sieht nicht nach einer E-Mail-Adresse aus.", + success: "Erfolg!", + invitations_sent: "Einladungen erfolgreich versendet.", + error: "Fehler!", + add_another: "Fügen Sie einen weiteren hinzu", + do_later: "Ich werde es später tun", + join_invites_title: "Nehmen Sie an Einladungen teil oder erstellen Sie einen Arbeitsbereich", + unified_description: "Ihre gesamte Arbeit – einheitlich.", + create_new_workspace: "Neuen Arbeitsbereich erstellen", + no_invitations_found: "Keine Einladungen gefunden", + you_are_invited: "Sie sind eingeladen!", + accept_invites: "Nehmen Sie die Einladungen zur Zusammenarbeit mit Ihrem Team an.", + continue_to_workspace: "Weiter zum Arbeitsbereich", + or: "oder", + create_own_workspace: "Erstellen Sie Ihren eigenen Arbeitsbereich", + workspace_creation_disabled: + "Sie haben offenbar keine Einladungen zu einem Arbeitsbereich und Ihr Instanzadministrator hat die Erstellung neuer Arbeitsbereiche eingeschränkt. Bitten Sie einen Workspace-Inhaber oder Administrator, Sie zunächst zu einem Workspace einzuladen und zu diesem Bildschirm zurückzukehren, um beizutreten.", + create_workspace_title: "Erstellen Sie Ihren Arbeitsbereich", + enter_workspace_name: "Geben Sie den Namen des Arbeitsbereichs ein", + join_existing_workspace: "Treten Sie einem vorhandenen Arbeitsbereich bei", + profile_setup_completed: "Profileinrichtung abgeschlossen.", + profile_setup_failed: "Die Profileinrichtung ist fehlgeschlagen.", + usecase_title: "Wie planen Sie den Einsatz von Plane?", + usecase_description: "Wählen Sie eine oder mehrere Optionen aus, damit wir Ihr Erlebnis personalisieren können.", + select_one_or_more: "Wählen Sie eine oder mehrere aus", + select_at_least_one: "Wählen Sie mindestens eine Option aus.", + skip: "Überspringen", + }, + inbox: { + duplicate_issues_found: "{count} doppelte Arbeitselemente gefunden", + description_versions: { + intake_form_user: "Benutzer des Intake-Formulars", + }, + errors: { + asset_upload_failed: "Das Hochladen des Assets ist fehlgeschlagen. Bitte versuchen Sie es später noch einmal.", + asset_duplication_failed: + "Die Duplizierung von Assets ist fehlgeschlagen. Bitte versuchen Sie es später noch einmal.", + permission_denied: "Zugriff verweigert", + mark_duplicate_permission: "Nur Projektadministratoren können Arbeitselemente als Duplikat markieren", + mark_duplicate_permission_plural: "Nur Projektadministratoren können Arbeitselemente als Duplikat markieren", + }, + filters: { + created_date: "Erstellungsdatum", + updated_date: "Aktualisiertes Datum", + last_updated_date: "Datum der letzten Aktualisierung", + status: "Status", + work_item_status: "Arbeitselementstatus", + view_all: "Alle anzeigen", + view_less: "Weniger anzeigen", + date_options: { + today: "Heute", + yesterday: "Gestern", + last_7_days: "Letzte 7 Tage", + last_30_days: "Letzte 30 Tage", + }, + date_operators: { + after: "Nach", + before: "Vor", + }, + }, + navigation: { + previous_work_item: "Vorheriges Arbeitselement", + next_work_item: "Nächstes Arbeitselement", + }, + properties: { + duplicate_of: "Duplikat von", + }, + select_duplicate: { + select_work_item: "Arbeitselement auswählen", + }, + sidebar: { + label_count: "{count}-Etiketten", + }, + toasts: { + editor_processing: "Der Editor verarbeitet noch Änderungen. Bitte warten Sie, bevor Sie fortfahren.", + create_success: "Arbeitselement erfolgreich erstellt.", + delete_failed: "Das Löschen des Arbeitselements ist fehlgeschlagen", + update_failed: "Die Aktualisierung des Arbeitselements ist fehlgeschlagen", + }, + }, + space_public: { + error_title: "Hoppla! Das sieht nicht gut aus.", + error_description_prefix: + "Plane ist abgestürzt. Keine Sorge, unsere Entwickler wurden benachrichtigt. Wenn Sie weitere Details haben, schreiben Sie bitte an", + error_description_middle: "oder in unserem", + forum: "Forum", + refresh: "Aktualisieren", + not_found_title: "Das hat nicht funktioniert", + not_found_hint: "Prüfen Sie die URL in der Adressleiste des Browsers und versuchen Sie es erneut.", + user_already_logged_in: "Benutzer ist bereits angemeldet", + logged_in_title: "Gut! Nur noch ein Schritt.", + logged_in_hint: + "Geben Sie die öffentliche Freigabe-URL oder den Link der Ansicht oder Seite, die Sie öffnen möchten, in die Adressleiste des Browsers ein.", + by_creating_account: "Mit dem Erstellen eines Kontos", + by_signing_in: "Mit der Anmeldung", + you_agree_to_our: "stimmen Sie unseren", + terms_of_service: "Nutzungsbedingungen", + and: "und", + privacy_policy: "Datenschutzrichtlinie", + sign_up: "Registrieren", + oauth_with_provider: "{action} mit {provider}", + auth: { + sign_in_header: "Melden Sie sich an, um abzustimmen oder zu kommentieren", + sign_in_subheader: "Helfen Sie dabei, die Funktionen voranzubringen, die Sie umgesetzt sehen möchten.", + sign_up_header: "Ansehen, kommentieren und mehr tun", + sign_up_subheader: + "Registrieren Sie sich oder melden Sie sich an, um mit Plane-Arbeitselementen und Seiten zu arbeiten.", + }, + peek: { + side: "Seitenansicht", + modal: "Modal", + full_screen: "Vollbild", + }, + bot_name: "{name}-Bot", + commented_time: "kommentierte {time}", + and_more: "und {count} weitere", + no_upvotes_yet: "Noch keine Upvotes", + no_downvotes_yet: "Noch keine Downvotes", + view_less: "Weniger anzeigen", + view_all: "Alle anzeigen", + no_matches_found: "Keine Treffer gefunden", + no_date: "Kein Datum", + no_cycle: "Kein Zyklus", + no_modules: "Keine Module", + modules_count: "{count} Module", + no_assignees: "Keine Zuständigen", + labels_count: "{count} Labels", + page_not_found_alt: "Seite nicht gefunden", + something_went_wrong: "Hoppla! Etwas ist schiefgelaufen.", + page_not_found_description: "Die gesuchte Seite existiert nicht oder wurde verschoben.", + instance_failure_image_alt: "Instanzdetails konnten nicht abgerufen werden", + instance_failure_title: "Instanzdetails konnten nicht abgerufen werden.", + instance_failure_description: "Ihre Instanzdetails konnten nicht geladen werden.", + instance_failure_hint: "Prüfen Sie Ihre Verbindung und versuchen Sie es erneut.", + retry: "Erneut versuchen", + powered_by: "Bereitgestellt von", + sign_in_to_add_comment: "Melden Sie sich an, um einen Kommentar hinzuzufügen", + sign_in: "Anmelden", + link_copied: "Link kopiert!", + work_item_link_copied: "Link zum Arbeitselement in die Zwischenablage kopiert.", + comment_post_error: "Kommentar konnte nicht veröffentlicht werden. Bitte versuchen Sie es erneut.", + add_comment: "Kommentar hinzufügen", + public_board_not_found: "Das öffentliche Board existiert nicht. Bitte prüfen Sie die URL.", + no_work_items_found: "Keine Arbeitselemente gefunden", + no_labels: "Keine Labels", + user: "Benutzer", + }, + }, } as const; diff --git a/packages/i18n/src/locales/en/translations.ts b/packages/i18n/src/locales/en/translations.ts index 2885fd3f0a1..53abe2d826f 100644 --- a/packages/i18n/src/locales/en/translations.ts +++ b/packages/i18n/src/locales/en/translations.ts @@ -2748,4 +2748,313 @@ export default { enter_number_of_projects: "Enter number of projects", pin: "Pin", unpin: "Unpin", + localized_ui: { + not_found: { + alt: "404 - Page not found", + title: "Oops! Something went wrong.", + description: + "Sorry, the page you are looking for cannot be found. It may have been removed, renamed, or is temporarily unavailable.", + go_to_home: "Go to Home", + }, + workspace_views: { + page_title: "{workspaceName} - All Views", + }, + projects_empty_state: { + no_projects_yet: "No projects yet", + description: + "Projects act as the foundation for goal-driven work. They let you manage your teams, tasks, and everything you need to get things done.", + learn_more: "Learn more about projects", + start_first_project: "Start your first project", + }, + profile_activity: { + page_title: "Profile - Activity", + }, + pages: { + not_found_title: "Page not found", + not_found_description: + "The page you are trying to access does not exist or you do not have permission to view it.", + view_other_pages: "View other Pages", + }, + workspace_access: { + not_found_title: "Workspace not found", + not_found_description: + "No workspace was found for this URL. It may not exist or you may not have permission to view it.", + visit_profile: "Visit Profile", + not_authorized_title: "Not Authorized!", + not_authorized_description: + "You are not a member of this workspace. Please contact the workspace admin to get an invitation or check your pending invitations.", + check_pending_invites: "Check pending invites", + }, + editor: { + url: "URL", + enter_or_paste_url: "Enter or paste URL", + text: "Text", + enter_text_to_display: "Enter text to display", + remove_link: "Remove link", + edit_link: "Edit link", + color: "Color", + text_colors: "Text colors", + background_colors: "Background colors", + link: "Link", + enter_or_paste_link: "Enter or paste link", + please_enter_valid_url: "Please enter a valid URL", + delete: "Delete", + duplicate: "Duplicate", + multiple: "Multiple", + loading: "Loading", + no_results: "No results", + copy_code: "Copy code", + add_an_image: "Add an image", + error_loading_image: "Error loading image", + uploading: "Uploading", + drop_image_here: "Drop image here", + retry_duplication: "Retry duplication", + retry: "Retry", + no_emojis_found: "No emojis found", + fullscreen_image_viewer: "Fullscreen image viewer", + close_image_viewer: "Close image viewer", + zoom_out: "Zoom out", + zoom_in: "Zoom in", + download_image: "Download image", + open_image_in_new_tab: "Open image in new tab", + view_in_full_screen: "View in full screen", + view_image_in_full_screen: "View image in full screen", + align: "Align", + download: "Download", + clear_contents: "Clear contents", + insert_above: "Insert above", + insert_below: "Insert below", + insert_left: "Insert left", + insert_right: "Insert right", + header_row: "Header row", + header_column: "Header column", + alignment: { + left: "Left", + center: "Center", + right: "Right", + }, + menu_items: { + text: "Text", + h1: "Heading 1", + h2: "Heading 2", + h3: "Heading 3", + h4: "Heading 4", + h5: "Heading 5", + h6: "Heading 6", + "bulleted-list": "Bulleted list", + "numbered-list": "Numbered list", + "to-do-list": "To-do list", + quote: "Quote", + code: "Code", + table: "Table", + image: "Image", + divider: "Divider", + link: "Link", + bold: "Bold", + italic: "Italic", + underline: "Underline", + strikethrough: "Strikethrough", + "text-color": "Text color", + "background-color": "Background color", + "text-align": "Text align", + }, + }, + workspace_invitation: { + invitation_not_found: "Invitation not found", + invited_to_workspace: "You have been invited to {workspaceName}", + description: + "Your workspace is where you will create projects, collaborate on your work items, and organize different streams of work in your Plane account.", + accept: "Accept", + ignore: "Ignore", + already_member: "You are already a member of {workspaceName}", + continue_to_home: "Continue to home", + inactive_title: "This invitation link is not active anymore.", + empty_project_link: "Or start from an empty project", + sign_in_to_continue: "Sign in to continue", + star_on_github: "Star us on GitHub", + join_community: "Join our community of active creators", + }, + space_auth: { + email: "Email", + email_invalid: "Email is invalid", + clear_email: "Clear email", + password: "Password", + set_password: "Set a password", + enter_password: "Enter password", + confirm_password: "Confirm password", + passwords_dont_match: "Passwords do not match", + continue: "Continue", + go_to_workspace: "Go to workspace", + sign_in_with_unique_code: "Sign in with unique code", + create_account: "Create account", + unique_code: "Unique code", + paste_code_sent: "Paste the code sent to your email", + resend_in: "Resend in {seconds}s", + requesting_new_code: "Requesting new code", + resend: "Resend", + sending_code: "Sending code", + }, + onboarding: { + create_profile_title: "Create your profile.", + create_profile_description: "This is how you will appear in Plane.", + change_image: "Change image", + upload_image: "Upload image", + name: "Name", + name_required: "Name is required", + name_within_50: "Name must be within 50 characters.", + enter_full_name: "Enter your full name", + set_password: "Set a password", + optional: "Optional", + passwords_do_not_match: "Passwords do not match", + passwords_match: "Passwords match", + continue: "Continue", + invite_team_title: "Invite your teammates", + invite_team_description: + "Work in Plane happens best with your team. Invite them now to use Plane to its potential.", + invalid_email: "That does not look like an email address.", + success: "Success!", + invitations_sent: "Invitations sent successfully.", + error: "Error!", + add_another: "Add another", + do_later: "I will do it later", + join_invites_title: "Join invites or create a workspace", + unified_description: "All your work — unified.", + create_new_workspace: "Create new workspace", + no_invitations_found: "No invitations found", + you_are_invited: "You are invited!", + accept_invites: "Accept the invites to collaborate with your team.", + continue_to_workspace: "Continue to workspace", + or: "or", + create_own_workspace: "Create your own workspace", + workspace_creation_disabled: + "You do not seem to have any invites to a workspace and your instance admin has restricted creation of new workspaces. Please ask a workspace owner or admin to invite you to a workspace first and come back to this screen to join.", + create_workspace_title: "Create your workspace", + enter_workspace_name: "Enter workspace name", + join_existing_workspace: "Join existing workspace", + profile_setup_completed: "Profile setup completed.", + profile_setup_failed: "Profile setup failed.", + usecase_title: "How are you planning to use Plane?", + usecase_description: "Select one or more options so we can personalize your experience.", + select_one_or_more: "Select one or more", + select_at_least_one: "Select at least one option.", + skip: "Skip", + }, + inbox: { + duplicate_issues_found: "{count} duplicate issues found", + description_versions: { + intake_form_user: "Intake Form user", + }, + errors: { + asset_upload_failed: "Asset upload failed. Please try again later.", + asset_duplication_failed: "Asset duplication failed. Please try again later.", + permission_denied: "Permission denied", + mark_duplicate_permission: "Only project admins can mark work item as duplicate", + mark_duplicate_permission_plural: "Only project admins can mark work items as duplicate", + }, + filters: { + created_date: "Created date", + updated_date: "Updated date", + last_updated_date: "Last updated date", + status: "Status", + work_item_status: "Work item status", + view_all: "View all", + view_less: "View less", + date_options: { + today: "Today", + yesterday: "Yesterday", + last_7_days: "Last 7 days", + last_30_days: "Last 30 days", + }, + date_operators: { + after: "After", + before: "Before", + }, + }, + navigation: { + previous_work_item: "Previous work item", + next_work_item: "Next work item", + }, + properties: { + duplicate_of: "Duplicate of", + }, + select_duplicate: { + select_work_item: "Select work item", + }, + sidebar: { + label_count: "{count} labels", + }, + toasts: { + editor_processing: "Editor is still processing changes. Please wait before proceeding.", + create_success: "Work item created successfully.", + delete_failed: "Work item delete failed", + update_failed: "Work item update failed", + }, + }, + space_public: { + error_title: "Yikes! That does not look good.", + error_description_prefix: + "That crashed Plane, pun intended. No worries, though. Our engineers have been notified. If you have more details, please write to", + error_description_middle: "or on our", + forum: "Forum", + refresh: "Refresh", + not_found_title: "That did not work", + not_found_hint: "Check the URL you are entering in the browser address bar and try again.", + user_already_logged_in: "User already logged in", + logged_in_title: "Nice! Just one more step.", + logged_in_hint: + "Enter the public-share URL or link of the view or Page you are trying to see in the browser address bar.", + by_creating_account: "By creating an account", + by_signing_in: "By signing in", + you_agree_to_our: "you agree to our", + terms_of_service: "Terms of Service", + and: "and", + privacy_policy: "Privacy Policy", + sign_up: "Sign up", + oauth_with_provider: "{action} with {provider}", + auth: { + sign_in_header: "Sign in to upvote or comment", + sign_in_subheader: "Contribute in nudging the features you want to get built.", + sign_up_header: "View, comment, and do more", + sign_up_subheader: "Sign up or log in to work with Plane work items and Pages.", + }, + peek: { + side: "Side Peek", + modal: "Modal", + full_screen: "Full Screen", + }, + bot_name: "{name} Bot", + commented_time: "commented {time}", + and_more: "and {count} more", + no_upvotes_yet: "No upvotes yet", + no_downvotes_yet: "No downvotes yet", + view_less: "View less", + view_all: "View all", + no_matches_found: "No matches found", + no_date: "No Date", + no_cycle: "No Cycle", + no_modules: "No Modules", + modules_count: "{count} Modules", + no_assignees: "No Assignees", + labels_count: "{count} Labels", + page_not_found_alt: "Page not found", + something_went_wrong: "Oops! Something went wrong.", + page_not_found_description: "The page you are looking for does not exist or has been moved.", + instance_failure_image_alt: "Unable to fetch instance details", + instance_failure_title: "Unable to fetch instance details.", + instance_failure_description: "We could not load your instance details.", + instance_failure_hint: "Please check your connection and try again.", + retry: "Retry", + powered_by: "Powered by", + sign_in_to_add_comment: "Sign in to add a comment", + sign_in: "Sign in", + link_copied: "Link copied!", + work_item_link_copied: "Work item link copied to clipboard.", + comment_post_error: "Failed to post comment. Please try again.", + add_comment: "Add comment", + public_board_not_found: "The public board does not exist. Please check the URL.", + no_work_items_found: "No work items found", + no_labels: "No labels", + user: "User", + }, + }, } as const; diff --git a/packages/i18n/src/locales/es/translations.ts b/packages/i18n/src/locales/es/translations.ts index 5ed015d06ca..501c43d0d12 100644 --- a/packages/i18n/src/locales/es/translations.ts +++ b/packages/i18n/src/locales/es/translations.ts @@ -2718,4 +2718,314 @@ export default { close_button: "Cerrar panel de navegación", outline_floating_button: "Abrir esquema", }, + localized_ui: { + not_found: { + alt: "404 - Página no encontrada", + title: "¡Ups! Algo salió mal.", + description: + "Lo sentimos, no se pudo encontrar la página que buscas. Puede que se haya eliminado, cambiado de nombre o no esté disponible temporalmente.", + go_to_home: "Ir al inicio", + }, + workspace_views: { + page_title: "{workspaceName} - Todas las vistas", + }, + projects_empty_state: { + no_projects_yet: "Aún no hay proyectos", + description: + "Los proyectos son la base del trabajo orientado a objetivos. Te permiten gestionar equipos, tareas y todo lo necesario para completar el trabajo.", + learn_more: "Más información sobre proyectos", + start_first_project: "Inicia tu primer proyecto", + }, + profile_activity: { + page_title: "Perfil - Actividad", + }, + pages: { + not_found_title: "Página no encontrada", + not_found_description: "La página a la que intentas acceder no existe o no tienes permiso para verla.", + view_other_pages: "Ver otras páginas", + }, + workspace_access: { + not_found_title: "Espacio de trabajo no encontrado", + not_found_description: + "No se encontró ningún espacio de trabajo para esta URL. Puede que no exista o que no tengas permiso para verlo.", + visit_profile: "Visitar perfil", + not_authorized_title: "¡No autorizado!", + not_authorized_description: + "No eres miembro de este espacio de trabajo. Contacta con el administrador para recibir una invitación o revisa tus invitaciones pendientes.", + check_pending_invites: "Revisar invitaciones pendientes", + }, + editor: { + url: "URL", + enter_or_paste_url: "Introduce o pega la URL", + text: "Texto", + enter_text_to_display: "Ingrese el texto para mostrar", + remove_link: "Quitar enlace", + edit_link: "Editar enlace", + color: "Color", + text_colors: "Colores de texto", + background_colors: "Colores de fondo", + link: "Enlace", + enter_or_paste_link: "Ingresar o pegar enlace", + please_enter_valid_url: "Por favor ingresa un URL válido", + delete: "Borrar", + duplicate: "Duplicado", + multiple: "Múltiple", + loading: "Cargando", + no_results: "Sin resultados", + copy_code: "Copiar código", + add_an_image: "Añadir una imagen", + error_loading_image: "Error al cargar la imagen", + uploading: "Subiendo", + drop_image_here: "Suelta imagen aquí", + retry_duplication: "Reintentar la duplicación", + retry: "Reintentar", + no_emojis_found: "No se encontraron emojis", + fullscreen_image_viewer: "Visor de imágenes en pantalla completa", + close_image_viewer: "Cerrar visor de imágenes", + zoom_out: "Alejar", + zoom_in: "Acercar", + download_image: "Descargar imagen", + open_image_in_new_tab: "Abrir imagen en nueva pestaña", + view_in_full_screen: "Ver en pantalla completa", + view_image_in_full_screen: "Ver imagen en pantalla completa", + align: "Alinear", + download: "Descargar", + clear_contents: "Borrar contenidos", + insert_above: "Insertar arriba", + insert_below: "Insertar abajo", + insert_left: "Insertar a la izquierda", + insert_right: "Insertar a la derecha", + header_row: "fila de encabezado", + header_column: "Columna de encabezado", + alignment: { + left: "Izquierda", + center: "Centro", + right: "Derecha", + }, + menu_items: { + text: "Texto", + h1: "Título 1", + h2: "Título 2", + h3: "Título 3", + h4: "Título 4", + h5: "Título 5", + h6: "Título 6", + "bulleted-list": "Lista con viñetas", + "numbered-list": "lista numerada", + "to-do-list": "Lista de tareas pendientes", + quote: "Cita", + code: "Código", + table: "Tabla", + image: "Imagen", + divider: "Divisor", + link: "Enlace", + bold: "Negrita", + italic: "Itálico", + underline: "Subrayar", + strikethrough: "Tachado", + "text-color": "Color del texto", + "background-color": "Color de fondo", + "text-align": "Alinear texto", + }, + }, + workspace_invitation: { + invitation_not_found: "Invitación no encontrada", + invited_to_workspace: "Has sido invitado a {workspaceName}", + description: + "Su espacio de trabajo es donde creará proyectos, colaborará en sus elementos de trabajo y organizará diferentes flujos de trabajo en su cuenta Plane.", + accept: "Aceptar", + ignore: "Ignorar", + already_member: "Ya eres miembro de {workspaceName}", + continue_to_home: "Continuar a casa", + inactive_title: "Este enlace de invitación ya no está activo.", + empty_project_link: "O empezar desde un proyecto vacío", + sign_in_to_continue: "Inicia sesión para continuar", + star_on_github: "Destacanos en GitHub", + join_community: "Únete a nuestra comunidad de creadores activos", + }, + space_auth: { + email: "Correo electrónico", + email_invalid: "El correo electrónico no es válido", + clear_email: "Borrar correo electrónico", + password: "Contraseña", + set_password: "Establecer una contraseña", + enter_password: "Introduce la contraseña", + confirm_password: "Confirmar Contraseña", + passwords_dont_match: "Las contraseñas no coinciden", + continue: "Continuar", + go_to_workspace: "Ir al espacio de trabajo", + sign_in_with_unique_code: "Inicia sesión con código único", + create_account: "Crear una cuenta", + unique_code: "código único", + paste_code_sent: "Pega el código enviado a tu correo electrónico", + resend_in: "Reenviar en {seconds}s", + requesting_new_code: "Solicitando nuevo código", + resend: "Reenviar", + sending_code: "Enviando código", + }, + onboarding: { + create_profile_title: "Crea tu perfil.", + create_profile_description: "Así aparecerás en Plane.", + change_image: "Cambiar imagen", + upload_image: "Subir imagen", + name: "Nombre", + name_required: "El nombre es obligatorio", + name_within_50: "El nombre debe tener 50 caracteres como máximo.", + enter_full_name: "Introduce tu nombre completo", + set_password: "Establecer una contraseña", + optional: "Opcional", + passwords_do_not_match: "Las contraseñas no coinciden", + passwords_match: "Las contraseñas coinciden", + continue: "Continuar", + invite_team_title: "Invita a tus compañeros de equipo", + invite_team_description: + "El trabajo en Plane se desarrolla mejor con tu equipo. Invítalos ahora a utilizar Plane en todo su potencial.", + invalid_email: "Eso no parece una dirección de correo electrónico.", + success: "¡Éxito!", + invitations_sent: "Invitaciones enviadas exitosamente.", + error: "¡Error!", + add_another: "agregar otro", + do_later: "lo haré más tarde", + join_invites_title: "Únase a invitaciones o cree un espacio de trabajo", + unified_description: "Todo tu trabajo, unificado.", + create_new_workspace: "Crear nuevo espacio de trabajo", + no_invitations_found: "No se encontraron invitaciones", + you_are_invited: "¡Estás invitado!", + accept_invites: "Acepta las invitaciones para colaborar con tu equipo.", + continue_to_workspace: "Continuar al espacio de trabajo", + or: "o", + create_own_workspace: "Crea tu propio espacio de trabajo", + workspace_creation_disabled: + "Parece que no tiene ninguna invitación a un espacio de trabajo y el administrador de su instancia ha restringido la creación de nuevos espacios de trabajo. Pídale al propietario o administrador del espacio de trabajo que lo invite primero a un espacio de trabajo y regrese a esta pantalla para unirse.", + create_workspace_title: "Crea tu espacio de trabajo", + enter_workspace_name: "Introduzca el nombre del espacio de trabajo", + join_existing_workspace: "Unirse al espacio de trabajo existente", + profile_setup_completed: "Configuración del perfil completada.", + profile_setup_failed: "Error en la configuración del perfil.", + usecase_title: "¿Cómo planeas utilizar Plane?", + usecase_description: "Seleccione una o más opciones para que podamos personalizar su experiencia.", + select_one_or_more: "Seleccione uno o más", + select_at_least_one: "Seleccione al menos una opción.", + skip: "Saltar", + }, + inbox: { + duplicate_issues_found: "Se encontraron {count} elementos de trabajo duplicados", + description_versions: { + intake_form_user: "Usuario del formulario de recepción", + }, + errors: { + asset_upload_failed: "Error al cargar el recurso. Inténtelo de nuevo más tarde.", + asset_duplication_failed: "Falló la duplicación de activos. Inténtelo de nuevo más tarde.", + permission_denied: "Permiso denegado", + mark_duplicate_permission: + "Solo los administradores del proyecto pueden marcar un elemento de trabajo como duplicado", + mark_duplicate_permission_plural: + "Solo los administradores del proyecto pueden marcar elementos de trabajo como duplicados", + }, + filters: { + created_date: "Fecha de creación", + updated_date: "Fecha actualizada", + last_updated_date: "Fecha de última actualización", + status: "Estado", + work_item_status: "Estado del elemento de trabajo", + view_all: "Ver todo", + view_less: "Ver menos", + date_options: { + today: "Hoy", + yesterday: "Ayer", + last_7_days: "últimos 7 días", + last_30_days: "últimos 30 días", + }, + date_operators: { + after: "Después", + before: "Antes", + }, + }, + navigation: { + previous_work_item: "Elemento de trabajo anterior", + next_work_item: "Siguiente elemento de trabajo", + }, + properties: { + duplicate_of: "Duplicado de", + }, + select_duplicate: { + select_work_item: "Seleccionar elemento de trabajo", + }, + sidebar: { + label_count: "Etiquetas {count}", + }, + toasts: { + editor_processing: "El editor todavía está procesando cambios. Espere antes de continuar.", + create_success: "Elemento de trabajo creado correctamente.", + delete_failed: "Error al eliminar el elemento de trabajo", + update_failed: "Error al actualizar el elemento de trabajo", + }, + }, + space_public: { + error_title: "¡Vaya! Esto no se ve bien.", + error_description_prefix: + "Plane se bloqueó. No te preocupes, nuestros ingenieros ya fueron notificados. Si tienes más detalles, escribe a", + error_description_middle: "o en nuestro", + forum: "Foro", + refresh: "Actualizar", + not_found_title: "Eso no funcionó", + not_found_hint: "Comprueba la URL en la barra de direcciones del navegador e inténtalo de nuevo.", + user_already_logged_in: "El usuario ya ha iniciado sesión", + logged_in_title: "Bien. Solo falta un paso.", + logged_in_hint: + "Introduce en la barra de direcciones del navegador la URL pública compartida o el enlace de la vista o página que quieres ver.", + by_creating_account: "Al crear una cuenta", + by_signing_in: "Al iniciar sesión", + you_agree_to_our: "aceptas nuestros", + terms_of_service: "Términos de servicio", + and: "y", + privacy_policy: "Política de privacidad", + sign_up: "Registrarse", + oauth_with_provider: "{action} con {provider}", + auth: { + sign_in_header: "Inicia sesión para votar o comentar", + sign_in_subheader: "Ayuda a impulsar las funciones que quieres que se creen.", + sign_up_header: "Ver, comentar y hacer más", + sign_up_subheader: "Regístrate o inicia sesión para trabajar con elementos de trabajo y páginas de Plane.", + }, + peek: { + side: "Vista lateral", + modal: "Modal", + full_screen: "Pantalla completa", + }, + bot_name: "Bot de {name}", + commented_time: "comentó {time}", + and_more: "y {count} más", + no_upvotes_yet: "Aún no hay votos positivos", + no_downvotes_yet: "Aún no hay votos negativos", + view_less: "Ver menos", + view_all: "Ver todo", + no_matches_found: "No se encontraron coincidencias", + no_date: "Sin fecha", + no_cycle: "Sin ciclo", + no_modules: "Sin módulos", + modules_count: "{count} módulos", + no_assignees: "Sin responsables", + labels_count: "{count} etiquetas", + page_not_found_alt: "Página no encontrada", + something_went_wrong: "¡Ups! Algo salió mal.", + page_not_found_description: "La página que buscas no existe o se ha movido.", + instance_failure_image_alt: "No se pudieron obtener los detalles de la instancia", + instance_failure_title: "No se pudieron obtener los detalles de la instancia.", + instance_failure_description: "No pudimos cargar los detalles de tu instancia.", + instance_failure_hint: "Comprueba tu conexión e inténtalo de nuevo.", + retry: "Reintentar", + powered_by: "Con tecnología de", + sign_in_to_add_comment: "Inicia sesión para añadir un comentario", + sign_in: "Iniciar sesión", + link_copied: "¡Enlace copiado!", + work_item_link_copied: "Enlace del elemento de trabajo copiado al portapapeles.", + comment_post_error: "No se pudo publicar el comentario. Inténtalo de nuevo.", + add_comment: "Añadir comentario", + public_board_not_found: "El tablero público no existe. Comprueba la URL.", + no_work_items_found: "No se encontraron elementos de trabajo", + no_labels: "Sin etiquetas", + user: "Usuario", + }, + }, } as const; diff --git a/packages/i18n/src/locales/fr/translations.ts b/packages/i18n/src/locales/fr/translations.ts index f7ace4c6914..4f73d02afab 100644 --- a/packages/i18n/src/locales/fr/translations.ts +++ b/packages/i18n/src/locales/fr/translations.ts @@ -2713,4 +2713,318 @@ export default { close_button: "Fermer le panneau de navigation", outline_floating_button: "Ouvrir le plan", }, + localized_ui: { + not_found: { + alt: "404 - Page introuvable", + title: "Oups ! Une erreur s'est produite.", + description: + "Désolé, la page que vous recherchez est introuvable. Elle a peut-être été supprimée, renommée ou est temporairement indisponible.", + go_to_home: "Aller à l'accueil", + }, + workspace_views: { + page_title: "{workspaceName} - Toutes les vues", + }, + projects_empty_state: { + no_projects_yet: "Aucun projet pour le moment", + description: + "Les projets sont la base du travail orienté objectifs. Ils vous permettent de gérer vos équipes, vos tâches et tout ce dont vous avez besoin pour avancer.", + learn_more: "En savoir plus sur les projets", + start_first_project: "Démarrer votre premier projet", + }, + profile_activity: { + page_title: "Profil - Activité", + }, + pages: { + not_found_title: "Page introuvable", + not_found_description: + "La page à laquelle vous essayez d’accéder n’existe pas ou vous n’êtes pas autorisé à la consulter.", + view_other_pages: "Voir d’autres pages", + }, + workspace_access: { + not_found_title: "Espace de travail introuvable", + not_found_description: + "Aucun espace de travail n’a été trouvé pour cette URL. Il n’existe peut-être pas ou vous n’êtes pas autorisé à le consulter.", + visit_profile: "Voir le profil", + not_authorized_title: "Non autorisé !", + not_authorized_description: + "Vous n’êtes pas membre de cet espace de travail. Contactez l’administrateur de l’espace de travail pour obtenir une invitation ou vérifiez vos invitations en attente.", + check_pending_invites: "Vérifier les invitations en attente", + }, + editor: { + url: "URL", + enter_or_paste_url: "Saisissez ou collez l'URL", + text: "Texte", + enter_text_to_display: "Saisissez le texte à afficher", + remove_link: "Supprimer le lien", + edit_link: "Modifier le lien", + color: "Couleur", + text_colors: "Couleurs du texte", + background_colors: "Couleurs d'arrière-plan", + link: "Lien", + enter_or_paste_link: "Saisir ou coller le lien", + please_enter_valid_url: "Veuillez entrer un URL valide", + delete: "Supprimer", + duplicate: "Double", + multiple: "Multiple", + loading: "Chargement", + no_results: "Aucun résultat", + copy_code: "Copier le code", + add_an_image: "Ajouter une image", + error_loading_image: "Erreur de chargement de l'image", + uploading: "Téléchargement", + drop_image_here: "Déposez l'image ici", + retry_duplication: "Réessayer la duplication", + retry: "Réessayer", + no_emojis_found: "Aucun emoji trouvé", + fullscreen_image_viewer: "Visionneuse d'images plein écran", + close_image_viewer: "Fermer la visionneuse d'images", + zoom_out: "Zoom arrière", + zoom_in: "Zoomer", + download_image: "Télécharger l'image", + open_image_in_new_tab: "Ouvrir l'image dans un nouvel onglet", + view_in_full_screen: "Afficher en plein écran", + view_image_in_full_screen: "Afficher l'image en plein écran", + align: "Aligner", + download: "Télécharger", + clear_contents: "Effacer le contenu", + insert_above: "Insérer ci-dessus", + insert_below: "Insérer ci-dessous", + insert_left: "Insérer à gauche", + insert_right: "Insérer à droite", + header_row: "Ligne d'en-tête", + header_column: "Colonne d'en-tête", + alignment: { + left: "Gauche", + center: "Centre", + right: "Droite", + }, + menu_items: { + text: "Texte", + h1: "Titre 1", + h2: "Titre 2", + h3: "Titre 3", + h4: "Titre 4", + h5: "Titre 5", + h6: "Rubrique 6", + "bulleted-list": "Liste à puces", + "numbered-list": "Liste numérotée", + "to-do-list": "Liste de choses à faire", + quote: "Citation", + code: "Code", + table: "Tableau", + image: "Image", + divider: "Diviseur", + link: "Lien", + bold: "Gras", + italic: "Italique", + underline: "Souligner", + strikethrough: "Barré", + "text-color": "Couleur du texte", + "background-color": "Couleur de fond", + "text-align": "Aligner le texte", + }, + }, + workspace_invitation: { + invitation_not_found: "Invitation introuvable", + invited_to_workspace: "Vous avez été invité à {workspaceName}", + description: + "Votre espace de travail est l'endroit où vous créerez des projets, collaborerez sur vos éléments de travail et organiserez différents flux de travail dans votre compte Plane.", + accept: "Accepter", + ignore: "Ignorer", + already_member: "Vous êtes déjà membre de {workspaceName}", + continue_to_home: "Continuer à la maison", + inactive_title: "Ce lien d'invitation n'est plus actif.", + empty_project_link: "Ou partir d'un projet vide", + sign_in_to_continue: "Connectez-vous pour continuer", + star_on_github: "Mettez-nous en vedette sur GitHub", + join_community: "Rejoignez notre communauté de créateurs actifs", + }, + space_auth: { + email: "E-mail", + email_invalid: "L'e-mail n'est pas valide", + clear_email: "Effacer l'e-mail", + password: "Mot de passe", + set_password: "Définir un mot de passe", + enter_password: "Entrez le mot de passe", + confirm_password: "Confirmez le mot de passe", + passwords_dont_match: "Les mots de passe ne correspondent pas", + continue: "Continuer", + go_to_workspace: "Aller à l'espace de travail", + sign_in_with_unique_code: "Connectez-vous avec un code unique", + create_account: "Créer un compte", + unique_code: "Code unique", + paste_code_sent: "Collez le code envoyé sur votre email", + resend_in: "Renvoyer dans {seconds}s", + requesting_new_code: "Demander un nouveau code", + resend: "Renvoyer", + sending_code: "Envoi du code", + }, + onboarding: { + create_profile_title: "Créez votre profil.", + create_profile_description: "C'est ainsi que vous apparaîtrez dans Plane.", + change_image: "Changer l'image", + upload_image: "Télécharger une image", + name: "Nom", + name_required: "Le nom est requis", + name_within_50: "Le nom doit contenir moins de 50 caractères.", + enter_full_name: "Entrez votre nom complet", + set_password: "Définir un mot de passe", + optional: "Facultatif", + passwords_do_not_match: "Les mots de passe ne correspondent pas", + passwords_match: "Les mots de passe correspondent", + continue: "Continuer", + invite_team_title: "Invitez vos coéquipiers", + invite_team_description: + "Le travail chez Plane se déroule mieux avec votre équipe. Invitez-les maintenant à utiliser Plane à son potentiel.", + invalid_email: "Cela ne ressemble pas à une adresse e-mail.", + success: "Succès!", + invitations_sent: "Invitations envoyées avec succès.", + error: "Erreur!", + add_another: "Ajoutez-en un autre", + do_later: "je le ferai plus tard", + join_invites_title: "Rejoignez des invitations ou créez un espace de travail", + unified_description: "Tout votre travail – unifié.", + create_new_workspace: "Créer un nouvel espace de travail", + no_invitations_found: "Aucune invitation trouvée", + you_are_invited: "Vous êtes invité !", + accept_invites: "Acceptez les invitations à collaborer avec votre équipe.", + continue_to_workspace: "Continuer vers l'espace de travail", + or: "ou", + create_own_workspace: "Créez votre propre espace de travail", + workspace_creation_disabled: + "Vous ne semblez recevoir aucune invitation à un espace de travail et l'administrateur de votre instance a restreint la création de nouveaux espaces de travail. Veuillez d'abord demander à un propriétaire ou à un administrateur d'espace de travail de vous inviter à un espace de travail, puis de revenir sur cet écran pour le rejoindre.", + create_workspace_title: "Créez votre espace de travail", + enter_workspace_name: "Entrez le nom de l'espace de travail", + join_existing_workspace: "Rejoindre l'espace de travail existant", + profile_setup_completed: "Configuration du profil terminée.", + profile_setup_failed: "La configuration du profil a échoué.", + usecase_title: "Comment comptez-vous utiliser Plane ?", + usecase_description: + "Sélectionnez une ou plusieurs options afin que nous puissions personnaliser votre expérience.", + select_one_or_more: "Sélectionnez un ou plusieurs", + select_at_least_one: "Sélectionnez au moins une option.", + skip: "Sauter", + }, + inbox: { + duplicate_issues_found: "{count} éléments de travail en double trouvés", + description_versions: { + intake_form_user: "Utilisateur du formulaire de réception", + }, + errors: { + asset_upload_failed: "Échec du téléchargement de l'élément. Veuillez réessayer plus tard.", + asset_duplication_failed: "La duplication des actifs a échoué. Veuillez réessayer plus tard.", + permission_denied: "Autorisation refusée", + mark_duplicate_permission: + "Seuls les administrateurs de projet peuvent marquer un élément de travail comme doublon", + mark_duplicate_permission_plural: + "Seuls les administrateurs de projet peuvent marquer les éléments de travail comme doublons", + }, + filters: { + created_date: "Date de création", + updated_date: "Date mise à jour", + last_updated_date: "Date de dernière mise à jour", + status: "Statut", + work_item_status: "Statut de l'élément de travail", + view_all: "Voir tout", + view_less: "Voir moins", + date_options: { + today: "Aujourd'hui", + yesterday: "Hier", + last_7_days: "7 derniers jours", + last_30_days: "30 derniers jours", + }, + date_operators: { + after: "Après", + before: "Avant", + }, + }, + navigation: { + previous_work_item: "Élément de travail précédent", + next_work_item: "Élément de travail suivant", + }, + properties: { + duplicate_of: "Doublon de", + }, + select_duplicate: { + select_work_item: "Sélectionner un élément de travail", + }, + sidebar: { + label_count: "Étiquettes {count}", + }, + toasts: { + editor_processing: + "L'éditeur est toujours en train de traiter les modifications. Veuillez patienter avant de continuer.", + create_success: "Élément de travail créé avec succès.", + delete_failed: "Échec de la suppression de l'élément de travail", + update_failed: "Échec de la mise à jour de l'élément de travail", + }, + }, + space_public: { + error_title: "Oups ! Cela ne semble pas bon.", + error_description_prefix: + "Plane a planté. Pas d'inquiétude, nos ingénieurs ont été informés. Si vous avez plus de détails, écrivez à", + error_description_middle: "ou sur notre", + forum: "Forum", + refresh: "Actualiser", + not_found_title: "Cela n'a pas fonctionné", + not_found_hint: "Vérifiez l'URL dans la barre d'adresse du navigateur puis réessayez.", + user_already_logged_in: "Utilisateur déjà connecté", + logged_in_title: "Parfait ! Plus qu'une étape.", + logged_in_hint: + "Saisissez dans la barre d'adresse du navigateur l'URL publique partagée ou le lien de la vue ou de la page que vous souhaitez consulter.", + by_creating_account: "En créant un compte", + by_signing_in: "En vous connectant", + you_agree_to_our: "vous acceptez nos", + terms_of_service: "Conditions d'utilisation", + and: "et", + privacy_policy: "Politique de confidentialité", + sign_up: "S'inscrire", + oauth_with_provider: "{action} avec {provider}", + auth: { + sign_in_header: "Connectez-vous pour voter ou commenter", + sign_in_subheader: "Aidez à faire avancer les fonctionnalités que vous souhaitez voir créées.", + sign_up_header: "Consultez, commentez et faites plus", + sign_up_subheader: + "Inscrivez-vous ou connectez-vous pour travailler avec les éléments de travail et les pages Plane.", + }, + peek: { + side: "Aperçu latéral", + modal: "Fenêtre modale", + full_screen: "Plein écran", + }, + bot_name: "Bot {name}", + commented_time: "a commenté {time}", + and_more: "et {count} de plus", + no_upvotes_yet: "Aucun vote positif pour le moment", + no_downvotes_yet: "Aucun vote négatif pour le moment", + view_less: "Voir moins", + view_all: "Tout voir", + no_matches_found: "Aucune correspondance trouvée", + no_date: "Aucune date", + no_cycle: "Aucun cycle", + no_modules: "Aucun module", + modules_count: "{count} modules", + no_assignees: "Aucune personne assignée", + labels_count: "{count} étiquettes", + page_not_found_alt: "Page introuvable", + something_went_wrong: "Oups ! Une erreur s'est produite.", + page_not_found_description: "La page que vous recherchez n'existe pas ou a été déplacée.", + instance_failure_image_alt: "Impossible de récupérer les détails de l'instance", + instance_failure_title: "Impossible de récupérer les détails de l'instance.", + instance_failure_description: "Nous n'avons pas pu charger les détails de votre instance.", + instance_failure_hint: "Vérifiez votre connexion puis réessayez.", + retry: "Réessayer", + powered_by: "Fourni par", + sign_in_to_add_comment: "Connectez-vous pour ajouter un commentaire", + sign_in: "Se connecter", + link_copied: "Lien copié !", + work_item_link_copied: "Lien de l'élément de travail copié dans le presse-papiers.", + comment_post_error: "Impossible de publier le commentaire. Veuillez réessayer.", + add_comment: "Ajouter un commentaire", + public_board_not_found: "Le tableau public n'existe pas. Veuillez vérifier l'URL.", + no_work_items_found: "Aucun élément de travail trouvé", + no_labels: "Aucune étiquette", + user: "Utilisateur", + }, + }, } as const; diff --git a/packages/i18n/src/locales/id/translations.ts b/packages/i18n/src/locales/id/translations.ts index f933b215e04..6acb5aa7f86 100644 --- a/packages/i18n/src/locales/id/translations.ts +++ b/packages/i18n/src/locales/id/translations.ts @@ -2693,4 +2693,312 @@ export default { close_button: "Tutup panel navigasi", outline_floating_button: "Buka garis besar", }, + localized_ui: { + not_found: { + alt: "404 - Halaman tidak ditemukan", + title: "Ups! Terjadi kesalahan.", + description: + "Maaf, halaman yang Anda cari tidak dapat ditemukan. Halaman tersebut mungkin telah dihapus, diganti namanya, atau sementara tidak tersedia.", + go_to_home: "Ke Beranda", + }, + workspace_views: { + page_title: "{workspaceName} - Semua Tampilan", + }, + projects_empty_state: { + no_projects_yet: "Belum ada proyek", + description: + "Proyek adalah dasar kerja berbasis tujuan. Proyek membantu Anda mengelola tim, tugas, dan semua hal yang diperlukan untuk menyelesaikan pekerjaan.", + learn_more: "Pelajari lebih lanjut tentang proyek", + start_first_project: "Mulai proyek pertama Anda", + }, + profile_activity: { + page_title: "Profil - Aktivitas", + }, + pages: { + not_found_title: "Halaman tidak ditemukan", + not_found_description: "Halaman yang Anda coba akses tidak ada atau Anda tidak memiliki izin untuk melihatnya.", + view_other_pages: "Lihat halaman lainnya", + }, + workspace_access: { + not_found_title: "Workspace tidak ditemukan", + not_found_description: + "Tidak ada workspace yang ditemukan untuk URL ini. Workspace tersebut mungkin tidak ada atau Anda tidak memiliki izin untuk melihatnya.", + visit_profile: "Kunjungi profil", + not_authorized_title: "Tidak diizinkan!", + not_authorized_description: + "Anda bukan anggota workspace ini. Hubungi admin workspace untuk mendapatkan undangan atau periksa undangan yang tertunda.", + check_pending_invites: "Periksa undangan tertunda", + }, + editor: { + url: "URL", + enter_or_paste_url: "Masukkan atau tempel URL", + text: "Teks", + enter_text_to_display: "Masukkan teks untuk ditampilkan", + remove_link: "Hapus tautan", + edit_link: "Sunting tautan", + color: "Warna", + text_colors: "Warna teks", + background_colors: "Warna latar belakang", + link: "Link", + enter_or_paste_link: "Masukkan atau tempel tautan", + please_enter_valid_url: "Silakan masukkan URL yang valid", + delete: "Menghapus", + duplicate: "Duplikat", + multiple: "Banyak", + loading: "Memuat", + no_results: "Tidak ada hasil", + copy_code: "Salin kode", + add_an_image: "Tambahkan gambar", + error_loading_image: "Terjadi kesalahan saat memuat gambar", + uploading: "Mengunggah", + drop_image_here: "Jatuhkan gambar di sini", + retry_duplication: "Coba lagi duplikasi", + retry: "Mencoba kembali", + no_emojis_found: "Tidak ada emoji yang ditemukan", + fullscreen_image_viewer: "Penampil gambar layar penuh", + close_image_viewer: "Tutup penampil gambar", + zoom_out: "Perkecil", + zoom_in: "Perbesar", + download_image: "Unduh gambar", + open_image_in_new_tab: "Buka gambar di tab baru", + view_in_full_screen: "Lihat dalam layar penuh", + view_image_in_full_screen: "Lihat gambar dalam layar penuh", + align: "Meluruskan", + download: "Unduh", + clear_contents: "Hapus isinya", + insert_above: "Sisipkan di atas", + insert_below: "Sisipkan di bawah", + insert_left: "Sisipkan ke kiri", + insert_right: "Masukkan ke kanan", + header_row: "Baris tajuk", + header_column: "Kolom tajuk", + alignment: { + left: "Kiri", + center: "Tengah", + right: "Kanan", + }, + menu_items: { + text: "Teks", + h1: "Judul 1", + h2: "Judul 2", + h3: "Pos 3", + h4: "Pos 4", + h5: "Pos 5", + h6: "Pos 6", + "bulleted-list": "Daftar berpoin", + "numbered-list": "Daftar bernomor", + "to-do-list": "Daftar tugas", + quote: "Mengutip", + code: "Kode", + table: "Tabel", + image: "Gambar", + divider: "Pembagi", + link: "Link", + bold: "Tebal", + italic: "miring", + underline: "Garis bawah", + strikethrough: "Dicoret", + "text-color": "Warna teks", + "background-color": "Warna latar belakang", + "text-align": "Perataan teks", + }, + }, + workspace_invitation: { + invitation_not_found: "Undangan tidak ditemukan", + invited_to_workspace: "Anda telah diundang ke {workspaceName}", + description: + "Ruang kerja Anda adalah tempat Anda membuat proyek, berkolaborasi pada item pekerjaan Anda, dan mengatur berbagai aliran pekerjaan di akun Plane Anda.", + accept: "Menerima", + ignore: "Mengabaikan", + already_member: "Anda sudah menjadi anggota {workspaceName}", + continue_to_home: "Lanjutkan ke rumah", + inactive_title: "Tautan undangan ini sudah tidak aktif lagi.", + empty_project_link: "Atau mulai dari proyek kosong", + sign_in_to_continue: "Masuk untuk melanjutkan", + star_on_github: "Bintangi kami di GitHub", + join_community: "Bergabunglah dengan komunitas pembuat konten aktif kami", + }, + space_auth: { + email: "E-mail", + email_invalid: "Email tidak valid", + clear_email: "Hapus email", + password: "Kata sandi", + set_password: "Tetapkan kata sandi", + enter_password: "Masukkan kata sandi", + confirm_password: "Konfirmasikan kata sandi", + passwords_dont_match: "Kata sandi tidak cocok", + continue: "Melanjutkan", + go_to_workspace: "Pergi ke ruang kerja", + sign_in_with_unique_code: "Masuk dengan kode unik", + create_account: "Buat akun", + unique_code: "Kode unik", + paste_code_sent: "Tempelkan kode yang dikirimkan ke email Anda", + resend_in: "Kirim ulang dalam {seconds}s", + requesting_new_code: "Meminta kode baru", + resend: "Kirim ulang", + sending_code: "Mengirim kode", + }, + onboarding: { + create_profile_title: "Buat profil Anda.", + create_profile_description: "Ini adalah tampilan Anda di Plane.", + change_image: "Ubah gambar", + upload_image: "Unggah gambar", + name: "Nama", + name_required: "Nama wajib diisi", + name_within_50: "Nama harus dalam 50 karakter.", + enter_full_name: "Masukkan nama lengkap Anda", + set_password: "Tetapkan kata sandi", + optional: "Opsional", + passwords_do_not_match: "Kata sandi tidak cocok", + passwords_match: "Kata sandi cocok", + continue: "Melanjutkan", + invite_team_title: "Undang rekan satu tim Anda", + invite_team_description: + "Pekerjaan di Plane paling baik dilakukan bersama tim Anda. Undang mereka sekarang untuk menggunakan Plane semaksimal mungkin.", + invalid_email: "Itu tidak terlihat seperti alamat email.", + success: "Kesuksesan!", + invitations_sent: "Undangan berhasil dikirim.", + error: "Kesalahan!", + add_another: "Tambahkan yang lain", + do_later: "Saya akan melakukannya nanti", + join_invites_title: "Bergabunglah dengan undangan atau buat ruang kerja", + unified_description: "Semua pekerjaan Anda — terpadu.", + create_new_workspace: "Buat ruang kerja baru", + no_invitations_found: "Tidak ada undangan yang ditemukan", + you_are_invited: "Anda diundang!", + accept_invites: "Terima undangan untuk berkolaborasi dengan tim Anda.", + continue_to_workspace: "Lanjutkan ke ruang kerja", + or: "atau", + create_own_workspace: "Buat ruang kerja Anda sendiri", + workspace_creation_disabled: + "Tampaknya Anda tidak mendapat undangan apa pun ke ruang kerja dan admin instans Anda telah membatasi pembuatan ruang kerja baru. Silakan minta pemilik atau admin ruang kerja untuk mengundang Anda ke ruang kerja terlebih dahulu dan kembali ke layar ini untuk bergabung.", + create_workspace_title: "Ciptakan ruang kerja Anda", + enter_workspace_name: "Masukkan nama ruang kerja", + join_existing_workspace: "Bergabunglah dengan ruang kerja yang ada", + profile_setup_completed: "Penyiapan profil selesai.", + profile_setup_failed: "Penyiapan profil gagal.", + usecase_title: "Bagaimana Anda berencana menggunakan Plane?", + usecase_description: "Pilih satu atau lebih opsi sehingga kami dapat mempersonalisasi pengalaman Anda.", + select_one_or_more: "Pilih satu atau lebih", + select_at_least_one: "Pilih setidaknya satu opsi.", + skip: "Melewati", + }, + inbox: { + duplicate_issues_found: "{count} item kerja duplikat ditemukan", + description_versions: { + intake_form_user: "Pengguna formulir intake", + }, + errors: { + asset_upload_failed: "Pengunggahan aset gagal. Silakan coba lagi nanti.", + asset_duplication_failed: "Duplikasi aset gagal. Silakan coba lagi nanti.", + permission_denied: "Izin ditolak", + mark_duplicate_permission: "Hanya admin proyek yang dapat menandai item pekerjaan sebagai duplikat", + mark_duplicate_permission_plural: "Hanya admin proyek yang dapat menandai item pekerjaan sebagai duplikat", + }, + filters: { + created_date: "Tanggal dibuat", + updated_date: "Tanggal diperbarui", + last_updated_date: "Tanggal terakhir diperbarui", + status: "Status", + work_item_status: "Status item pekerjaan", + view_all: "Lihat semuanya", + view_less: "Lihat lebih sedikit", + date_options: { + today: "Hari ini", + yesterday: "Kemarin", + last_7_days: "7 hari terakhir", + last_30_days: "30 hari terakhir", + }, + date_operators: { + after: "Setelah", + before: "Sebelum", + }, + }, + navigation: { + previous_work_item: "Item pekerjaan sebelumnya", + next_work_item: "Item pekerjaan berikutnya", + }, + properties: { + duplicate_of: "Duplikat dari", + }, + select_duplicate: { + select_work_item: "Pilih item pekerjaan", + }, + sidebar: { + label_count: "label {count}", + }, + toasts: { + editor_processing: "Editor masih memproses perubahan. Harap tunggu sebelum melanjutkan.", + create_success: "Item pekerjaan berhasil dibuat.", + delete_failed: "Penghapusan item pekerjaan gagal", + update_failed: "Pembaruan item pekerjaan gagal", + }, + }, + space_public: { + error_description_prefix: + "Plane mengalami crash. Teknisi kami telah diberi tahu. Jika Anda memiliki detail tambahan, silakan tulis ke", + error_description_middle: "atau di", + not_found_hint: "Periksa URL di bilah alamat browser lalu coba lagi.", + logged_in_hint: + "Masukkan URL berbagi publik atau tautan tampilan maupun Halaman yang ingin Anda lihat di bilah alamat browser.", + oauth_with_provider: "{action} dengan {provider}", + auth: { + sign_in_header: "Masuk untuk memberi suara atau berkomentar", + sign_in_subheader: "Bantu mendorong fitur yang ingin Anda lihat dibangun.", + sign_up_header: "Lihat, komentari, dan lakukan lebih banyak", + sign_up_subheader: "Daftar atau masuk untuk bekerja dengan item kerja dan Halaman Plane.", + }, + peek: { + side: "Pratinjau Samping", + modal: "Modal", + full_screen: "Layar Penuh", + }, + bot_name: "Bot {name}", + commented_time: "berkomentar {time}", + and_more: "dan {count} lainnya", + no_upvotes_yet: "Belum ada suara positif", + no_downvotes_yet: "Belum ada suara negatif", + modules_count: "{count} Modul", + labels_count: "{count} Label", + page_not_found_alt: "Halaman tidak ditemukan", + something_went_wrong: "Ups! Terjadi kesalahan.", + page_not_found_description: "Halaman yang Anda cari tidak ada atau telah dipindahkan.", + instance_failure_image_alt: "Tidak dapat mengambil detail instans", + instance_failure_title: "Tidak dapat mengambil detail instans.", + instance_failure_description: "Kami tidak dapat memuat detail instans Anda.", + instance_failure_hint: "Periksa koneksi Anda lalu coba lagi.", + powered_by: "Didukung oleh", + sign_in_to_add_comment: "Masuk untuk menambahkan komentar", + link_copied: "Tautan disalin!", + work_item_link_copied: "Tautan item kerja disalin ke papan klip.", + comment_post_error: "Gagal mengirim komentar. Silakan coba lagi.", + add_comment: "Tambahkan komentar", + public_board_not_found: "Papan publik tidak ada. Periksa URL.", + no_work_items_found: "Tidak ada item kerja yang ditemukan", + error_title: "Ups! Ini tidak terlihat baik.", + refresh: "Muat ulang", + forum: "Forum", + not_found_title: "Itu tidak berhasil", + user_already_logged_in: "Pengguna sudah masuk", + logged_in_title: "Bagus! Tinggal satu langkah lagi.", + by_creating_account: "Dengan membuat akun", + by_signing_in: "Dengan masuk", + you_agree_to_our: "Anda menyetujui", + terms_of_service: "Ketentuan Layanan", + and: "dan", + privacy_policy: "Kebijakan Privasi", + sign_up: "Daftar", + sign_in: "Masuk", + retry: "Coba lagi", + view_less: "Tampilkan lebih sedikit", + view_all: "Tampilkan semua", + no_matches_found: "Tidak ada hasil yang cocok", + no_date: "Tanpa Tanggal", + no_cycle: "Tanpa Siklus", + no_modules: "Tanpa Modul", + no_assignees: "Tanpa Penanggung Jawab", + no_labels: "Tanpa label", + user: "Pengguna", + }, + }, } as const; diff --git a/packages/i18n/src/locales/it/translations.ts b/packages/i18n/src/locales/it/translations.ts index a0cb1b5c54f..c2a87ed6491 100644 --- a/packages/i18n/src/locales/it/translations.ts +++ b/packages/i18n/src/locales/it/translations.ts @@ -2703,4 +2703,315 @@ export default { close_button: "Chiudi pannello di navigazione", outline_floating_button: "Apri schema", }, + localized_ui: { + not_found: { + alt: "404 - Pagina non trovata", + title: "Ops! Qualcosa è andato storto.", + description: + "Spiacenti, la pagina che stai cercando non è stata trovata. Potrebbe essere stata rimossa, rinominata o essere temporaneamente non disponibile.", + go_to_home: "Vai alla home", + }, + workspace_views: { + page_title: "{workspaceName} - Tutte le viste", + }, + projects_empty_state: { + no_projects_yet: "Nessun progetto ancora", + description: + "I progetti sono la base del lavoro orientato agli obiettivi. Ti aiutano a gestire team, attività e tutto ciò che serve per portare a termine il lavoro.", + learn_more: "Scopri di più sui progetti", + start_first_project: "Avvia il tuo primo progetto", + }, + profile_activity: { + page_title: "Profilo - Attività", + }, + pages: { + not_found_title: "Pagina non trovata", + not_found_description: + "La pagina a cui stai tentando di accedere non esiste o non hai l’autorizzazione per visualizzarla.", + view_other_pages: "Visualizza altre pagine", + }, + workspace_access: { + not_found_title: "Workspace non trovato", + not_found_description: + "Non è stato trovato alcuno workspace per questo URL. Potrebbe non esistere o potresti non avere l’autorizzazione per visualizzarlo.", + visit_profile: "Visita profilo", + not_authorized_title: "Non autorizzato!", + not_authorized_description: + "Non sei membro di questo workspace. Contatta l’amministratore del workspace per ricevere un invito o controlla gli inviti in sospeso.", + check_pending_invites: "Controlla inviti in sospeso", + }, + editor: { + url: "URL", + enter_or_paste_url: "Inserisci o incolla l'URL", + text: "Testo", + enter_text_to_display: "Inserisci il testo da visualizzare", + remove_link: "Rimuovi collegamento", + edit_link: "Modifica collegamento", + color: "Colore", + text_colors: "Colori del testo", + background_colors: "Colori di sfondo", + link: "Collegamento", + enter_or_paste_link: "Inserisci o incolla il collegamento", + please_enter_valid_url: "Inserisci un URL valido", + delete: "Eliminare", + duplicate: "Duplicato", + multiple: "Molteplici", + loading: "Caricamento", + no_results: "Nessun risultato", + copy_code: "Copia il codice", + add_an_image: "Aggiungi un'immagine", + error_loading_image: "Errore durante il caricamento dell'immagine", + uploading: "Caricamento", + drop_image_here: "Rilascia l'immagine qui", + retry_duplication: "Riprovare la duplicazione", + retry: "Riprova", + no_emojis_found: "Nessun emoji trovato", + fullscreen_image_viewer: "Visualizzatore di immagini a schermo intero", + close_image_viewer: "Chiudi il visualizzatore di immagini", + zoom_out: "Rimpicciolisci", + zoom_in: "Ingrandisci", + download_image: "Scarica l'immagine", + open_image_in_new_tab: "Apri l'immagine in una nuova scheda", + view_in_full_screen: "Visualizza a schermo intero", + view_image_in_full_screen: "Visualizza l'immagine a schermo intero", + align: "Allineare", + download: "Scarica", + clear_contents: "Cancella contenuto", + insert_above: "Inserisci sopra", + insert_below: "Inserisci qui sotto", + insert_left: "Inserisci a sinistra", + insert_right: "Inserisci a destra", + header_row: "Riga di intestazione", + header_column: "Colonna di intestazione", + alignment: { + left: "Sinistra", + center: "Centro", + right: "Destra", + }, + menu_items: { + text: "Testo", + h1: "Rubrica 1", + h2: "Rubrica 2", + h3: "Rubrica 3", + h4: "Rubrica 4", + h5: "Rubrica 5", + h6: "Rubrica 6", + "bulleted-list": "Elenco puntato", + "numbered-list": "Elenco numerato", + "to-do-list": "Lista delle cose da fare", + quote: "Citazione", + code: "Codice", + table: "Tabella", + image: "Immagine", + divider: "Divisore", + link: "Collegamento", + bold: "Grassetto", + italic: "Corsivo", + underline: "Sottolineato", + strikethrough: "Barrato", + "text-color": "Colore del testo", + "background-color": "Colore di sfondo", + "text-align": "Allinea il testo", + }, + }, + workspace_invitation: { + invitation_not_found: "Invito non trovato", + invited_to_workspace: "Sei stato invitato a {workspaceName}", + description: + "Il tuo spazio di lavoro è il luogo in cui creerai progetti, collaborerai sui tuoi elementi di lavoro e organizzerai diversi flussi di lavoro nel tuo account Plane.", + accept: "Accettare", + ignore: "Ignorare", + already_member: "Sei già membro di {workspaceName}", + continue_to_home: "Continua a casa", + inactive_title: "Questo collegamento di invito non è più attivo.", + empty_project_link: "Oppure inizia da un progetto vuoto", + sign_in_to_continue: "Accedi per continuare", + star_on_github: "Stella su GitHub", + join_community: "Unisciti alla nostra community di creatori attivi", + }, + space_auth: { + email: "E-mail", + email_invalid: "L'e-mail non è valida", + clear_email: "Cancella e-mail", + password: "Password", + set_password: "Imposta una password", + enter_password: "Inserisci la password", + confirm_password: "Conferma password", + passwords_dont_match: "Le password non corrispondono", + continue: "Continuare", + go_to_workspace: "Vai all'area di lavoro", + sign_in_with_unique_code: "Accedi con codice univoco", + create_account: "Creare un account", + unique_code: "Codice univoco", + paste_code_sent: "Incolla il codice inviato alla tua email", + resend_in: "Invia nuovamente tra {seconds}s", + requesting_new_code: "Richiesta nuovo codice", + resend: "Invia nuovamente", + sending_code: "Invio del codice", + }, + onboarding: { + create_profile_title: "Crea il tuo profilo.", + create_profile_description: "Ecco come apparirai in Plane.", + change_image: "Cambia immagine", + upload_image: "Carica immagine", + name: "Nome", + name_required: "Il nome è obbligatorio", + name_within_50: "Il nome deve contenere massimo 50 caratteri.", + enter_full_name: "Inserisci il tuo nome completo", + set_password: "Imposta una password", + optional: "Opzionale", + passwords_do_not_match: "Le password non corrispondono", + passwords_match: "Le password corrispondono", + continue: "Continuare", + invite_team_title: "Invita i tuoi compagni di squadra", + invite_team_description: + "Il lavoro in Plane avviene meglio con il tuo team. Invitali ora a sfruttare Plane al massimo delle sue potenzialità.", + invalid_email: "Non sembra un indirizzo email.", + success: "Successo!", + invitations_sent: "Inviti inviati con successo.", + error: "Errore!", + add_another: "Aggiungine un altro", + do_later: "Lo farò più tardi", + join_invites_title: "Partecipa agli inviti o crea uno spazio di lavoro", + unified_description: "Tutto il tuo lavoro: unificato.", + create_new_workspace: "Crea un nuovo spazio di lavoro", + no_invitations_found: "Nessun invito trovato", + you_are_invited: "Sei invitato!", + accept_invites: "Accetta gli inviti a collaborare con il tuo team.", + continue_to_workspace: "Continua nell'area di lavoro", + or: "O", + create_own_workspace: "Crea il tuo spazio di lavoro", + workspace_creation_disabled: + "Sembra che tu non abbia inviti a un'area di lavoro e l'amministratore dell'istanza ha limitato la creazione di nuove aree di lavoro. Chiedi prima al proprietario o all'amministratore di un'area di lavoro di invitarti in un'area di lavoro e di tornare a questa schermata per partecipare.", + create_workspace_title: "Crea il tuo spazio di lavoro", + enter_workspace_name: "Inserisci il nome dell'area di lavoro", + join_existing_workspace: "Unisciti allo spazio di lavoro esistente", + profile_setup_completed: "Configurazione del profilo completata.", + profile_setup_failed: "La configurazione del profilo non è riuscita.", + usecase_title: "Come intendi utilizzare Plane?", + usecase_description: "Seleziona una o più opzioni per consentirci di personalizzare la tua esperienza.", + select_one_or_more: "Seleziona uno o più", + select_at_least_one: "Seleziona almeno un'opzione.", + skip: "Saltare", + }, + inbox: { + duplicate_issues_found: "Trovati {count} elementi di lavoro duplicati", + description_versions: { + intake_form_user: "Utente del modulo di raccolta", + }, + errors: { + asset_upload_failed: "Caricamento della risorsa non riuscito. Per favore riprova più tardi.", + asset_duplication_failed: "Duplicazione della risorsa non riuscita. Per favore riprova più tardi.", + permission_denied: "Autorizzazione negata", + mark_duplicate_permission: + "Solo gli amministratori del progetto possono contrassegnare l'elemento di lavoro come duplicato", + mark_duplicate_permission_plural: + "Solo gli amministratori del progetto possono contrassegnare gli elementi di lavoro come duplicati", + }, + filters: { + created_date: "Data di creazione", + updated_date: "Data aggiornata", + last_updated_date: "Data dell'ultimo aggiornamento", + status: "Stato", + work_item_status: "Stato dell'elemento di lavoro", + view_all: "Visualizza tutto", + view_less: "Visualizza meno", + date_options: { + today: "Oggi", + yesterday: "Ieri", + last_7_days: "Ultimi 7 giorni", + last_30_days: "Ultimi 30 giorni", + }, + date_operators: { + after: "Dopo", + before: "Prima", + }, + }, + navigation: { + previous_work_item: "Elemento di lavoro precedente", + next_work_item: "Elemento di lavoro successivo", + }, + properties: { + duplicate_of: "Duplicato di", + }, + select_duplicate: { + select_work_item: "Seleziona elemento di lavoro", + }, + sidebar: { + label_count: "Etichette {count}", + }, + toasts: { + editor_processing: "L'editor sta ancora elaborando le modifiche. Si prega di attendere prima di procedere.", + create_success: "Elemento di lavoro creato correttamente.", + delete_failed: "Eliminazione dell'elemento di lavoro non riuscita", + update_failed: "Aggiornamento dell'elemento di lavoro non riuscito", + }, + }, + space_public: { + error_description_prefix: + "Plane è andato in crash. I nostri ingegneri sono stati avvisati. Se hai altri dettagli, scrivi a", + error_description_middle: "o sul nostro", + not_found_hint: "Controlla l'URL nella barra degli indirizzi del browser e riprova.", + logged_in_hint: + "Inserisci nella barra degli indirizzi del browser l'URL pubblico condiviso o il link della vista o della Pagina che vuoi visualizzare.", + oauth_with_provider: "{action} con {provider}", + auth: { + sign_in_header: "Accedi per votare o commentare", + sign_in_subheader: "Aiuta a spingere le funzionalità che vuoi vedere realizzate.", + sign_up_header: "Visualizza, commenta e fai di più", + sign_up_subheader: "Registrati o accedi per lavorare con gli elementi di lavoro e le Pagine di Plane.", + }, + peek: { + side: "Anteprima laterale", + modal: "Modale", + full_screen: "Schermo intero", + }, + bot_name: "Bot {name}", + commented_time: "ha commentato {time}", + and_more: "e altri {count}", + no_upvotes_yet: "Ancora nessun voto positivo", + no_downvotes_yet: "Ancora nessun voto negativo", + modules_count: "{count} moduli", + labels_count: "{count} etichette", + page_not_found_alt: "Pagina non trovata", + something_went_wrong: "Ops! Qualcosa è andato storto.", + page_not_found_description: "La pagina che stai cercando non esiste o è stata spostata.", + instance_failure_image_alt: "Impossibile recuperare i dettagli dell'istanza", + instance_failure_title: "Impossibile recuperare i dettagli dell'istanza.", + instance_failure_description: "Non siamo riusciti a caricare i dettagli della tua istanza.", + instance_failure_hint: "Controlla la connessione e riprova.", + powered_by: "Offerto da", + sign_in_to_add_comment: "Accedi per aggiungere un commento", + link_copied: "Link copiato!", + work_item_link_copied: "Link dell'elemento di lavoro copiato negli appunti.", + comment_post_error: "Impossibile pubblicare il commento. Riprova.", + add_comment: "Aggiungi commento", + public_board_not_found: "La bacheca pubblica non esiste. Controlla l'URL.", + no_work_items_found: "Nessun elemento di lavoro trovato", + error_title: "Ops! Non sembra andare bene.", + refresh: "Aggiorna", + forum: "Forum", + not_found_title: "Non ha funzionato", + user_already_logged_in: "Utente già connesso", + logged_in_title: "Bene! Manca solo un passaggio.", + by_creating_account: "Creando un account", + by_signing_in: "Accedendo", + you_agree_to_our: "accetti i nostri", + terms_of_service: "Termini di servizio", + and: "e", + privacy_policy: "Informativa sulla privacy", + sign_up: "Registrati", + sign_in: "Accedi", + retry: "Riprova", + view_less: "Mostra meno", + view_all: "Mostra tutto", + no_matches_found: "Nessuna corrispondenza trovata", + no_date: "Nessuna data", + no_cycle: "Nessun ciclo", + no_modules: "Nessun modulo", + no_assignees: "Nessun assegnatario", + no_labels: "Nessuna etichetta", + user: "Utente", + }, + }, } as const; diff --git a/packages/i18n/src/locales/ja/translations.ts b/packages/i18n/src/locales/ja/translations.ts index 6d79979904e..9f9dae5742f 100644 --- a/packages/i18n/src/locales/ja/translations.ts +++ b/packages/i18n/src/locales/ja/translations.ts @@ -2681,4 +2681,311 @@ export default { close_button: "ナビゲーションパネルを閉じる", outline_floating_button: "アウトラインを開く", }, + localized_ui: { + not_found: { + alt: "404 - ページが見つかりません", + title: "問題が発生しました。", + description: "お探しのページは見つかりません。削除、名前変更、または一時的に利用できない可能性があります。", + go_to_home: "ホームへ移動", + }, + workspace_views: { + page_title: "{workspaceName} - すべてのビュー", + }, + projects_empty_state: { + no_projects_yet: "プロジェクトはまだありません", + description: + "プロジェクトは、目標に基づく作業の基盤です。チーム、タスク、作業を進めるために必要なものをまとめて管理できます。", + learn_more: "プロジェクトの詳細を見る", + start_first_project: "最初のプロジェクトを開始", + }, + profile_activity: { + page_title: "プロフィール - アクティビティ", + }, + pages: { + not_found_title: "ページが見つかりません", + not_found_description: "アクセスしようとしているページは存在しないか、表示する権限がありません。", + view_other_pages: "他のページを表示", + }, + workspace_access: { + not_found_title: "ワークスペースが見つかりません", + not_found_description: + "この URL に対応するワークスペースが見つかりません。存在しないか、表示する権限がない可能性があります。", + visit_profile: "プロフィールを表示", + not_authorized_title: "権限がありません", + not_authorized_description: + "あなたはこのワークスペースのメンバーではありません。ワークスペース管理者に招待を依頼するか、保留中の招待を確認してください。", + check_pending_invites: "保留中の招待を確認", + }, + editor: { + url: "URL", + enter_or_paste_url: "URLを入力または貼り付けます", + text: "文章", + enter_text_to_display: "表示するテキストを入力してください", + remove_link: "リンクを削除する", + edit_link: "リンクを編集", + color: "色", + text_colors: "文字の色", + background_colors: "背景色", + link: "リンク", + enter_or_paste_link: "リンクを入力または貼り付けます", + please_enter_valid_url: "有効な URL を入力してください", + delete: "消去", + duplicate: "重複", + multiple: "複数", + loading: "読み込み中", + no_results: "結果はありません", + copy_code: "コードをコピーする", + add_an_image: "画像を追加する", + error_loading_image: "画像の読み込みエラー", + uploading: "アップロード中", + drop_image_here: "ここに画像をドロップ", + retry_duplication: "重複を再試行する", + retry: "リトライ", + no_emojis_found: "絵文字が見つかりませんでした", + fullscreen_image_viewer: "全画面画像ビューア", + close_image_viewer: "画像ビューアを閉じる", + zoom_out: "ズームアウト", + zoom_in: "ズームイン", + download_image: "画像をダウンロード", + open_image_in_new_tab: "新しいタブで画像を開く", + view_in_full_screen: "全画面で表示する", + view_image_in_full_screen: "画像を全画面で表示する", + align: "整列", + download: "ダウンロード", + clear_contents: "クリアコンテンツ", + insert_above: "上に挿入", + insert_below: "以下に挿入", + insert_left: "左に挿入", + insert_right: "右に挿入", + header_row: "ヘッダー行", + header_column: "ヘッダー列", + alignment: { + left: "左", + center: "中心", + right: "右", + }, + menu_items: { + text: "文章", + h1: "見出し1", + h2: "見出し2", + h3: "見出し 3", + h4: "見出し 4", + h5: "見出し 5", + h6: "見出し6", + "bulleted-list": "箇条書きリスト", + "numbered-list": "番号付きリスト", + "to-do-list": "やることリスト", + quote: "引用", + code: "コード", + table: "テーブル", + image: "画像", + divider: "ディバイダー", + link: "リンク", + bold: "太字", + italic: "イタリック", + underline: "下線", + strikethrough: "取り消し線", + "text-color": "文字の色", + "background-color": "背景色", + "text-align": "テキストの配置", + }, + }, + workspace_invitation: { + invitation_not_found: "招待状が見つかりません", + invited_to_workspace: "{workspaceName} に招待されました", + description: + "ワークスペースは、Plane アカウントでプロジェクトを作成し、作業項目で共同作業し、さまざまな作業ストリームを整理する場所です。", + accept: "受け入れる", + ignore: "無視する", + already_member: "あなたはすでに {workspaceName} のメンバーです", + continue_to_home: "家に帰る", + inactive_title: "この招待リンクはもうアクティブではありません。", + empty_project_link: "または空のプロジェクトから開始します", + sign_in_to_continue: "続行するにはサインインしてください", + star_on_github: "GitHub でスターを付けてください", + join_community: "アクティブなクリエイターのコミュニティに参加しましょう", + }, + space_auth: { + email: "電子メール", + email_invalid: "電子メールが無効です", + clear_email: "クリアメール", + password: "パスワード", + set_password: "パスワードを設定する", + enter_password: "パスワードを入力してください", + confirm_password: "パスワードを認証する", + passwords_dont_match: "パスワードが一致しません", + continue: "続く", + go_to_workspace: "ワークスペースに移動", + sign_in_with_unique_code: "固有のコードでサインインする", + create_account: "アカウントを作成する", + unique_code: "固有のコード", + paste_code_sent: "メールに送信されたコードを貼り付けます", + resend_in: "{seconds}sで再送信", + requesting_new_code: "新しいコードをリクエストする", + resend: "再送信", + sending_code: "コードの送信", + }, + onboarding: { + create_profile_title: "プロフィールを作成します。", + create_profile_description: "これがPlaneに登場する様子です。", + change_image: "イメージを変更する", + upload_image: "画像をアップロードする", + name: "名前", + name_required: "名前は必須です", + name_within_50: "名前は50文字以内にしてください。", + enter_full_name: "フルネームを入力してください", + set_password: "パスワードを設定する", + optional: "オプション", + passwords_do_not_match: "パスワードが一致しません", + passwords_match: "パスワードが一致する", + continue: "続く", + invite_team_title: "チームメイトを招待する", + invite_team_description: + "Plane での作業は、チームと一緒に行うのが最も効果的です。今すぐ彼らを招待して、Plane の可能性を最大限に活用してください。", + invalid_email: "それは電子メールアドレスのようには見えません。", + success: "成功!", + invitations_sent: "招待状は正常に送信されました。", + error: "エラー!", + add_another: "別のを追加", + do_later: "後でやります", + join_invites_title: "招待に参加するか、ワークスペースを作成する", + unified_description: "すべての作業を統合します。", + create_new_workspace: "新しいワークスペースを作成する", + no_invitations_found: "招待状が見つかりませんでした", + you_are_invited: "あなたは招待されています!", + accept_invites: "チームと共同作業するための招待を受け入れます。", + continue_to_workspace: "ワークスペースに進む", + or: "または", + create_own_workspace: "独自のワークスペースを作成する", + workspace_creation_disabled: + "ワークスペースへの招待がなく、インスタンス管理者によって新しいワークスペースの作成が制限されているようです。まずワークスペースに招待するようワークスペースの所有者または管理者に依頼してから、この画面に戻って参加してください。", + create_workspace_title: "ワークスペースを作成する", + enter_workspace_name: "ワークスペース名を入力してください", + join_existing_workspace: "既存のワークスペースに参加する", + profile_setup_completed: "プロファイルの設定が完了しました。", + profile_setup_failed: "プロファイルのセットアップに失敗しました。", + usecase_title: "Planeをどのように使用する予定ですか?", + usecase_description: "エクスペリエンスをパーソナライズできるように、1 つ以上のオプションを選択してください。", + select_one_or_more: "1 つ以上を選択してください", + select_at_least_one: "少なくとも 1 つのオプションを選択してください。", + skip: "スキップ", + }, + inbox: { + duplicate_issues_found: "{count} 件の重複する作業項目が見つかりました", + description_versions: { + intake_form_user: "インテークフォームユーザー", + }, + errors: { + asset_upload_failed: "アセットのアップロードに失敗しました。後でもう一度試してください。", + asset_duplication_failed: "アセットの複製に失敗しました。後でもう一度試してください。", + permission_denied: "許可が拒否されました", + mark_duplicate_permission: "プロジェクト管理者のみが作業項目を重複としてマークできます", + mark_duplicate_permission_plural: "プロジェクト管理者のみが作業項目を重複としてマークできます", + }, + filters: { + created_date: "作成日", + updated_date: "更新日", + last_updated_date: "最終更新日", + status: "状態", + work_item_status: "作業項目のステータス", + view_all: "すべて見る", + view_less: "表示を減らす", + date_options: { + today: "今日", + yesterday: "昨日", + last_7_days: "過去 7 日間", + last_30_days: "過去 30 日間", + }, + date_operators: { + after: "後", + before: "前に", + }, + }, + navigation: { + previous_work_item: "前の作業項目", + next_work_item: "次の作業項目", + }, + properties: { + duplicate_of: "重複元", + }, + select_duplicate: { + select_work_item: "作業項目を選択してください", + }, + sidebar: { + label_count: "{count} ラベル", + }, + toasts: { + editor_processing: "エディターはまだ変更を処理中です。続行する前にお待ちください。", + create_success: "作業項目が正常に作成されました。", + delete_failed: "作業項目の削除に失敗しました", + update_failed: "作業項目の更新に失敗しました", + }, + }, + space_public: { + error_description_prefix: + "Plane がクラッシュしました。担当エンジニアには通知済みです。追加の詳細がある場合は、次までご連絡ください", + error_description_middle: "または次の場所で", + not_found_hint: "ブラウザーのアドレスバーに入力した URL を確認して、もう一度お試しください。", + logged_in_hint: + "表示したいビューまたはページの公開共有 URL もしくはリンクをブラウザーのアドレスバーに入力してください。", + oauth_with_provider: "{provider} で{action}", + auth: { + sign_in_header: "投票またはコメントするにはサインインしてください", + sign_in_subheader: "実装してほしい機能を後押ししましょう。", + sign_up_header: "表示、コメント、さらに多くの操作", + sign_up_subheader: "Plane の作業項目とページを扱うには、登録またはサインインしてください。", + }, + peek: { + side: "サイドピーク", + modal: "モーダル", + full_screen: "全画面", + }, + bot_name: "{name} ボット", + commented_time: "{time}にコメント", + and_more: "他 {count} 件", + no_upvotes_yet: "賛成票はまだありません", + no_downvotes_yet: "反対票はまだありません", + modules_count: "{count} 個のモジュール", + labels_count: "{count} 個のラベル", + page_not_found_alt: "ページが見つかりません", + something_went_wrong: "問題が発生しました。", + page_not_found_description: "お探しのページは存在しないか、移動されました。", + instance_failure_image_alt: "インスタンスの詳細を取得できません", + instance_failure_title: "インスタンスの詳細を取得できません。", + instance_failure_description: "インスタンスの詳細を読み込めませんでした。", + instance_failure_hint: "接続を確認して、もう一度お試しください。", + powered_by: "提供元", + sign_in_to_add_comment: "コメントを追加するにはサインインしてください", + link_copied: "リンクをコピーしました。", + work_item_link_copied: "作業項目のリンクをクリップボードにコピーしました。", + comment_post_error: "コメントを投稿できませんでした。もう一度お試しください。", + add_comment: "コメントを追加", + public_board_not_found: "公開ボードが存在しません。URL を確認してください。", + no_work_items_found: "作業項目が見つかりません", + error_title: "問題が発生しました。", + refresh: "再読み込み", + forum: "フォーラム", + not_found_title: "うまくいきませんでした", + user_already_logged_in: "ユーザーはすでにログインしています", + logged_in_title: "あと 1 ステップです。", + by_creating_account: "アカウントを作成すると", + by_signing_in: "サインインすると", + you_agree_to_our: "以下に同意したことになります", + terms_of_service: "利用規約", + and: "および", + privacy_policy: "プライバシーポリシー", + sign_up: "登録", + sign_in: "サインイン", + retry: "再試行", + view_less: "少なく表示", + view_all: "すべて表示", + no_matches_found: "一致するものが見つかりません", + no_date: "日付なし", + no_cycle: "サイクルなし", + no_modules: "モジュールなし", + no_assignees: "担当者なし", + no_labels: "ラベルなし", + user: "ユーザー", + }, + }, } as const; diff --git a/packages/i18n/src/locales/ko/translations.ts b/packages/i18n/src/locales/ko/translations.ts index cf7e68d36a2..48962640f6f 100644 --- a/packages/i18n/src/locales/ko/translations.ts +++ b/packages/i18n/src/locales/ko/translations.ts @@ -2667,4 +2667,310 @@ export default { close_button: "네비게이션 패널 닫기", outline_floating_button: "개요 열기", }, + localized_ui: { + not_found: { + alt: "404 - 페이지를 찾을 수 없습니다", + title: "문제가 발생했습니다.", + description: + "찾고 있는 페이지를 찾을 수 없습니다. 삭제되었거나 이름이 변경되었거나 일시적으로 사용할 수 없을 수 있습니다.", + go_to_home: "홈으로 이동", + }, + workspace_views: { + page_title: "{workspaceName} - 모든 보기", + }, + projects_empty_state: { + no_projects_yet: "아직 프로젝트가 없습니다", + description: "프로젝트는 목표 중심 업무의 기반입니다. 팀, 작업, 업무 완료에 필요한 모든 것을 관리할 수 있습니다.", + learn_more: "프로젝트 자세히 알아보기", + start_first_project: "첫 프로젝트 시작", + }, + profile_activity: { + page_title: "프로필 - 활동", + }, + pages: { + not_found_title: "페이지를 찾을 수 없습니다", + not_found_description: "접근하려는 페이지가 존재하지 않거나 볼 권한이 없습니다.", + view_other_pages: "다른 페이지 보기", + }, + workspace_access: { + not_found_title: "워크스페이스를 찾을 수 없습니다", + not_found_description: + "이 URL에 해당하는 워크스페이스를 찾을 수 없습니다. 존재하지 않거나 볼 권한이 없을 수 있습니다.", + visit_profile: "프로필 방문", + not_authorized_title: "권한이 없습니다", + not_authorized_description: + "이 워크스페이스의 멤버가 아닙니다. 워크스페이스 관리자에게 초대를 요청하거나 대기 중인 초대를 확인하세요.", + check_pending_invites: "보류 중인 초대 확인", + }, + editor: { + url: "URL", + enter_or_paste_url: "URL을 입력하거나 붙여넣으세요.", + text: "텍스트", + enter_text_to_display: "표시할 텍스트를 입력하세요.", + remove_link: "링크 삭제", + edit_link: "링크 수정", + color: "색상", + text_colors: "텍스트 색상", + background_colors: "배경색", + link: "링크", + enter_or_paste_link: "링크 입력 또는 붙여넣기", + please_enter_valid_url: "유효한 URL를 입력하세요.", + delete: "삭제", + duplicate: "복제하다", + multiple: "여러 개", + loading: "로드 중", + no_results: "결과 없음", + copy_code: "코드 복사", + add_an_image: "이미지 추가", + error_loading_image: "이미지를 로드하는 중에 오류가 발생했습니다.", + uploading: "업로드 중", + drop_image_here: "여기에 이미지를 드롭하세요.", + retry_duplication: "복제 재시도", + retry: "다시 해 보다", + no_emojis_found: "이모티콘을 찾을 수 없습니다.", + fullscreen_image_viewer: "전체 화면 이미지 뷰어", + close_image_viewer: "이미지 뷰어 닫기", + zoom_out: "축소", + zoom_in: "확대", + download_image: "이미지 다운로드", + open_image_in_new_tab: "새 탭에서 이미지 열기", + view_in_full_screen: "전체 화면으로 보기", + view_image_in_full_screen: "전체 화면으로 이미지 보기", + align: "정렬", + download: "다운로드", + clear_contents: "내용 지우기", + insert_above: "위에 삽입", + insert_below: "아래에 삽입", + insert_left: "왼쪽에 삽입", + insert_right: "오른쪽에 삽입", + header_row: "헤더 행", + header_column: "헤더 열", + alignment: { + left: "왼쪽", + center: "가운데", + right: "오른쪽", + }, + menu_items: { + text: "텍스트", + h1: "제목 1", + h2: "제목 2", + h3: "제목 3", + h4: "제목 4", + h5: "제목 5", + h6: "제목 6", + "bulleted-list": "글머리 기호 목록", + "numbered-list": "번호가 매겨진 목록", + "to-do-list": "할 일 목록", + quote: "인용하다", + code: "코드", + table: "표", + image: "이미지", + divider: "구분선", + link: "링크", + bold: "굵게", + italic: "이탤릭체", + underline: "밑줄", + strikethrough: "취소선", + "text-color": "텍스트 색상", + "background-color": "배경색", + "text-align": "텍스트 정렬", + }, + }, + workspace_invitation: { + invitation_not_found: "초대장을 찾을 수 없습니다.", + invited_to_workspace: "{workspaceName}에 초대되었습니다", + description: + "작업 공간은 Plane 계정에서 프로젝트를 생성하고, 작업 항목에 대해 공동 작업하고, 다양한 작업 흐름을 구성하는 곳입니다.", + accept: "수용하다", + ignore: "무시하다", + already_member: "귀하는 이미 {workspaceName}의 회원입니다.", + continue_to_home: "집으로 계속", + inactive_title: "이 초대 링크는 더 이상 활성화되지 않습니다.", + empty_project_link: "또는 빈 프로젝트에서 시작", + sign_in_to_continue: "계속하려면 로그인하세요.", + star_on_github: "GitHub에 별표를 표시해 주세요.", + join_community: "활동적인 제작자 커뮤니티에 참여하세요", + }, + space_auth: { + email: "이메일", + email_invalid: "이메일이 잘못되었습니다", + clear_email: "이메일 지우기", + password: "비밀번호", + set_password: "비밀번호를 설정하세요", + enter_password: "비밀번호를 입력하세요", + confirm_password: "비밀번호 확인", + passwords_dont_match: "비밀번호가 일치하지 않습니다.", + continue: "계속하다", + go_to_workspace: "작업공간으로 이동", + sign_in_with_unique_code: "고유 코드로 로그인", + create_account: "계정 만들기", + unique_code: "고유 코드", + paste_code_sent: "이메일로 전송된 코드를 붙여넣으세요.", + resend_in: "{seconds}s 후에 재전송", + requesting_new_code: "새 코드 요청 중", + resend: "재전송", + sending_code: "코드 전송 중", + }, + onboarding: { + create_profile_title: "프로필을 만드세요.", + create_profile_description: "이것이 Plane에 나타나는 모습입니다.", + change_image: "이미지 변경", + upload_image: "이미지 업로드", + name: "이름", + name_required: "이름은 필수입니다", + name_within_50: "이름은 50자 이내로 입력해야 합니다.", + enter_full_name: "이름을 입력하세요", + set_password: "비밀번호를 설정하세요", + optional: "선택 과목", + passwords_do_not_match: "비밀번호가 일치하지 않습니다.", + passwords_match: "비밀번호가 일치합니다.", + continue: "계속하다", + invite_team_title: "팀원을 초대하세요", + invite_team_description: + "Plane에서의 작업은 팀과 함께 가장 잘 이루어집니다. 지금 Plane를 활용해 잠재력을 발휘하도록 초대하세요.", + invalid_email: "이메일 주소가 아닌 것 같습니다.", + success: "성공!", + invitations_sent: "초대장이 성공적으로 전송되었습니다.", + error: "오류!", + add_another: "다른 것을 추가하세요", + do_later: "나중에 할게요", + join_invites_title: "초대에 참여하거나 작업 공간 만들기", + unified_description: "모든 작업이 통합됩니다.", + create_new_workspace: "새 작업공간 만들기", + no_invitations_found: "초대장을 찾을 수 없습니다.", + you_are_invited: "당신을 초대합니다!", + accept_invites: "팀과 협력하려면 초대를 수락하세요.", + continue_to_workspace: "계속해서 작업공간으로 이동", + or: "또는", + create_own_workspace: "나만의 작업 공간 만들기", + workspace_creation_disabled: + "워크스페이스에 대한 초대가 없는 것 같고 인스턴스 관리자가 새 워크스페이스 생성을 제한했습니다. 먼저 워크스페이스 소유자나 관리자에게 워크스페이스에 초대해 달라고 요청한 후 이 화면으로 돌아와 참여하세요.", + create_workspace_title: "작업 공간 만들기", + enter_workspace_name: "작업공간 이름을 입력하세요.", + join_existing_workspace: "기존 작업공간에 참여", + profile_setup_completed: "프로필 설정이 완료되었습니다.", + profile_setup_failed: "프로필 설정에 실패했습니다.", + usecase_title: "Plane를 어떻게 사용할 계획인가요?", + usecase_description: "귀하의 경험을 개인화할 수 있도록 하나 이상의 옵션을 선택하십시오.", + select_one_or_more: "하나 이상 선택", + select_at_least_one: "옵션을 하나 이상 선택하세요.", + skip: "건너뛰다", + }, + inbox: { + duplicate_issues_found: "중복 작업 항목 {count}개 발견", + description_versions: { + intake_form_user: "접수 양식 사용자", + }, + errors: { + asset_upload_failed: "자산 업로드에 실패했습니다. 나중에 다시 시도해 주세요.", + asset_duplication_failed: "자산 복제에 실패했습니다. 나중에 다시 시도해 주세요.", + permission_denied: "허가가 거부되었습니다", + mark_duplicate_permission: "프로젝트 관리자만 작업 항목을 중복으로 표시할 수 있습니다.", + mark_duplicate_permission_plural: "프로젝트 관리자만 작업 항목을 중복으로 표시할 수 있습니다.", + }, + filters: { + created_date: "생성일", + updated_date: "업데이트된 날짜", + last_updated_date: "마지막 업데이트 날짜", + status: "상태", + work_item_status: "작업 항목 상태", + view_all: "모두 보기", + view_less: "간략히 보기", + date_options: { + today: "오늘", + yesterday: "어제", + last_7_days: "지난 7일", + last_30_days: "지난 30일", + }, + date_operators: { + after: "후에", + before: "전에", + }, + }, + navigation: { + previous_work_item: "이전 작업 항목", + next_work_item: "다음 작업 항목", + }, + properties: { + duplicate_of: "중복 항목", + }, + select_duplicate: { + select_work_item: "작업 항목 선택", + }, + sidebar: { + label_count: "{count} 라벨", + }, + toasts: { + editor_processing: "편집기가 아직 변경사항을 처리 중입니다. 계속하기 전에 잠시 기다려 주십시오.", + create_success: "작업 항목이 성공적으로 생성되었습니다.", + delete_failed: "작업 항목 삭제 실패", + update_failed: "작업 항목 업데이트 실패", + }, + }, + space_public: { + error_description_prefix: + "Plane이 충돌했습니다. 담당 엔지니어에게 알림이 전송되었습니다. 추가 세부 정보가 있으면 다음으로 보내 주세요", + error_description_middle: "또는 다음에서", + not_found_hint: "브라우저 주소 표시줄의 URL을 확인한 뒤 다시 시도하세요.", + logged_in_hint: "보려는 보기 또는 페이지의 공개 공유 URL이나 링크를 브라우저 주소 표시줄에 입력하세요.", + oauth_with_provider: "{provider}(으)로 {action}", + auth: { + sign_in_header: "투표하거나 댓글을 달려면 로그인하세요", + sign_in_subheader: "원하는 기능이 만들어지도록 의견을 보태세요.", + sign_up_header: "보고, 댓글을 달고, 더 많은 작업을 수행하세요", + sign_up_subheader: "Plane 작업 항목과 페이지를 사용하려면 가입하거나 로그인하세요.", + }, + peek: { + side: "사이드 피크", + modal: "모달", + full_screen: "전체 화면", + }, + bot_name: "{name} 봇", + commented_time: "{time}에 댓글 작성", + and_more: "외 {count}명", + no_upvotes_yet: "아직 찬성표가 없습니다", + no_downvotes_yet: "아직 반대표가 없습니다", + modules_count: "모듈 {count}개", + labels_count: "라벨 {count}개", + page_not_found_alt: "페이지를 찾을 수 없음", + something_went_wrong: "문제가 발생했습니다.", + page_not_found_description: "찾고 있는 페이지가 없거나 이동되었습니다.", + instance_failure_image_alt: "인스턴스 세부 정보를 가져올 수 없음", + instance_failure_title: "인스턴스 세부 정보를 가져올 수 없습니다.", + instance_failure_description: "인스턴스 세부 정보를 로드할 수 없습니다.", + instance_failure_hint: "연결을 확인한 뒤 다시 시도하세요.", + powered_by: "제공", + sign_in_to_add_comment: "댓글을 추가하려면 로그인하세요", + link_copied: "링크가 복사되었습니다!", + work_item_link_copied: "작업 항목 링크가 클립보드에 복사되었습니다.", + comment_post_error: "댓글을 게시하지 못했습니다. 다시 시도하세요.", + add_comment: "댓글 추가", + public_board_not_found: "공개 보드가 없습니다. URL을 확인하세요.", + no_work_items_found: "작업 항목을 찾을 수 없습니다", + error_title: "문제가 발생했습니다.", + refresh: "새로 고침", + forum: "포럼", + not_found_title: "작동하지 않았습니다", + user_already_logged_in: "이미 로그인한 사용자입니다", + logged_in_title: "좋습니다! 한 단계만 더 남았습니다.", + by_creating_account: "계정을 만들면", + by_signing_in: "로그인하면", + you_agree_to_our: "다음에 동의하게 됩니다", + terms_of_service: "서비스 약관", + and: "및", + privacy_policy: "개인정보 처리방침", + sign_up: "가입", + sign_in: "로그인", + retry: "다시 시도", + view_less: "간단히 보기", + view_all: "모두 보기", + no_matches_found: "일치하는 항목이 없습니다", + no_date: "날짜 없음", + no_cycle: "사이클 없음", + no_modules: "모듈 없음", + no_assignees: "담당자 없음", + no_labels: "라벨 없음", + user: "사용자", + }, + }, } as const; diff --git a/packages/i18n/src/locales/pl/translations.ts b/packages/i18n/src/locales/pl/translations.ts index 225859e9635..99a19dc38c9 100644 --- a/packages/i18n/src/locales/pl/translations.ts +++ b/packages/i18n/src/locales/pl/translations.ts @@ -2660,4 +2660,313 @@ export default { close_button: "Zamknij panel nawigacji", outline_floating_button: "Otwórz konspekt", }, + localized_ui: { + not_found: { + alt: "404 - Nie znaleziono strony", + title: "Ups! Coś poszło nie tak.", + description: + "Nie można znaleźć strony, której szukasz. Mogła zostać usunięta, zmieniono jej nazwę albo jest tymczasowo niedostępna.", + go_to_home: "Przejdź do strony głównej", + }, + workspace_views: { + page_title: "{workspaceName} - Wszystkie widoki", + }, + projects_empty_state: { + no_projects_yet: "Brak projektów", + description: + "Projekty są podstawą pracy ukierunkowanej na cele. Pozwalają zarządzać zespołami, zadaniami i wszystkim, czego potrzebujesz, aby wykonać pracę.", + learn_more: "Dowiedz się więcej o projektach", + start_first_project: "Rozpocznij pierwszy projekt", + }, + profile_activity: { + page_title: "Profil - Aktywność", + }, + pages: { + not_found_title: "Nie znaleziono strony", + not_found_description: + "Strona, do której próbujesz uzyskać dostęp, nie istnieje albo nie masz uprawnień do jej wyświetlenia.", + view_other_pages: "Wyświetl inne strony", + }, + workspace_access: { + not_found_title: "Nie znaleziono obszaru roboczego", + not_found_description: + "Nie znaleziono obszaru roboczego dla tego adresu URL. Może nie istnieć albo nie masz uprawnień do jego wyświetlenia.", + visit_profile: "Odwiedź profil", + not_authorized_title: "Brak autoryzacji!", + not_authorized_description: + "Nie jesteś członkiem tego obszaru roboczego. Skontaktuj się z administratorem obszaru roboczego, aby otrzymać zaproszenie, albo sprawdź oczekujące zaproszenia.", + check_pending_invites: "Sprawdź oczekujące zaproszenia", + }, + editor: { + url: "URL", + enter_or_paste_url: "Wpisz lub wklej adres URL", + text: "Tekst", + enter_text_to_display: "Wprowadź tekst do wyświetlenia", + remove_link: "Usuń link", + edit_link: "Edytuj link", + color: "Kolor", + text_colors: "Kolory tekstu", + background_colors: "Kolory tła", + link: "Link", + enter_or_paste_link: "Wpisz lub wklej link", + please_enter_valid_url: "Proszę wprowadzić prawidłowy URL", + delete: "Usuń", + duplicate: "Duplikat", + multiple: "Wiele", + loading: "Ładowanie", + no_results: "Brak wyników", + copy_code: "Skopiuj kod", + add_an_image: "Dodaj obraz", + error_loading_image: "Błąd ładowania obrazu", + uploading: "Przesyłanie", + drop_image_here: "Upuść obraz tutaj", + retry_duplication: "Ponów próbę duplikacji", + retry: "Spróbuj ponownie", + no_emojis_found: "Nie znaleziono emoji", + fullscreen_image_viewer: "Pełnoekranowa przeglądarka obrazów", + close_image_viewer: "Zamknij przeglądarkę zdjęć", + zoom_out: "Pomniejsz", + zoom_in: "Powiększ", + download_image: "Pobierz obraz", + open_image_in_new_tab: "Otwórz obraz w nowej karcie", + view_in_full_screen: "Wyświetl na pełnym ekranie", + view_image_in_full_screen: "Wyświetl obraz na pełnym ekranie", + align: "Wyrównaj", + download: "Pobierz", + clear_contents: "Wyczyść zawartość", + insert_above: "Wstaw powyżej", + insert_below: "Wstaw poniżej", + insert_left: "Wstaw lewy", + insert_right: "Wstaw po prawej", + header_row: "Wiersz nagłówka", + header_column: "Kolumna nagłówka", + alignment: { + left: "Lewy", + center: "Centrum", + right: "Do prawej", + }, + menu_items: { + text: "Tekst", + h1: "Nagłówek 1", + h2: "Nagłówek 2", + h3: "Nagłówek 3", + h4: "Nagłówek 4", + h5: "Nagłówek 5", + h6: "Nagłówek 6", + "bulleted-list": "Lista punktowana", + "numbered-list": "Lista numerowana", + "to-do-list": "Lista rzeczy do zrobienia", + quote: "Cytat", + code: "Kod", + table: "Tabela", + image: "Obraz", + divider: "Rozdzielacz", + link: "Link", + bold: "Pogrubiony", + italic: "Kursywa", + underline: "Podkreślenie", + strikethrough: "Przekreślenie", + "text-color": "Kolor tekstu", + "background-color": "Kolor tła", + "text-align": "Wyrównaj tekst", + }, + }, + workspace_invitation: { + invitation_not_found: "Nie znaleziono zaproszenia", + invited_to_workspace: "Zostałeś zaproszony do {workspaceName}", + description: + "Twój obszar roboczy to miejsce, w którym będziesz tworzyć projekty, współpracować nad elementami pracy i organizować różne strumienie pracy na swoim koncie Plane.", + accept: "Przyjąć", + ignore: "Ignorować", + already_member: "Jesteś już członkiem {workspaceName}", + continue_to_home: "Przejdź do strony głównej", + inactive_title: "Ten link z zaproszeniem nie jest już aktywny.", + empty_project_link: "Lub zacznij od pustego projektu", + sign_in_to_continue: "Zaloguj się, aby kontynuować", + star_on_github: "Oznacz nas na GitHub", + join_community: "Dołącz do naszej społeczności aktywnych twórców", + }, + space_auth: { + email: "E-mail", + email_invalid: "Adres e-mail jest nieprawidłowy", + clear_email: "Wyczyść e-mail", + password: "Hasło", + set_password: "Ustaw hasło", + enter_password: "Wprowadź hasło", + confirm_password: "Potwierdź hasło", + passwords_dont_match: "Hasła nie pasują", + continue: "Kontynuować", + go_to_workspace: "Przejdź do obszaru roboczego", + sign_in_with_unique_code: "Zaloguj się za pomocą unikalnego kodu", + create_account: "Utwórz konto", + unique_code: "Unikalny kod", + paste_code_sent: "Wklej kod przesłany na Twój adres e-mail", + resend_in: "Wyślij ponownie za {seconds}s", + requesting_new_code: "Prośba o nowy kod", + resend: "Wyślij ponownie", + sending_code: "Wysyłanie kodu", + }, + onboarding: { + create_profile_title: "Utwórz swój profil.", + create_profile_description: "Tak będziesz wyglądać w Plane.", + change_image: "Zmień obraz", + upload_image: "Prześlij obraz", + name: "Nazwa", + name_required: "Imię i nazwisko jest wymagane", + name_within_50: "Nazwa musi zawierać maksymalnie 50 znaków.", + enter_full_name: "Wpisz swoje pełne imię i nazwisko", + set_password: "Ustaw hasło", + optional: "Opcjonalnie", + passwords_do_not_match: "Hasła nie pasują", + passwords_match: "Hasła się zgadzają", + continue: "Kontynuować", + invite_team_title: "Zaproś swoich kolegów z drużyny", + invite_team_description: + "Praca w Plane najlepiej przebiega z Twoim zespołem. Zaproś ich teraz, aby wykorzystali cały potencjał Plane.", + invalid_email: "To nie wygląda na adres e-mail.", + success: "Sukces!", + invitations_sent: "Zaproszenia wysłane pomyślnie.", + error: "Błąd!", + add_another: "Dodaj kolejny", + do_later: "Zrobię to później", + join_invites_title: "Dołącz do zaproszeń lub utwórz obszar roboczy", + unified_description: "Cała Twoja praca — ujednolicona.", + create_new_workspace: "Utwórz nowy obszar roboczy", + no_invitations_found: "Nie znaleziono zaproszeń", + you_are_invited: "Zapraszamy!", + accept_invites: "Zaakceptuj zaproszenia do współpracy ze swoim zespołem.", + continue_to_workspace: "Przejdź do obszaru roboczego", + or: "Lub", + create_own_workspace: "Stwórz własną przestrzeń do pracy", + workspace_creation_disabled: + "Wygląda na to, że nie masz żadnych zaproszeń do obszaru roboczego, a administrator Twojej instancji ograniczył tworzenie nowych obszarów roboczych. Poproś właściciela lub administratora obszaru roboczego, aby najpierw zaprosił Cię do obszaru roboczego, a następnie wróć do tego ekranu, aby dołączyć.", + create_workspace_title: "Stwórz swoje miejsce do pracy", + enter_workspace_name: "Wprowadź nazwę obszaru roboczego", + join_existing_workspace: "Dołącz do istniejącego obszaru roboczego", + profile_setup_completed: "Konfiguracja profilu zakończona.", + profile_setup_failed: "Konfiguracja profilu nie powiodła się.", + usecase_title: "Jak planujesz używać Plane?", + usecase_description: "Wybierz jedną lub więcej opcji, abyśmy mogli spersonalizować Twoje doświadczenia.", + select_one_or_more: "Wybierz jeden lub więcej", + select_at_least_one: "Wybierz co najmniej jedną opcję.", + skip: "Pominąć", + }, + inbox: { + duplicate_issues_found: "Znaleziono {count} zduplikowanych elementów pracy", + description_versions: { + intake_form_user: "Użytkownik formularza przyjęcia", + }, + errors: { + asset_upload_failed: "Przesyłanie zasobu nie powiodło się. Spróbuj ponownie później.", + asset_duplication_failed: "Powielanie zasobów nie powiodło się. Spróbuj ponownie później.", + permission_denied: "Odmowa pozwolenia", + mark_duplicate_permission: "Tylko administratorzy projektu mogą oznaczać element pracy jako duplikat", + mark_duplicate_permission_plural: "Tylko administratorzy projektu mogą oznaczać elementy pracy jako duplikaty", + }, + filters: { + created_date: "Data utworzenia", + updated_date: "Zaktualizowana data", + last_updated_date: "Ostatnia aktualizacja", + status: "Status", + work_item_status: "Stan elementu pracy", + view_all: "Zobacz wszystkie", + view_less: "Zobacz mniej", + date_options: { + today: "Dzisiaj", + yesterday: "Wczoraj", + last_7_days: "Ostatnie 7 dni", + last_30_days: "Ostatnie 30 dni", + }, + date_operators: { + after: "Po", + before: "Zanim", + }, + }, + navigation: { + previous_work_item: "Poprzedni element pracy", + next_work_item: "Następny element pracy", + }, + properties: { + duplicate_of: "Duplikat elementu", + }, + select_duplicate: { + select_work_item: "Wybierz element pracy", + }, + sidebar: { + label_count: "Etykiety {count}", + }, + toasts: { + editor_processing: "Edytor nadal przetwarza zmiany. Proszę poczekać przed kontynuowaniem.", + create_success: "Element pracy został pomyślnie utworzony.", + delete_failed: "Nie udało się usunąć elementu roboczego", + update_failed: "Aktualizacja elementu roboczego nie powiodła się", + }, + }, + space_public: { + error_description_prefix: + "Plane uległ awarii. Nasi inżynierowie zostali powiadomieni. Jeśli masz więcej szczegółów, napisz na", + error_description_middle: "lub na naszym", + not_found_hint: "Sprawdź URL w pasku adresu przeglądarki i spróbuj ponownie.", + logged_in_hint: + "Wprowadź w pasku adresu przeglądarki publiczny URL udostępnienia lub link do widoku albo strony, którą chcesz zobaczyć.", + oauth_with_provider: "{action} przez {provider}", + auth: { + sign_in_header: "Zaloguj się, aby głosować lub komentować", + sign_in_subheader: "Pomóż przesuwać do przodu funkcje, które chcesz zobaczyć.", + sign_up_header: "Przeglądaj, komentuj i rób więcej", + sign_up_subheader: "Zarejestruj się lub zaloguj, aby pracować z elementami pracy i stronami Plane.", + }, + peek: { + side: "Podgląd boczny", + modal: "Okno modalne", + full_screen: "Pełny ekran", + }, + bot_name: "Bot {name}", + commented_time: "skomentowano {time}", + and_more: "i jeszcze {count}", + no_upvotes_yet: "Brak głosów za", + no_downvotes_yet: "Brak głosów przeciw", + modules_count: "{count} modułów", + labels_count: "{count} etykiet", + page_not_found_alt: "Strona nie znaleziona", + something_went_wrong: "Ups! Coś poszło nie tak.", + page_not_found_description: "Strona, której szukasz, nie istnieje lub została przeniesiona.", + instance_failure_image_alt: "Nie można pobrać szczegółów instancji", + instance_failure_title: "Nie można pobrać szczegółów instancji.", + instance_failure_description: "Nie mogliśmy załadować szczegółów Twojej instancji.", + instance_failure_hint: "Sprawdź połączenie i spróbuj ponownie.", + powered_by: "Obsługiwane przez", + sign_in_to_add_comment: "Zaloguj się, aby dodać komentarz", + link_copied: "Link skopiowany!", + work_item_link_copied: "Link do elementu pracy skopiowany do schowka.", + comment_post_error: "Nie udało się opublikować komentarza. Spróbuj ponownie.", + add_comment: "Dodaj komentarz", + public_board_not_found: "Publiczna tablica nie istnieje. Sprawdź URL.", + no_work_items_found: "Nie znaleziono elementów pracy", + error_title: "Ups! To nie wygląda dobrze.", + refresh: "Odśwież", + forum: "Forum", + not_found_title: "To nie zadziałało", + user_already_logged_in: "Użytkownik jest już zalogowany", + logged_in_title: "Świetnie! Jeszcze jeden krok.", + by_creating_account: "Tworząc konto", + by_signing_in: "Logując się", + you_agree_to_our: "akceptujesz nasze", + terms_of_service: "Warunki korzystania", + and: "oraz", + privacy_policy: "Politykę prywatności", + sign_up: "Zarejestruj się", + sign_in: "Zaloguj się", + retry: "Spróbuj ponownie", + view_less: "Pokaż mniej", + view_all: "Pokaż wszystko", + no_matches_found: "Nie znaleziono dopasowań", + no_date: "Brak daty", + no_cycle: "Brak cyklu", + no_modules: "Brak modułów", + no_assignees: "Brak przypisanych", + no_labels: "Brak etykiet", + user: "Użytkownik", + }, + }, } as const; diff --git a/packages/i18n/src/locales/pt-BR/translations.ts b/packages/i18n/src/locales/pt-BR/translations.ts index 5282692a17b..0620367153e 100644 --- a/packages/i18n/src/locales/pt-BR/translations.ts +++ b/packages/i18n/src/locales/pt-BR/translations.ts @@ -2705,4 +2705,315 @@ export default { close_button: "Fechar painel de navegação", outline_floating_button: "Abrir estrutura", }, + localized_ui: { + not_found: { + alt: "404 - Página não encontrada", + title: "Ops! Algo deu errado.", + description: + "A página que você está procurando não foi encontrada. Ela pode ter sido removida, renomeada ou estar temporariamente indisponível.", + go_to_home: "Ir para o início", + }, + workspace_views: { + page_title: "{workspaceName} - Todas as visualizações", + }, + projects_empty_state: { + no_projects_yet: "Ainda não há projetos", + description: + "Os projetos são a base do trabalho orientado por objetivos. Eles permitem gerenciar equipes, tarefas e tudo o que você precisa para concluir o trabalho.", + learn_more: "Saiba mais sobre projetos", + start_first_project: "Comece seu primeiro projeto", + }, + profile_activity: { + page_title: "Perfil - Atividade", + }, + pages: { + not_found_title: "Página não encontrada", + not_found_description: + "A página que você está tentando acessar não existe ou você não tem permissão para visualizá-la.", + view_other_pages: "Ver outras Páginas", + }, + workspace_access: { + not_found_title: "Workspace não encontrado", + not_found_description: + "Nenhum espaço de trabalho foi encontrado para este URL. Ele pode não existir ou você pode não ter permissão para visualizá-lo.", + visit_profile: "Visitar perfil", + not_authorized_title: "Não autorizado!", + not_authorized_description: + "Você não é membro deste espaço de trabalho. Entre em contato com o administrador do espaço de trabalho para receber um convite ou verifique seus convites pendentes.", + check_pending_invites: "Verificar convites pendentes", + }, + editor: { + url: "URL", + enter_or_paste_url: "Insira ou cole o URL", + text: "Texto", + enter_text_to_display: "Digite o texto para exibir", + remove_link: "Remover link", + edit_link: "Editar link", + color: "Cor", + text_colors: "Cores do texto", + background_colors: "Cores de fundo", + link: "Link", + enter_or_paste_link: "Insira ou cole o link", + please_enter_valid_url: "Insira um URL válido", + delete: "Excluir", + duplicate: "Duplicado", + multiple: "Múltiplo", + loading: "Carregando", + no_results: "Nenhum resultado", + copy_code: "Copiar código", + add_an_image: "Adicione uma imagem", + error_loading_image: "Erro ao carregar a imagem", + uploading: "Enviando", + drop_image_here: "Solte a imagem aqui", + retry_duplication: "Tentar novamente a duplicação", + retry: "Tentar novamente", + no_emojis_found: "Nenhum emoji encontrado", + fullscreen_image_viewer: "Visualizador de imagens em tela cheia", + close_image_viewer: "Fechar visualizador de imagens", + zoom_out: "Diminuir zoom", + zoom_in: "Ampliar", + download_image: "Baixar imagem", + open_image_in_new_tab: "Abrir imagem em nova aba", + view_in_full_screen: "Ver em tela cheia", + view_image_in_full_screen: "Ver imagem em tela cheia", + align: "Alinhar", + download: "Baixar", + clear_contents: "Limpar conteúdo", + insert_above: "Inserir acima", + insert_below: "Inserir abaixo", + insert_left: "Inserir à esquerda", + insert_right: "Inserir à direita", + header_row: "Linha de cabeçalho", + header_column: "Coluna de cabeçalho", + alignment: { + left: "Esquerda", + center: "Centro", + right: "Direita", + }, + menu_items: { + text: "Texto", + h1: "Título 1", + h2: "Título 2", + h3: "Título 3", + h4: "Título 4", + h5: "Título 5", + h6: "Título 6", + "bulleted-list": "Lista com marcadores", + "numbered-list": "Lista numerada", + "to-do-list": "Lista de tarefas", + quote: "Citar", + code: "Código", + table: "Tabela", + image: "Imagem", + divider: "Divisor", + link: "Link", + bold: "Negrito", + italic: "Itálico", + underline: "Sublinhado", + strikethrough: "Tachado", + "text-color": "Cor do texto", + "background-color": "Cor de fundo", + "text-align": "Alinhamento de texto", + }, + }, + workspace_invitation: { + invitation_not_found: "Convite não encontrado", + invited_to_workspace: "Você foi convidado para {workspaceName}", + description: + "Seu espaço de trabalho é onde você criará projetos, colaborará em seus itens de trabalho e organizará diferentes fluxos de trabalho em sua conta Plane.", + accept: "Aceitar", + ignore: "Ignorar", + already_member: "Você já é membro do {workspaceName}", + continue_to_home: "Continuar para casa", + inactive_title: "Este link de convite não está mais ativo.", + empty_project_link: "Ou comece com um projeto vazio", + sign_in_to_continue: "Faça login para continuar", + star_on_github: "Marque-nos no GitHub", + join_community: "Junte-se à nossa comunidade de criadores ativos", + }, + space_auth: { + email: "E-mail", + email_invalid: "O e-mail é inválido", + clear_email: "Limpar e-mail", + password: "Senha", + set_password: "Defina uma senha", + enter_password: "Digite a senha", + confirm_password: "Confirme sua senha", + passwords_dont_match: "As senhas não coincidem", + continue: "Continuar", + go_to_workspace: "Ir para o espaço de trabalho", + sign_in_with_unique_code: "Faça login com código exclusivo", + create_account: "Criar uma conta", + unique_code: "Código exclusivo", + paste_code_sent: "Cole o código enviado para seu e-mail", + resend_in: "Reenviar em {seconds}s", + requesting_new_code: "Solicitando novo código", + resend: "Reenviar", + sending_code: "Enviando código", + }, + onboarding: { + create_profile_title: "Crie seu perfil.", + create_profile_description: "É assim que você aparecerá no Plane.", + change_image: "Alterar imagem", + upload_image: "Carregar imagem", + name: "Nome", + name_required: "O nome é obrigatório", + name_within_50: "O nome deve ter até 50 caracteres.", + enter_full_name: "Digite seu nome completo", + set_password: "Defina uma senha", + optional: "Opcional", + passwords_do_not_match: "As senhas não coincidem", + passwords_match: "Correspondência de senhas", + continue: "Continuar", + invite_team_title: "Convide seus companheiros de equipe", + invite_team_description: + "O trabalho no Plane acontece melhor com sua equipe. Convide-os agora a usar o Plane em todo o seu potencial.", + invalid_email: "Isso não se parece com um endereço de e-mail.", + success: "Sucesso!", + invitations_sent: "Convites enviados com sucesso.", + error: "Erro!", + add_another: "Adicionar outro", + do_later: "Eu farei isso mais tarde", + join_invites_title: "Participe de convites ou crie um espaço de trabalho", + unified_description: "Todo o seu trabalho — unificado.", + create_new_workspace: "Criar novo espaço de trabalho", + no_invitations_found: "Nenhum convite encontrado", + you_are_invited: "Você está convidado!", + accept_invites: "Aceite os convites para colaborar com sua equipe.", + continue_to_workspace: "Continuar para o espaço de trabalho", + or: "ou", + create_own_workspace: "Crie seu próprio espaço de trabalho", + workspace_creation_disabled: + "Parece que você não tem nenhum convite para um espaço de trabalho e o administrador da sua instância restringiu a criação de novos espaços de trabalho. Peça a um proprietário ou administrador do espaço de trabalho para convidá-lo primeiro para um espaço de trabalho e volte a esta tela para ingressar.", + create_workspace_title: "Crie seu espaço de trabalho", + enter_workspace_name: "Insira o nome do espaço de trabalho", + join_existing_workspace: "Junte-se ao espaço de trabalho existente", + profile_setup_completed: "Configuração do perfil concluída.", + profile_setup_failed: "Falha na configuração do perfil.", + usecase_title: "Como você planeja usar o Plane?", + usecase_description: "Selecione uma ou mais opções para que possamos personalizar sua experiência.", + select_one_or_more: "Selecione um ou mais", + select_at_least_one: "Selecione pelo menos uma opção.", + skip: "Pular", + }, + inbox: { + duplicate_issues_found: + "{count, plural, one {# item de trabalho duplicado encontrado} other {# itens de trabalho duplicados encontrados}}", + description_versions: { + intake_form_user: "Usuário do formulário de admissão", + }, + errors: { + asset_upload_failed: "Falha no upload do recurso. Por favor, tente novamente mais tarde.", + asset_duplication_failed: "Falha na duplicação de recursos. Por favor, tente novamente mais tarde.", + permission_denied: "Permissão negada", + mark_duplicate_permission: "Somente administradores de projeto podem marcar itens de trabalho como duplicados", + mark_duplicate_permission_plural: + "Somente administradores de projeto podem marcar itens de trabalho como duplicados", + }, + filters: { + created_date: "Data de criação", + updated_date: "Data atualizada", + last_updated_date: "Data da última atualização", + status: "Status", + work_item_status: "Status do item de trabalho", + view_all: "Ver tudo", + view_less: "Ver menos", + date_options: { + today: "Hoje", + yesterday: "Ontem", + last_7_days: "Últimos 7 dias", + last_30_days: "Últimos 30 dias", + }, + date_operators: { + after: "Depois", + before: "Antes", + }, + }, + navigation: { + previous_work_item: "Item de trabalho anterior", + next_work_item: "Próximo item de trabalho", + }, + properties: { + duplicate_of: "Duplicado de", + }, + select_duplicate: { + select_work_item: "Selecione o item de trabalho", + }, + sidebar: { + label_count: "Etiquetas {count}", + }, + toasts: { + editor_processing: "O editor ainda está processando as alterações. Aguarde antes de continuar.", + create_success: "Item de trabalho criado com sucesso.", + delete_failed: "Falha na exclusão do item de trabalho", + update_failed: "Falha na atualização do item de trabalho", + }, + }, + space_public: { + error_description_prefix: + "O Plane travou. Nossos engenheiros foram notificados. Se você tiver mais detalhes, escreva para", + error_description_middle: "ou em nosso", + not_found_hint: "Confira a URL na barra de endereços do navegador e tente novamente.", + logged_in_hint: + "Insira na barra de endereços do navegador a URL pública compartilhada ou o link da visualização ou Página que você quer ver.", + oauth_with_provider: "{action} com {provider}", + auth: { + sign_in_header: "Entre para votar ou comentar", + sign_in_subheader: "Ajude a impulsionar as funcionalidades que você quer ver criadas.", + sign_up_header: "Veja, comente e faça mais", + sign_up_subheader: "Cadastre-se ou entre para trabalhar com itens de trabalho e Páginas do Plane.", + }, + peek: { + side: "Visualização lateral", + modal: "Modal", + full_screen: "Tela cheia", + }, + bot_name: "Bot {name}", + commented_time: "comentou {time}", + and_more: "e mais {count}", + no_upvotes_yet: "Ainda sem votos positivos", + no_downvotes_yet: "Ainda sem votos negativos", + modules_count: "{count, plural, one {# módulo} other {# módulos}}", + labels_count: "{count, plural, one {# etiqueta} other {# etiquetas}}", + page_not_found_alt: "Página não encontrada", + something_went_wrong: "Ops! Algo deu errado.", + page_not_found_description: "A página que você está procurando não existe ou foi movida.", + instance_failure_image_alt: "Não foi possível buscar os detalhes da instância", + instance_failure_title: "Não foi possível buscar os detalhes da instância.", + instance_failure_description: "Não conseguimos carregar os detalhes da sua instância.", + instance_failure_hint: "Verifique sua conexão e tente novamente.", + powered_by: "Desenvolvido por", + sign_in_to_add_comment: "Entre para adicionar um comentário", + link_copied: "Link copiado!", + work_item_link_copied: "Link do item de trabalho copiado para a área de transferência.", + comment_post_error: "Falha ao publicar o comentário. Tente novamente.", + add_comment: "Adicionar comentário", + public_board_not_found: "O quadro público não existe. Verifique a URL.", + no_work_items_found: "Nenhum item de trabalho encontrado", + error_title: "Ops! Isso não parece bom.", + refresh: "Atualizar", + forum: "Fórum", + not_found_title: "Isso não funcionou", + user_already_logged_in: "Usuário já conectado", + logged_in_title: "Ótimo! Só falta mais uma etapa.", + by_creating_account: "Ao criar uma conta", + by_signing_in: "Ao entrar", + you_agree_to_our: "você concorda com nossos", + terms_of_service: "Termos de Serviço", + and: "e", + privacy_policy: "Política de Privacidade", + sign_up: "Cadastrar-se", + sign_in: "Entrar", + retry: "Tentar novamente", + view_less: "Ver menos", + view_all: "Ver tudo", + no_matches_found: "Nenhuma correspondência encontrada", + no_date: "Sem data", + no_cycle: "Sem ciclo", + no_modules: "Sem módulos", + no_assignees: "Sem responsáveis", + no_labels: "Sem etiquetas", + user: "Usuário", + }, + }, } as const; diff --git a/packages/i18n/src/locales/ro/translations.ts b/packages/i18n/src/locales/ro/translations.ts index 09a3312b6c8..46a2d2a5bd8 100644 --- a/packages/i18n/src/locales/ro/translations.ts +++ b/packages/i18n/src/locales/ro/translations.ts @@ -2698,4 +2698,312 @@ export default { close_button: "Închide panoul de navigare", outline_floating_button: "Deschide conturul", }, + localized_ui: { + not_found: { + alt: "404 - Pagina nu a fost găsită", + title: "Ups! Ceva nu a mers bine.", + description: + "Ne pare rău, pagina pe care o cauți nu a fost găsită. Este posibil să fi fost eliminată, redenumită sau să fie temporar indisponibilă.", + go_to_home: "Mergi la pagina principală", + }, + workspace_views: { + page_title: "{workspaceName} - Toate vizualizările", + }, + projects_empty_state: { + no_projects_yet: "Încă nu există proiecte", + description: + "Proiectele sunt baza muncii orientate spre obiective. Te ajută să gestionezi echipe, sarcini și tot ce ai nevoie pentru a duce lucrurile la bun sfârșit.", + learn_more: "Află mai multe despre proiecte", + start_first_project: "Începe primul proiect", + }, + profile_activity: { + page_title: "Profil - Activitate", + }, + pages: { + not_found_title: "Pagina nu a fost găsită", + not_found_description: "Pagina pe care încerci să o accesezi nu există sau nu ai permisiunea să o vizualizezi.", + view_other_pages: "Vezi alte pagini", + }, + workspace_access: { + not_found_title: "Spațiul de lucru nu a fost găsit", + not_found_description: + "Nu a fost găsit niciun spațiu de lucru pentru acest URL. Este posibil să nu existe sau să nu ai permisiunea să îl vizualizezi.", + visit_profile: "Vizitează profilul", + not_authorized_title: "Neautorizat!", + not_authorized_description: + "Nu ești membru al acestui spațiu de lucru. Contactează administratorul spațiului de lucru pentru o invitație sau verifică invitațiile în așteptare.", + check_pending_invites: "Verifică invitațiile în așteptare", + }, + editor: { + url: "URL", + enter_or_paste_url: "Introduceți sau inserați adresa URL", + text: "Text", + enter_text_to_display: "Introduceți textul de afișat", + remove_link: "Eliminați linkul", + edit_link: "Editați linkul", + color: "Culoare", + text_colors: "Culorile textului", + background_colors: "Culori de fundal", + link: "Link", + enter_or_paste_link: "Introduceți sau inserați linkul", + please_enter_valid_url: "Vă rugăm să introduceți un URL valid", + delete: "Şterge", + duplicate: "Duplicat", + multiple: "Multiplu", + loading: "Încărcare", + no_results: "Niciun rezultat", + copy_code: "Copiați codul", + add_an_image: "Adăugați o imagine", + error_loading_image: "Eroare la încărcarea imaginii", + uploading: "Încărcare", + drop_image_here: "Pune imaginea aici", + retry_duplication: "Reîncercați duplicarea", + retry: "Reîncercați", + no_emojis_found: "Nu s-au găsit emoji", + fullscreen_image_viewer: "Vizualizator de imagini pe ecran complet", + close_image_viewer: "Închideți vizualizatorul de imagini", + zoom_out: "Micșorați", + zoom_in: "Măriți", + download_image: "Descărcați imaginea", + open_image_in_new_tab: "Deschide imaginea într-o filă nouă", + view_in_full_screen: "Vizualizați pe ecran complet", + view_image_in_full_screen: "Vizualizați imaginea pe tot ecranul", + align: "Alinia", + download: "Descărcați", + clear_contents: "Șterge conținutul", + insert_above: "Introduceți mai sus", + insert_below: "Inserați mai jos", + insert_left: "Inserați stânga", + insert_right: "Inserați dreapta", + header_row: "Rând antet", + header_column: "Coloana antet", + alignment: { + left: "Stânga", + center: "Centru", + right: "Dreapta", + }, + menu_items: { + text: "Text", + h1: "Titlul 1", + h2: "Titlul 2", + h3: "Titlul 3", + h4: "Titlul 4", + h5: "Titlul 5", + h6: "Titlul 6", + "bulleted-list": "Lista cu marcatori", + "numbered-list": "Lista numerotata", + "to-do-list": "Lista de lucruri de făcut", + quote: "Citat", + code: "Cod", + table: "Tabel", + image: "Imagine", + divider: "Divizor", + link: "Link", + bold: "Aldin", + italic: "Cursiv", + underline: "Subliniat", + strikethrough: "Striat", + "text-color": "Culoarea textului", + "background-color": "Culoare de fundal", + "text-align": "Alinierea textului", + }, + }, + workspace_invitation: { + invitation_not_found: "Invitația nu a fost găsită", + invited_to_workspace: "Ai fost invitat la {workspaceName}", + description: + "Spațiul tău de lucru este locul în care vei crea proiecte, vei colabora la elementele tale de lucru și vei organiza diferite fluxuri de lucru în contul tău Plane.", + accept: "Accepta", + ignore: "Ignora", + already_member: "Sunteți deja membru {workspaceName}", + continue_to_home: "Continuați spre casă", + inactive_title: "Acest link de invitație nu mai este activ.", + empty_project_link: "Sau începeți de la un proiect gol", + sign_in_to_continue: "Conectați-vă pentru a continua", + star_on_github: "Afișează-ne pe GitHub", + join_community: "Alăturați-vă comunității noastre de creatori activi", + }, + space_auth: { + email: "E-mail", + email_invalid: "E-mailul este nevalid", + clear_email: "Ștergeți e-mailul", + password: "Parolă", + set_password: "Setați o parolă", + enter_password: "Introduceți parola", + confirm_password: "Confirmați parola", + passwords_dont_match: "Parolele nu se potrivesc", + continue: "Continua", + go_to_workspace: "Accesați spațiul de lucru", + sign_in_with_unique_code: "Conectați-vă cu codul unic", + create_account: "Creează cont", + unique_code: "Cod unic", + paste_code_sent: "Lipiți codul trimis pe e-mailul dvs", + resend_in: "Retrimiteți în {seconds}s", + requesting_new_code: "Se solicită cod nou", + resend: "Retrimiteți", + sending_code: "Se trimite cod", + }, + onboarding: { + create_profile_title: "Creează-ți profilul.", + create_profile_description: "Așa vei apărea în Plane.", + change_image: "Schimbați imaginea", + upload_image: "Încărcați imaginea", + name: "Nume", + name_required: "Numele este obligatoriu", + name_within_50: "Numele trebuie să aibă maximum 50 de caractere.", + enter_full_name: "Introduceți numele dvs. complet", + set_password: "Setați o parolă", + optional: "Opțional", + passwords_do_not_match: "Parolele nu se potrivesc", + passwords_match: "Parolele se potrivesc", + continue: "Continua", + invite_team_title: "Invită-ți colegii de echipă", + invite_team_description: + "Lucrul în Plane se întâmplă cel mai bine cu echipa ta. Invitați-i acum să folosească Plane la potențialul său.", + invalid_email: "Nu arată ca o adresă de e-mail.", + success: "Succes!", + invitations_sent: "Invitațiile trimise cu succes.", + error: "Eroare!", + add_another: "Adăugați altul", + do_later: "O voi face mai târziu", + join_invites_title: "Alăturați-vă invitațiilor sau creați un spațiu de lucru", + unified_description: "Toată munca ta — unificată.", + create_new_workspace: "Creați un spațiu de lucru nou", + no_invitations_found: "Nu au fost găsite invitații", + you_are_invited: "Esti invitat!", + accept_invites: "Acceptă invitațiile de a colabora cu echipa ta.", + continue_to_workspace: "Continuați spre spațiul de lucru", + or: "sau", + create_own_workspace: "Creează-ți propriul spațiu de lucru", + workspace_creation_disabled: + "Se pare că nu aveți nicio invitație la un spațiu de lucru și administratorul instanței dvs. a restricționat crearea de noi spații de lucru. Vă rugăm să cereți unui proprietar sau unui administrator de spațiu de lucru să vă invite mai întâi într-un spațiu de lucru și să reveniți la acest ecran pentru a vă alătura.", + create_workspace_title: "Creează-ți spațiul de lucru", + enter_workspace_name: "Introduceți numele spațiului de lucru", + join_existing_workspace: "Alăturați-vă spațiului de lucru existent", + profile_setup_completed: "Configurarea profilului a fost finalizată.", + profile_setup_failed: "Configurarea profilului a eșuat.", + usecase_title: "Cum plănuiți să utilizați Plane?", + usecase_description: "Selectați una sau mai multe opțiuni pentru a vă putea personaliza experiența.", + select_one_or_more: "Selectați unul sau mai multe", + select_at_least_one: "Selectați cel puțin o opțiune.", + skip: "Sari peste", + }, + inbox: { + duplicate_issues_found: "{count} elemente de lucru duplicate găsite", + description_versions: { + intake_form_user: "Utilizator formular de colectare", + }, + errors: { + asset_upload_failed: "Încărcarea materialelor nu a reușit. Vă rugăm să încercați din nou mai târziu.", + asset_duplication_failed: "Dublarea materialelor nu a reușit. Vă rugăm să încercați din nou mai târziu.", + permission_denied: "Acces refuzat", + mark_duplicate_permission: "Numai administratorii de proiect pot marca elementul de lucru ca duplicat", + mark_duplicate_permission_plural: "Numai administratorii de proiect pot marca elementele de lucru ca duplicate", + }, + filters: { + created_date: "Data creată", + updated_date: "Data actualizată", + last_updated_date: "Data ultimei actualizări", + status: "Stare", + work_item_status: "Starea elementului de lucru", + view_all: "Vezi toate", + view_less: "Vedeți mai puțin", + date_options: { + today: "Astăzi", + yesterday: "Ieri", + last_7_days: "Ultimele 7 zile", + last_30_days: "Ultimele 30 de zile", + }, + date_operators: { + after: "După", + before: "Înainte", + }, + }, + navigation: { + previous_work_item: "Element de lucru anterior", + next_work_item: "Următorul articol de lucru", + }, + properties: { + duplicate_of: "Duplicat de", + }, + select_duplicate: { + select_work_item: "Selectați elementul de lucru", + }, + sidebar: { + label_count: "{count} etichete", + }, + toasts: { + editor_processing: "Editorul încă procesează modificări. Vă rugăm să așteptați înainte de a continua.", + create_success: "Element de lucru creat cu succes.", + delete_failed: "Ștergerea elementului de lucru nu a reușit", + update_failed: "Actualizarea articolului de lucru nu a reușit", + }, + }, + space_public: { + error_description_prefix: + "Plane s-a blocat. Inginerii noștri au fost anunțați. Dacă aveți mai multe detalii, scrieți la", + error_description_middle: "sau pe", + not_found_hint: "Verificați URL-ul din bara de adrese a browserului și încercați din nou.", + logged_in_hint: + "Introduceți în bara de adrese a browserului URL-ul public partajat sau linkul vizualizării ori Paginii pe care doriți să o vedeți.", + oauth_with_provider: "{action} cu {provider}", + auth: { + sign_in_header: "Autentificați-vă pentru a vota sau comenta", + sign_in_subheader: "Ajutați la promovarea funcționalităților pe care doriți să le vedeți construite.", + sign_up_header: "Vizualizați, comentați și faceți mai mult", + sign_up_subheader: "Înregistrați-vă sau autentificați-vă pentru a lucra cu elemente de lucru și Pagini Plane.", + }, + peek: { + side: "Previzualizare laterală", + modal: "Modal", + full_screen: "Ecran complet", + }, + bot_name: "Bot {name}", + commented_time: "a comentat {time}", + and_more: "și încă {count}", + no_upvotes_yet: "Încă nu există voturi pozitive", + no_downvotes_yet: "Încă nu există voturi negative", + modules_count: "{count} module", + labels_count: "{count} etichete", + page_not_found_alt: "Pagina nu a fost găsită", + something_went_wrong: "Ups! Ceva nu a mers bine.", + page_not_found_description: "Pagina pe care o căutați nu există sau a fost mutată.", + instance_failure_image_alt: "Nu se pot obține detaliile instanței", + instance_failure_title: "Nu se pot obține detaliile instanței.", + instance_failure_description: "Nu am putut încărca detaliile instanței dvs.", + instance_failure_hint: "Verificați conexiunea și încercați din nou.", + powered_by: "Propulsat de", + sign_in_to_add_comment: "Autentificați-vă pentru a adăuga un comentariu", + link_copied: "Link copiat!", + work_item_link_copied: "Linkul elementului de lucru a fost copiat în clipboard.", + comment_post_error: "Comentariul nu a putut fi publicat. Încercați din nou.", + add_comment: "Adăugați comentariu", + public_board_not_found: "Panoul public nu există. Verificați URL-ul.", + no_work_items_found: "Nu s-au găsit elemente de lucru", + error_title: "Ups! Nu arată bine.", + refresh: "Reîmprospătează", + forum: "Forum", + not_found_title: "Nu a funcționat", + user_already_logged_in: "Utilizatorul este deja autentificat", + logged_in_title: "Perfect! Încă un pas.", + by_creating_account: "Prin crearea unui cont", + by_signing_in: "Prin autentificare", + you_agree_to_our: "sunteți de acord cu", + terms_of_service: "Termenii serviciului", + and: "și", + privacy_policy: "Politica de confidențialitate", + sign_up: "Înregistrare", + sign_in: "Autentificare", + retry: "Reîncearcă", + view_less: "Vezi mai puțin", + view_all: "Vezi tot", + no_matches_found: "Nu s-au găsit potriviri", + no_date: "Fără dată", + no_cycle: "Fără ciclu", + no_modules: "Fără module", + no_assignees: "Fără responsabili", + no_labels: "Fără etichete", + user: "Utilizator", + }, + }, } as const; diff --git a/packages/i18n/src/locales/ru/translations.ts b/packages/i18n/src/locales/ru/translations.ts index 52024d06cd1..ca0bf44ae4f 100644 --- a/packages/i18n/src/locales/ru/translations.ts +++ b/packages/i18n/src/locales/ru/translations.ts @@ -2919,4 +2919,314 @@ export default { enter_number_of_projects: "Введите количество проектов", pin: "Закрепить", unpin: "Открепить", + localized_ui: { + not_found: { + alt: "404 - Страница не найдена", + title: "Упс! Что-то пошло не так.", + description: + "Страница, которую вы ищете, не найдена. Возможно, она была удалена, переименована или временно недоступна.", + go_to_home: "На главную", + }, + workspace_views: { + page_title: "{workspaceName} - Все представления", + }, + projects_empty_state: { + no_projects_yet: "Проектов пока нет", + description: + "Проекты служат основой работы, ориентированной на цели. Они помогают управлять командами, задачами и всем, что нужно для выполнения работы.", + learn_more: "Подробнее о проектах", + start_first_project: "Начать первый проект", + }, + profile_activity: { + page_title: "Профиль - Активность", + }, + pages: { + not_found_title: "Страница не найдена", + not_found_description: + "Страница, к которой вы пытаетесь получить доступ, не существует или у вас нет разрешения на ее просмотр.", + view_other_pages: "Посмотреть другие страницы", + }, + workspace_access: { + not_found_title: "Рабочая область не найдена", + not_found_description: + "Для этого URL рабочая область не найдена. Возможно, она не существует или у вас нет разрешения на ее просмотр.", + visit_profile: "Открыть профиль", + not_authorized_title: "Нет доступа!", + not_authorized_description: + "Вы не являетесь участником этой рабочей области. Обратитесь к администратору рабочей области за приглашением или проверьте ожидающие приглашения.", + check_pending_invites: "Проверить ожидающие приглашения", + }, + editor: { + url: "URL", + enter_or_paste_url: "Введите или вставьте URL-адрес", + text: "Текст", + enter_text_to_display: "Введите текст для отображения", + remove_link: "Удалить ссылку", + edit_link: "Изменить ссылку", + color: "Цвет", + text_colors: "Цвета текста", + background_colors: "Цвета фона", + link: "Ссылка", + enter_or_paste_link: "Введите или вставьте ссылку", + please_enter_valid_url: "Пожалуйста, введите действительный URL", + delete: "Удалить", + duplicate: "Дублировать", + multiple: "Несколько", + loading: "Загрузка", + no_results: "Нет результатов", + copy_code: "Скопировать код", + add_an_image: "Добавить изображение", + error_loading_image: "Ошибка загрузки изображения.", + uploading: "Загрузка", + drop_image_here: "Перетащите изображение сюда", + retry_duplication: "Повторить попытку дублирования", + retry: "Повторить попытку", + no_emojis_found: "Смайлики не найдены", + fullscreen_image_viewer: "Полноэкранный просмотр изображений", + close_image_viewer: "Закрыть просмотрщик изображений", + zoom_out: "Уменьшить масштаб", + zoom_in: "Увеличить масштаб", + download_image: "Скачать изображение", + open_image_in_new_tab: "Открыть изображение в новой вкладке", + view_in_full_screen: "Посмотреть в полноэкранном режиме", + view_image_in_full_screen: "Посмотреть изображение в полноэкранном режиме", + align: "Выровнять", + download: "Скачать", + clear_contents: "Очистить содержимое", + insert_above: "Вставьте выше", + insert_below: "Вставьте ниже", + insert_left: "Вставить слева", + insert_right: "Вставить вправо", + header_row: "Строка заголовка", + header_column: "Столбец заголовка", + alignment: { + left: "Слева", + center: "Центр", + right: "Справа", + }, + menu_items: { + text: "Текст", + h1: "Заголовок 1", + h2: "Заголовок 2", + h3: "Заголовок 3", + h4: "Заголовок 4", + h5: "Заголовок 5", + h6: "Заголовок 6", + "bulleted-list": "Маркированный список", + "numbered-list": "Нумерованный список", + "to-do-list": "Список дел", + quote: "Цитировать", + code: "Код", + table: "Таблица", + image: "Изображение", + divider: "Разделитель", + link: "Ссылка", + bold: "Жирный", + italic: "Курсив", + underline: "Подчеркнуть", + strikethrough: "Зачеркивание", + "text-color": "Цвет текста", + "background-color": "Цвет фона", + "text-align": "Выравнивание текста", + }, + }, + workspace_invitation: { + invitation_not_found: "Приглашение не найдено", + invited_to_workspace: "Вас пригласили в {workspaceName}.", + description: + "Ваше рабочее пространство — это место, где вы будете создавать проекты, совместно работать над рабочими элементами и организовывать различные потоки работы в своей учетной записи Plane.", + accept: "Принимать", + ignore: "игнорировать", + already_member: "Вы уже являетесь участником {workspaceName}.", + continue_to_home: "Продолжить путь домой", + inactive_title: "Эта ссылка-приглашение больше не активна.", + empty_project_link: "Или начать с пустого проекта", + sign_in_to_continue: "Войдите, чтобы продолжить", + star_on_github: "Поставьте нам звезду на GitHub", + join_community: "Присоединяйтесь к нашему сообществу активных авторов", + }, + space_auth: { + email: "Электронная почта", + email_invalid: "Электронная почта недействительна", + clear_email: "Очистить электронную почту", + password: "Пароль", + set_password: "Установить пароль", + enter_password: "Введите пароль", + confirm_password: "Подтвердите пароль", + passwords_dont_match: "Пароли не совпадают", + continue: "Продолжать", + go_to_workspace: "Перейти в рабочую область", + sign_in_with_unique_code: "Войдите с помощью уникального кода", + create_account: "Зарегистрироваться", + unique_code: "Уникальный код", + paste_code_sent: "Вставьте код, отправленный на вашу электронную почту", + resend_in: "Отправить повторно через {seconds}s", + requesting_new_code: "Запрос нового кода", + resend: "Отправить повторно", + sending_code: "Отправка кода", + }, + onboarding: { + create_profile_title: "Создайте свой профиль.", + create_profile_description: "Вот как вы будете выглядеть в Plane.", + change_image: "Изменить изображение", + upload_image: "Загрузить изображение", + name: "Имя", + name_required: "Требуется имя", + name_within_50: "Имя должно быть не более 50 символов.", + enter_full_name: "Введите свое полное имя", + set_password: "Установить пароль", + optional: "Необязательный", + passwords_do_not_match: "Пароли не совпадают", + passwords_match: "Пароли совпадают", + continue: "Продолжать", + invite_team_title: "Пригласите своих товарищей по команде", + invite_team_description: + "Работать в Plane лучше всего вместе с вашей командой. Предложите им сейчас использовать Plane в полной мере.", + invalid_email: "Это не похоже на адрес электронной почты.", + success: "Успех!", + invitations_sent: "Приглашения успешно отправлены.", + error: "Ошибка!", + add_another: "Добавить еще", + do_later: "я сделаю это позже", + join_invites_title: "Присоединяйтесь к приглашениям или создайте рабочее пространство", + unified_description: "Вся ваша работа — едина.", + create_new_workspace: "Создать новое рабочее пространство", + no_invitations_found: "Приглашения не найдены", + you_are_invited: "Вы приглашены!", + accept_invites: "Примите приглашения к сотрудничеству с вашей командой.", + continue_to_workspace: "Перейти в рабочую область", + or: "или", + create_own_workspace: "Создайте свое собственное рабочее пространство", + workspace_creation_disabled: + "Похоже, у вас нет приглашений в рабочую область, а администратор вашего экземпляра ограничил создание новых рабочих областей. Попросите владельца или администратора рабочей области сначала пригласить вас в рабочую область, а затем вернитесь на этот экран, чтобы присоединиться.", + create_workspace_title: "Создайте свое рабочее пространство", + enter_workspace_name: "Введите имя рабочей области", + join_existing_workspace: "Присоединиться к существующей рабочей области", + profile_setup_completed: "Настройка профиля завершена.", + profile_setup_failed: "Настройка профиля не удалась.", + usecase_title: "Как вы планируете использовать Plane?", + usecase_description: "Выберите один или несколько вариантов, чтобы мы могли персонализировать ваш опыт.", + select_one_or_more: "Выберите один или несколько", + select_at_least_one: "Выберите хотя бы один вариант.", + skip: "Пропускать", + }, + inbox: { + duplicate_issues_found: "Найдено дублирующихся рабочих элементов: {count}", + description_versions: { + intake_form_user: "Пользователь формы сбора", + }, + errors: { + asset_upload_failed: "Не удалось загрузить актив. Пожалуйста, повторите попытку позже.", + asset_duplication_failed: "Дублирование активов не удалось. Пожалуйста, повторите попытку позже.", + permission_denied: "Доступ запрещен", + mark_duplicate_permission: "Только администраторы проекта могут пометить рабочий элемент как дубликат.", + mark_duplicate_permission_plural: + "Только администраторы проекта могут отмечать рабочие элементы как повторяющиеся.", + }, + filters: { + created_date: "Дата создания", + updated_date: "Дата обновления", + last_updated_date: "Дата последнего обновления", + status: "Статус", + work_item_status: "Статус рабочего элемента", + view_all: "Посмотреть все", + view_less: "Посмотреть меньше", + date_options: { + today: "Сегодня", + yesterday: "Вчера", + last_7_days: "Последние 7 дней", + last_30_days: "Последние 30 дней", + }, + date_operators: { + after: "После", + before: "До", + }, + }, + navigation: { + previous_work_item: "Предыдущий рабочий элемент", + next_work_item: "Следующий рабочий элемент", + }, + properties: { + duplicate_of: "Дубликат элемента", + }, + select_duplicate: { + select_work_item: "Выберите рабочий элемент", + }, + sidebar: { + label_count: "Этикетки {count}", + }, + toasts: { + editor_processing: "Редактор все еще обрабатывает изменения. Пожалуйста, подождите, прежде чем продолжить.", + create_success: "Рабочий элемент успешно создан.", + delete_failed: "Удаление рабочего элемента не удалось", + update_failed: "Обновление рабочего элемента не удалось", + }, + }, + space_public: { + error_description_prefix: + "Plane аварийно завершил работу. Наши инженеры уже уведомлены. Если у вас есть дополнительные сведения, напишите на", + error_description_middle: "или в нашем", + not_found_hint: "Проверьте URL в адресной строке браузера и попробуйте еще раз.", + logged_in_hint: + "Введите в адресной строке браузера публичный URL или ссылку на представление либо страницу, которую хотите открыть.", + oauth_with_provider: "{action} через {provider}", + auth: { + sign_in_header: "Войдите, чтобы голосовать или комментировать", + sign_in_subheader: "Помогите продвинуть функции, которые вы хотите увидеть реализованными.", + sign_up_header: "Просматривайте, комментируйте и делайте больше", + sign_up_subheader: "Зарегистрируйтесь или войдите, чтобы работать с рабочими элементами и страницами Plane.", + }, + peek: { + side: "Боковой просмотр", + modal: "Модальное окно", + full_screen: "Полный экран", + }, + bot_name: "Бот {name}", + commented_time: "прокомментировал {time}", + and_more: "и еще {count}", + no_upvotes_yet: "Пока нет голосов за", + no_downvotes_yet: "Пока нет голосов против", + modules_count: "{count} модулей", + labels_count: "{count} меток", + page_not_found_alt: "Страница не найдена", + something_went_wrong: "Упс! Что-то пошло не так.", + page_not_found_description: "Страница, которую вы ищете, не существует или была перемещена.", + instance_failure_image_alt: "Не удалось получить сведения об инстансе", + instance_failure_title: "Не удалось получить сведения об инстансе.", + instance_failure_description: "Не удалось загрузить сведения о вашем инстансе.", + instance_failure_hint: "Проверьте подключение и попробуйте еще раз.", + powered_by: "Работает на", + sign_in_to_add_comment: "Войдите, чтобы добавить комментарий", + link_copied: "Ссылка скопирована!", + work_item_link_copied: "Ссылка на рабочий элемент скопирована в буфер обмена.", + comment_post_error: "Не удалось опубликовать комментарий. Попробуйте еще раз.", + add_comment: "Добавить комментарий", + public_board_not_found: "Публичная доска не существует. Проверьте URL.", + no_work_items_found: "Рабочие элементы не найдены", + error_title: "Упс! Что-то пошло не так.", + refresh: "Обновить", + forum: "Форум", + not_found_title: "Не получилось", + user_already_logged_in: "Пользователь уже вошел", + logged_in_title: "Отлично! Остался еще один шаг.", + by_creating_account: "Создавая учетную запись", + by_signing_in: "Входя в систему", + you_agree_to_our: "вы соглашаетесь с нашими", + terms_of_service: "Условиями обслуживания", + and: "и", + privacy_policy: "Политикой конфиденциальности", + sign_up: "Зарегистрироваться", + sign_in: "Войти", + retry: "Повторить", + view_less: "Показать меньше", + view_all: "Показать все", + no_matches_found: "Совпадений не найдено", + no_date: "Без даты", + no_cycle: "Без цикла", + no_modules: "Без модулей", + no_assignees: "Без исполнителей", + no_labels: "Без меток", + user: "Пользователь", + }, + }, } as const; diff --git a/packages/i18n/src/locales/sk/translations.ts b/packages/i18n/src/locales/sk/translations.ts index 9a0c42e8e9e..ff2e636c693 100644 --- a/packages/i18n/src/locales/sk/translations.ts +++ b/packages/i18n/src/locales/sk/translations.ts @@ -2658,4 +2658,313 @@ export default { close_button: "Zavrieť navigačný panel", outline_floating_button: "Otvoriť osnovu", }, + localized_ui: { + not_found: { + alt: "404 - Stránka sa nenašla", + title: "Ups! Niečo sa pokazilo.", + description: + "Stránku, ktorú hľadáte, sa nepodarilo nájsť. Mohla byť odstránená, premenovaná alebo je dočasne nedostupná.", + go_to_home: "Prejsť domov", + }, + workspace_views: { + page_title: "{workspaceName} - Všetky zobrazenia", + }, + projects_empty_state: { + no_projects_yet: "Zatiaľ žiadne projekty", + description: + "Projekty sú základom práce riadenej cieľmi. Pomáhajú spravovať tímy, úlohy a všetko potrebné na dokončenie práce.", + learn_more: "Zistiť viac o projektoch", + start_first_project: "Začať prvý projekt", + }, + profile_activity: { + page_title: "Profil - Aktivita", + }, + pages: { + not_found_title: "Stránka sa nenašla", + not_found_description: + "Stránka, ku ktorej sa pokúšate pristúpiť, neexistuje alebo na jej zobrazenie nemáte oprávnenie.", + view_other_pages: "Zobraziť ďalšie stránky", + }, + workspace_access: { + not_found_title: "Pracovný priestor sa nenašiel", + not_found_description: + "Pre túto URL adresu sa nenašiel žiadny pracovný priestor. Možno neexistuje alebo na jeho zobrazenie nemáte oprávnenie.", + visit_profile: "Navštíviť profil", + not_authorized_title: "Bez oprávnenia!", + not_authorized_description: + "Nie ste členom tohto pracovného priestoru. Požiadajte správcu pracovného priestoru o pozvánku alebo skontrolujte čakajúce pozvánky.", + check_pending_invites: "Skontrolovať čakajúce pozvánky", + }, + editor: { + url: "URL", + enter_or_paste_url: "Zadajte alebo prilepte adresu URL", + text: "Text", + enter_text_to_display: "Zadajte text, ktorý sa má zobraziť", + remove_link: "Odstrániť odkaz", + edit_link: "Upraviť odkaz", + color: "Farba", + text_colors: "Farby textu", + background_colors: "Farby pozadia", + link: "Odkaz", + enter_or_paste_link: "Zadajte alebo prilepte odkaz", + please_enter_valid_url: "Zadajte platný URL", + delete: "Odstrániť", + duplicate: "Duplicitné", + multiple: "Viacnásobné", + loading: "Načítava sa", + no_results: "Žiadne výsledky", + copy_code: "Kopírovať kód", + add_an_image: "Pridajte obrázok", + error_loading_image: "Chyba pri načítavaní obrázka", + uploading: "Nahráva sa", + drop_image_here: "Sem presuňte obrázok", + retry_duplication: "Opakovať duplikáciu", + retry: "Skúste to znova", + no_emojis_found: "Nenašli sa žiadne emotikony", + fullscreen_image_viewer: "Prehliadač obrázkov na celú obrazovku", + close_image_viewer: "Zatvorte prehliadač obrázkov", + zoom_out: "Oddialiť", + zoom_in: "Priblížiť", + download_image: "Stiahnite si obrázok", + open_image_in_new_tab: "Otvoriť obrázok na novej karte", + view_in_full_screen: "Zobraziť na celej obrazovke", + view_image_in_full_screen: "Zobraziť obrázok na celej obrazovke", + align: "Zarovnať", + download: "Stiahnuť", + clear_contents: "Vymazať obsah", + insert_above: "Vložte vyššie", + insert_below: "Vložte nižšie", + insert_left: "Vložte vľavo", + insert_right: "Vložte vpravo", + header_row: "Riadok hlavičky", + header_column: "Hlavička stĺpca", + alignment: { + left: "Vľavo", + center: "Stred", + right: "Vpravo", + }, + menu_items: { + text: "Text", + h1: "Nadpis 1", + h2: "Nadpis 2", + h3: "Nadpis 3", + h4: "Nadpis 4", + h5: "Nadpis 5", + h6: "Nadpis 6", + "bulleted-list": "Zoznam s odrážkami", + "numbered-list": "Číslovaný zoznam", + "to-do-list": "Zoznam úloh", + quote: "Citovať", + code: "Kód", + table: "Tabuľka", + image: "Obrázok", + divider: "Rozdeľovač", + link: "Odkaz", + bold: "Tučné", + italic: "Kurzíva", + underline: "Podčiarknuté", + strikethrough: "Prečiarknuté", + "text-color": "Farba textu", + "background-color": "Farba pozadia", + "text-align": "Zarovnanie textu", + }, + }, + workspace_invitation: { + invitation_not_found: "Pozvánka sa nenašla", + invited_to_workspace: "Boli ste pozvaní do {workspaceName}", + description: + "Váš pracovný priestor je miesto, kde budete vytvárať projekty, spolupracovať na svojich pracovných položkách a organizovať rôzne toky práce vo svojom účte Plane.", + accept: "Prijať", + ignore: "Ignorovať", + already_member: "Už ste členom {workspaceName}", + continue_to_home: "Pokračujte domov", + inactive_title: "Tento odkaz na pozvánku už nie je aktívny.", + empty_project_link: "Alebo začnite od prázdneho projektu", + sign_in_to_continue: "Ak chcete pokračovať, prihláste sa", + star_on_github: "Zahviezdite nás na GitHub", + join_community: "Pridajte sa k našej komunite aktívnych tvorcov", + }, + space_auth: { + email: "Email", + email_invalid: "E-mail je neplatný", + clear_email: "Vymazať e-mail", + password: "heslo", + set_password: "Nastavte heslo", + enter_password: "Zadajte heslo", + confirm_password: "Potvrďte heslo", + passwords_dont_match: "Heslá sa nezhodujú", + continue: "Pokračovať", + go_to_workspace: "Prejdite do pracovného priestoru", + sign_in_with_unique_code: "Prihláste sa pomocou jedinečného kódu", + create_account: "Vytvoriť účet", + unique_code: "Jedinečný kód", + paste_code_sent: "Prilepte kód odoslaný na váš e-mail", + resend_in: "Znova odoslať v {seconds}s", + requesting_new_code: "Požaduje sa nový kód", + resend: "Znova odoslať", + sending_code: "Odosiela sa kód", + }, + onboarding: { + create_profile_title: "Vytvorte si profil.", + create_profile_description: "Takto sa objavíte v Plane.", + change_image: "Zmeniť obrázok", + upload_image: "Nahrajte obrázok", + name: "Meno", + name_required: "Meno je povinné", + name_within_50: "Názov musí mať maximálne 50 znakov.", + enter_full_name: "Zadajte svoje celé meno", + set_password: "Nastavte heslo", + optional: "Voliteľné", + passwords_do_not_match: "Heslá sa nezhodujú", + passwords_match: "Heslá sa zhodujú", + continue: "Pokračovať", + invite_team_title: "Pozvite svojich spoluhráčov", + invite_team_description: + "Práca v Plane prebieha najlepšie s vaším tímom. Pozvite ich, aby využili potenciál Plane.", + invalid_email: "To nevyzerá ako e-mailová adresa.", + success: "Úspech!", + invitations_sent: "Pozvánky boli úspešne odoslané.", + error: "Chyba!", + add_another: "Pridajte ďalší", + do_later: "Urobím to neskôr", + join_invites_title: "Pripojte sa k pozvánkam alebo vytvorte pracovný priestor", + unified_description: "Celá vaša práca – jednotná.", + create_new_workspace: "Vytvorte nový pracovný priestor", + no_invitations_found: "Nenašli sa žiadne pozvánky", + you_are_invited: "Ste pozvaní!", + accept_invites: "Prijmite pozvánky na spoluprácu so svojím tímom.", + continue_to_workspace: "Pokračujte do pracovného priestoru", + or: "alebo", + create_own_workspace: "Vytvorte si vlastný pracovný priestor", + workspace_creation_disabled: + "Zdá sa, že nemáte žiadne pozvánky do pracovného priestoru a váš správca inštancie obmedzil vytváranie nových pracovných priestorov. Požiadajte vlastníka alebo správcu pracovného priestoru, aby vás najprv pozval do pracovného priestoru a vráťte sa na túto obrazovku a pripojte sa.", + create_workspace_title: "Vytvorte si pracovný priestor", + enter_workspace_name: "Zadajte názov pracovného priestoru", + join_existing_workspace: "Pripojte sa k existujúcemu pracovnému priestoru", + profile_setup_completed: "Nastavenie profilu je dokončené.", + profile_setup_failed: "Nastavenie profilu zlyhalo.", + usecase_title: "Ako plánujete používať Plane?", + usecase_description: "Vyberte jednu alebo viac možností, aby sme vám mohli prispôsobiť váš zážitok.", + select_one_or_more: "Vyberte jednu alebo viac", + select_at_least_one: "Vyberte aspoň jednu možnosť.", + skip: "Preskočiť", + }, + inbox: { + duplicate_issues_found: "Našlo sa {count} duplicitných pracovných položiek", + description_versions: { + intake_form_user: "Používateľ zberného formulára", + }, + errors: { + asset_upload_failed: "Nahranie diela zlyhalo. Skúste to znova neskôr.", + asset_duplication_failed: "Duplikácia aktív zlyhala. Skúste to znova neskôr.", + permission_denied: "Povolenie zamietnuté", + mark_duplicate_permission: "Iba správcovia projektu môžu označiť pracovnú položku ako duplikát", + mark_duplicate_permission_plural: "Iba správcovia projektu môžu označiť pracovné položky ako duplicitné", + }, + filters: { + created_date: "Dátum vytvorenia", + updated_date: "Aktualizovaný dátum", + last_updated_date: "Dátum poslednej aktualizácie", + status: "Stav", + work_item_status: "Stav pracovnej položky", + view_all: "Zobraziť všetky", + view_less: "Zobraziť menej", + date_options: { + today: "Dnes", + yesterday: "včera", + last_7_days: "Posledných 7 dní", + last_30_days: "Posledných 30 dní", + }, + date_operators: { + after: "Po", + before: "Predtým", + }, + }, + navigation: { + previous_work_item: "Predchádzajúca pracovná položka", + next_work_item: "Ďalšia pracovná položka", + }, + properties: { + duplicate_of: "Duplikát položky", + }, + select_duplicate: { + select_work_item: "Vyberte pracovnú položku", + }, + sidebar: { + label_count: "{count} štítky", + }, + toasts: { + editor_processing: "Editor stále spracováva zmeny. Pred pokračovaním počkajte.", + create_success: "Pracovná položka bola úspešne vytvorená.", + delete_failed: "Odstránenie pracovnej položky zlyhalo", + update_failed: "Aktualizácia pracovnej položky zlyhala", + }, + }, + space_public: { + error_description_prefix: "Plane zlyhal. Naši inžinieri boli upozornení. Ak máte ďalšie podrobnosti, napíšte na", + error_description_middle: "alebo na našom", + not_found_hint: "Skontrolujte URL v paneli s adresou prehliadača a skúste to znova.", + logged_in_hint: + "Do panela s adresou prehliadača zadajte verejnú zdieľanú URL alebo odkaz na zobrazenie či stránku, ktorú chcete vidieť.", + oauth_with_provider: "{action} cez {provider}", + auth: { + sign_in_header: "Prihláste sa, aby ste mohli hlasovať alebo komentovať", + sign_in_subheader: "Pomôžte posunúť funkcie, ktoré chcete mať vytvorené.", + sign_up_header: "Zobrazujte, komentujte a robte viac", + sign_up_subheader: + "Zaregistrujte sa alebo sa prihláste, aby ste mohli pracovať s pracovnými položkami a Stránkami Plane.", + }, + peek: { + side: "Bočný náhľad", + modal: "Modálne okno", + full_screen: "Celá obrazovka", + }, + bot_name: "Bot {name}", + commented_time: "komentoval {time}", + and_more: "a ďalších {count}", + no_upvotes_yet: "Zatiaľ žiadne hlasy za", + no_downvotes_yet: "Zatiaľ žiadne hlasy proti", + modules_count: "{count} modulov", + labels_count: "{count} štítkov", + page_not_found_alt: "Stránka sa nenašla", + something_went_wrong: "Ups! Niečo sa pokazilo.", + page_not_found_description: "Stránka, ktorú hľadáte, neexistuje alebo bola presunutá.", + instance_failure_image_alt: "Nie je možné načítať podrobnosti inštancie", + instance_failure_title: "Nie je možné načítať podrobnosti inštancie.", + instance_failure_description: "Nepodarilo sa načítať podrobnosti vašej inštancie.", + instance_failure_hint: "Skontrolujte pripojenie a skúste to znova.", + powered_by: "Používa", + sign_in_to_add_comment: "Prihláste sa a pridajte komentár", + link_copied: "Odkaz skopírovaný!", + work_item_link_copied: "Odkaz na pracovnú položku bol skopírovaný do schránky.", + comment_post_error: "Komentár sa nepodarilo uverejniť. Skúste to znova.", + add_comment: "Pridať komentár", + public_board_not_found: "Verejná nástenka neexistuje. Skontrolujte URL.", + no_work_items_found: "Nenašli sa žiadne pracovné položky", + error_title: "Ups! Toto nevyzerá dobre.", + refresh: "Obnoviť", + forum: "Fórum", + not_found_title: "Toto nefungovalo", + user_already_logged_in: "Používateľ je už prihlásený", + logged_in_title: "Výborne! Ešte jeden krok.", + by_creating_account: "Vytvorením účtu", + by_signing_in: "Prihlásením", + you_agree_to_our: "súhlasíte s našimi", + terms_of_service: "Podmienkami služby", + and: "a", + privacy_policy: "Zásadami ochrany osobných údajov", + sign_up: "Zaregistrovať sa", + sign_in: "Prihlásiť sa", + retry: "Skúsiť znova", + view_less: "Zobraziť menej", + view_all: "Zobraziť všetko", + no_matches_found: "Nenašli sa žiadne zhody", + no_date: "Bez dátumu", + no_cycle: "Bez cyklu", + no_modules: "Bez modulov", + no_assignees: "Bez priradených osôb", + no_labels: "Žiadne štítky", + user: "Používateľ", + }, + }, } as const; diff --git a/packages/i18n/src/locales/tr-TR/translations.ts b/packages/i18n/src/locales/tr-TR/translations.ts index 4e60e0cfbec..91c7036789c 100644 --- a/packages/i18n/src/locales/tr-TR/translations.ts +++ b/packages/i18n/src/locales/tr-TR/translations.ts @@ -2669,4 +2669,312 @@ export default { close_button: "Navigasyon panelini kapat", outline_floating_button: "Ana hatları aç", }, + localized_ui: { + not_found: { + alt: "404 - Sayfa bulunamadı", + title: "Hata! Bir şeyler ters gitti.", + description: + "Aradığınız sayfa bulunamadı. Kaldırılmış, yeniden adlandırılmış veya geçici olarak kullanılamıyor olabilir.", + go_to_home: "Ana sayfaya git", + }, + workspace_views: { + page_title: "{workspaceName} - Tüm Görünümler", + }, + projects_empty_state: { + no_projects_yet: "Henüz proje yok", + description: + "Projeler, hedef odaklı çalışmanın temelidir. Ekipleri, görevleri ve işi tamamlamak için gereken her şeyi yönetmenizi sağlar.", + learn_more: "Projeler hakkında daha fazla bilgi edinin", + start_first_project: "İlk projenizi başlatın", + }, + profile_activity: { + page_title: "Profil - Etkinlik", + }, + pages: { + not_found_title: "Sayfa bulunamadı", + not_found_description: "Erişmeye çalıştığınız sayfa mevcut değil veya görüntüleme izniniz yok.", + view_other_pages: "Diğer sayfaları görüntüle", + }, + workspace_access: { + not_found_title: "Çalışma alanı bulunamadı", + not_found_description: + "Bu URL için çalışma alanı bulunamadı. Mevcut olmayabilir veya görüntüleme izniniz olmayabilir.", + visit_profile: "Profili ziyaret et", + not_authorized_title: "Yetkili değilsiniz!", + not_authorized_description: + "Bu çalışma alanının üyesi değilsiniz. Davet almak için çalışma alanı yöneticisiyle iletişime geçin veya bekleyen davetlerinizi kontrol edin.", + check_pending_invites: "Bekleyen davetleri kontrol et", + }, + editor: { + url: "URL", + enter_or_paste_url: "URL'yi girin veya yapıştırın", + text: "Metin", + enter_text_to_display: "Görüntülenecek metni girin", + remove_link: "Bağlantıyı kaldır", + edit_link: "Bağlantıyı düzenle", + color: "Renk", + text_colors: "Metin renkleri", + background_colors: "Arka plan renkleri", + link: "Bağlantı", + enter_or_paste_link: "Bağlantıyı girin veya yapıştırın", + please_enter_valid_url: "Lütfen geçerli bir URL girin", + delete: "Silmek", + duplicate: "Kopyalamak", + multiple: "Çoklu", + loading: "Yükleniyor", + no_results: "Sonuç yok", + copy_code: "Kodu kopyala", + add_an_image: "Resim ekle", + error_loading_image: "Resim yüklenirken hata oluştu", + uploading: "Yükleniyor", + drop_image_here: "Resmi buraya bırakın", + retry_duplication: "Çoğaltmayı yeniden dene", + retry: "Yeniden dene", + no_emojis_found: "Hiçbir emoji bulunamadı", + fullscreen_image_viewer: "Tam ekran resim görüntüleyici", + close_image_viewer: "Resim görüntüleyiciyi kapat", + zoom_out: "Uzaklaştır", + zoom_in: "Yakınlaştır", + download_image: "Resmi indir", + open_image_in_new_tab: "Resmi yeni sekmede aç", + view_in_full_screen: "Tam ekranda görüntüle", + view_image_in_full_screen: "Resmi tam ekranda görüntüle", + align: "Hizala", + download: "İndir", + clear_contents: "İçeriği temizle", + insert_above: "Yukarıya ekle", + insert_below: "Aşağıya ekle", + insert_left: "Sola ekle", + insert_right: "Sağa ekle", + header_row: "Başlık satırı", + header_column: "Başlık sütunu", + alignment: { + left: "Sol", + center: "Merkez", + right: "Sağ", + }, + menu_items: { + text: "Metin", + h1: "Başlık 1", + h2: "Başlık 2", + h3: "Başlık 3", + h4: "Başlık 4", + h5: "Başlık 5", + h6: "Başlık 6", + "bulleted-list": "Madde işaretli liste", + "numbered-list": "Numaralı liste", + "to-do-list": "Yapılacaklar listesi", + quote: "Alıntı", + code: "Kod", + table: "Tablo", + image: "Resim", + divider: "Bölücü", + link: "Bağlantı", + bold: "Kalın", + italic: "İtalik", + underline: "Altı çizili", + strikethrough: "Üstü çizili", + "text-color": "Metin rengi", + "background-color": "Arka plan rengi", + "text-align": "Metin hizalama", + }, + }, + workspace_invitation: { + invitation_not_found: "Davetiye bulunamadı", + invited_to_workspace: "{workspaceName}'e davet edildiniz", + description: + "Çalışma alanınız, Plane hesabınızda projeler oluşturacağınız, çalışma öğeleriniz üzerinde işbirliği yapacağınız ve farklı iş akışlarını organize edeceğiniz yerdir.", + accept: "Kabul etmek", + ignore: "Görmezden gelmek", + already_member: "Zaten {workspaceName} üyesisiniz", + continue_to_home: "Eve devam et", + inactive_title: "Bu davet bağlantısı artık aktif değil.", + empty_project_link: "Veya boş bir projeden başlayın", + sign_in_to_continue: "Devam etmek için oturum açın", + star_on_github: "GitHub'da bize yıldız verin", + join_community: "Aktif yaratıcılardan oluşan topluluğumuza katılın", + }, + space_auth: { + email: "E-posta", + email_invalid: "E-posta geçersiz", + clear_email: "E-postayı temizle", + password: "Şifre", + set_password: "Bir şifre belirleyin", + enter_password: "Şifreyi girin", + confirm_password: "Şifreyi onayla", + passwords_dont_match: "Şifreler eşleşmiyor", + continue: "Devam etmek", + go_to_workspace: "Çalışma alanına git", + sign_in_with_unique_code: "Benzersiz kodla oturum açın", + create_account: "Hesap oluşturmak", + unique_code: "Benzersiz kod", + paste_code_sent: "E-postanıza gönderilen kodu yapıştırın", + resend_in: "{seconds}s içinde tekrar gönder", + requesting_new_code: "Yeni kod isteniyor", + resend: "Yeniden gönder", + sending_code: "Kod gönderiliyor", + }, + onboarding: { + create_profile_title: "Profilinizi oluşturun.", + create_profile_description: "Plane'de bu şekilde görüneceksiniz.", + change_image: "Resmi değiştir", + upload_image: "Resim yükle", + name: "İsim", + name_required: "Ad gerekli", + name_within_50: "Ad 50 karakterden oluşmalıdır.", + enter_full_name: "Tam adınızı girin", + set_password: "Bir şifre belirleyin", + optional: "İsteğe bağlı", + passwords_do_not_match: "Şifreler eşleşmiyor", + passwords_match: "Şifreler eşleşiyor", + continue: "Devam etmek", + invite_team_title: "Takım arkadaşlarınızı davet edin", + invite_team_description: + "Plane'de çalışmak ekibinizle en iyi şekilde gerçekleşir. Onları şimdi Plane'in potansiyelini sonuna kadar kullanmaya davet edin.", + invalid_email: "Bu bir e-posta adresine benzemiyor.", + success: "Başarı!", + invitations_sent: "Davetiyeler başarıyla gönderildi.", + error: "Hata!", + add_another: "Başka ekle", + do_later: "Daha sonra yapacağım", + join_invites_title: "Davetlere katılın veya bir çalışma alanı oluşturun", + unified_description: "Tüm çalışmalarınız — birleştirilmiş.", + create_new_workspace: "Yeni çalışma alanı oluştur", + no_invitations_found: "Hiçbir davetiye bulunamadı", + you_are_invited: "Davetlisiniz!", + accept_invites: "Ekibinizle işbirliği yapma davetlerini kabul edin.", + continue_to_workspace: "Çalışma alanına devam et", + or: "veya", + create_own_workspace: "Kendi çalışma alanınızı yaratın", + workspace_creation_disabled: + "Bir çalışma alanına davetiniz yok gibi görünüyor ve örnek yöneticiniz yeni çalışma alanlarının oluşturulmasını kısıtladı. Lütfen bir çalışma alanı sahibinden veya yöneticisinden önce sizi bir çalışma alanına davet etmesini ve katılmak için bu ekrana geri dönmesini isteyin.", + create_workspace_title: "Çalışma alanınızı yaratın", + enter_workspace_name: "Çalışma alanı adını girin", + join_existing_workspace: "Mevcut çalışma alanına katılın", + profile_setup_completed: "Profil kurulumu tamamlandı.", + profile_setup_failed: "Profil kurulumu başarısız oldu.", + usecase_title: "Plane'i nasıl kullanmayı planlıyorsunuz?", + usecase_description: "Deneyiminizi kişiselleştirebilmemiz için bir veya daha fazla seçeneği seçin.", + select_one_or_more: "Bir veya daha fazlasını seçin", + select_at_least_one: "En az bir seçeneği seçin.", + skip: "Atlamak", + }, + inbox: { + duplicate_issues_found: "{count} yinelenen iş öğesi bulundu", + description_versions: { + intake_form_user: "Başvuru Formu kullanıcısı", + }, + errors: { + asset_upload_failed: "Öğe yükleme başarısız oldu. Lütfen daha sonra tekrar deneyin.", + asset_duplication_failed: "Varlık çoğaltması başarısız oldu. Lütfen daha sonra tekrar deneyin.", + permission_denied: "İzin reddedildi", + mark_duplicate_permission: "Yalnızca proje yöneticileri iş öğesini kopya olarak işaretleyebilir", + mark_duplicate_permission_plural: "Yalnızca proje yöneticileri iş öğelerini kopya olarak işaretleyebilir", + }, + filters: { + created_date: "Oluşturulma tarihi", + updated_date: "Güncellenme tarihi", + last_updated_date: "Son güncelleme tarihi", + status: "Durum", + work_item_status: "İş öğesi durumu", + view_all: "Tümünü görüntüle", + view_less: "Daha az görüntüle", + date_options: { + today: "Bugün", + yesterday: "Dün", + last_7_days: "Son 7 gün", + last_30_days: "Son 30 gün", + }, + date_operators: { + after: "Sonrasında", + before: "Önce", + }, + }, + navigation: { + previous_work_item: "Önceki iş öğesi", + next_work_item: "Sonraki iş öğesi", + }, + properties: { + duplicate_of: "Şunun yineleneni", + }, + select_duplicate: { + select_work_item: "İş öğesini seçin", + }, + sidebar: { + label_count: "{count} etiketleri", + }, + toasts: { + editor_processing: "Düzenleyici hâlâ değişiklikleri işliyor. Devam etmeden önce lütfen bekleyin.", + create_success: "İş öğesi başarıyla oluşturuldu.", + delete_failed: "İş öğesi silinemedi", + update_failed: "İş öğesi güncellemesi başarısız oldu", + }, + }, + space_public: { + error_description_prefix: + "Plane çöktü. Mühendislerimiz bilgilendirildi. Daha fazla ayrıntınız varsa lütfen şuraya yazın", + error_description_middle: "veya bizim", + not_found_hint: "Tarayıcı adres çubuğundaki URL'yi kontrol edip tekrar deneyin.", + logged_in_hint: + "Görmek istediğiniz görünümün veya Sayfanın herkese açık paylaşım URL'sini ya da bağlantısını tarayıcı adres çubuğuna girin.", + oauth_with_provider: "{provider} ile {action}", + auth: { + sign_in_header: "Oy vermek veya yorum yapmak için oturum açın", + sign_in_subheader: "Yapılmasını istediğiniz özelliklerin ilerlemesine katkıda bulunun.", + sign_up_header: "Görüntüleyin, yorum yapın ve daha fazlasını yapın", + sign_up_subheader: "Plane iş öğeleri ve Sayfaları ile çalışmak için kaydolun veya oturum açın.", + }, + peek: { + side: "Yan Önizleme", + modal: "Modal", + full_screen: "Tam Ekran", + }, + bot_name: "{name} Botu", + commented_time: "{time} yorum yaptı", + and_more: "ve {count} kişi daha", + no_upvotes_yet: "Henüz olumlu oy yok", + no_downvotes_yet: "Henüz olumsuz oy yok", + modules_count: "{count} Modül", + labels_count: "{count} Etiket", + page_not_found_alt: "Sayfa bulunamadı", + something_went_wrong: "Hata! Bir şeyler ters gitti.", + page_not_found_description: "Aradığınız sayfa yok veya taşınmış.", + instance_failure_image_alt: "Örnek ayrıntıları alınamadı", + instance_failure_title: "Örnek ayrıntıları alınamadı.", + instance_failure_description: "Örnek ayrıntılarınız yüklenemedi.", + instance_failure_hint: "Bağlantınızı kontrol edip tekrar deneyin.", + powered_by: "Destekleyen", + sign_in_to_add_comment: "Yorum eklemek için oturum açın", + link_copied: "Bağlantı kopyalandı!", + work_item_link_copied: "İş öğesi bağlantısı panoya kopyalandı.", + comment_post_error: "Yorum gönderilemedi. Lütfen tekrar deneyin.", + add_comment: "Yorum ekle", + public_board_not_found: "Herkese açık pano mevcut değil. Lütfen URL'yi kontrol edin.", + no_work_items_found: "İş öğesi bulunamadı", + error_title: "Eyvah! Bu iyi görünmüyor.", + refresh: "Yenile", + forum: "Forum", + not_found_title: "Bu işe yaramadı", + user_already_logged_in: "Kullanıcı zaten oturum açmış", + logged_in_title: "Güzel! Sadece bir adım kaldı.", + by_creating_account: "Hesap oluşturarak", + by_signing_in: "Oturum açarak", + you_agree_to_our: "şunları kabul etmiş olursunuz", + terms_of_service: "Hizmet Şartları", + and: "ve", + privacy_policy: "Gizlilik Politikası", + sign_up: "Kaydol", + sign_in: "Oturum aç", + retry: "Tekrar dene", + view_less: "Daha az göster", + view_all: "Tümünü göster", + no_matches_found: "Eşleşme bulunamadı", + no_date: "Tarih yok", + no_cycle: "Döngü yok", + no_modules: "Modül yok", + no_assignees: "Atanan yok", + no_labels: "Etiket yok", + user: "Kullanıcı", + }, + }, } as const; diff --git a/packages/i18n/src/locales/ua/translations.ts b/packages/i18n/src/locales/ua/translations.ts index 0c949cf0567..0cb9e5ba7d3 100644 --- a/packages/i18n/src/locales/ua/translations.ts +++ b/packages/i18n/src/locales/ua/translations.ts @@ -2911,4 +2911,313 @@ export default { enter_number_of_projects: "Введіть кількість проєктів", pin: "Закріпити", unpin: "Відкріпити", + localized_ui: { + not_found: { + alt: "404 - Сторінку не знайдено", + title: "Ой! Щось пішло не так.", + description: + "Сторінку, яку ви шукаєте, не знайдено. Її могли видалити, перейменувати або вона тимчасово недоступна.", + go_to_home: "На головну", + }, + workspace_views: { + page_title: "{workspaceName} - Усі подання", + }, + projects_empty_state: { + no_projects_yet: "Проєктів ще немає", + description: + "Проєкти є основою роботи, орієнтованої на цілі. Вони допомагають керувати командами, завданнями та всім необхідним для виконання роботи.", + learn_more: "Дізнатися більше про проєкти", + start_first_project: "Почати перший проєкт", + }, + profile_activity: { + page_title: "Профіль - Активність", + }, + pages: { + not_found_title: "Сторінку не знайдено", + not_found_description: + "Сторінка, до якої ви намагаєтеся отримати доступ, не існує або у вас немає дозволу на її перегляд.", + view_other_pages: "Переглянути інші сторінки", + }, + workspace_access: { + not_found_title: "Робочу область не знайдено", + not_found_description: + "Для цієї URL-адреси робочу область не знайдено. Можливо, вона не існує або у вас немає дозволу на її перегляд.", + visit_profile: "Відвідати профіль", + not_authorized_title: "Немає доступу!", + not_authorized_description: + "Ви не є учасником цієї робочої області. Зверніться до адміністратора робочої області, щоб отримати запрошення, або перевірте запрошення, що очікують.", + check_pending_invites: "Перевірити очікувані запрошення", + }, + editor: { + url: "URL", + enter_or_paste_url: "Введіть або вставте URL", + text: "текст", + enter_text_to_display: "Введіть текст для відображення", + remove_link: "Видалити посилання", + edit_link: "Редагувати посилання", + color: "Колір", + text_colors: "Кольори тексту", + background_colors: "Кольори фону", + link: "Посилання", + enter_or_paste_link: "Введіть або вставте посилання", + please_enter_valid_url: "Введіть дійсний URL", + delete: "Видалити", + duplicate: "дублікат", + multiple: "Кілька", + loading: "Завантаження", + no_results: "Результатів немає", + copy_code: "Скопіюйте код", + add_an_image: "Додайте зображення", + error_loading_image: "Помилка завантаження зображення", + uploading: "Завантаження", + drop_image_here: "Перетягніть зображення сюди", + retry_duplication: "Повторіть спробу дублювання", + retry: "Повторіть спробу", + no_emojis_found: "Емодзі не знайдено", + fullscreen_image_viewer: "Переглядач повноекранних зображень", + close_image_viewer: "Закрити переглядач зображень", + zoom_out: "Зменшити масштаб", + zoom_in: "Збільшити", + download_image: "Завантажити зображення", + open_image_in_new_tab: "Відкрити зображення в новій вкладці", + view_in_full_screen: "Переглянути на весь екран", + view_image_in_full_screen: "Переглянути зображення на весь екран", + align: "Вирівняти", + download: "Завантажити", + clear_contents: "Очистити вміст", + insert_above: "Вставте вище", + insert_below: "Вставте нижче", + insert_left: "Вставте ліворуч", + insert_right: "Вставте праворуч", + header_row: "Рядок заголовка", + header_column: "Стовпець заголовка", + alignment: { + left: "Ліворуч", + center: "По центру", + right: "Праворуч", + }, + menu_items: { + text: "текст", + h1: "Заголовок 1", + h2: "Заголовок 2", + h3: "Заголовок 3", + h4: "Заголовок 4", + h5: "Заголовок 5", + h6: "Заголовок 6", + "bulleted-list": "Маркірований список", + "numbered-list": "Нумерований список", + "to-do-list": "Список справ", + quote: "Цитата", + code: "Код", + table: "Таблиця", + image: "Зображення", + divider: "Роздільник", + link: "Посилання", + bold: "Жирний", + italic: "Курсив", + underline: "Підкреслити", + strikethrough: "Закреслення", + "text-color": "Колір тексту", + "background-color": "Колір фону", + "text-align": "Вирівнювання тексту", + }, + }, + workspace_invitation: { + invitation_not_found: "Запрошення не знайдено", + invited_to_workspace: "Вас запросили до {workspaceName}", + description: + "У вашому робочому просторі ви створюватимете проекти, співпрацюватимете над своїми робочими елементами та організовуватимете різні потоки роботи у своєму обліковому записі Plane.", + accept: "прийняти", + ignore: "Ігнорувати", + already_member: "Ви вже є учасником {workspaceName}", + continue_to_home: "Продовжуйте додому", + inactive_title: "Це посилання для запрошення більше не активне.", + empty_project_link: "Або почати з порожнього проекту", + sign_in_to_continue: "Увійдіть, щоб продовжити", + star_on_github: "Зіркою нас на GitHub", + join_community: "Приєднуйтесь до нашої спільноти активних творців", + }, + space_auth: { + email: "Електронна пошта", + email_invalid: "Електронна адреса недійсна", + clear_email: "Очистити електронну пошту", + password: "Пароль", + set_password: "Встановіть пароль", + enter_password: "Введіть пароль", + confirm_password: "Підтвердьте пароль", + passwords_dont_match: "Паролі не збігаються", + continue: "Продовжити", + go_to_workspace: "Перейдіть до робочої області", + sign_in_with_unique_code: "Увійдіть за допомогою унікального коду", + create_account: "Створити акаунт", + unique_code: "Унікальний код", + paste_code_sent: "Вставте код, надісланий на вашу електронну пошту", + resend_in: "Повторно надішліть через {seconds}s", + requesting_new_code: "Запит на новий код", + resend: "Надіслати повторно", + sending_code: "Надсилання коду", + }, + onboarding: { + create_profile_title: "Створіть свій профіль.", + create_profile_description: "Ось як ви будете виглядати в Plane.", + change_image: "Змінити зображення", + upload_image: "Завантажити зображення", + name: "Ім'я", + name_required: "Необхідно вказати ім'я", + name_within_50: "Назва має містити не більше 50 символів.", + enter_full_name: "Введіть своє повне ім'я", + set_password: "Встановіть пароль", + optional: "Додатково", + passwords_do_not_match: "Паролі не збігаються", + passwords_match: "Паролі збігаються", + continue: "Продовжити", + invite_team_title: "Запросіть своїх товаришів по команді", + invite_team_description: + "Робота в Plane найкраще відбувається з вашою командою. Запропонуйте їм зараз використати потенціал Plane.", + invalid_email: "Це не схоже на електронну адресу.", + success: "Успіх!", + invitations_sent: "Запрошення успішно надіслано.", + error: "Помилка!", + add_another: "Додайте іншу", + do_later: "Я зроблю це пізніше", + join_invites_title: "Приєднайтеся до запрошень або створіть робочу область", + unified_description: "Вся ваша робота — єдина.", + create_new_workspace: "Створіть новий робочий простір", + no_invitations_found: "Запрошень не знайдено", + you_are_invited: "Ви запрошені!", + accept_invites: "Прийміть запрошення співпрацювати з вашою командою.", + continue_to_workspace: "Продовжуйте до робочої області", + or: "або", + create_own_workspace: "Створіть власний робочий простір", + workspace_creation_disabled: + "Схоже, у вас немає запрошень до робочої області, а адміністратор вашого екземпляра обмежив створення нових робочих областей. Будь ласка, попросіть власника робочої області або адміністратора запросити вас у робочу область і поверніться на цей екран, щоб приєднатися.", + create_workspace_title: "Створіть свій робочий простір", + enter_workspace_name: "Введіть назву робочої області", + join_existing_workspace: "Приєднайтеся до існуючої робочої області", + profile_setup_completed: "Налаштування профілю завершено.", + profile_setup_failed: "Помилка налаштування профілю.", + usecase_title: "Як ви плануєте використовувати Plane?", + usecase_description: "Виберіть один або кілька варіантів, щоб ми могли персоналізувати ваш досвід.", + select_one_or_more: "Виберіть один або декілька", + select_at_least_one: "Виберіть хоча б один варіант.", + skip: "Пропустити", + }, + inbox: { + duplicate_issues_found: "Знайдено {count} дубльованих робочих елементів", + description_versions: { + intake_form_user: "Користувач форми збору", + }, + errors: { + asset_upload_failed: "Не вдалося завантажити ресурс. Спробуйте пізніше.", + asset_duplication_failed: "Помилка копіювання ресурсу. Спробуйте пізніше.", + permission_denied: "У дозволі відмовлено", + mark_duplicate_permission: "Лише адміністратори проекту можуть позначити робочий елемент як дублікат", + mark_duplicate_permission_plural: "Лише адміністратори проекту можуть позначати робочі елементи як дублікати", + }, + filters: { + created_date: "Дата створення", + updated_date: "Оновлена ​​дата", + last_updated_date: "Дата останнього оновлення", + status: "Статус", + work_item_status: "Статус робочого елемента", + view_all: "Переглянути всі", + view_less: "Переглянути менше", + date_options: { + today: "Сьогодні", + yesterday: "вчора", + last_7_days: "Останні 7 днів", + last_30_days: "Останні 30 днів", + }, + date_operators: { + after: "після", + before: "Раніше", + }, + }, + navigation: { + previous_work_item: "Попередній робочий елемент", + next_work_item: "Наступний робочий елемент", + }, + properties: { + duplicate_of: "Дублікат елемента", + }, + select_duplicate: { + select_work_item: "Виберіть робочий елемент", + }, + sidebar: { + label_count: "{count} міток", + }, + toasts: { + editor_processing: "Редактор ще обробляє зміни. Зачекайте, перш ніж продовжити.", + create_success: "Робочий елемент створено успішно.", + delete_failed: "Не вдалося видалити робочий елемент", + update_failed: "Не вдалося оновити робочий елемент", + }, + }, + space_public: { + error_description_prefix: + "Plane аварійно завершив роботу. Наших інженерів уже повідомлено. Якщо у вас є більше деталей, напишіть на", + error_description_middle: "або на нашому", + not_found_hint: "Перевірте URL в адресному рядку браузера та спробуйте ще раз.", + logged_in_hint: + "Введіть в адресному рядку браузера публічну URL-адресу спільного доступу або посилання на подання чи сторінку, яку хочете переглянути.", + oauth_with_provider: "{action} через {provider}", + auth: { + sign_in_header: "Увійдіть, щоб голосувати або коментувати", + sign_in_subheader: "Допоможіть просувати функції, які хочете бачити реалізованими.", + sign_up_header: "Переглядайте, коментуйте та робіть більше", + sign_up_subheader: "Зареєструйтеся або увійдіть, щоб працювати з робочими елементами та сторінками Plane.", + }, + peek: { + side: "Бічний перегляд", + modal: "Модальне вікно", + full_screen: "Повний екран", + }, + bot_name: "Бот {name}", + commented_time: "прокоментував {time}", + and_more: "і ще {count}", + no_upvotes_yet: "Поки що немає голосів за", + no_downvotes_yet: "Поки що немає голосів проти", + modules_count: "{count} модулів", + labels_count: "{count} міток", + page_not_found_alt: "Сторінку не знайдено", + something_went_wrong: "Ой! Щось пішло не так.", + page_not_found_description: "Сторінка, яку ви шукаєте, не існує або була переміщена.", + instance_failure_image_alt: "Не вдалося отримати деталі інстансу", + instance_failure_title: "Не вдалося отримати деталі інстансу.", + instance_failure_description: "Не вдалося завантажити деталі вашого інстансу.", + instance_failure_hint: "Перевірте підключення та спробуйте ще раз.", + powered_by: "Працює на", + sign_in_to_add_comment: "Увійдіть, щоб додати коментар", + link_copied: "Посилання скопійовано!", + work_item_link_copied: "Посилання на робочий елемент скопійовано в буфер обміну.", + comment_post_error: "Не вдалося опублікувати коментар. Спробуйте ще раз.", + add_comment: "Додати коментар", + public_board_not_found: "Публічна дошка не існує. Перевірте URL.", + no_work_items_found: "Робочих елементів не знайдено", + error_title: "Ой! Це виглядає не дуже добре.", + refresh: "Оновити", + forum: "Форум", + not_found_title: "Це не спрацювало", + user_already_logged_in: "Користувач уже ввійшов", + logged_in_title: "Чудово! Залишився ще один крок.", + by_creating_account: "Створюючи обліковий запис", + by_signing_in: "Входячи", + you_agree_to_our: "ви погоджуєтеся з нашими", + terms_of_service: "Умовами надання послуг", + and: "і", + privacy_policy: "Політикою конфіденційності", + sign_up: "Зареєструватися", + sign_in: "Увійти", + retry: "Повторити", + view_less: "Показати менше", + view_all: "Показати все", + no_matches_found: "Збігів не знайдено", + no_date: "Без дати", + no_cycle: "Без циклу", + no_modules: "Без модулів", + no_assignees: "Без виконавців", + no_labels: "Без міток", + user: "Користувач", + }, + }, } as const; diff --git a/packages/i18n/src/locales/vi-VN/translations.ts b/packages/i18n/src/locales/vi-VN/translations.ts index 0cc12c75ea0..5b069375ddf 100644 --- a/packages/i18n/src/locales/vi-VN/translations.ts +++ b/packages/i18n/src/locales/vi-VN/translations.ts @@ -2692,4 +2692,312 @@ export default { close_button: "Đóng bảng điều hướng", outline_floating_button: "Mở phác thảo", }, + localized_ui: { + not_found: { + alt: "404 - Không tìm thấy trang", + title: "Rất tiếc! Đã xảy ra lỗi.", + description: + "Rất tiếc, không tìm thấy trang bạn đang tìm. Trang có thể đã bị xóa, đổi tên hoặc tạm thời không khả dụng.", + go_to_home: "Về trang chủ", + }, + workspace_views: { + page_title: "{workspaceName} - Tất cả chế độ xem", + }, + projects_empty_state: { + no_projects_yet: "Chưa có dự án", + description: + "Dự án là nền tảng cho công việc theo mục tiêu. Dự án giúp bạn quản lý đội nhóm, nhiệm vụ và mọi thứ cần thiết để hoàn thành công việc.", + learn_more: "Tìm hiểu thêm về dự án", + start_first_project: "Bắt đầu dự án đầu tiên", + }, + profile_activity: { + page_title: "Hồ sơ - Hoạt động", + }, + pages: { + not_found_title: "Không tìm thấy trang", + not_found_description: "Trang bạn đang cố truy cập không tồn tại hoặc bạn không có quyền xem.", + view_other_pages: "Xem các trang khác", + }, + workspace_access: { + not_found_title: "Không tìm thấy workspace", + not_found_description: + "Không tìm thấy không gian làm việc nào cho URL này. Không gian này có thể không tồn tại hoặc bạn không có quyền xem.", + visit_profile: "Xem hồ sơ", + not_authorized_title: "Không được phép!", + not_authorized_description: + "Bạn không phải là thành viên của không gian làm việc này. Hãy liên hệ quản trị viên để nhận lời mời hoặc kiểm tra các lời mời đang chờ.", + check_pending_invites: "Kiểm tra lời mời đang chờ", + }, + editor: { + url: "URL", + enter_or_paste_url: "Nhập hoặc dán URL", + text: "Chữ", + enter_text_to_display: "Nhập văn bản để hiển thị", + remove_link: "Xóa liên kết", + edit_link: "Chỉnh sửa liên kết", + color: "Màu sắc", + text_colors: "Màu văn bản", + background_colors: "Màu nền", + link: "Liên kết", + enter_or_paste_link: "Nhập hoặc dán liên kết", + please_enter_valid_url: "Vui lòng nhập URL hợp lệ", + delete: "Xóa bỏ", + duplicate: "Nhân bản", + multiple: "Nhiều", + loading: "Đang tải", + no_results: "Không có kết quả", + copy_code: "Sao chép mã", + add_an_image: "Thêm một hình ảnh", + error_loading_image: "Lỗi tải hình ảnh", + uploading: "Đang tải lên", + drop_image_here: "Thả hình ảnh ở đây", + retry_duplication: "Thử lại việc sao chép", + retry: "Thử lại", + no_emojis_found: "Không tìm thấy biểu tượng cảm xúc nào", + fullscreen_image_viewer: "Trình xem ảnh toàn màn hình", + close_image_viewer: "Đóng trình xem ảnh", + zoom_out: "Thu nhỏ", + zoom_in: "Phóng to", + download_image: "Tải hình ảnh xuống", + open_image_in_new_tab: "Mở hình ảnh trong tab mới", + view_in_full_screen: "Xem toàn màn hình", + view_image_in_full_screen: "Xem hình ảnh toàn màn hình", + align: "Căn chỉnh", + download: "Tải xuống", + clear_contents: "Xóa nội dung", + insert_above: "Chèn ở trên", + insert_below: "Chèn bên dưới", + insert_left: "Chèn trái", + insert_right: "Chèn bên phải", + header_row: "Hàng tiêu đề", + header_column: "Cột tiêu đề", + alignment: { + left: "Trái", + center: "Giữa", + right: "Phải", + }, + menu_items: { + text: "Chữ", + h1: "Tiêu đề 1", + h2: "Tiêu đề 2", + h3: "Tiêu đề 3", + h4: "Tiêu đề 4", + h5: "Tiêu đề 5", + h6: "Tiêu đề 6", + "bulleted-list": "Danh sách có dấu đầu dòng", + "numbered-list": "Danh sách đánh số", + "to-do-list": "Danh sách việc cần làm", + quote: "Trích dẫn", + code: "Mã", + table: "Bảng", + image: "Hình ảnh", + divider: "Dải phân cách", + link: "Liên kết", + bold: "In đậm", + italic: "Nghiêng", + underline: "Gạch chân", + strikethrough: "Gạch ngang", + "text-color": "Màu văn bản", + "background-color": "Màu nền", + "text-align": "Căn chỉnh văn bản", + }, + }, + workspace_invitation: { + invitation_not_found: "Không tìm thấy lời mời", + invited_to_workspace: "Bạn đã được mời tham gia {workspaceName}", + description: + "Không gian làm việc của bạn là nơi bạn sẽ tạo các dự án, cộng tác trên các mục công việc của mình và sắp xếp các luồng công việc khác nhau trong tài khoản Plane của bạn.", + accept: "Chấp nhận", + ignore: "Phớt lờ", + already_member: "Bạn đã là thành viên của {workspaceName}", + continue_to_home: "Tiếp tục về nhà", + inactive_title: "Liên kết lời mời này không còn hoạt động nữa.", + empty_project_link: "Hoặc bắt đầu từ một dự án trống", + sign_in_to_continue: "Đăng nhập để tiếp tục", + star_on_github: "Gắn sao cho chúng tôi trên GitHub", + join_community: "Tham gia cộng đồng những người sáng tạo tích cực của chúng tôi", + }, + space_auth: { + email: "E-mail", + email_invalid: "Email không hợp lệ", + clear_email: "Xóa email", + password: "Mật khẩu", + set_password: "Đặt mật khẩu", + enter_password: "Nhập mật khẩu", + confirm_password: "Xác nhận mật khẩu", + passwords_dont_match: "Mật khẩu không khớp", + continue: "Tiếp tục", + go_to_workspace: "Đi tới không gian làm việc", + sign_in_with_unique_code: "Đăng nhập bằng mã duy nhất", + create_account: "Tạo tài khoản", + unique_code: "Mã duy nhất", + paste_code_sent: "Dán mã được gửi tới email của bạn", + resend_in: "Gửi lại sau {seconds}s", + requesting_new_code: "Yêu cầu mã mới", + resend: "Gửi lại", + sending_code: "Đang gửi mã", + }, + onboarding: { + create_profile_title: "Tạo hồ sơ của bạn.", + create_profile_description: "Đây là cách bạn sẽ xuất hiện trong Plane.", + change_image: "Thay đổi hình ảnh", + upload_image: "Tải hình ảnh lên", + name: "Tên", + name_required: "Tên là bắt buộc", + name_within_50: "Tên phải trong vòng 50 ký tự.", + enter_full_name: "Nhập tên đầy đủ của bạn", + set_password: "Đặt mật khẩu", + optional: "Không bắt buộc", + passwords_do_not_match: "Mật khẩu không khớp", + passwords_match: "Mật khẩu trùng khớp", + continue: "Tiếp tục", + invite_team_title: "Mời đồng đội của bạn", + invite_team_description: + "Làm việc trong Plane hiệu quả nhất khi có đội nhóm của bạn. Hãy mời họ ngay để tận dụng tối đa Plane.", + invalid_email: "Đó không giống như một địa chỉ email.", + success: "Thành công!", + invitations_sent: "Lời mời đã được gửi thành công.", + error: "Lỗi!", + add_another: "Thêm cái khác", + do_later: "tôi sẽ làm nó sau", + join_invites_title: "Tham gia lời mời hoặc tạo không gian làm việc", + unified_description: "Tất cả công việc của bạn - thống nhất.", + create_new_workspace: "Tạo không gian làm việc mới", + no_invitations_found: "Không tìm thấy lời mời nào", + you_are_invited: "Bạn được mời!", + accept_invites: "Chấp nhận lời mời cộng tác với nhóm của bạn.", + continue_to_workspace: "Tiếp tục đến không gian làm việc", + or: "hoặc", + create_own_workspace: "Tạo không gian làm việc của riêng bạn", + workspace_creation_disabled: + "Có vẻ như bạn không nhận được bất kỳ lời mời nào vào không gian làm việc và quản trị viên phiên bản của bạn đã hạn chế việc tạo không gian làm việc mới. Vui lòng yêu cầu chủ sở hữu hoặc quản trị viên không gian làm việc mời bạn đến không gian làm việc trước và quay lại màn hình này để tham gia.", + create_workspace_title: "Tạo không gian làm việc của bạn", + enter_workspace_name: "Nhập tên không gian làm việc", + join_existing_workspace: "Tham gia không gian làm việc hiện có", + profile_setup_completed: "Thiết lập hồ sơ đã hoàn tất.", + profile_setup_failed: "Thiết lập hồ sơ không thành công.", + usecase_title: "Bạn dự định sử dụng ZXPLaneZ như thế nào?", + usecase_description: "Chọn một hoặc nhiều tùy chọn để chúng tôi có thể cá nhân hóa trải nghiệm của bạn.", + select_one_or_more: "Chọn một hoặc nhiều", + select_at_least_one: "Chọn ít nhất một tùy chọn.", + skip: "Nhảy", + }, + inbox: { + duplicate_issues_found: "Đã tìm thấy {count} mục công việc trùng lặp", + description_versions: { + intake_form_user: "Người dùng biểu mẫu tiếp nhận", + }, + errors: { + asset_upload_failed: "Tải nội dung lên không thành công. Vui lòng thử lại sau.", + asset_duplication_failed: "Sao chép nội dung không thành công. Vui lòng thử lại sau.", + permission_denied: "Quyền bị từ chối", + mark_duplicate_permission: "Chỉ quản trị viên dự án mới có thể đánh dấu mục công việc là trùng lặp", + mark_duplicate_permission_plural: "Chỉ quản trị viên dự án mới có thể đánh dấu các mục công việc là trùng lặp", + }, + filters: { + created_date: "Ngày tạo", + updated_date: "Ngày cập nhật", + last_updated_date: "Ngày cập nhật lần cuối", + status: "Trạng thái", + work_item_status: "Trạng thái mục công việc", + view_all: "Xem tất cả", + view_less: "Xem ít hơn", + date_options: { + today: "Hôm nay", + yesterday: "Hôm qua", + last_7_days: "7 ngày qua", + last_30_days: "30 ngày qua", + }, + date_operators: { + after: "Sau đó", + before: "Trước", + }, + }, + navigation: { + previous_work_item: "Mục công việc trước đó", + next_work_item: "Mục công việc tiếp theo", + }, + properties: { + duplicate_of: "Bản sao của", + }, + select_duplicate: { + select_work_item: "Chọn mục công việc", + }, + sidebar: { + label_count: "Nhãn {count}", + }, + toasts: { + editor_processing: "Trình chỉnh sửa vẫn đang xử lý các thay đổi. Vui lòng đợi trước khi tiếp tục.", + create_success: "Mục công việc được tạo thành công.", + delete_failed: "Xóa mục công việc không thành công", + update_failed: "Cập nhật mục công việc không thành công", + }, + }, + space_public: { + error_description_prefix: + "Plane đã gặp sự cố. Kỹ sư của chúng tôi đã được thông báo. Nếu bạn có thêm chi tiết, vui lòng viết tới", + error_description_middle: "hoặc trên", + not_found_hint: "Kiểm tra URL trong thanh địa chỉ trình duyệt rồi thử lại.", + logged_in_hint: + "Nhập URL chia sẻ công khai hoặc liên kết của chế độ xem hay Trang bạn muốn xem vào thanh địa chỉ trình duyệt.", + oauth_with_provider: "{action} bằng {provider}", + auth: { + sign_in_header: "Đăng nhập để bình chọn hoặc bình luận", + sign_in_subheader: "Góp phần thúc đẩy các tính năng bạn muốn được xây dựng.", + sign_up_header: "Xem, bình luận và làm nhiều việc hơn", + sign_up_subheader: "Đăng ký hoặc đăng nhập để làm việc với các mục công việc và Trang của Plane.", + }, + peek: { + side: "Xem nhanh bên cạnh", + modal: "Hộp thoại", + full_screen: "Toàn màn hình", + }, + bot_name: "Bot {name}", + commented_time: "đã bình luận {time}", + and_more: "và {count} người khác", + no_upvotes_yet: "Chưa có lượt ủng hộ", + no_downvotes_yet: "Chưa có lượt phản đối", + modules_count: "{count} mô-đun", + labels_count: "{count} nhãn", + page_not_found_alt: "Không tìm thấy trang", + something_went_wrong: "Rất tiếc! Đã xảy ra lỗi.", + page_not_found_description: "Trang bạn đang tìm không tồn tại hoặc đã được di chuyển.", + instance_failure_image_alt: "Không thể lấy chi tiết phiên bản", + instance_failure_title: "Không thể lấy chi tiết phiên bản.", + instance_failure_description: "Chúng tôi không thể tải chi tiết phiên bản của bạn.", + instance_failure_hint: "Vui lòng kiểm tra kết nối rồi thử lại.", + powered_by: "Được hỗ trợ bởi", + sign_in_to_add_comment: "Đăng nhập để thêm bình luận", + link_copied: "Đã sao chép liên kết!", + work_item_link_copied: "Đã sao chép liên kết mục công việc vào bảng nhớ tạm.", + comment_post_error: "Không thể đăng bình luận. Vui lòng thử lại.", + add_comment: "Thêm bình luận", + public_board_not_found: "Bảng công khai không tồn tại. Vui lòng kiểm tra URL.", + no_work_items_found: "Không tìm thấy mục công việc", + error_title: "Rất tiếc! Có vẻ không ổn.", + refresh: "Làm mới", + forum: "Diễn đàn", + not_found_title: "Thao tác không thành công", + user_already_logged_in: "Người dùng đã đăng nhập", + logged_in_title: "Tốt rồi! Chỉ còn một bước nữa.", + by_creating_account: "Bằng cách tạo tài khoản", + by_signing_in: "Bằng cách đăng nhập", + you_agree_to_our: "bạn đồng ý với", + terms_of_service: "Điều khoản dịch vụ", + and: "và", + privacy_policy: "Chính sách quyền riêng tư", + sign_up: "Đăng ký", + sign_in: "Đăng nhập", + retry: "Thử lại", + view_less: "Xem ít hơn", + view_all: "Xem tất cả", + no_matches_found: "Không tìm thấy kết quả phù hợp", + no_date: "Không có ngày", + no_cycle: "Không có chu kỳ", + no_modules: "Không có mô-đun", + no_assignees: "Không có người phụ trách", + no_labels: "Không có nhãn", + user: "Người dùng", + }, + }, } as const; diff --git a/packages/i18n/src/locales/zh-CN/translations.ts b/packages/i18n/src/locales/zh-CN/translations.ts index 585ae13aa68..041003cdb4b 100644 --- a/packages/i18n/src/locales/zh-CN/translations.ts +++ b/packages/i18n/src/locales/zh-CN/translations.ts @@ -218,6 +218,8 @@ export default { your_account: "您的账号", security: "安全", activity: "活动", + preferences: "偏好设置", + language_and_time: "语言与时间", appearance: "外观", notifications: "通知", workspaces: "工作区", @@ -231,6 +233,10 @@ export default { something_went_wrong_please_try_again: "出现错误。请重试。", load_more: "加载更多", select_or_customize_your_interface_color_scheme: "选择或自定义您的界面配色方案。", + timezone_setting: "当前时区设置。", + language_setting: "选择用户界面使用的语言。", + settings_moved_to_preferences: "时区和语言设置已移至偏好设置。", + go_to_preferences: "前往偏好设置", theme: "主题", system_preference: "系统偏好", light: "浅色", @@ -514,6 +520,8 @@ export default { new_password_must_be_different_from_old_password: "新密码必须不同于旧密码", edited: "已编辑", bot: "机器人", + settings_description: "在一个地方管理您的账号、工作区和项目偏好设置。在各标签页之间切换以便轻松配置。", + back_to_workspace: "返回工作区", project_view: { sort_by: { created_at: "创建时间", @@ -634,6 +642,7 @@ export default { }, }, common: { + overview: "概览", all: "全部", no_items_in_this_group: "此组中没有项目", drop_here_to_move: "拖放到此处以移动", @@ -807,6 +816,8 @@ export default { show_weekends: "显示周末", enable: "启用", disable: "禁用", + restore: "恢复", + copy_markdown: "复制 Markdown", }, name: "名称", discard: "放弃", @@ -1405,6 +1416,7 @@ export default { label: "添加项目", }, network: { + label: "网络", private: { title: "私有", description: "仅限邀请访问", @@ -1551,6 +1563,25 @@ export default { }, }, }, + preferences: { + heading: "偏好设置", + description: "按照您的工作方式自定义应用体验", + }, + notifications: { + heading: "邮件通知", + description: "保持对您所订阅的工作项的最新动态的了解。启用此功能以接收通知。", + }, + security: { + heading: "安全", + }, + api_tokens: { + heading: "个人访问令牌", + description: "生成安全 API 令牌以将您的数据与外部系统和应用程序集成。", + }, + activity: { + heading: "活动", + description: "跨所有项目和工作项跟踪您的近期操作和变更。", + }, }, workspace_settings: { label: "工作区设置", @@ -1619,14 +1650,20 @@ export default { }, }, billing_and_plans: { + heading: "账单与计划", + description: "选择您的计划、管理订阅,并随着需求的增长轻松升级。", title: "账单与计划", current_plan: "当前计划", free_plan: "您目前使用的是免费计划", view_plans: "查看计划", }, exports: { + heading: "导出", + description: "以各种格式导出项目数据,并访问包含下载链接的导出历史记录。", title: "导出", exporting: "导出中", + exporting_projects: "正在导出项目", + format: "格式", previous_exports: "以前的导出", export_separate_files: "将数据导出为单独的文件", filters_info: "应用筛选器以根据您的条件导出特定工作项。", @@ -1645,6 +1682,8 @@ export default { }, }, webhooks: { + heading: "Webhooks", + description: "当项目事件发生时,自动向外部服务发送通知。", title: "Webhooks", add_webhook: "添加 webhook", modal: { @@ -1770,6 +1809,8 @@ export default { activity: "活动", appearance: "外观", notifications: "通知", + preferences: "偏好设置", + "api-tokens": "个人访问令牌", }, tabs: { summary: "摘要", @@ -1832,6 +1873,8 @@ export default { }, }, states: { + heading: "状态", + description: "定义和自定义工作流程状态以跟踪工作项的进度。", describe_this_state_for_your_members: "为您的成员描述此状态。", empty_state: { title: "{groupKey} 组中没有状态", @@ -1839,6 +1882,8 @@ export default { }, }, labels: { + heading: "标签", + description: "创建自定义标签以对工作项进行分类和整理", label_title: "标签标题", label_title_is_required: "标签标题为必填项", label_max_char: "标签名称不应超过255个字符", @@ -1847,9 +1892,11 @@ export default { }, }, estimates: { + heading: "估算", + description: "设置估算系统以跟踪和传达每个工作项所需的工作量。", label: "估算", title: "为我的项目启用估算", - description: "它们有助于您传达团队的复杂性和工作量。", + enable_description: "它们有助于您传达团队的复杂性和工作量。", no_estimate: "无估算", new: "新估算系统", create: { @@ -1899,6 +1946,25 @@ export default { }, }, }, + systems: { + points: { + label: "点数", + fibonacci: "斐波那契", + linear: "线性", + squares: "平方", + custom: "自定义", + }, + categories: { + label: "分类", + t_shirt_sizes: "T恤尺码", + easy_to_hard: "从简单到困难", + custom: "自定义", + }, + time: { + label: "时间", + hours: "小时", + }, + }, validation: { min_length: "估算需要大于0。", unable_to_process: "我们无法处理您的请求,请重试。", @@ -1912,6 +1978,8 @@ export default { }, automations: { label: "自动化", + heading: "自动化", + description: "配置自动化操作以简化项目管理流程并减少手动任务。", "auto-archive": { title: "自动归档已关闭的工作项", description: "Plane 将自动归档已完成或已取消的工作项。", @@ -2623,4 +2691,502 @@ export default { close_button: "关闭导航面板", outline_floating_button: "打开大纲", }, + project_members: { + full_name: "全名", + display_name: "显示名称", + email: "邮箱", + joining_date: "加入日期", + role: "角色", + }, + power_k: { + contextual_actions: { + work_item: { + title: "工作项操作", + indicator: "工作项", + change_state: "更改状态", + change_priority: "更改优先级", + change_assignees: "分配给", + assign_to_me: "分配给我", + unassign_from_me: "从我这里取消分配", + change_estimate: "更改估算", + add_to_cycle: "添加到周期", + add_to_modules: "添加到模块", + add_labels: "添加标签", + subscribe: "订阅通知", + unsubscribe: "取消订阅通知", + delete: "删除", + copy_id: "复制 ID", + copy_id_toast_success: "工作项 ID 已复制到剪贴板。", + copy_id_toast_error: "复制工作项 ID 到剪贴板时发生错误。", + copy_title: "复制标题", + copy_title_toast_success: "工作项标题已复制到剪贴板。", + copy_title_toast_error: "复制工作项标题到剪贴板时发生错误。", + copy_url: "复制 URL", + copy_url_toast_success: "工作项 URL 已复制到剪贴板。", + copy_url_toast_error: "复制工作项 URL 到剪贴板时发生错误。", + }, + cycle: { + title: "周期操作", + indicator: "周期", + add_to_favorites: "添加到收藏", + remove_from_favorites: "从收藏中移除", + copy_url: "复制 URL", + copy_url_toast_success: "周期 URL 已复制到剪贴板。", + copy_url_toast_error: "复制周期 URL 到剪贴板时发生错误。", + }, + module: { + title: "模块操作", + indicator: "模块", + add_remove_members: "添加/移除成员", + change_status: "更改状态", + add_to_favorites: "添加到收藏", + remove_from_favorites: "从收藏中移除", + copy_url: "复制 URL", + copy_url_toast_success: "模块 URL 已复制到剪贴板。", + copy_url_toast_error: "复制模块 URL 到剪贴板时发生错误。", + }, + page: { + title: "页面操作", + indicator: "页面", + lock: "锁定", + unlock: "解锁", + make_private: "设为私有", + make_public: "设为公开", + archive: "归档", + restore: "恢复", + add_to_favorites: "添加到收藏", + remove_from_favorites: "从收藏中移除", + copy_url: "复制 URL", + copy_url_toast_success: "页面 URL 已复制到剪贴板。", + copy_url_toast_error: "复制页面 URL 到剪贴板时发生错误。", + }, + }, + creation_actions: { + create_work_item: "新建工作项", + create_page: "新建页面", + create_view: "新建视图", + create_cycle: "新建周期", + create_module: "新建模块", + create_project: "新建项目", + create_workspace: "新建工作区", + }, + navigation_actions: { + open_workspace: "打开工作区", + nav_home: "前往主页", + nav_inbox: "前往收件箱", + nav_your_work: "前往我的工作", + nav_account_settings: "前往账号设置", + open_project: "打开项目", + nav_projects_list: "前往项目列表", + nav_all_workspace_work_items: "前往所有工作项", + nav_assigned_workspace_work_items: "前往已分配的工作项", + nav_created_workspace_work_items: "前往我创建的工作项", + nav_subscribed_workspace_work_items: "前往我订阅的工作项", + nav_workspace_analytics: "前往工作区分析", + nav_workspace_drafts: "前往工作区草稿", + nav_workspace_archives: "前往工作区归档", + open_workspace_setting: "打开工作区设置", + nav_workspace_settings: "前往工作区设置", + nav_project_work_items: "前往工作项", + open_project_cycle: "打开周期", + nav_project_cycles: "前往周期", + open_project_module: "打开模块", + nav_project_modules: "前往模块", + open_project_view: "打开项目视图", + nav_project_views: "前往项目视图", + nav_project_pages: "前往页面", + nav_project_intake: "前往收集", + nav_project_archives: "前往项目归档", + open_project_setting: "打开项目设置", + nav_project_settings: "前往项目设置", + }, + account_actions: { + sign_out: "退出登录", + workspace_invites: "工作区邀请", + }, + miscellaneous_actions: { + toggle_app_sidebar: "切换应用侧边栏", + copy_current_page_url: "复制当前页面 URL", + copy_current_page_url_toast_success: "当前页面 URL 已复制到剪贴板。", + copy_current_page_url_toast_error: "复制当前页面 URL 到剪贴板时发生错误。", + focus_top_nav_search: "聚焦顶部导航搜索", + }, + preferences_actions: { + update_theme: "更改界面主题", + update_timezone: "更改时区", + update_start_of_week: "更改每周起始日", + update_language: "更改界面语言", + toast: { + theme: { + success: "主题更新成功。", + error: "主题更新失败。请重试。", + }, + timezone: { + success: "时区更新成功。", + error: "时区更新失败。请重试。", + }, + generic: { + success: "偏好设置更新成功。", + error: "偏好设置更新失败。请重试。", + }, + }, + }, + help_actions: { + open_keyboard_shortcuts: "打开键盘快捷键", + open_plane_documentation: "打开 Plane 文档", + join_forum: "加入论坛", + report_bug: "报告问题", + chat_with_us: "联系我们", + }, + page_placeholders: { + default: "输入命令或搜索", + open_workspace: "打开工作区", + open_project: "打开项目", + open_workspace_setting: "打开工作区设置", + open_project_cycle: "打开周期", + open_project_module: "打开模块", + open_project_view: "打开项目视图", + open_project_setting: "打开项目设置", + update_work_item_state: "更改状态", + update_work_item_priority: "更改优先级", + update_work_item_assignee: "分配给", + update_work_item_estimate: "更改估算", + update_work_item_cycle: "添加到周期", + update_work_item_module: "添加到模块", + update_work_item_labels: "添加标签", + update_module_member: "更改成员", + update_module_status: "更改状态", + update_theme: "更改主题", + update_timezone: "更改时区", + update_start_of_week: "更改每周起始日", + update_language: "更改语言", + }, + search_menu: { + no_results: "未找到结果", + clear_search: "清除搜索", + }, + footer: { + workspace_level: "工作区级别", + }, + group_titles: { + contextual: "上下文", + navigation: "导航", + create: "创建", + general: "常规", + settings: "设置", + account: "账号", + miscellaneous: "杂项", + preferences: "偏好设置", + help: "帮助", + }, + }, + // Navigation customization + customize_navigation: "自定义导航", + personal: "个人", + accordion_navigation_control: "手风琴式侧边栏导航", + horizontal_navigation_bar: "标签页导航", + show_limited_projects_on_sidebar: "在侧边栏显示有限项目", + enter_number_of_projects: "输入项目数量", + pin: "固定", + unpin: "取消固定", + localized_ui: { + not_found: { + alt: "404 - 找不到页面", + title: "哎呀,出了点问题。", + description: "抱歉,找不到您要访问的页面。它可能已被移除、重命名,或暂时不可用。", + go_to_home: "返回首页", + }, + workspace_views: { + page_title: "{workspaceName} - 全部视图", + }, + projects_empty_state: { + no_projects_yet: "暂无项目", + description: "项目是目标驱动工作的基础。你可以用项目管理团队、任务以及完成工作所需的一切。", + learn_more: "了解更多项目内容", + start_first_project: "开始你的第一个项目", + }, + profile_activity: { + page_title: "个人资料 - 活动", + }, + pages: { + not_found_title: "找不到页面", + not_found_description: "你尝试访问的页面不存在,或你没有权限查看。", + view_other_pages: "查看其他页面", + }, + workspace_access: { + not_found_title: "找不到工作区", + not_found_description: "此 URL 对应的工作区不存在,或你没有权限查看。", + visit_profile: "访问个人资料", + not_authorized_title: "未授权!", + not_authorized_description: "你不是此工作区的成员。请联系工作区管理员邀请你加入,或检查待处理的邀请。", + check_pending_invites: "查看待处理邀请", + }, + editor: { + url: "URL", + enter_or_paste_url: "输入或粘贴 URL", + text: "文本", + enter_text_to_display: "输入要显示的文本", + remove_link: "移除链接", + edit_link: "编辑链接", + color: "颜色", + text_colors: "文字颜色", + background_colors: "背景颜色", + link: "链接", + enter_or_paste_link: "输入或粘贴链接", + please_enter_valid_url: "请输入有效的URL", + delete: "删除", + duplicate: "复制", + multiple: "多个", + loading: "加载中", + no_results: "没有结果", + copy_code: "复制代码", + add_an_image: "添加图像", + error_loading_image: "加载图像时出错", + uploading: "上传中", + drop_image_here: "将图像拖放到此处", + retry_duplication: "重试复制", + retry: "重试", + no_emojis_found: "没有找到表情符号", + fullscreen_image_viewer: "全屏图像查看器", + close_image_viewer: "关闭图像查看器", + zoom_out: "缩小", + zoom_in: "放大", + download_image: "下载图片", + open_image_in_new_tab: "在新选项卡中打开图像", + view_in_full_screen: "全屏查看", + view_image_in_full_screen: "全屏查看图像", + align: "对齐", + download: "下载", + clear_contents: "清除内容", + insert_above: "在上面插入", + insert_below: "在下面插入", + insert_left: "向左插入", + insert_right: "向右插入", + header_row: "标题行", + header_column: "标题列", + alignment: { + left: "左对齐", + center: "居中", + right: "右对齐", + }, + menu_items: { + text: "文本", + h1: "标题 1", + h2: "标题 2", + h3: "标题 3", + h4: "标题 4", + h5: "标题 5", + h6: "标题 6", + "bulleted-list": "项目符号列表", + "numbered-list": "编号列表", + "to-do-list": "待办事项清单", + quote: "引用", + code: "代码", + table: "表格", + image: "图像", + divider: "分隔线", + link: "链接", + bold: "加粗", + italic: "斜体", + underline: "下划线", + strikethrough: "删除线", + "text-color": "文字颜色", + "background-color": "背景颜色", + "text-align": "文本对齐", + }, + }, + workspace_invitation: { + invitation_not_found: "未找到邀请", + invited_to_workspace: "你已受邀加入 {workspaceName}", + description: "工作区用于创建项目、协作处理工作项,并在 Plane 账户中组织不同的工作流。", + accept: "接受", + ignore: "忽略", + already_member: "你已经是 {workspaceName} 的成员", + continue_to_home: "返回主页", + inactive_title: "此邀请链接已失效。", + empty_project_link: "或从空项目开始", + sign_in_to_continue: "登录以继续", + star_on_github: "在 GitHub 上给我们加星", + join_community: "加入我们的创作者社区", + }, + space_auth: { + email: "邮箱", + email_invalid: "邮箱格式无效", + clear_email: "清空邮箱", + password: "密码", + set_password: "设置密码", + enter_password: "输入密码", + confirm_password: "确认密码", + passwords_dont_match: "密码不匹配", + continue: "继续", + go_to_workspace: "前往工作区", + sign_in_with_unique_code: "使用唯一码登录", + create_account: "创建账号", + unique_code: "唯一码", + paste_code_sent: "粘贴发送到你邮箱的验证码", + resend_in: "{seconds} 秒后重新发送", + requesting_new_code: "正在请求新验证码", + resend: "重新发送", + sending_code: "正在发送验证码", + }, + onboarding: { + create_profile_title: "创建你的个人资料。", + create_profile_description: "这是你在 Plane 中显示给他人的信息。", + change_image: "更换图片", + upload_image: "上传图片", + name: "姓名", + name_required: "姓名为必填项", + name_within_50: "姓名必须在 50 个字符以内。", + enter_full_name: "输入你的全名", + set_password: "设置密码", + optional: "可选", + passwords_do_not_match: "密码不匹配", + passwords_match: "密码匹配", + continue: "继续", + invite_team_title: "邀请你的队友", + invite_team_description: "Plane 最适合团队协作使用。现在邀请团队成员,充分发挥 Plane 的价值。", + invalid_email: "这看起来不像有效的邮箱地址。", + success: "成功!", + invitations_sent: "邀请已成功发送。", + error: "错误!", + add_another: "再添加一个", + do_later: "稍后再说", + join_invites_title: "加入邀请或创建工作区", + unified_description: "所有工作,统一管理。", + create_new_workspace: "创建新工作区", + no_invitations_found: "未找到邀请", + you_are_invited: "你收到了邀请!", + accept_invites: "接受邀请,与团队一起协作。", + continue_to_workspace: "继续前往工作区", + or: "或", + create_own_workspace: "创建自己的工作区", + workspace_creation_disabled: + "你似乎没有任何工作区邀请,且实例管理员已限制创建新工作区。请先让工作区所有者或管理员邀请你加入工作区,然后回到此页面继续。", + create_workspace_title: "创建你的工作区", + enter_workspace_name: "输入工作区名称", + join_existing_workspace: "加入现有工作区", + profile_setup_completed: "个人资料设置完成。", + profile_setup_failed: "配置文件设置失败。", + usecase_title: "您打算如何使用 Plane?", + usecase_description: "选择一个或多个选项,以便我们为您提供个性化体验。", + select_one_or_more: "选择一个或多个", + select_at_least_one: "至少选择一个选项。", + skip: "跳过", + }, + inbox: { + duplicate_issues_found: "发现 {count} 个重复工作项", + description_versions: { + intake_form_user: "收集表单用户", + }, + errors: { + asset_upload_failed: "资源上传失败。请稍后重试。", + asset_duplication_failed: "资产复制失败。请稍后重试。", + permission_denied: "没有权限", + mark_duplicate_permission: "只有项目管理员可以将工作项标记为重复", + mark_duplicate_permission_plural: "只有项目管理员可以将工作项标记为重复", + }, + filters: { + created_date: "创建日期", + updated_date: "更新日期", + last_updated_date: "最后更新日期", + status: "状态", + work_item_status: "工作项状态", + view_all: "查看全部", + view_less: "查看较少", + date_options: { + today: "今天", + yesterday: "昨天", + last_7_days: "过去 7 天", + last_30_days: "过去 30 天", + }, + date_operators: { + after: "后", + before: "前", + }, + }, + navigation: { + previous_work_item: "上一个工作项", + next_work_item: "下一个工作项", + }, + properties: { + duplicate_of: "重复于", + }, + select_duplicate: { + select_work_item: "选择工作项", + }, + sidebar: { + label_count: "{count} 标签", + }, + toasts: { + editor_processing: "编辑器仍在处理更改。请稍候再继续。", + create_success: "工作项创建成功。", + delete_failed: "工作项删除失败", + update_failed: "工作项更新失败", + }, + }, + space_public: { + error_title: "糟糕,看起来不太妙。", + error_description_prefix: "Plane 崩溃了。别担心,我们的工程师已经收到通知。如果你有更多细节,请写信到", + error_description_middle: "或前往我们的", + forum: "论坛", + refresh: "刷新", + not_found_title: "这个链接无法打开", + not_found_hint: "请检查浏览器地址栏中的 URL,然后重试。", + user_already_logged_in: "用户已登录", + logged_in_title: "很好,还差最后一步。", + logged_in_hint: "请在浏览器地址栏中输入你要查看的公开分享视图或页面 URL。", + by_creating_account: "创建账户即表示", + by_signing_in: "登录即表示", + you_agree_to_our: "你同意我们的", + terms_of_service: "服务条款", + and: "和", + privacy_policy: "隐私政策", + sign_up: "注册", + oauth_with_provider: "使用 {provider} {action}", + auth: { + sign_in_header: "登录后即可投票或评论", + sign_in_subheader: "为你希望构建的功能提供反馈。", + sign_up_header: "查看、评论并执行更多操作", + sign_up_subheader: "注册或登录后即可处理 Plane 工作项和页面。", + }, + peek: { + side: "侧边预览", + modal: "弹窗", + full_screen: "全屏", + }, + bot_name: "{name} 机器人", + commented_time: "评论于 {time}", + and_more: "还有 {count} 个", + no_upvotes_yet: "暂无赞成票", + no_downvotes_yet: "暂无反对票", + view_less: "收起", + view_all: "查看全部", + no_matches_found: "未找到匹配项", + no_date: "无日期", + no_cycle: "无周期", + no_modules: "无模块", + modules_count: "{count} 个模块", + no_assignees: "无负责人", + labels_count: "{count} 个标签", + page_not_found_alt: "找不到页面", + something_went_wrong: "哎呀!出了点问题。", + page_not_found_description: "您要查找的页面不存在或已被移动。", + instance_failure_image_alt: "无法获取实例详细信息", + instance_failure_title: "无法获取实例详细信息。", + instance_failure_description: "我们无法加载您的实例详细信息。", + instance_failure_hint: "请检查您的连接并重试。", + retry: "重试", + powered_by: "提供支持", + sign_in_to_add_comment: "登录以添加评论", + sign_in: "登录", + link_copied: "链接已复制!", + work_item_link_copied: "工作项链接已复制到剪贴板。", + comment_post_error: "无法发表评论。请再试一次。", + add_comment: "添加评论", + public_board_not_found: "公开看板不存在。请检查 URL。", + no_work_items_found: "未找到工作项", + no_labels: "无标签", + user: "用户", + }, + }, } as const; diff --git a/packages/i18n/src/locales/zh-TW/translations.ts b/packages/i18n/src/locales/zh-TW/translations.ts index 1fcf528fb1d..8158e8dd7ea 100644 --- a/packages/i18n/src/locales/zh-TW/translations.ts +++ b/packages/i18n/src/locales/zh-TW/translations.ts @@ -2644,4 +2644,304 @@ export default { close_button: "關閉導航面板", outline_floating_button: "打開大綱", }, + localized_ui: { + not_found: { + alt: "404 - 找不到頁面", + title: "糟糕,發生了一些問題。", + description: "抱歉,找不到您要前往的頁面。它可能已被移除、重新命名,或暫時無法使用。", + go_to_home: "返回首頁", + }, + workspace_views: { + page_title: "{workspaceName} - 全部檢視", + }, + projects_empty_state: { + no_projects_yet: "尚無專案", + description: "專案是目標導向工作的基礎。你可以用專案管理團隊、任務,以及完成工作所需的一切。", + learn_more: "了解更多專案內容", + start_first_project: "開始你的第一個專案", + }, + profile_activity: { + page_title: "個人資料 - 活動", + }, + pages: { + not_found_title: "找不到頁面", + not_found_description: "你嘗試存取的頁面不存在,或你沒有權限檢視。", + view_other_pages: "檢視其他頁面", + }, + workspace_access: { + not_found_title: "找不到工作區", + not_found_description: "此 URL 對應的工作區不存在,或你沒有權限檢視。", + visit_profile: "前往個人資料", + not_authorized_title: "未授權!", + not_authorized_description: "你不是此工作區的成員。請聯絡工作區管理員邀請你加入,或檢查待處理的邀請。", + check_pending_invites: "查看待處理邀請", + }, + editor: { + url: "網址", + enter_or_paste_url: "輸入或貼上網址", + text: "文字", + enter_text_to_display: "輸入要顯示的文字", + remove_link: "刪除連結", + edit_link: "編輯連結", + color: "顏色", + text_colors: "文字顏色", + background_colors: "背景顏色", + link: "連結", + enter_or_paste_link: "輸入或貼上連結", + please_enter_valid_url: "請輸入有效的URL", + delete: "刪除", + duplicate: "複製", + multiple: "多個", + loading: "載入中", + no_results: "沒有結果", + copy_code: "複製程式碼", + add_an_image: "新增影像", + error_loading_image: "載入圖片時出錯", + uploading: "上傳中", + drop_image_here: "將圖像拖放到此處", + retry_duplication: "重試複製", + retry: "重試", + no_emojis_found: "沒有找到表情符號", + fullscreen_image_viewer: "全螢幕影像檢視器", + close_image_viewer: "關閉影像檢視器", + zoom_out: "縮小", + zoom_in: "放大", + download_image: "下載圖片", + open_image_in_new_tab: "在新分頁中開啟圖像", + view_in_full_screen: "全螢幕檢視", + view_image_in_full_screen: "全螢幕檢視影像", + align: "對齊", + download: "下載", + clear_contents: "清除內容", + insert_above: "在上面插入", + insert_below: "在下面插入", + insert_left: "向左插入", + insert_right: "向右插入", + header_row: "標題行", + header_column: "標題列", + alignment: { + left: "左對齊", + center: "置中", + right: "右對齊", + }, + menu_items: { + text: "文字", + h1: "標題 1", + h2: "標題 2", + h3: "標題 3", + h4: "標題 4", + h5: "標題 5", + h6: "標題 6", + "bulleted-list": "項目符號列表", + "numbered-list": "編號列表", + "to-do-list": "待辦事項清單", + quote: "引用", + code: "程式碼", + table: "表格", + image: "影像", + divider: "分隔線", + link: "連結", + bold: "粗體", + italic: "斜體", + underline: "底線", + strikethrough: "刪除線", + "text-color": "文字顏色", + "background-color": "背景顏色", + "text-align": "文字對齊", + }, + }, + workspace_invitation: { + invitation_not_found: "未找到邀請", + invited_to_workspace: "您已被邀請加入 {workspaceName}", + description: "您可以在工作區中建立專案、協作處理工作專案以及在 Plane 帳戶中組織不同的工作流程。", + accept: "接受", + ignore: "忽略", + already_member: "您已經是 {workspaceName} 的會員", + continue_to_home: "繼續回家", + inactive_title: "此邀請連結不再有效。", + empty_project_link: "或從一個空項目開始", + sign_in_to_continue: "登入以繼續", + star_on_github: "在 GitHub 上給我們加星標", + join_community: "加入我們的活躍創作者社群", + }, + space_auth: { + email: "電子郵件", + email_invalid: "電子郵件無效", + clear_email: "清除電子郵件", + password: "密碼", + set_password: "設定密碼", + enter_password: "輸入密碼", + confirm_password: "確認密碼", + passwords_dont_match: "密碼不匹配", + continue: "繼續", + go_to_workspace: "轉到工作區", + sign_in_with_unique_code: "使用唯一代碼登入", + create_account: "建立帳戶", + unique_code: "唯一代碼", + paste_code_sent: "貼上發送到您的電子郵件的代碼", + resend_in: "在 {seconds}s 中重新傳送", + requesting_new_code: "請求新代碼", + resend: "重新發送", + sending_code: "傳送代碼", + }, + onboarding: { + create_profile_title: "建立您的個人資料。", + create_profile_description: "這就是您在 Plane 中的顯示方式。", + change_image: "更改圖像", + upload_image: "上傳圖片", + name: "姓名", + name_required: "姓名為必填項", + name_within_50: "名稱必須在 50 個字元以內。", + enter_full_name: "輸入您的全名", + set_password: "設定密碼", + optional: "選修的", + passwords_do_not_match: "密碼不匹配", + passwords_match: "密碼匹配", + continue: "繼續", + invite_team_title: "邀請你的隊友", + invite_team_description: "在 Plane 的工作最適合您的團隊。現在邀請他們充分發揮 Plane 的潛力。", + invalid_email: "這看起來不像電子郵件地址。", + success: "成功!", + invitations_sent: "邀請已成功發送。", + error: "錯誤!", + add_another: "添加另一個", + do_later: "我稍後會做", + join_invites_title: "加入邀請或創建工作區", + unified_description: "您的所有工作 — 統一。", + create_new_workspace: "建立新工作區", + no_invitations_found: "未找到邀請", + you_are_invited: "誠摯邀請您!", + accept_invites: "接受邀請與您的團隊合作。", + continue_to_workspace: "繼續工作區", + or: "或者", + create_own_workspace: "創建您自己的工作空間", + workspace_creation_disabled: + "您似乎沒有任何工作區邀請,而您的實例管理員限制了新工作區的建立。請讓工作區擁有者或管理員先邀請您加入工作區,然後再回到此畫面加入。", + create_workspace_title: "創建您的工作空間", + enter_workspace_name: "輸入工作區名稱", + join_existing_workspace: "加入現有工作區", + profile_setup_completed: "個人資料設定完成。", + profile_setup_failed: "設定檔設定失敗。", + usecase_title: "您打算如何使用 Plane?", + usecase_description: "選擇一個或多個選項,以便我們為您提供個人化體驗。", + select_one_or_more: "選擇一個或多個", + select_at_least_one: "至少選擇一個選項。", + skip: "跳過", + }, + inbox: { + duplicate_issues_found: "發現 {count} 個重複工作項", + description_versions: { + intake_form_user: "收集表單使用者", + }, + errors: { + asset_upload_failed: "資源上傳失敗。請稍後重試。", + asset_duplication_failed: "資產複製失敗。請稍後重試。", + permission_denied: "沒有權限", + mark_duplicate_permission: "只有專案管理員可以將工作項目標記為重複", + mark_duplicate_permission_plural: "只有專案管理員可以將工作項目標記為重複", + }, + filters: { + created_date: "建立日期", + updated_date: "更新日期", + last_updated_date: "最後更新日期", + status: "狀態", + work_item_status: "工作項狀態", + view_all: "看全部", + view_less: "查看較少", + date_options: { + today: "今天", + yesterday: "昨天", + last_7_days: "過去 7 天", + last_30_days: "過去 30 天", + }, + date_operators: { + after: "後", + before: "前", + }, + }, + navigation: { + previous_work_item: "上一個工作項", + next_work_item: "下一個工作項", + }, + properties: { + duplicate_of: "重複於", + }, + select_duplicate: { + select_work_item: "選擇工作項", + }, + sidebar: { + label_count: "{count} 標籤", + }, + toasts: { + editor_processing: "編輯器仍在處理更改。請稍候再繼續。", + create_success: "工作項目建立成功。", + delete_failed: "工作項目刪除失敗", + update_failed: "工作項目更新失敗", + }, + }, + space_public: { + error_title: "糟糕,看起來不太妙。", + error_description_prefix: "Plane 當掉了。別擔心,我們的工程師已收到通知。如果你有更多細節,請寫信到", + error_description_middle: "或前往我們的", + forum: "論壇", + refresh: "重新整理", + not_found_title: "這個連結無法開啟", + not_found_hint: "請檢查瀏覽器位址列中的 URL,然後再試一次。", + user_already_logged_in: "使用者已登入", + logged_in_title: "很好,還差最後一步。", + logged_in_hint: "請在瀏覽器位址列中輸入你要查看的公開分享檢視或頁面 URL。", + by_creating_account: "建立帳戶即表示", + by_signing_in: "登入即表示", + you_agree_to_our: "你同意我們的", + terms_of_service: "服務條款", + and: "和", + privacy_policy: "隱私權政策", + sign_up: "註冊", + oauth_with_provider: "使用 {provider} {action}", + auth: { + sign_in_header: "登入後即可投票或評論", + sign_in_subheader: "為你希望建置的功能提供回饋。", + sign_up_header: "查看、評論並執行更多操作", + sign_up_subheader: "註冊或登入後即可處理 Plane 工作項目和頁面。", + }, + peek: { + side: "側邊預覽", + modal: "彈窗", + full_screen: "全螢幕", + }, + bot_name: "{name} 機器人", + commented_time: "評論於 {time}", + and_more: "還有 {count} 個", + no_upvotes_yet: "暫無贊成票", + no_downvotes_yet: "暫無反對票", + view_less: "收起", + view_all: "查看全部", + no_matches_found: "未找到相符項目", + no_date: "無日期", + no_cycle: "無週期", + no_modules: "無模組", + modules_count: "{count} 個模組", + no_assignees: "無負責人", + labels_count: "{count} 個標籤", + page_not_found_alt: "找不到頁面", + something_went_wrong: "糟糕!出了點問題。", + page_not_found_description: "你要尋找的頁面不存在或已被移動。", + instance_failure_image_alt: "無法取得執行個體詳細資訊", + instance_failure_title: "無法取得執行個體詳細資訊。", + instance_failure_description: "我們無法載入你的執行個體詳細資訊。", + instance_failure_hint: "請檢查連線並重試。", + retry: "重試", + powered_by: "技術支援", + sign_in_to_add_comment: "登入以新增評論", + sign_in: "登入", + link_copied: "連結已複製!", + work_item_link_copied: "工作項目連結已複製到剪貼簿。", + comment_post_error: "評論發布失敗。請再試一次。", + add_comment: "新增評論", + public_board_not_found: "公開看板不存在。請檢查 URL。", + no_work_items_found: "未找到工作項", + no_labels: "無標籤", + user: "使用者", + }, + }, } as const; diff --git a/packages/propel/src/banner/banner.tsx b/packages/propel/src/banner/banner.tsx index 6afab1248f3..4227e64fa40 100644 --- a/packages/propel/src/banner/banner.tsx +++ b/packages/propel/src/banner/banner.tsx @@ -32,6 +32,8 @@ export interface BannerProps extends Omit, visible?: boolean; /** Animation duration for show/hide */ animationDuration?: number; + /** Accessible label for the dismiss button */ + dismissLabel?: string; } export const Banner = React.forwardRef(function Banner( @@ -44,6 +46,7 @@ export const Banner = React.forwardRef(function Banner( onDismiss, visible = true, animationDuration = 200, + dismissLabel = "Dismiss banner", className, children, ...props @@ -83,7 +86,7 @@ export const Banner = React.forwardRef(function Banner( if (!dismissible) return null; return ( -