[WEB-2870]feat: language support (#6215)
* fix: adding language support package * fix: language support implementation using mobx * fix: adding more languages for support * fix: profile settings translations * feat: added language support for sidebar and user settings * feat: added language support for deactivation modal * fix: added project sync after transfer issues (#6200) * code refactor and improvement (#6203) * chore: package code refactoring * chore: component restructuring and refactor * chore: comment create improvement * refactor: enhance workspace and project wrapper modularity (#6207) * [WEB-2678]feat: added functionality to add labels directly from dropdown (#6211) * enhancement:added functionality to add features directly from dropdown * fix: fixed import order * fix: fixed lint errors * chore: added common component for project activity (#6212) * chore: added common component for project activity * fix: added enum * fix: added enum for initiatives * - Do not clear temp files that are locked. (#6214) - Handle edge cases in sync workspace * fix: labels empty state for drop down (#6216) * refactor: remove cn helper function from the editor package (#6217) * * feat: added language support to issue create modal in sidebar * fix: project activity type * * fix: added missing translations * fix: modified translation for plurals * fix: fixed spanish translation * dev: language type error in space user profile types * fix: type fixes * chore: added alpha tag --------- Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com> Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com> Co-authored-by: Akshita Goyal <36129505+gakshita@users.noreply.github.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com> Co-authored-by: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Co-authored-by: gurusinath <gurusainath007@gmail.com>
This commit is contained in:
parent
ade0aa1643
commit
873e4330bc
84 changed files with 2588 additions and 873 deletions
|
|
@ -1,29 +1,16 @@
|
|||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// types
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { IUserTheme } from "@plane/types";
|
||||
// ui
|
||||
import { Button, InputColorPicker, setPromiseToast } from "@plane/ui";
|
||||
// hooks
|
||||
import { useUserProfile } from "@/hooks/store";
|
||||
|
||||
const inputRules = {
|
||||
minLength: {
|
||||
value: 7,
|
||||
message: "Enter a valid hex code of 6 characters",
|
||||
},
|
||||
maxLength: {
|
||||
value: 7,
|
||||
message: "Enter a valid hex code of 6 characters",
|
||||
},
|
||||
pattern: {
|
||||
value: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
|
||||
message: "Enter a valid hex code of 6 characters",
|
||||
},
|
||||
};
|
||||
|
||||
type TCustomThemeSelector = {
|
||||
applyThemeChange: (theme: Partial<IUserTheme>) => void;
|
||||
};
|
||||
|
|
@ -32,7 +19,7 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
const { applyThemeChange } = props;
|
||||
// hooks
|
||||
const { data: userProfile, updateUserTheme } = useUserProfile();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
control,
|
||||
formState: { errors, isSubmitting },
|
||||
|
|
@ -51,6 +38,24 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
},
|
||||
});
|
||||
|
||||
const inputRules = useMemo(
|
||||
() => ({
|
||||
minLength: {
|
||||
value: 7,
|
||||
message: t("enter_a_valid_hex_code_of_6_characters"),
|
||||
},
|
||||
maxLength: {
|
||||
value: 7,
|
||||
message: t("enter_a_valid_hex_code_of_6_characters"),
|
||||
},
|
||||
pattern: {
|
||||
value: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
|
||||
message: t("enter_a_valid_hex_code_of_6_characters"),
|
||||
},
|
||||
}),
|
||||
[t] // Empty dependency array since these rules never change
|
||||
);
|
||||
|
||||
const handleUpdateTheme = async (formData: Partial<IUserTheme>) => {
|
||||
const payload: IUserTheme = {
|
||||
background: formData.background,
|
||||
|
|
@ -66,14 +71,14 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
|
||||
const updateCurrentUserThemePromise = updateUserTheme(payload);
|
||||
setPromiseToast(updateCurrentUserThemePromise, {
|
||||
loading: "Updating theme...",
|
||||
loading: t("updating_theme"),
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Theme updated successfully!",
|
||||
title: t("success"),
|
||||
message: () => t("theme_updated_successfully"),
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Failed to Update the theme",
|
||||
title: t("error"),
|
||||
message: () => t("failed_to_update_the_theme"),
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -91,16 +96,16 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
return (
|
||||
<form onSubmit={handleSubmit(handleUpdateTheme)}>
|
||||
<div className="space-y-5">
|
||||
<h3 className="text-lg font-semibold text-custom-text-100">Customize your theme</h3>
|
||||
<h3 className="text-lg font-semibold text-custom-text-100">{t("customize_your_theme")}</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-4 sm:grid-cols-2 md:grid-cols-3">
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">Background color</h3>
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("background_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
name="background"
|
||||
rules={{ ...inputRules, required: "Background color is required" }}
|
||||
rules={{ ...inputRules, required: t("background_color_is_required") }}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<InputColorPicker
|
||||
name="background"
|
||||
|
|
@ -121,12 +126,12 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">Text color</h3>
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("text_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
name="text"
|
||||
rules={{ ...inputRules, required: "Text color is required" }}
|
||||
rules={{ ...inputRules, required: t("text_color_is_required") }}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<InputColorPicker
|
||||
name="text"
|
||||
|
|
@ -147,12 +152,12 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">Primary(Theme) color</h3>
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("primary_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
name="primary"
|
||||
rules={{ ...inputRules, required: "Primary color is required" }}
|
||||
rules={{ ...inputRules, required: t("primary_color_is_required") }}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<InputColorPicker
|
||||
name="primary"
|
||||
|
|
@ -173,12 +178,12 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">Sidebar background color</h3>
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("sidebar_background_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
name="sidebarBackground"
|
||||
rules={{ ...inputRules, required: "Sidebar background color is required" }}
|
||||
rules={{ ...inputRules, required: t("sidebar_background_color_is_required") }}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<InputColorPicker
|
||||
name="sidebarBackground"
|
||||
|
|
@ -201,12 +206,12 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">Sidebar text color</h3>
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("sidebar_text_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
name="sidebarText"
|
||||
rules={{ ...inputRules, required: "Sidebar text color is required" }}
|
||||
rules={{ ...inputRules, required: t("sidebar_text_color_is_required") }}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<InputColorPicker
|
||||
name="sidebarText"
|
||||
|
|
@ -230,7 +235,7 @@ export const CustomThemeSelector: React.FC<TCustomThemeSelector> = observer((pro
|
|||
</div>
|
||||
<div className="mt-5 flex justify-end gap-2">
|
||||
<Button variant="primary" type="submit" loading={isSubmitting}>
|
||||
{isSubmitting ? "Creating Theme..." : "Set Theme"}
|
||||
{isSubmitting ? t("creating_theme") : t("set_theme")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// constants
|
||||
import { CustomSelect } from "@plane/ui";
|
||||
import { THEME_OPTIONS, I_THEME_OPTION } from "@/constants/themes";
|
||||
|
|
@ -13,7 +14,7 @@ type Props = {
|
|||
|
||||
export const ThemeSwitch: FC<Props> = (props) => {
|
||||
const { value, onChange } = props;
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<CustomSelect
|
||||
value={value}
|
||||
|
|
@ -40,10 +41,10 @@ export const ThemeSwitch: FC<Props> = (props) => {
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
{value.label}
|
||||
{t(value.key)}
|
||||
</div>
|
||||
) : (
|
||||
"Select your theme"
|
||||
t("select_your_theme")
|
||||
)
|
||||
}
|
||||
onChange={onChange}
|
||||
|
|
@ -72,7 +73,7 @@ export const ThemeSwitch: FC<Props> = (props) => {
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
{themeOption.label}
|
||||
{t(themeOption.key)}
|
||||
</div>
|
||||
</CustomSelect.Option>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue