translate comment of frontend/components/web
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
//一个自定义封装,便于简单使用
|
||||
//简单用法,使用便捷组件
|
||||
// A custom wrapper for simple use
|
||||
// Simple usage, use the convenience component
|
||||
// import { Tooltip } from '@/components/Tooltip';
|
||||
|
||||
// <Tooltip content="这是提示内容">
|
||||
// <button>悬停查看</button>
|
||||
// <Tooltip content="This is the tooltip content">
|
||||
// <button>Hover to see</button>
|
||||
// </Tooltip>
|
||||
|
||||
// // 需要更多自定义时,使用基础组件
|
||||
// When more customization is needed, use the base components
|
||||
// import {
|
||||
// Tooltip,
|
||||
// TooltipContent,
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
// <TooltipProvider>
|
||||
// <Tooltip>
|
||||
// <TooltipTrigger>悬停查看</TooltipTrigger>
|
||||
// <TooltipTrigger>Hover to see</TooltipTrigger>
|
||||
// <TooltipContent>
|
||||
// 这是提示内容
|
||||
// This is the tooltip content
|
||||
// </TooltipContent>
|
||||
// </Tooltip>
|
||||
// </TooltipProvider>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//弹窗会在满足条件时自动弹出,并确保只弹出一次
|
||||
// The pop-up dialog will appear automatically when conditions are met, and ensures it only appears once.
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -11,13 +11,13 @@ import {
|
||||
} from '@/components/ui/dialog';
|
||||
|
||||
interface AutoPopupDialogProps {
|
||||
// 用于localStorage的唯一标识
|
||||
// Unique identifier for localStorage
|
||||
storageKey: string;
|
||||
// 弹窗标题
|
||||
// Dialog title
|
||||
title: string;
|
||||
// 弹窗描述内容
|
||||
// Dialog description content
|
||||
description: string;
|
||||
// 触发弹窗的条件函数
|
||||
// Condition function to trigger the dialog
|
||||
condition?: () => boolean;
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ export function AutoPopupDialog({
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// 检查是否已经显示过
|
||||
const hasShown = localStorage.getItem(storageKey);//localStorage 是一种 Web Storage 技术,允许浏览器在客户端本地存储数据。它可以存储键值对(key-value),并且这些数据在页面刷新、浏览器重启后仍然存在,直到手动删除或通过代码清除。
|
||||
// Check if it has been shown before using localStorage
|
||||
const hasShown = localStorage.getItem(storageKey);
|
||||
|
||||
if (!hasShown && condition()) {
|
||||
setOpen(true);
|
||||
// 标记为已显示
|
||||
// Mark as shown
|
||||
localStorage.setItem(storageKey, 'true');
|
||||
}
|
||||
}, [storageKey, condition]);
|
||||
|
||||
@@ -19,15 +19,15 @@ const generateFAQs = (messages: { text: { faqs: FAQMessage } }): FAQ[] => {
|
||||
const faqs: FAQ[] = [];
|
||||
const faqsData = messages.text.faqs;
|
||||
|
||||
// 获取所有问题的数量(通过查找 question_ 开头的键)
|
||||
// Get the total number of questions (by finding keys starting with question_)
|
||||
const questionKeys = Object.keys(faqsData).filter(key => key.startsWith('question_'));
|
||||
|
||||
// 根据问题数量自动生成FAQ数组
|
||||
// Automatically generate FAQ array based on the number of questions
|
||||
questionKeys.forEach(qKey => {
|
||||
const index = qKey.split('_')[1]; // 获取数字索引
|
||||
const index = qKey.split('_')[1]; // Get the numeric index
|
||||
const aKey = `answer_${index}`;
|
||||
|
||||
if (faqsData[aKey]) { // 确保对应的答案存在
|
||||
if (faqsData[aKey]) { // Ensure the corresponding answer exists
|
||||
faqs.push({
|
||||
question: faqsData[qKey],
|
||||
answer: faqsData[aKey]
|
||||
@@ -39,14 +39,14 @@ const generateFAQs = (messages: { text: { faqs: FAQMessage } }): FAQ[] => {
|
||||
};
|
||||
|
||||
interface FAQSectionProps {
|
||||
isMainPage?: boolean; // 是否为主页面的FAQ部分
|
||||
className?: string; // 允许传入自定义className
|
||||
showTitle?: boolean; // 是否显示标题
|
||||
titleClassName?: string; // 标题样式类
|
||||
isMainPage?: boolean; // Whether it is the FAQ section of the main page
|
||||
className?: string; // Allow passing custom className
|
||||
showTitle?: boolean; // Whether to display the title
|
||||
titleClassName?: string; // Title style class
|
||||
lang?: string;
|
||||
messages: Messages;
|
||||
}
|
||||
//通过 props 来控制标题的级别和样式,这样可以用在其他页面也可以用在独立页面
|
||||
// Control the level and style of the title through props, so it can be used on other pages as well as on a standalone page
|
||||
export default function FAQSection({
|
||||
isMainPage = false,
|
||||
className = "",
|
||||
@@ -57,7 +57,7 @@ export default function FAQSection({
|
||||
|
||||
const faqs = generateFAQs(messages);
|
||||
|
||||
// 为不同场景设置默认样式
|
||||
// Set default styles for different scenarios
|
||||
const containerClasses = `container mx-auto px-4 py-8 ${className}`;
|
||||
const defaultTitleClasses = "font-bold mb-8";
|
||||
const titleClasses = `${defaultTitleClasses} ${titleClassName}`.trim();
|
||||
@@ -82,14 +82,14 @@ export default function FAQSection({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
// // 在独立的FAQ页面
|
||||
// <FAQSection /> // 使用 h1 标签
|
||||
// // On the standalone FAQ page
|
||||
// <FAQSection /> // Use h1 tag
|
||||
|
||||
// // 在首页
|
||||
// // On the home page
|
||||
// <FAQSection
|
||||
// isMainPage
|
||||
// titleClassName="text-2xl md:text-3xl" // 可选:在首页使用稍小的字号
|
||||
// /> // 使用 h2 标签
|
||||
// titleClassName="text-2xl md:text-3xl" // Optional: use a slightly smaller font size on the home page
|
||||
// /> // Use h2 tag
|
||||
|
||||
// // 如果不需要显示标题
|
||||
// // If you don't need to display the title
|
||||
// <FAQSection showTitle={false} />
|
||||
@@ -13,7 +13,7 @@ export function Footer({ messages, lang }: FooterProps) {
|
||||
<footer className="bg-background border-t mt-auto">
|
||||
<div className="container mx-auto px-4 py-6">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-center space-y-4 sm:space-y-0">
|
||||
{/* 左侧Logo和版权信息 */}
|
||||
{/* Left: Logo and copyright information */}
|
||||
<div className="flex items-center">
|
||||
<Image
|
||||
src="/logo.png"
|
||||
@@ -28,10 +28,10 @@ export function Footer({ messages, lang }: FooterProps) {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 右侧导航 */}
|
||||
{/* Right: Navigation */}
|
||||
<nav>
|
||||
<ul className="flex flex-wrap justify-center gap-4">
|
||||
{/* 条款和隐私政策 */}
|
||||
{/* Terms and Privacy Policy */}
|
||||
<li>
|
||||
<Link
|
||||
href={`/${lang}/terms`}
|
||||
@@ -49,7 +49,7 @@ export function Footer({ messages, lang }: FooterProps) {
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
{/* 支持的语言入口 */}
|
||||
{/* Entry for supported languages */}
|
||||
<li>
|
||||
<span className="text-sm text-muted-foreground font-bold">
|
||||
{messages.text.Footer.SupportedLanguages}:
|
||||
|
||||
@@ -2,11 +2,11 @@ import { Github } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
const GitHubRibbon = () => {
|
||||
// 定义基础尺寸,便于统一调整
|
||||
const squareSize = "170px"; // 正方形大小
|
||||
const triangleSize = "150px"; // 三角形大小
|
||||
const ribbonWidth = "280px"; // 彩带宽度
|
||||
const ribbonHeight = "34px"; // 彩带高度
|
||||
// Define base dimensions for easy adjustment
|
||||
const squareSize = "170px"; // Square size
|
||||
const triangleSize = "150px"; // Triangle size
|
||||
const ribbonWidth = "280px"; // Ribbon width
|
||||
const ribbonHeight = "34px"; // Ribbon height
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -22,7 +22,7 @@ const GitHubRibbon = () => {
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
>
|
||||
{/* 三角形背景 */}
|
||||
{/* Triangle background */}
|
||||
<div
|
||||
className="absolute top-0 right-0 bg-black dark:bg-gray-800"
|
||||
style={{
|
||||
@@ -32,7 +32,7 @@ const GitHubRibbon = () => {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* GitHub 图标 */}
|
||||
{/* GitHub Icon */}
|
||||
<Github
|
||||
className="absolute text-primary-foreground rotate-45"
|
||||
style={{
|
||||
@@ -42,7 +42,7 @@ const GitHubRibbon = () => {
|
||||
size={38}
|
||||
/>
|
||||
|
||||
{/* Fork me 彩带 */}
|
||||
{/* Fork me Ribbon */}
|
||||
<Link
|
||||
href="https://github.com/david-bai00/PrivyDrop"
|
||||
target="_blank"
|
||||
|
||||
@@ -45,7 +45,7 @@ const Header = ({ messages, lang }: HeaderProps) => {
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* 桌面端导航和语言切换 */}
|
||||
{/* Desktop navigation and language switcher */}
|
||||
<div className="hidden md:flex items-center space-x-4">
|
||||
<nav>
|
||||
<ul className="flex space-x-2">
|
||||
@@ -69,7 +69,7 @@ const Header = ({ messages, lang }: HeaderProps) => {
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
|
||||
{/* 移动端菜单按钮 */}
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden flex items-center space-x-2">
|
||||
<LanguageSwitcher />
|
||||
<Button asChild variant="ghost" size="icon">
|
||||
@@ -91,7 +91,7 @@ const Header = ({ messages, lang }: HeaderProps) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 移动端导航菜单 */}
|
||||
{/* Mobile navigation menu */}
|
||||
{isOpen && (
|
||||
<nav className="md:hidden mt-4">
|
||||
<ul className="flex flex-col space-y-2">
|
||||
|
||||
@@ -69,7 +69,7 @@ export default function HowItWorks({ messages }: PageContentProps){
|
||||
{/* Right Side - Demo Animation */}
|
||||
<div className="w-full md:w-1/2">
|
||||
<div className="bg-white rounded-lg shadow-lg overflow-hidden">
|
||||
{/* Next.js 默认的图片优化器不支持 GIF 动画的处理 */}
|
||||
{/* The default Next.js image optimizer does not support handling of GIF animations */}
|
||||
<Image src="/HowItWorks.gif" alt="How SecureShare Works" unoptimized width={700} height={921} className="mx-auto mb-6" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user