feat(i18n): add backend multi-language support with user language preference

- Add go-i18n library for internationalization
- Create i18n package with translation keys and YAML locale files (zh/en)
- Implement i18n middleware for language detection from user settings and Accept-Language header
- Add Language field to UserSetting DTO
- Update API response helpers with i18n support (ApiErrorI18n, ApiSuccessI18n)
- Migrate hardcoded messages in token, redemption, and user controllers
- Add frontend language preference settings component
- Sync language preference across header selector and user settings
- Auto-restore user language preference on login
This commit is contained in:
CaIon
2026-02-05 00:07:54 +08:00
parent ded79c7684
commit f60fce6584
20 changed files with 1393 additions and 317 deletions

View File

@@ -39,6 +39,7 @@ import { useTranslation } from 'react-i18next';
import UserInfoHeader from './personal/components/UserInfoHeader';
import AccountManagement from './personal/cards/AccountManagement';
import NotificationSettings from './personal/cards/NotificationSettings';
import PreferencesSettings from './personal/cards/PreferencesSettings';
import CheckinCalendar from './personal/cards/CheckinCalendar';
import EmailBindModal from './personal/modals/EmailBindModal';
import WeChatBindModal from './personal/modals/WeChatBindModal';
@@ -463,24 +464,29 @@ const PersonalSetting = () => {
{/* 账户管理和其他设置 */}
<div className='grid grid-cols-1 xl:grid-cols-2 items-start gap-4 md:gap-6 mt-4 md:mt-6'>
{/* 左侧:账户管理设置 */}
<AccountManagement
t={t}
userState={userState}
status={status}
systemToken={systemToken}
setShowEmailBindModal={setShowEmailBindModal}
setShowWeChatBindModal={setShowWeChatBindModal}
generateAccessToken={generateAccessToken}
handleSystemTokenClick={handleSystemTokenClick}
setShowChangePasswordModal={setShowChangePasswordModal}
setShowAccountDeleteModal={setShowAccountDeleteModal}
passkeyStatus={passkeyStatus}
passkeySupported={passkeySupported}
passkeyRegisterLoading={passkeyRegisterLoading}
passkeyDeleteLoading={passkeyDeleteLoading}
onPasskeyRegister={handleRegisterPasskey}
onPasskeyDelete={handleRemovePasskey}
/>
<div className='flex flex-col gap-4 md:gap-6'>
<AccountManagement
t={t}
userState={userState}
status={status}
systemToken={systemToken}
setShowEmailBindModal={setShowEmailBindModal}
setShowWeChatBindModal={setShowWeChatBindModal}
generateAccessToken={generateAccessToken}
handleSystemTokenClick={handleSystemTokenClick}
setShowChangePasswordModal={setShowChangePasswordModal}
setShowAccountDeleteModal={setShowAccountDeleteModal}
passkeyStatus={passkeyStatus}
passkeySupported={passkeySupported}
passkeyRegisterLoading={passkeyRegisterLoading}
passkeyDeleteLoading={passkeyDeleteLoading}
onPasskeyRegister={handleRegisterPasskey}
onPasskeyDelete={handleRemovePasskey}
/>
{/* 偏好设置(语言等) */}
<PreferencesSettings t={t} />
</div>
{/* 右侧:其他设置 */}
<NotificationSettings