feat: 修改翻译

This commit is contained in:
2025-08-10 09:28:39 -07:00
parent c8bf1d484e
commit 130a2506ac
25 changed files with 218 additions and 141 deletions
@@ -1,3 +1,4 @@
import { useTranslations } from 'next-intl';
import React from 'react';
import { PlanList } from './index';
import { ProcessedPlanData } from './types';
@@ -23,6 +24,7 @@ export const TabContent: React.FC<TabContentProps> = ({
onSubscribe,
firstPlanCardRef,
}) => {
const t = useTranslations('components.offerDialog');
return (
<div>
{tabValue === 'year' && (
@@ -32,7 +34,7 @@ export const TabContent: React.FC<TabContentProps> = ({
tabValue={tabValue}
error={error}
onRetry={onRetry}
emptyMessage='暂无年付套餐'
emptyMessage={t('noYearlyPlan')}
onSubscribe={onSubscribe}
firstPlanCardRef={firstPlanCardRef}
/>
@@ -44,7 +46,7 @@ export const TabContent: React.FC<TabContentProps> = ({
isLoading={isLoading}
error={error}
onRetry={onRetry}
emptyMessage='暂无月付套餐'
emptyMessage={t('noMonthlyPlan')}
onSubscribe={onSubscribe}
firstPlanCardRef={firstPlanCardRef}
/>
+54 -45
View File
@@ -1,11 +1,9 @@
import CloseSvg from '@/components/CustomIcon/icons/close.svg';
import { getSubscription } from '@/services/user/portal';
import { useQuery } from '@tanstack/react-query';
import { Dialog, DialogContent, DialogTitle } from '@workspace/airo-ui/components/dialog';
import { ScrollArea } from '@workspace/airo-ui/components/scroll-area';
import { Tabs, TabsList, TabsTrigger } from '@workspace/airo-ui/components/tabs';
import { unitConversion } from '@workspace/airo-ui/utils';
import Image from 'next/image';
import {
forwardRef,
useCallback,
@@ -20,25 +18,31 @@ import { TabContent } from './TabContent';
import { ProcessedPlanData } from './types';
// 加载状态组件
const LoadingState = () => (
<div className='py-12 text-center'>
<div className='mx-auto h-12 w-12 animate-spin rounded-full border-b-2 border-[#0F2C53]'></div>
<p className='mt-4 text-gray-600'>...</p>
</div>
);
const LoadingState = () => {
const t = useTranslations('components.offerDialog');
return (
<div className='py-12 text-center'>
<div className='mx-auto h-12 w-12 animate-spin rounded-full border-b-2 border-[#0F2C53]'></div>
<p className='mt-4 text-gray-600'>{t('loading')}</p>
</div>
);
};
// 错误状态组件
const ErrorState = ({ onRetry }: { onRetry: () => void }) => (
<div className='py-12 text-center'>
<p className='text-lg text-red-500'></p>
<button
onClick={onRetry}
className='mt-4 rounded-lg bg-[#0F2C53] px-6 py-2 text-white transition-colors hover:bg-[#0A2C47]'
>
</button>
</div>
);
const ErrorState = ({ onRetry }: { onRetry: () => void }) => {
const t = useTranslations('components.offerDialog');
return (
<div className='py-12 text-center'>
<p className='text-lg text-red-500'>{t('loadFailed')}</p>
<button
onClick={onRetry}
className='mt-4 rounded-lg bg-[#0F2C53] px-6 py-2 text-white transition-colors hover:bg-[#0A2C47]'
>
{t('reload')}
</button>
</div>
);
};
// 空状态组件
const EmptyState = ({ message }: { message: string }) => (
@@ -48,34 +52,41 @@ const EmptyState = ({ message }: { message: string }) => (
);
// 价格显示组件
const PriceDisplay = ({ plan }: { plan: ProcessedPlanData }) => (
<div className='mb-2 sm:mb-4'>
<div className='mb-1 flex items-baseline gap-2'>
{plan.origin_price && (
<span className='text-2xl font-bold leading-[1.125em] text-[#666666] line-through'>
${plan.origin_price}
const PriceDisplay = ({ plan }: { plan: ProcessedPlanData }) => {
const t = useTranslations('components.offerDialog');
return (
<div className='mb-2 sm:mb-4'>
<div className='mb-1 flex items-baseline gap-2'>
{plan.origin_price && (
<span className='text-2xl font-bold leading-[1.125em] text-[#666666] line-through'>
${plan.origin_price}
</span>
)}
<span className='text-2xl font-bold leading-[1.125em] text-[#091B33]'>
${plan.discount_price}
</span>
<span className='text-sm font-normal leading-[1.8em] text-[#4D4D4D] sm:text-[15px]'>
{t('perYear')}
</span>
</div>
{plan.origin_price && (
<p className='text-left text-[10px] font-normal text-black'>{t('yearlyDiscount')}</p>
)}
<span className='text-2xl font-bold leading-[1.125em] text-[#091B33]'>
${plan.discount_price}
</span>
<span className='text-sm font-normal leading-[1.8em] text-[#4D4D4D] sm:text-[15px]'>/</span>
</div>
{plan.origin_price && (
<p className='text-left text-[10px] font-normal text-black'>8</p>
)}
</div>
);
);
};
import { useLoginDialog } from '@/app/auth/LoginDialogContext';
import { Display } from '@/components/display';
import Purchase from '@/components/subscribe/purchase';
import useGlobalStore from '@/config/use-global';
import { useTranslations } from 'next-intl';
// 订阅按钮组件
const SubscribeButton = ({ onClick }: { onClick?: () => void }) => {
const { user } = useGlobalStore();
const { openLoginDialog } = useLoginDialog();
const t = useTranslations('components.offerDialog');
function handleClick() {
console.log('click', user);
@@ -92,7 +103,7 @@ const SubscribeButton = ({ onClick }: { onClick?: () => void }) => {
onClick={handleClick}
className='h-10 w-full rounded-full bg-[#0F2C53] text-sm font-medium text-white shadow-md transition-all duration-300 hover:bg-[#225BA9] sm:h-10 sm:text-sm md:h-[40px] md:text-[14px]'
>
{t('subscribe')}
</button>
);
};
@@ -111,7 +122,8 @@ const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: num
// 功能列表组件
const FeatureList = ({ plan }: { plan: ProcessedPlanData }) => {
const t = useTranslations('subscribe.detail');
const features = [{ label: '可用节点', value: plan.features?.nodes || '11' }];
const tOffer = useTranslations('components.offerDialog');
const features = [{ label: tOffer('availableNodes'), value: plan.features?.nodes || '11' }];
return (
<div className='mt-6 space-y-0 sm:mt-6'>
@@ -154,7 +166,7 @@ const FeatureList = ({ plan }: { plan: ProcessedPlanData }) => {
<li className='py-1'>
<div className={'flex items-start justify-between'}>
<span className='text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
:
{tOffer('networkStabilityIndex')}
</span>
<StarRating rating={plan.features?.stability || 4} />
</div>
@@ -246,6 +258,7 @@ export interface OfferDialogRef {
}
const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
const t = useTranslations('components.offerDialog');
const [open, setOpen] = useState(false);
const [tabValue, setTabValue] = useState('year');
const [selectedPlan, setSelectedPlan] = useState<ProcessedPlanData | null>(null);
@@ -379,17 +392,13 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
<DialogContent
ref={dialogRef}
className='rounded-0 !container h-full w-full gap-0 px-8 py-8 sm:h-auto sm:!rounded-[32px] sm:px-12 sm:py-12 md:w-[1000px]'
closeIcon={<Image src={CloseSvg} alt={'close'} />}
closeClassName={
'right-6 top-6 font-bold text-black opacity-100 focus:ring-0 focus:ring-offset-0'
}
>
<DialogTitle className={'sr-only'}></DialogTitle>
<div className={'text-4xl font-bold text-[#0F2C53] md:mb-4 md:text-center md:text-5xl'}>
{t('selectPlan')}
</div>
<div className={'text-lg font-medium text-[#666666] md:text-center'}>
{t('selectYourPlan')}
</div>
<div>
<Tabs
@@ -421,7 +430,7 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
}
value='year'
>
{t('yearlyPlan')}
</TabsTrigger>
<TabsTrigger
className={
@@ -429,7 +438,7 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
}
value='month'
>
{t('monthlyPlan')}
</TabsTrigger>
</TabsList>
</Tabs>