mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
* feat(email): auto switch for existing language templates * feat(email): use friendly lang display name * fix(email): prevent infinite loop when updating templates * feat(email): adjust email template order by drag-and-drop * revoke(email): remove drag-and-drop for email template order * feat(email): support magic variables in email title * feat(email): add preferred language setting in email template editor
This commit is contained in:
parent
63c7abf214
commit
c786f843f9
|
|
@ -567,10 +567,14 @@
|
|||
"quotaExceededEmailTemplateDes": "E-Mail-Vorlage, die an Benutzer gesendet wird, wenn sie ihr Speicherkontingent überschreiten.",
|
||||
"resetPasswordEmailTemplate": "Passwort-Reset-Vorlage",
|
||||
"resetPasswordEmailTemplateDes": "E-Mail-Vorlage, die an Benutzer gesendet wird, wenn sie ein Passwort-Reset anfordern.",
|
||||
"preferredLanguage": "Bevorzugte Sprache",
|
||||
"setAsPreferredLanguage": "Als bevorzugte Sprache festlegen",
|
||||
"setAsPreferredLanguageDes": "Wenn die Sprache des Benutzers nicht festgelegt ist, wird diese bevorzugte Sprache verwendet.",
|
||||
"alreadyAsPreferredLanguageDes": "Die aktuelle Sprache ist bereits als bevorzugte Sprache festgelegt. Wenn die Sprache des Benutzers nicht festgelegt ist, wird diese bevorzugte Sprache verwendet.",
|
||||
"addLanguage": "Sprache hinzufügen",
|
||||
"languageCodeDes": "Bitte wählen Sie die Sprache aus, die Sie hinzufügen möchten.",
|
||||
"emailSubject": "E-Mail-Betreff",
|
||||
"emailSubjectDes": "Die Betreffzeile der E-Mail.",
|
||||
"emailSubjectDes": "Die Betreffzeile der E-Mail. Sie können <0>magische Variablen</0> verwenden, um den E-Mail-Betreff anzupassen.",
|
||||
"emailBody": "E-Mail-Inhalt",
|
||||
"emailBodyDes": "HTML-Inhalt der E-Mail. Sie können <0>magische Variablen</0> verwenden, um den E-Mail-Inhalt anzupassen.",
|
||||
"orderTitle": "Bestelltitel",
|
||||
|
|
|
|||
|
|
@ -566,10 +566,14 @@
|
|||
"quotaExceededEmailTemplateDes": "Email template sent to users when they exceed their storage quota.",
|
||||
"resetPasswordEmailTemplate": "Password reset template",
|
||||
"resetPasswordEmailTemplateDes": "Email template sent to users when they request a password reset.",
|
||||
"preferredLanguage": "Preferred language",
|
||||
"setAsPreferredLanguage": "Set as preferred language",
|
||||
"setAsPreferredLanguageDes": "This language will be used as the default email template if the user's language preference cannot be determined.",
|
||||
"alreadyAsPreferredLanguageDes": "This language is already set as the preferred language. If the user's language preference cannot be determined, this email template will be used.",
|
||||
"addLanguage": "Add language",
|
||||
"languageCodeDes": "Please select the language you want to add.",
|
||||
"emailSubject": "Email saveChanges",
|
||||
"emailSubjectDes": "The subject line of the email.",
|
||||
"emailSubjectDes": "The subject line of the email. You can use <0>magic variables</0> to customize the email subject.",
|
||||
"emailBody": "Email body",
|
||||
"emailBodyDes": "HTML content of the email. You can use <0>magic variables</0> to customize the email content.",
|
||||
"orderTitle": "Order title",
|
||||
|
|
|
|||
|
|
@ -567,10 +567,14 @@
|
|||
"quotaExceededEmailTemplateDes": "Plantilla de email enviada a los usuarios cuando exceden su cuota de almacenamiento.",
|
||||
"resetPasswordEmailTemplate": "Plantilla de restablecimiento de contraseña",
|
||||
"resetPasswordEmailTemplateDes": "Plantilla de email enviada a los usuarios cuando solicitan un restablecimiento de contraseña.",
|
||||
"preferredLanguage": "Idioma preferido",
|
||||
"setAsPreferredLanguage": "Establecer como idioma preferido",
|
||||
"setAsPreferredLanguageDes": "Si no se puede obtener la preferencia de idioma del usuario, se utilizará la plantilla de correo electrónico del idioma preferido.",
|
||||
"alreadyAsPreferredLanguageDes": "El idioma actual ya está establecido como preferido. Si no se puede obtener la preferencia de idioma del usuario, se utilizará esta plantilla de correo electrónico.",
|
||||
"addLanguage": "Agregar idioma",
|
||||
"languageCodeDes": "Por favor selecciona el idioma que quieres agregar.",
|
||||
"emailSubject": "Asunto del email",
|
||||
"emailSubjectDes": "La línea de asunto del email.",
|
||||
"emailSubjectDes": "La línea de asunto del email. Puedes usar <0>variables mágicas</0> para personalizar el asunto del email.",
|
||||
"emailBody": "Cuerpo del email",
|
||||
"emailBodyDes": "Contenido HTML del email. Puedes usar <0>variables mágicas</0> para personalizar el contenido del email.",
|
||||
"orderTitle": "Título de la orden",
|
||||
|
|
|
|||
|
|
@ -567,10 +567,14 @@
|
|||
"quotaExceededEmailTemplateDes": "Modèle d'e-mail envoyé aux utilisateurs lorsqu'ils dépassent leur quota de stockage.",
|
||||
"resetPasswordEmailTemplate": "Modèle de réinitialisation de mot de passe",
|
||||
"resetPasswordEmailTemplateDes": "Modèle d'e-mail envoyé aux utilisateurs lorsqu'ils demandent une réinitialisation de mot de passe.",
|
||||
"preferredLanguage": "Langue préférée",
|
||||
"setAsPreferredLanguage": "Définir comme langue préférée",
|
||||
"setAsPreferredLanguageDes": "Si la préférence de langue de l'utilisateur ne peut pas être obtenue, le modèle d'e-mail de la langue préférée sera utilisé.",
|
||||
"alreadyAsPreferredLanguageDes": "La langue actuelle est déjà définie comme langue préférée. Si la préférence de langue de l'utilisateur ne peut pas être obtenue, ce modèle d'e-mail sera utilisé.",
|
||||
"addLanguage": "Ajouter une langue",
|
||||
"languageCodeDes": "Veuillez sélectionner la langue que vous souhaitez ajouter.",
|
||||
"emailSubject": "Sujet de l'e-mail",
|
||||
"emailSubjectDes": "La ligne d'objet de l'e-mail.",
|
||||
"emailSubjectDes": "La ligne d'objet de l'e-mail. Vous pouvez utiliser des <0>variables magiques</0> pour personnaliser le sujet de l'e-mail.",
|
||||
"emailBody": "Corps de l'e-mail",
|
||||
"emailBodyDes": "Contenu HTML de l'e-mail. Vous pouvez utiliser des <0>variables magiques</0> pour personnaliser le contenu de l'e-mail.",
|
||||
"orderTitle": "Titre de la commande",
|
||||
|
|
|
|||
|
|
@ -567,10 +567,14 @@
|
|||
"quotaExceededEmailTemplateDes": "Template email inviato agli utenti quando superano la loro quota di archiviazione.",
|
||||
"resetPasswordEmailTemplate": "Template reset password",
|
||||
"resetPasswordEmailTemplateDes": "Template email inviato agli utenti quando richiedono un reset della password.",
|
||||
"preferredLanguage": "Lingua preferita",
|
||||
"setAsPreferredLanguage": "Imposta come lingua preferita",
|
||||
"setAsPreferredLanguageDes": "Se non è possibile ottenere le preferenze linguistiche dell'utente, verrà utilizzato il template email della lingua preferita.",
|
||||
"alreadyAsPreferredLanguageDes": "La lingua corrente è già impostata come preferita. Se non è possibile ottenere le preferenze linguistiche dell'utente, verrà utilizzato il template email della lingua corrente.",
|
||||
"addLanguage": "Aggiungi lingua",
|
||||
"languageCodeDes": "Seleziona la lingua che vuoi aggiungere.",
|
||||
"emailSubject": "Oggetto email",
|
||||
"emailSubjectDes": "L'oggetto dell'email.",
|
||||
"emailSubjectDes": "L'oggetto dell'email. Puoi usare <0>variabili magiche</0> per personalizzare l'oggetto dell'email.",
|
||||
"emailBody": "Corpo email",
|
||||
"emailBodyDes": "Contenuto HTML dell'email. Puoi usare <0>variabili magiche</0> per personalizzare il contenuto dell'email.",
|
||||
"orderTitle": "Titolo ordine",
|
||||
|
|
|
|||
|
|
@ -566,10 +566,14 @@
|
|||
"quotaExceededEmailTemplateDes": "ユーザーがストレージクォータを超過した際にユーザーに送信されるメールテンプレート。",
|
||||
"resetPasswordEmailTemplate": "パスワードリセットテンプレート",
|
||||
"resetPasswordEmailTemplateDes": "ユーザーがパスワードのリセットを要求した際にユーザーに送信されるメールテンプレート。",
|
||||
"preferredLanguage": "優先言語",
|
||||
"setAsPreferredLanguage": "優先言語に設定",
|
||||
"setAsPreferredLanguageDes": "ユーザーの言語設定が取得できない場合、優先言語のメールテンプレートが使用されます。",
|
||||
"alreadyAsPreferredLanguageDes": "現在の言語は既に優先言語として設定されています。ユーザーの言語設定が取得できない場合、優先言語のメールテンプレートが使用されます。",
|
||||
"addLanguage": "言語を追加",
|
||||
"languageCodeDes": "追加する言語を選択してください。",
|
||||
"emailSubject": "メール件名",
|
||||
"emailSubjectDes": "メールの件名。",
|
||||
"emailSubjectDes": "メールの件名。<0>魔法変数</0> を使用して件名をカスタマイズできます。",
|
||||
"emailBody": "メール本文",
|
||||
"emailBodyDes": "メールの本文です。<0>魔法変数</0> を使用して本文をカスタマイズできます。",
|
||||
"orderTitle": "注文タイトル",
|
||||
|
|
|
|||
|
|
@ -566,10 +566,14 @@
|
|||
"quotaExceededEmailTemplateDes": "사용자가 저장 할당량을 초과할 때 보내는 이메일 템플릿",
|
||||
"resetPasswordEmailTemplate": "비밀번호 재설정 템플릿",
|
||||
"resetPasswordEmailTemplateDes": "사용자가 비밀번호 재설정을 요청할 때 보내는 이메일 템플릿",
|
||||
"preferredLanguage": "선호 언어",
|
||||
"setAsPreferredLanguage": "선호 언어로 설정",
|
||||
"setAsPreferredLanguageDes": "사용자의 언어 선호도를 가져올 수 없는 경우 선호 언어의 이메일 템플릿이 사용됩니다.",
|
||||
"alreadyAsPreferredLanguageDes": "현재 언어가 선호 언어로 설정되어 있습니다. 사용자의 언어 선호도를 가져올 수 없는 경우 이 이메일 템플릿이 사용됩니다.",
|
||||
"addLanguage": "언어 추가",
|
||||
"languageCodeDes": "추가할 언어를 선택해 주세요.",
|
||||
"emailSubject": "이메일 제목",
|
||||
"emailSubjectDes": "이메일의 제목",
|
||||
"emailSubjectDes": "이메일의 제목. <0>매직 변수</0>를 사용하여 사용자 정의할 수 있습니다.",
|
||||
"emailBody": "이메일 내용",
|
||||
"emailBodyDes": "이메일의 내용입니다. <0>매직 변수</0>를 사용하여 이메일 내용을 사용자 정의할 수 있습니다.",
|
||||
"orderTitle": "주문 제목",
|
||||
|
|
|
|||
|
|
@ -567,10 +567,14 @@
|
|||
"quotaExceededEmailTemplateDes": "Modelo de email enviado aos usuários quando excedem sua cota de armazenamento.",
|
||||
"resetPasswordEmailTemplate": "Modelo de redefinição de senha",
|
||||
"resetPasswordEmailTemplateDes": "Modelo de email enviado aos usuários quando solicitam redefinição de senha.",
|
||||
"preferredLanguage": "Idioma preferido",
|
||||
"setAsPreferredLanguage": "Definir como idioma preferido",
|
||||
"setAsPreferredLanguageDes": "Se o idioma preferido do usuário não puder ser obtido, o modelo de email deste idioma será usado.",
|
||||
"alreadyAsPreferredLanguageDes": "O idioma atual já está definido como preferido. Se o idioma preferido do usuário não puder ser obtido, o modelo de email deste idioma será usado.",
|
||||
"addLanguage": "Adicionar idioma",
|
||||
"languageCodeDes": "Selecione o idioma que deseja adicionar.",
|
||||
"emailSubject": "Assunto do email",
|
||||
"emailSubjectDes": "A linha de assunto do email.",
|
||||
"emailSubjectDes": "A linha de assunto do email. Você pode usar <0>variáveis mágicas</0> para personalizar o assunto do email.",
|
||||
"emailBody": "Corpo do email",
|
||||
"emailBodyDes": "Conteúdo HTML do email. Você pode usar <0>variáveis mágicas</0> para personalizar o conteúdo do email.",
|
||||
"orderTitle": "Título do pedido",
|
||||
|
|
|
|||
|
|
@ -567,10 +567,14 @@
|
|||
"quotaExceededEmailTemplateDes": "Шаблон электронного письма, отправляемого пользователю при превышении квоты хранилища.",
|
||||
"resetPasswordEmailTemplate": "Шаблон сброса пароля",
|
||||
"resetPasswordEmailTemplateDes": "Шаблон электронного письма, отправляемого пользователю при запросе сброса пароля.",
|
||||
"preferredLanguage": "Предпочитаемый язык",
|
||||
"setAsPreferredLanguage": "Установить как предпочитаемый язык",
|
||||
"setAsPreferredLanguageDes": "Если язык пользователя не может быть определен, будет использоваться предпочитаемый язык.",
|
||||
"alreadyAsPreferredLanguageDes": "Этот язык уже установлен как предпочитаемый. Если язык пользователя не может быть определен, будет использоваться этот шаблон письма.",
|
||||
"addLanguage": "Добавить язык",
|
||||
"languageCodeDes": "Пожалуйста, выберите язык для добавления.",
|
||||
"emailSubject": "Тема письма",
|
||||
"emailSubjectDes": "Тема электронного письма.",
|
||||
"emailSubjectDes": "Тема электронного письма. Вы можете использовать <0>магические переменные</0> для настройки темы письма.",
|
||||
"emailBody": "Содержимое письма",
|
||||
"emailBodyDes": "Содержимое электронного письма. Вы можете использовать <0>магические переменные</0> для настройки содержимого письма.",
|
||||
"orderTitle": "Название заказа",
|
||||
|
|
|
|||
|
|
@ -566,10 +566,14 @@
|
|||
"quotaExceededEmailTemplateDes": "当用户超出存储配额时发送给用户的邮件模板。",
|
||||
"resetPasswordEmailTemplate": "密码重置模板",
|
||||
"resetPasswordEmailTemplateDes": "当用户请求重置密码时发送给用户的邮件模板。",
|
||||
"preferredLanguage": "首选语言",
|
||||
"setAsPreferredLanguage": "设为首选语言",
|
||||
"setAsPreferredLanguageDes": "如果无法获取用户的语言偏好,将使用首选语言的邮件模板。",
|
||||
"alreadyAsPreferredLanguageDes": "当前语言已设为首选语言。如果无法获取用户的语言偏好,将使用此邮件模板。",
|
||||
"addLanguage": "添加语言",
|
||||
"languageCodeDes": "请选择要添加的语言。",
|
||||
"emailSubject": "邮件主题",
|
||||
"emailSubjectDes": "邮件的主题。",
|
||||
"emailSubjectDes": "邮件的主题。你可以使用 <0>魔法变量</0> 来定制邮件主题。",
|
||||
"emailBody": "邮件内容",
|
||||
"emailBodyDes": "邮件的内容。你可以使用 <0>魔法变量</0> 来定制邮件内容。",
|
||||
"orderTitle": "订单标题",
|
||||
|
|
|
|||
|
|
@ -566,10 +566,14 @@
|
|||
"quotaExceededEmailTemplateDes": "當使用者超出儲存配額時傳送給使用者的郵件模板。",
|
||||
"resetPasswordEmailTemplate": "密碼重置模板",
|
||||
"resetPasswordEmailTemplateDes": "當使用者請求重置密碼時傳送給使用者的郵件模板。",
|
||||
"preferredLanguage": "首選語言",
|
||||
"setAsPreferredLanguage": "設為首選語言",
|
||||
"setAsPreferredLanguageDes": "如果無法獲取使用者的語言偏好,將使用首選語言的郵件模板。",
|
||||
"alreadyAsPreferredLanguageDes": "當前語言已設為首選語言。如果無法獲取使用者的語言偏好,將使用此郵件模板。",
|
||||
"addLanguage": "新增語言",
|
||||
"languageCodeDes": "請選擇要新增的語言。",
|
||||
"emailSubject": "郵件主題",
|
||||
"emailSubjectDes": "郵件的主題。",
|
||||
"emailSubjectDes": "郵件的主題。你可以使用 <0>魔法變數</0> 來定製郵件主題。",
|
||||
"emailBody": "郵件內容",
|
||||
"emailBodyDes": "郵件的內容。你可以使用 <0>魔法變數</0> 來定製郵件內容。",
|
||||
"orderTitle": "訂單標題",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Add } from "@mui/icons-material";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
|
|
@ -15,7 +14,8 @@ import React, { lazy, Suspense, useCallback, useEffect, useRef, useState } from
|
|||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { languages } from "../../../../i18n.ts";
|
||||
import CircularProgress from "../../../Common/CircularProgress.tsx";
|
||||
import { DenseFilledTextField, DenseSelect } from "../../../Common/StyledComponents.tsx";
|
||||
import { DenseFilledTextField, DenseSelect, SecondaryButton } from "../../../Common/StyledComponents.tsx";
|
||||
import Add from "../../../Icons/Add";
|
||||
import DraggableDialog from "../../../Dialogs/DraggableDialog.tsx";
|
||||
import { SquareMenuItem } from "../../../FileManager/ContextMenu/ContextMenu.tsx";
|
||||
import SettingForm from "../../../Pages/Setting/SettingForm.tsx";
|
||||
|
|
@ -57,13 +57,16 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({ value, onChan
|
|||
if (parsedTemplates.length === 0) {
|
||||
setTemplates([{ language: "en-US", title: "", body: "" }]);
|
||||
}
|
||||
if (currentTab > parsedTemplates.length) {
|
||||
setCurrentTab(0);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse email template:", e);
|
||||
setTemplates([{ language: "en-US", title: "", body: "" }]);
|
||||
} finally {
|
||||
// Use setTimeout to ensure this runs after React finishes the update
|
||||
setTimeout(() => {
|
||||
isUpdatingFromProp.current = false;
|
||||
isUpdatingFromProp.current = true; // Prevent infinite loop
|
||||
}, 0);
|
||||
}
|
||||
}, [value]);
|
||||
|
|
@ -93,10 +96,12 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({ value, onChan
|
|||
if (!newLanguageCode.trim()) return;
|
||||
|
||||
// Check if language already exists
|
||||
if (templates.some((t) => t.language === newLanguageCode)) {
|
||||
// Could show an error message here
|
||||
const langTemplateIndex = templates.findIndex((l) => l.language === newLanguageCode);
|
||||
if (langTemplateIndex !== -1) {
|
||||
setNewLanguageCode("");
|
||||
setAddLanguageOpen(false);
|
||||
|
||||
setCurrentTab(langTemplateIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -112,6 +117,12 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({ value, onChan
|
|||
setCurrentTab(templates.length);
|
||||
};
|
||||
|
||||
const setPreferredLanguage = (index: number) => {
|
||||
isUpdatingFromProp.current = false; // Ensure this is a user interaction
|
||||
setTemplates([templates[index], ...templates.filter((_, i) => i !== index)]);
|
||||
setCurrentTab(0); // Switch to the first tab as the preferred language is now at the top
|
||||
};
|
||||
|
||||
const openMagicVar = useCallback((e: React.MouseEvent<HTMLElement>) => {
|
||||
setMagicVarOpen(true);
|
||||
e.stopPropagation();
|
||||
|
|
@ -128,9 +139,10 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({ value, onChan
|
|||
scrollButtons="auto"
|
||||
sx={{ flexGrow: 1 }}
|
||||
>
|
||||
{templates.map((template, index) => (
|
||||
<Tab key={index} label={template.language} />
|
||||
))}
|
||||
{templates.map((template, index) => {
|
||||
const lang = languages.find((l) => l.code === template.language);
|
||||
return <Tab key={index} label={lang ? lang.displayName : template.language} />;
|
||||
})}
|
||||
</Tabs>
|
||||
<Button
|
||||
startIcon={<Add />}
|
||||
|
|
@ -151,6 +163,23 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({ value, onChan
|
|||
>
|
||||
{currentTab === index && (
|
||||
<Box>
|
||||
<FormControl fullWidth sx={{ mb: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
{t("settings.preferredLanguage")}
|
||||
</Typography>
|
||||
<Box>
|
||||
<SecondaryButton
|
||||
variant="contained"
|
||||
onClick={() => (index === 0 ? undefined : setPreferredLanguage(index))}
|
||||
>
|
||||
{t("settings.setAsPreferredLanguage")}
|
||||
</SecondaryButton>
|
||||
</Box>
|
||||
<NoMarginHelperText>
|
||||
{t(index === 0 ? "settings.alreadyAsPreferredLanguageDes" : "settings.setAsPreferredLanguageDes")}
|
||||
</NoMarginHelperText>
|
||||
</FormControl>
|
||||
|
||||
<FormControl fullWidth sx={{ mb: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
{t("settings.emailSubject")}
|
||||
|
|
@ -160,7 +189,13 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({ value, onChan
|
|||
value={template.title}
|
||||
onChange={(e) => updateTemplate(index, "title", e.target.value)}
|
||||
/>
|
||||
<NoMarginHelperText>{t("settings.emailSubjectDes")}</NoMarginHelperText>
|
||||
<NoMarginHelperText>
|
||||
<Trans
|
||||
i18nKey={"settings.emailSubjectDes"}
|
||||
ns={"dashboard"}
|
||||
components={[<Link onClick={openMagicVar} href={"#"} />]}
|
||||
/>
|
||||
</NoMarginHelperText>
|
||||
</FormControl>
|
||||
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
|
|
|
|||
Loading…
Reference in New Issue