Skip to content

Commit 9b4e086

Browse files
chore project settings language support (#6502)
* chore: project settings language support * chore: code refactor
1 parent 394bb6d commit 9b4e086

File tree

16 files changed

+206
-83
lines changed

16 files changed

+206
-83
lines changed

packages/i18n/src/locales/en/translations.json

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
"description": "Description",
1515
"search": "Search",
1616
"add_member": "Add member",
17+
"adding_members": "Adding members",
18+
"no_matching_members": "No matching members",
1719
"remove_member": "Remove member",
1820
"add_members": "Add members",
21+
"adding_member": "Adding members",
1922
"remove_members": "Remove members",
2023
"add": "Add",
2124
"adding": "Adding",
@@ -184,6 +187,10 @@
184187
"description_placeholder": "Description...",
185188
"only_alphanumeric_non_latin_characters_allowed": "Only Alphanumeric & Non-latin characters are allowed.",
186189
"project_id_is_required": "Project ID is required",
190+
"project_id_allowed_char": "Only Alphanumeric & Non-latin characters are allowed.",
191+
"project_id_min_char": "Project ID must at least be of 1 character",
192+
"project_id_max_char": "Project ID must at most be of 5 characters",
193+
"project_description_placeholder": "Enter project description",
187194
"select_network": "Select network",
188195
"lead": "Lead",
189196
"date_range": "Date range",
@@ -515,6 +522,20 @@
515522
"description": "Description",
516523
"title": "Title",
517524
"attachment": "Attachment",
525+
"general": "General",
526+
"features": "Features",
527+
"automation": "Automation",
528+
"project_name": "Project name",
529+
"project_id": "Project ID",
530+
"project_timezone": "Project Timezone",
531+
"created_on": "Created on",
532+
"update_project": "Update project",
533+
"identifier_already_exists": "Identifier already exists",
534+
"add_more": "Add more",
535+
"defaults": "Defaults",
536+
"add_label": "Add label",
537+
"estimates": "estimates",
538+
"customize_time_range": "Customize time range",
518539
"loading": "Loading...",
519540
"attachments": "Attachments",
520541
"properties": "Properties",
@@ -1229,10 +1250,77 @@
12291250
},
12301251

12311252
"project_settings": {
1253+
"general": {
1254+
"enter_project_id": "Enter project ID",
1255+
"please_select_a_timezone": "Please select a timezone",
1256+
"archive_project": {
1257+
"title": "Archive project",
1258+
"description": "Archiving a project will unlist your project from your side navigation although you will still be able to access it from your projects page. You can restore the project or delete it whenever you want.",
1259+
"button": "Archive project"
1260+
},
1261+
"delete_project": {
1262+
"title": "Delete project",
1263+
"description": "When deleting a project, all of the data and resources within that project will be permanently removed and cannot be recovered.",
1264+
"button": "Delete my project"
1265+
},
1266+
"toast": {
1267+
"success": "Project updated successfully",
1268+
"error": "Project could not be updated. Please try again."
1269+
}
1270+
},
1271+
"members": {
1272+
"label": "Members",
1273+
"project_lead": "Project lead",
1274+
"default_assignee": "Default assignee",
1275+
"guest_super_permissions": {
1276+
"title": "Grant view access to all issues for guest users:",
1277+
"sub_heading": "This will allow guests to have view access to all the project issues."
1278+
},
1279+
"invite_members": {
1280+
"title": "Invite members",
1281+
"sub_heading": "Invite members to work on your project.",
1282+
"select_co_worker": "Select co-worker"
1283+
}
1284+
},
1285+
"states": {
1286+
"describe_this_state_for_your_members": "Describe this state for your members."
1287+
},
1288+
"labels": {
1289+
"label_title": "Label title",
1290+
"label_title_is_required": "Label title is required",
1291+
"label_max_char": "Label name should not exceed 255 characters",
1292+
"toast": {
1293+
"error": "Error while updating the label"
1294+
}
1295+
},
1296+
"estimates": {
1297+
"title": "Enable estimates for my project",
1298+
"description": "They help you in communicating complexity and workload of the team."
1299+
},
1300+
"automations": {
1301+
"label": "Automations",
1302+
"auto-archive": {
1303+
"title": "Auto-archive closed issues",
1304+
"description": "Plane will auto archive issues that have been completed or canceled.",
1305+
"duration": "Auto-archive issues that are closed for"
1306+
},
1307+
"auto-close": {
1308+
"title": "Auto-close issues",
1309+
"description": "Plane will automatically close issues that haven't been completed or canceled.",
1310+
"duration": "Auto-close issues that are inactive for",
1311+
"auto_close_status": "Auto-close status"
1312+
}
1313+
},
1314+
12321315
"empty_state": {
12331316
"labels": {
12341317
"title": "No labels yet",
12351318
"description": "Create labels to help organize and filter issues in you project."
1319+
},
1320+
"estimates": {
1321+
"title": "No estimate systems yet",
1322+
"description": "Create a set of estimates to communicate the amount of work per issue.",
1323+
"primary_button": "Add estimate system"
12361324
}
12371325
}
12381326
},

web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/automations/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { observer } from "mobx-react";
55
import { useParams } from "next/navigation";
66
import { IProject } from "@plane/types";
77
// ui
8+
import { useTranslation } from "@plane/i18n";
89
import { TOAST_TYPE, setToast } from "@plane/ui";
910
// components
1011
import { NotAuthorizedView } from "@/components/auth-screens";
@@ -21,6 +22,8 @@ const AutomationSettingsPage = observer(() => {
2122
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
2223
const { currentProjectDetails: projectDetails, updateProject } = useProject();
2324

25+
const { t } = useTranslation();
26+
2427
// derived values
2528
const canPerformProjectAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT);
2629

@@ -48,7 +51,7 @@ const AutomationSettingsPage = observer(() => {
4851
<PageHead title={pageTitle} />
4952
<section className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
5053
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
51-
<h3 className="text-xl font-medium leading-normal">Automations</h3>
54+
<h3 className="text-xl font-medium leading-normal">{t("project_settings.automations.label")}</h3>
5255
</div>
5356
<AutoArchiveAutomation handleChange={handleChange} />
5457
<AutoCloseAutomation handleChange={handleChange} />

web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/header.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { observer } from "mobx-react";
55
import { useParams } from "next/navigation";
66
// ui
77
import { Settings } from "lucide-react";
8+
import { useTranslation } from "@plane/i18n";
89
import { Breadcrumbs, CustomMenu, Header } from "@plane/ui";
910
// components
1011
import { BreadcrumbLink } from "@/components/common";
@@ -24,6 +25,8 @@ export const ProjectSettingHeader: FC = observer(() => {
2425
const { allowPermissions } = useUserPermissions();
2526
const { loader } = useProject();
2627

28+
const { t } = useTranslation();
29+
2730
return (
2831
<Header>
2932
<Header.LeftItem>
@@ -65,7 +68,7 @@ export const ProjectSettingHeader: FC = observer(() => {
6568
key={item.key}
6669
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}${item.href}`)}
6770
>
68-
{item.label}
71+
{t(item.i18n_label)}
6972
</CustomMenu.MenuItem>
7073
)
7174
)}

web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/sidebar.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import range from "lodash/range";
55
import { observer } from "mobx-react";
66
import Link from "next/link";
77
import { useParams, usePathname } from "next/navigation";
8+
import { useTranslation } from "@plane/i18n";
89
// ui
910
import { Loader } from "@plane/ui";
1011
// components
@@ -21,6 +22,8 @@ export const ProjectSettingsSidebar = observer(() => {
2122
// mobx store
2223
const { allowPermissions, projectUserInfo } = useUserPermissions();
2324

25+
const { t } = useTranslation();
26+
2427
// derived values
2528
const currentProjectRole = projectUserInfo?.[workspaceSlug?.toString()]?.[projectId?.toString()]?.role;
2629

@@ -58,7 +61,7 @@ export const ProjectSettingsSidebar = observer(() => {
5861
isActive={link.highlight(pathname, `/${workspaceSlug}/projects/${projectId}`)}
5962
className="text-sm font-medium px-4 py-2"
6063
>
61-
{link.label}
64+
{t(link.i18n_label)}
6265
</SidebarNavItem>
6366
</Link>
6467
)

web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/states/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { observer } from "mobx-react";
44
import { useParams } from "next/navigation";
5+
import { useTranslation } from "@plane/i18n";
56
// components
67
import { NotAuthorizedView } from "@/components/auth-screens";
78
import { PageHead } from "@/components/core";
@@ -16,6 +17,8 @@ const StatesSettingsPage = observer(() => {
1617
const { currentProjectDetails } = useProject();
1718
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
1819

20+
const { t } = useTranslation();
21+
1922
// derived values
2023
const pageTitle = currentProjectDetails?.name ? `${currentProjectDetails?.name} - States` : undefined;
2124
// derived values
@@ -32,7 +35,7 @@ const StatesSettingsPage = observer(() => {
3235
<>
3336
<PageHead title={pageTitle} />
3437
<div className="flex items-center border-b border-custom-border-100">
35-
<h3 className="text-xl font-medium">States</h3>
38+
<h3 className="text-xl font-medium">{t("states")}</h3>
3639
</div>
3740
{workspaceSlug && projectId && (
3841
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />

web/ce/constants/project/settings/tabs.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,55 +8,55 @@ import { EUserPermissions } from "../../user-permissions";
88
export const PROJECT_SETTINGS = {
99
general: {
1010
key: "general",
11-
label: "General",
11+
i18n_label: "common.general",
1212
href: `/settings`,
1313
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST],
1414
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/`,
1515
Icon: SettingIcon,
1616
},
1717
members: {
1818
key: "members",
19-
label: "Members",
19+
i18n_label: "members",
2020
href: `/settings/members`,
2121
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
2222
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/members/`,
2323
Icon: SettingIcon,
2424
},
2525
features: {
2626
key: "features",
27-
label: "Features",
27+
i18n_label: "common.features",
2828
href: `/settings/features`,
2929
access: [EUserPermissions.ADMIN],
3030
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/features/`,
3131
Icon: SettingIcon,
3232
},
3333
states: {
3434
key: "states",
35-
label: "States",
35+
i18n_label: "common.states",
3636
href: `/settings/states`,
3737
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
3838
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/states/`,
3939
Icon: SettingIcon,
4040
},
4141
labels: {
42-
key: "labels",
43-
label: "Labels",
42+
key: "i18n_labels",
43+
i18n_label: "common.labels",
4444
href: `/settings/labels`,
4545
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
4646
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/labels/`,
4747
Icon: SettingIcon,
4848
},
4949
estimates: {
5050
key: "estimates",
51-
label: "Estimates",
51+
i18n_label: "common.estimates",
5252
href: `/settings/estimates`,
5353
access: [EUserPermissions.ADMIN],
5454
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/estimates/`,
5555
Icon: SettingIcon,
5656
},
5757
automations: {
5858
key: "automations",
59-
label: "Automations",
59+
i18n_label: "common.automations",
6060
href: `/settings/automations`,
6161
access: [EUserPermissions.ADMIN],
6262
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/automations/`,
@@ -66,7 +66,7 @@ export const PROJECT_SETTINGS = {
6666

6767
export const PROJECT_SETTINGS_LINKS: {
6868
key: string;
69-
label: string;
69+
i18n_label: string;
7070
href: string;
7171
access: EUserPermissions[];
7272
highlight: (pathname: string, baseUrl: string) => boolean;

web/core/components/automation/auto-archive-automation.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
5555
<ArchiveRestore className="h-4 w-4 flex-shrink-0 text-custom-text-100" />
5656
</div>
5757
<div className="">
58-
<h4 className="text-sm font-medium">Auto-archive closed issues</h4>
58+
<h4 className="text-sm font-medium">{t("project_settings.automations.auto-archive.title")}</h4>
5959
<p className="text-sm tracking-tight text-custom-text-200">
60-
Plane will auto archive issues that have been completed or canceled.
60+
{t("project_settings.automations.auto-archive.description")}
6161
</p>
6262
</div>
6363
</div>
@@ -77,7 +77,9 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
7777
currentProjectDetails.archive_in !== 0 && (
7878
<div className="mx-6">
7979
<div className="flex w-full items-center justify-between gap-2 rounded border border-custom-border-200 bg-custom-background-90 px-5 py-4">
80-
<div className="w-1/2 text-sm font-medium">Auto-archive issues that are closed for</div>
80+
<div className="w-1/2 text-sm font-medium">
81+
{t("project_settings.automations.auto-archive.duration")}
82+
</div>
8183
<div className="w-1/2">
8284
<CustomSelect
8385
value={currentProjectDetails?.archive_in}
@@ -102,7 +104,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
102104
className="flex w-full select-none items-center rounded px-1 py-1.5 text-sm text-custom-text-200 hover:bg-custom-background-80"
103105
onClick={() => setmonthModal(true)}
104106
>
105-
Customize time range
107+
{t("customize_time_range")}
106108
</button>
107109
</>
108110
</CustomSelect>

web/core/components/automation/auto-close-automation.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
8181
<ArchiveX className="h-4 w-4 flex-shrink-0 text-red-500" />
8282
</div>
8383
<div className="">
84-
<h4 className="text-sm font-medium">Auto-close issues</h4>
84+
<h4 className="text-sm font-medium">{t("project_settings.automations.auto-close.title")}</h4>
8585
<p className="text-sm tracking-tight text-custom-text-200">
86-
Plane will automatically close issues that haven{"'"}t been completed or canceled.
86+
{t("project_settings.automations.auto-close.description")}
8787
</p>
8888
</div>
8989
</div>
@@ -104,7 +104,9 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
104104
<div className="mx-6">
105105
<div className="flex flex-col rounded border border-custom-border-200 bg-custom-background-90">
106106
<div className="flex w-full items-center justify-between gap-2 px-5 py-4">
107-
<div className="w-1/2 text-sm font-medium">Auto-close issues that are inactive for</div>
107+
<div className="w-1/2 text-sm font-medium">
108+
{t("project_settings.automations.auto-close.duration")}
109+
</div>
108110
<div className="w-1/2">
109111
<CustomSelect
110112
value={currentProjectDetails?.close_in}
@@ -128,15 +130,17 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
128130
className="flex w-full select-none items-center rounded px-1 py-1.5 text-custom-text-200 hover:bg-custom-background-80"
129131
onClick={() => setmonthModal(true)}
130132
>
131-
Customize time range
133+
{t("customize_time_range")}
132134
</button>
133135
</>
134136
</CustomSelect>
135137
</div>
136138
</div>
137139

138140
<div className="flex w-full items-center justify-between gap-2 px-5 py-4">
139-
<div className="w-1/2 text-sm font-medium">Auto-close status</div>
141+
<div className="w-1/2 text-sm font-medium">
142+
{t("project_settings.automations.auto-close.auto_close_status")}
143+
</div>
140144
<div className="w-1/2 ">
141145
<CustomSearchSelect
142146
value={currentProjectDetails?.default_state ?? defaultState}
@@ -161,7 +165,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
161165
)}
162166
{selectedOption?.name
163167
? selectedOption.name
164-
: (currentDefaultState?.name ?? <span className="text-custom-text-200">State</span>)}
168+
: (currentDefaultState?.name ?? <span className="text-custom-text-200">{t("state")}</span>)}
165169
</div>
166170
}
167171
onChange={(val: string) => {

0 commit comments

Comments
 (0)