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 732d501f75
commit c444746088
20 changed files with 1393 additions and 317 deletions

View File

@@ -146,10 +146,41 @@ export const useHeaderBar = ({ onMobileMenuToggle, drawerOpen }) => {
}, [navigate, t, userDispatch]);
const handleLanguageChange = useCallback(
(lang) => {
async (lang) => {
// Change language immediately for responsive UX
i18n.changeLanguage(lang);
// If user is logged in, save preference to backend
if (userState?.user?.id) {
try {
const res = await API.put('/api/user/self', {
language: lang,
});
if (res.data.success) {
// Update user context with new setting
if (userState?.user?.setting) {
try {
const settings = JSON.parse(userState.user.setting);
settings.language = lang;
userDispatch({
type: 'login',
payload: {
...userState.user,
setting: JSON.stringify(settings),
},
});
} catch (e) {
// Ignore parse errors
}
}
}
} catch (error) {
// Silently ignore errors - language was already changed locally
console.error('Failed to save language preference:', error);
}
}
},
[i18n],
[i18n, userState, userDispatch],
);
const handleThemeToggle = useCallback(