add locales

This commit is contained in:
yesmore committed 2024-04-05 19:44:56 +08:00
1 parent 6ac67596f5
commit d9183b6d2c
15 files changed
+228 -90

No files matched your search

+2 -2
View File
@@ -85,9 +85,9 @@ export function MailList(props: { mails: Email[] }) {
</button>
</div>
<div className="grids flex flex-col flex-1 h-[418px] overflow-y-auto p-2">
<div className="grids flex flex-col flex-1 h-[450px] overflow-y-auto p-2">
{data.length === 0 && (
<div className="w-full items-center h-[418px] flex-col justify-center flex">
<div className="w-full items-center h-[450px] flex-col justify-center flex">
<Loader />
<p className="text-zinc-400 mt-6">{t("Waiting for emails...")}</p>
</div>
+45 -42
View File
@@ -7,6 +7,7 @@ import {
} from "react";
import Modal from "./modal";
import { Form, useNavigation } from "@remix-run/react";
import { useTranslation } from "react-i18next";
export default function SenderModal({
senderEmail,
@@ -18,25 +19,22 @@ export default function SenderModal({
setShowSenderModal: Dispatch<SetStateAction<boolean>>;
}) {
const navigation = useNavigation();
const { t } = useTranslation();
return (
<Modal showModal={showSenderModal} setShowModal={setShowSenderModal}>
<div className="w-full overflow-hidden bg-white shadow-xl p-4 md:max-w-3xl md:rounded-2xl md:border md:border-gray-200">
<div className="w-full overflow-hidden bg-white/95 backdrop-blur-xl shadow-xl p-4 md:max-w-3xl md:rounded-2xl md:border md:border-gray-200">
<div className="flex flex-col items-center justify-center space-y-3 border-b border-gray-200 px-4 py-5 pt-8 text-center md:px-16">
<h3 className="font-display text-2xl font-bold">Send email</h3>
<p className="text-gray-500">Forward only, no storage</p>
<p className="text-sm text-gray-500">
⚠️Please do not send illegal content such as politics, pornography,
etc
</p>
<h3 className="font-display text-2xl font-bold">Vmail Sender</h3>
<p className="text-gray-500">{t("Forward only, no storage")}</p>
</div>
<Form method="POST" className="flex flex-col mt-4 space-y-4">
<div className="w-full flex gap-4 md:flex-row px-4">
<Form method="POST" className="flex flex-col mt-4 space-y-4 px-4">
<div className="w-full flex flex-col gap-4 md:flex-row">
<input
value={senderEmail}
type="email"
name="senderEmail"
placeholder="发件人邮箱*"
placeholder={t("Sending email *")}
required
disabled
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full"
@@ -44,31 +42,29 @@ export default function SenderModal({
<input
type="text"
name="senderName"
placeholder="发件人昵称*"
placeholder={t("Sending name")}
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full"
/>
</div>
<div className="w-full flex flex-col gap-4 md:flex-row">
<input
type="email"
name="receiverEmail"
placeholder={t("Recipient email *")}
required
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full"
/>
<input
type="text"
name="subject"
placeholder={t("Email subject *")}
required
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full"
/>
</div>
<div className="w-full px-4">
<input
type="email"
name="receiverEmail"
placeholder="收件人邮箱*"
required
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full"
/>
</div>
<div className="w-full px-4">
<input
type="text"
name="subject"
placeholder="邮件主题*"
required
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full"
/>
</div>
<div className="w-full px-4">
<div className="w-full">
<select
name="type"
className="rounded-md border border-slate-200 px-3 py-2 shadow-inner w-full">
@@ -78,22 +74,29 @@ export default function SenderModal({
</option>
</select>
</div>
<div className="w-full px-4">
<div className="w-full">
<textarea
name="content"
placeholder="邮件内容*"
placeholder={t("Email content *")}
required
className="h-24 p-2 border border-slate-200 shadow-inner rounded-md w-full"></textarea>
</div>
<div className="w-full">
<button
type="submit"
value="send"
name="_action"
className="py-2.5 text-white rounded-md w-full bg-cyan-600 hover:opacity-90 disabled:cursor-not-allowed disabled:bg-zinc-500">
{navigation.state === "submitting" ? "Sending..." : "Send"}
</button>
className="min-h-24 p-2 border border-slate-200 shadow-inner rounded-md w-full"></textarea>
</div>
<button
type="submit"
value="send"
name="_action"
disabled={navigation.state != "idle"}
className="py-2.5 text-white rounded-md w-full bg-cyan-600 hover:opacity-90 disabled:cursor-not-allowed disabled:bg-zinc-500">
{navigation.state === "submitting" ? t("Sending...") : t("Send")}
</button>
<p className="text-sm text-gray-500 mt-4">
🚫
{t(
"Please do not send illegal content such as politics, pornography, etc"
)}
.
</p>
</Form>
</div>
</Modal>
+48 -34
View File
@@ -69,6 +69,7 @@ export const action: ActionFunction = async ({ request }) => {
((await userMailboxCookie.parse(
request.headers.get("Cookie")
)) as string) || undefined;
const sendWorkerUrl = process.env.SEND_WORKER_URL || "";
if (_action === "stop") {
if (IuserMailbox) {
@@ -81,32 +82,32 @@ export const action: ActionFunction = async ({ request }) => {
});
}
} else if (_action === "create") {
// const response = (await request.formData()).get("cf-turnstile-response");
// if (!response) {
// return {
// error: "No captcha response",
// };
// }
// const verifyEndpoint =
// "https://challenges.cloudflare.com/turnstile/v0/siteverify";
// const secret =
// process.env.TURNSTILE_SECRET || "1x0000000000000000000000000000000AA";
// const resp = await fetch(verifyEndpoint, {
// method: "POST",
// body: JSON.stringify({
// secret,
// response,
// }),
// headers: {
// "Content-Type": "application/json",
// },
// });
// const data = await resp.json();
// if (!data.success) {
// return {
// error: "Failed to verify captcha",
// };
// }
const response = (await request.formData()).get("cf-turnstile-response");
if (!response) {
return {
error: "No captcha response",
};
}
const verifyEndpoint =
"https://challenges.cloudflare.com/turnstile/v0/siteverify";
const secret =
process.env.TURNSTILE_SECRET || "1x0000000000000000000000000000000AA";
const resp = await fetch(verifyEndpoint, {
method: "POST",
body: JSON.stringify({
secret,
response,
}),
headers: {
"Content-Type": "application/json",
},
});
const data = await resp.json();
if (!data.success) {
return {
error: "Failed to verify captcha",
};
}
const domain = process.env.EMAIL_DOMAIN || "";
if (!domain) {
@@ -122,8 +123,8 @@ export const action: ActionFunction = async ({ request }) => {
"Set-Cookie": userMailbox,
},
});
} else if (_action === "send") {
const res = await fetch(process.env.SEND_WORKER_URL || "", {
} else if (_action === "send" && sendWorkerUrl) {
const res = await fetch(sendWorkerUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -131,7 +132,7 @@ export const action: ActionFunction = async ({ request }) => {
body: JSON.stringify({
from: {
email: IuserMailbox,
name: formData.get("senderName") as string,
name: formData.get("senderName") || "Anonymous",
},
personalizations: [
{
@@ -152,9 +153,12 @@ export const action: ActionFunction = async ({ request }) => {
],
}),
});
console.log("[res]", res);
return redirect("/", {});
console.log("[res]", res.status);
return redirect("/");
} else {
return {
error: "Invalid action",
};
}
};
@@ -215,6 +219,15 @@ export default function Index() {
className="py-2.5 rounded-md w-full bg-cyan-600 hover:opacity-90 disabled:cursor-not-allowed disabled:bg-zinc-500">
{t("Stop")}
</button>
<div className="text-sm text-gray-300 mt-4">
{t("Vmail sender is beta now. ")}
<span
onClick={() => setShowSenderModal(true)}
className="text-cyan-500 cursor-pointer">
{t("Try it")}.
</span>
</div>
</Form>
)}
@@ -240,6 +253,9 @@ export default function Index() {
className="py-2.5 rounded-md w-full bg-cyan-600 hover:opacity-90 disabled:cursor-not-allowed disabled:bg-zinc-500">
{t("Create temporary email")}
</button>
<p className="mt-4 text-sm text-gray-300">
Vmail can now send emails!
</p>
</Form>
)}
<div>
@@ -247,8 +263,6 @@ export default function Index() {
<div className="text-red-500">{t(actionData.error)}</div>
)}
</div>
<button onClick={() => setShowSenderModal(true)}>出来</button>
</div>
<div className="w-full flex-1 overflow-hidden">
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "Über",
"Privacy": "Datenschutz",
"INBOX": "POSTEINGANG",
"Waiting for emails...": "Warte auf E-Mails..."
"Waiting for emails...": "Warte auf E-Mails...",
"Try it": "Ausprobieren",
"Forward only, no storage": "Nur weiterleiten, keine Speicherung",
"Sending email *": "E-Mail senden *",
"Sending name": "Senden von Name",
"Recipient email *": "Empfänger-E-Mail *",
"Email subject *": "E-Mail-Betreff *",
"Email content *": "E-Mail-Inhalt *",
"Sending...": "Senden...",
"Send": "Senden",
"Please do not send illegal content such as politics, pornography, etc": "Bitte senden Sie keine illegalen Inhalte wie Politik, Pornografie, usw."
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "About",
"Privacy": "Privacy",
"INBOX": "INBOX",
"Waiting for emails...": "Waiting for emails..."
"Waiting for emails...": "Waiting for emails...",
"Try it": "Try it",
"Forward only, no storage": "Forward only, no storage",
"Sending email *": "Sending email *",
"Sending name": "Sending name",
"Recipient email *": "Recipient email *",
"Email subject *": "Email subject *",
"Email content *": "Email content *",
"Sending...": "Sending...",
"Send": "Send",
"Please do not send illegal content such as politics, pornography, etc": "Please do not send illegal content such as politics, pornography, etc"
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "À propos",
"Privacy": "Vie privée",
"INBOX": "BOÎTE DE RECEPTION",
"Waiting for emails...": "En attente de courriels..."
"Waiting for emails...": "En attente de courriels...",
"Try it": "Essayer",
"Forward only, no storage": "Transférer uniquement, pas de stockage",
"Sending email *": "Envoyer un email *",
"Sending name": "Nom d'envoi",
"Recipient email *": "Email du destinataire *",
"Email subject *": "Objet de l'email *",
"Email content *": "Contenu de l'email *",
"Sending...": "Envoi en cours...",
"Send": "Envoyer",
"Please do not send illegal content such as politics, pornography, etc": "Veuillez ne pas envoyer de contenu illégal tel que de la politique, de la pornographie, etc."
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "के बारे में",
"Privacy": "गोपनीयता",
"INBOX": "इनबॉक्स",
"Waiting for emails...": "ईमेल की प्रतीक्षा कर रहा है..."
"Waiting for emails...": "ईमेल की प्रतीक्षा कर रहा है...",
"Try it": "इसे प्रयास करें",
"Forward only, no storage": "केवल आगे भेजें, कोई संग्रहण नहीं",
"Sending email *": "ईमेल भेजना *",
"Sending name": "भेजने वाले का नाम",
"Recipient email *": "प्राप्तकर्ता ईमेल *",
"Email subject *": "ईमेल विषय *",
"Email content *": "ईमेल की सामग्री *",
"Sending...": "भेज रहा है...",
"Send": "भेजें",
"Please do not send illegal content such as politics, pornography, etc": "कृपया राजनीति, अश्लीलता आदि जैसी अवैध सामग्री न भेजें"
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "Informazioni",
"Privacy": "Privacy",
"INBOX": "INBOX",
"Waiting for emails...": "In attesa di email..."
"Waiting for emails...": "In attesa di email...",
"Try it": "Provalo",
"Forward only, no storage": "Solo inoltra, nessuna archiviazione",
"Sending email *": "Invio email *",
"Sending name": "Nome invio",
"Recipient email *": "Email del destinatario *",
"Email subject *": "Oggetto dell'email *",
"Email content *": "Contenuto dell'email *",
"Sending...": "Inviando...",
"Send": "Invia",
"Please do not send illegal content such as politics, pornography, etc": "Si prega di non inviare contenuti illegali come politica, pornografia, ecc."
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "について",
"Privacy": "プライバシー",
"INBOX": "インボックス",
"Waiting for emails...": "メールを待っています..."
"Waiting for emails...": "メールを待っています...",
"Try it": "試してみる",
"Forward only, no storage": "転送のみ、保存なし",
"Sending email *": "メールの送信 *",
"Sending name": "送信者名",
"Recipient email *": "受信者のメールアドレス *",
"Email subject *": "メールの件名 *",
"Email content *": "メールの内容 *",
"Sending...": "送信中...",
"Send": "送信",
"Please do not send illegal content such as politics, pornography, etc": "政治、ポルノなどの違法なコンテンツを送信しないでください"
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "소개",
"Privacy": "개인정보",
"INBOX": "인박스",
"Waiting for emails...": "이메일 기다리는 중..."
"Waiting for emails...": "이메일 기다리는 중...",
"Try it": "시도해 보세요",
"Forward only, no storage": "전달만, 저장 없음",
"Sending email *": "이메일 보내기 *",
"Sending name": "보내는 이름",
"Recipient email *": "수신자 이메일 *",
"Email subject *": "이메일 제목 *",
"Email content *": "이메일 내용 *",
"Sending...": "전송 중...",
"Send": "보내기",
"Please do not send illegal content such as politics, pornography, etc": "정치, 음란물 등과 같은 불법 콘텐츠를 보내지 마십시오"
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "Sobre",
"Privacy": "Privacidade",
"INBOX": "CAIXA DE ENTRADA",
"Waiting for emails...": "Aguardando e-mails..."
"Waiting for emails...": "Aguardando e-mails...",
"Try it": "Experimente",
"Forward only, no storage": "Apenas encaminhar, sem armazenamento",
"Sending email *": "Enviar e-mail *",
"Sending name": "Nome do remetente",
"Recipient email *": "Email do destinatário *",
"Email subject *": "Assunto do email *",
"Email content *": "Conteúdo do email *",
"Sending...": "Enviando...",
"Send": "Enviar",
"Please do not send illegal content such as politics, pornography, etc": "Por favor, não envie conteúdo ilegal como política, pornografia, etc."
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "О нас",
"Privacy": "Конфиденциальность",
"INBOX": "ВХОДЯЩИЕ",
"Waiting for emails...": "Ожидание писем..."
"Waiting for emails...": "Ожидание писем...",
"Try it": "Попробуйте",
"Forward only, no storage": "Только пересылка, без сохранения",
"Sending email *": "Отправка электронной почты *",
"Sending name": "Имя отправителя",
"Recipient email *": "Адресат электронной почты *",
"Email subject *": "Тема письма *",
"Email content *": "Содержимое письма *",
"Sending...": "Отправка...",
"Send": "Отправить",
"Please do not send illegal content such as politics, pornography, etc": "Пожалуйста, не отправляйте незаконный контент, такой как политика, порнография и т. д."
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "Hakkında",
"Privacy": "Gizlilik",
"INBOX": "GİRİŞ",
"Waiting for emails...": "E-Postalar Bekleniyor..."
"Waiting for emails...": "E-Postalar Bekleniyor...",
"Try it": "Deneyin",
"Forward only, no storage": "Sadece ileri, depolama yok",
"Sending email *": "E-posta gönderme *",
"Sending name": "Gönderen adı",
"Recipient email *": "Alıcı e-posta *",
"Email subject *": "E-posta konusu *",
"Email content *": "E-posta içeriği *",
"Sending...": "Gönderiliyor...",
"Send": "Gönder",
"Please do not send illegal content such as politics, pornography, etc": "Lütfen siyaset, pornografi vb. gibi yasa dışı içerikler göndermeyin"
}
+11 -1
View File
@@ -16,5 +16,15 @@
"About": "關於",
"Privacy": "隱私政策",
"INBOX": "收件匣",
"Waiting for emails...": "等待電子郵件..."
"Waiting for emails...": "等待電子郵件...",
"Try it": "試試看",
"Forward only, no storage": "僅轉發,不儲存",
"Sending email *": "發送電子郵件 *",
"Sending name": "發件人姓名",
"Recipient email *": "收件者電子郵件 *",
"Email subject *": "電子郵件主題 *",
"Email content *": "電子郵件內容 *",
"Sending...": "發送中...",
"Send": "發送",
"Please do not send illegal content such as politics, pornography, etc": "請不要發送政治、色情等非法內容"
}
+12 -1
View File
@@ -16,5 +16,16 @@
"About": "关于",
"Privacy": "隐私",
"INBOX": "INBOX",
"Waiting for emails...": "准备接收邮件..."
"Waiting for emails...": "准备接收邮件...",
"Vmail sender is beta now. ": "Vmail 发信公测中,",
"Try it": "试试匿名发件",
"Forward only, no storage": "仅转发,不存储",
"Sending email *": "发送电子邮件 *",
"Sending name": "发件人昵称",
"Recipient email *": "收件人电子邮件 *",
"Email subject *": "电子邮件主题 *",
"Email content *": "电子邮件内容 *",
"Sending...": "正在发送...",
"Send": "发送",
"Please do not send illegal content such as politics, pornography, etc": "请勿发送涉政、色情等违法内容"
}