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:
270
i18n/keys.go
Normal file
270
i18n/keys.go
Normal file
@@ -0,0 +1,270 @@
|
||||
package i18n
|
||||
|
||||
// Message keys for i18n translations
|
||||
// Use these constants instead of hardcoded strings
|
||||
|
||||
// Common error messages
|
||||
const (
|
||||
MsgInvalidParams = "common.invalid_params"
|
||||
MsgDatabaseError = "common.database_error"
|
||||
MsgRetryLater = "common.retry_later"
|
||||
MsgGenerateFailed = "common.generate_failed"
|
||||
MsgNotFound = "common.not_found"
|
||||
MsgUnauthorized = "common.unauthorized"
|
||||
MsgForbidden = "common.forbidden"
|
||||
MsgInvalidId = "common.invalid_id"
|
||||
MsgIdEmpty = "common.id_empty"
|
||||
MsgFeatureDisabled = "common.feature_disabled"
|
||||
MsgOperationSuccess = "common.operation_success"
|
||||
MsgOperationFailed = "common.operation_failed"
|
||||
MsgUpdateSuccess = "common.update_success"
|
||||
MsgUpdateFailed = "common.update_failed"
|
||||
MsgCreateSuccess = "common.create_success"
|
||||
MsgCreateFailed = "common.create_failed"
|
||||
MsgDeleteSuccess = "common.delete_success"
|
||||
MsgDeleteFailed = "common.delete_failed"
|
||||
MsgAlreadyExists = "common.already_exists"
|
||||
MsgNameCannotBeEmpty = "common.name_cannot_be_empty"
|
||||
)
|
||||
|
||||
// Token related messages
|
||||
const (
|
||||
MsgTokenNameTooLong = "token.name_too_long"
|
||||
MsgTokenQuotaNegative = "token.quota_negative"
|
||||
MsgTokenQuotaExceedMax = "token.quota_exceed_max"
|
||||
MsgTokenGenerateFailed = "token.generate_failed"
|
||||
MsgTokenGetInfoFailed = "token.get_info_failed"
|
||||
MsgTokenExpiredCannotEnable = "token.expired_cannot_enable"
|
||||
MsgTokenExhaustedCannotEable = "token.exhausted_cannot_enable"
|
||||
MsgTokenInvalid = "token.invalid"
|
||||
MsgTokenNotProvided = "token.not_provided"
|
||||
MsgTokenExpired = "token.expired"
|
||||
MsgTokenExhausted = "token.exhausted"
|
||||
MsgTokenStatusUnavailable = "token.status_unavailable"
|
||||
MsgTokenDbError = "token.db_error"
|
||||
)
|
||||
|
||||
// Redemption related messages
|
||||
const (
|
||||
MsgRedemptionNameLength = "redemption.name_length"
|
||||
MsgRedemptionCountPositive = "redemption.count_positive"
|
||||
MsgRedemptionCountMax = "redemption.count_max"
|
||||
MsgRedemptionCreateFailed = "redemption.create_failed"
|
||||
MsgRedemptionInvalid = "redemption.invalid"
|
||||
MsgRedemptionUsed = "redemption.used"
|
||||
MsgRedemptionExpired = "redemption.expired"
|
||||
MsgRedemptionFailed = "redemption.failed"
|
||||
MsgRedemptionNotProvided = "redemption.not_provided"
|
||||
MsgRedemptionExpireTimeInvalid = "redemption.expire_time_invalid"
|
||||
)
|
||||
|
||||
// User related messages
|
||||
const (
|
||||
MsgUserPasswordLoginDisabled = "user.password_login_disabled"
|
||||
MsgUserRegisterDisabled = "user.register_disabled"
|
||||
MsgUserPasswordRegisterDisabled = "user.password_register_disabled"
|
||||
MsgUserUsernameOrPasswordEmpty = "user.username_or_password_empty"
|
||||
MsgUserUsernameOrPasswordError = "user.username_or_password_error"
|
||||
MsgUserEmailOrPasswordEmpty = "user.email_or_password_empty"
|
||||
MsgUserExists = "user.exists"
|
||||
MsgUserNotExists = "user.not_exists"
|
||||
MsgUserDisabled = "user.disabled"
|
||||
MsgUserSessionSaveFailed = "user.session_save_failed"
|
||||
MsgUserRequire2FA = "user.require_2fa"
|
||||
MsgUserEmailVerificationRequired = "user.email_verification_required"
|
||||
MsgUserVerificationCodeError = "user.verification_code_error"
|
||||
MsgUserInputInvalid = "user.input_invalid"
|
||||
MsgUserNoPermissionSameLevel = "user.no_permission_same_level"
|
||||
MsgUserNoPermissionHigherLevel = "user.no_permission_higher_level"
|
||||
MsgUserCannotCreateHigherLevel = "user.cannot_create_higher_level"
|
||||
MsgUserCannotDeleteRootUser = "user.cannot_delete_root_user"
|
||||
MsgUserCannotDisableRootUser = "user.cannot_disable_root_user"
|
||||
MsgUserCannotDemoteRootUser = "user.cannot_demote_root_user"
|
||||
MsgUserAlreadyAdmin = "user.already_admin"
|
||||
MsgUserAlreadyCommon = "user.already_common"
|
||||
MsgUserAdminCannotPromote = "user.admin_cannot_promote"
|
||||
MsgUserOriginalPasswordError = "user.original_password_error"
|
||||
MsgUserInviteQuotaInsufficient = "user.invite_quota_insufficient"
|
||||
MsgUserTransferQuotaMinimum = "user.transfer_quota_minimum"
|
||||
MsgUserTransferSuccess = "user.transfer_success"
|
||||
MsgUserTransferFailed = "user.transfer_failed"
|
||||
MsgUserTopUpProcessing = "user.topup_processing"
|
||||
MsgUserRegisterFailed = "user.register_failed"
|
||||
MsgUserDefaultTokenFailed = "user.default_token_failed"
|
||||
MsgUserAffCodeEmpty = "user.aff_code_empty"
|
||||
MsgUserEmailEmpty = "user.email_empty"
|
||||
MsgUserGitHubIdEmpty = "user.github_id_empty"
|
||||
MsgUserDiscordIdEmpty = "user.discord_id_empty"
|
||||
MsgUserOidcIdEmpty = "user.oidc_id_empty"
|
||||
MsgUserWeChatIdEmpty = "user.wechat_id_empty"
|
||||
MsgUserTelegramIdEmpty = "user.telegram_id_empty"
|
||||
MsgUserTelegramNotBound = "user.telegram_not_bound"
|
||||
MsgUserLinuxDOIdEmpty = "user.linux_do_id_empty"
|
||||
)
|
||||
|
||||
// Quota related messages
|
||||
const (
|
||||
MsgQuotaNegative = "quota.negative"
|
||||
MsgQuotaExceedMax = "quota.exceed_max"
|
||||
MsgQuotaInsufficient = "quota.insufficient"
|
||||
MsgQuotaWarningInvalid = "quota.warning_invalid"
|
||||
MsgQuotaThresholdGtZero = "quota.threshold_gt_zero"
|
||||
)
|
||||
|
||||
// Subscription related messages
|
||||
const (
|
||||
MsgSubscriptionNotEnabled = "subscription.not_enabled"
|
||||
MsgSubscriptionTitleEmpty = "subscription.title_empty"
|
||||
MsgSubscriptionPriceNegative = "subscription.price_negative"
|
||||
MsgSubscriptionPriceMax = "subscription.price_max"
|
||||
MsgSubscriptionPurchaseLimitNeg = "subscription.purchase_limit_negative"
|
||||
MsgSubscriptionQuotaNegative = "subscription.quota_negative"
|
||||
MsgSubscriptionGroupNotExists = "subscription.group_not_exists"
|
||||
MsgSubscriptionResetCycleGtZero = "subscription.reset_cycle_gt_zero"
|
||||
MsgSubscriptionPurchaseMax = "subscription.purchase_max"
|
||||
MsgSubscriptionInvalidId = "subscription.invalid_id"
|
||||
MsgSubscriptionInvalidUserId = "subscription.invalid_user_id"
|
||||
)
|
||||
|
||||
// Payment related messages
|
||||
const (
|
||||
MsgPaymentNotConfigured = "payment.not_configured"
|
||||
MsgPaymentMethodNotExists = "payment.method_not_exists"
|
||||
MsgPaymentCallbackError = "payment.callback_error"
|
||||
MsgPaymentCreateFailed = "payment.create_failed"
|
||||
MsgPaymentStartFailed = "payment.start_failed"
|
||||
MsgPaymentAmountTooLow = "payment.amount_too_low"
|
||||
MsgPaymentStripeNotConfig = "payment.stripe_not_configured"
|
||||
MsgPaymentWebhookNotConfig = "payment.webhook_not_configured"
|
||||
MsgPaymentPriceIdNotConfig = "payment.price_id_not_configured"
|
||||
MsgPaymentCreemNotConfig = "payment.creem_not_configured"
|
||||
)
|
||||
|
||||
// Topup related messages
|
||||
const (
|
||||
MsgTopupNotProvided = "topup.not_provided"
|
||||
MsgTopupOrderNotExists = "topup.order_not_exists"
|
||||
MsgTopupOrderStatus = "topup.order_status"
|
||||
MsgTopupFailed = "topup.failed"
|
||||
MsgTopupInvalidQuota = "topup.invalid_quota"
|
||||
)
|
||||
|
||||
// Channel related messages
|
||||
const (
|
||||
MsgChannelNotExists = "channel.not_exists"
|
||||
MsgChannelIdFormatError = "channel.id_format_error"
|
||||
MsgChannelNoAvailableKey = "channel.no_available_key"
|
||||
MsgChannelGetListFailed = "channel.get_list_failed"
|
||||
MsgChannelGetTagsFailed = "channel.get_tags_failed"
|
||||
MsgChannelGetKeyFailed = "channel.get_key_failed"
|
||||
MsgChannelGetOllamaFailed = "channel.get_ollama_failed"
|
||||
MsgChannelQueryFailed = "channel.query_failed"
|
||||
MsgChannelNoValidUpstream = "channel.no_valid_upstream"
|
||||
MsgChannelUpstreamSaturated = "channel.upstream_saturated"
|
||||
MsgChannelGetAvailableFailed = "channel.get_available_failed"
|
||||
)
|
||||
|
||||
// Model related messages
|
||||
const (
|
||||
MsgModelNameEmpty = "model.name_empty"
|
||||
MsgModelNameExists = "model.name_exists"
|
||||
MsgModelIdMissing = "model.id_missing"
|
||||
MsgModelGetListFailed = "model.get_list_failed"
|
||||
MsgModelGetFailed = "model.get_failed"
|
||||
MsgModelResetSuccess = "model.reset_success"
|
||||
)
|
||||
|
||||
// Vendor related messages
|
||||
const (
|
||||
MsgVendorNameEmpty = "vendor.name_empty"
|
||||
MsgVendorNameExists = "vendor.name_exists"
|
||||
MsgVendorIdMissing = "vendor.id_missing"
|
||||
)
|
||||
|
||||
// Group related messages
|
||||
const (
|
||||
MsgGroupNameTypeEmpty = "group.name_type_empty"
|
||||
MsgGroupNameExists = "group.name_exists"
|
||||
MsgGroupIdMissing = "group.id_missing"
|
||||
)
|
||||
|
||||
// Checkin related messages
|
||||
const (
|
||||
MsgCheckinDisabled = "checkin.disabled"
|
||||
MsgCheckinAlreadyToday = "checkin.already_today"
|
||||
MsgCheckinFailed = "checkin.failed"
|
||||
MsgCheckinQuotaFailed = "checkin.quota_failed"
|
||||
)
|
||||
|
||||
// Passkey related messages
|
||||
const (
|
||||
MsgPasskeyCreateFailed = "passkey.create_failed"
|
||||
MsgPasskeyLoginAbnormal = "passkey.login_abnormal"
|
||||
MsgPasskeyUpdateFailed = "passkey.update_failed"
|
||||
MsgPasskeyInvalidUserId = "passkey.invalid_user_id"
|
||||
MsgPasskeyVerifyFailed = "passkey.verify_failed"
|
||||
)
|
||||
|
||||
// 2FA related messages
|
||||
const (
|
||||
MsgTwoFANotEnabled = "twofa.not_enabled"
|
||||
MsgTwoFAUserIdEmpty = "twofa.user_id_empty"
|
||||
MsgTwoFAAlreadyExists = "twofa.already_exists"
|
||||
MsgTwoFARecordIdEmpty = "twofa.record_id_empty"
|
||||
MsgTwoFACodeInvalid = "twofa.code_invalid"
|
||||
)
|
||||
|
||||
// Rate limit related messages
|
||||
const (
|
||||
MsgRateLimitReached = "rate_limit.reached"
|
||||
MsgRateLimitTotalReached = "rate_limit.total_reached"
|
||||
)
|
||||
|
||||
// Setting related messages
|
||||
const (
|
||||
MsgSettingInvalidType = "setting.invalid_type"
|
||||
MsgSettingWebhookEmpty = "setting.webhook_empty"
|
||||
MsgSettingWebhookInvalid = "setting.webhook_invalid"
|
||||
MsgSettingEmailInvalid = "setting.email_invalid"
|
||||
MsgSettingBarkUrlEmpty = "setting.bark_url_empty"
|
||||
MsgSettingBarkUrlInvalid = "setting.bark_url_invalid"
|
||||
MsgSettingGotifyUrlEmpty = "setting.gotify_url_empty"
|
||||
MsgSettingGotifyTokenEmpty = "setting.gotify_token_empty"
|
||||
MsgSettingGotifyUrlInvalid = "setting.gotify_url_invalid"
|
||||
MsgSettingUrlMustHttp = "setting.url_must_http"
|
||||
MsgSettingSaved = "setting.saved"
|
||||
)
|
||||
|
||||
// Deployment related messages (io.net)
|
||||
const (
|
||||
MsgDeploymentNotEnabled = "deployment.not_enabled"
|
||||
MsgDeploymentIdRequired = "deployment.id_required"
|
||||
MsgDeploymentContainerIdReq = "deployment.container_id_required"
|
||||
MsgDeploymentNameEmpty = "deployment.name_empty"
|
||||
MsgDeploymentNameTaken = "deployment.name_taken"
|
||||
MsgDeploymentHardwareIdReq = "deployment.hardware_id_required"
|
||||
MsgDeploymentHardwareInvId = "deployment.hardware_invalid_id"
|
||||
MsgDeploymentApiKeyRequired = "deployment.api_key_required"
|
||||
MsgDeploymentInvalidPayload = "deployment.invalid_payload"
|
||||
MsgDeploymentNotFound = "deployment.not_found"
|
||||
)
|
||||
|
||||
// Performance related messages
|
||||
const (
|
||||
MsgPerfDiskCacheCleared = "performance.disk_cache_cleared"
|
||||
MsgPerfStatsReset = "performance.stats_reset"
|
||||
MsgPerfGcExecuted = "performance.gc_executed"
|
||||
)
|
||||
|
||||
// Ability related messages
|
||||
const (
|
||||
MsgAbilityDbCorrupted = "ability.db_corrupted"
|
||||
MsgAbilityRepairRunning = "ability.repair_running"
|
||||
)
|
||||
|
||||
// OAuth related messages
|
||||
const (
|
||||
MsgOAuthInvalidCode = "oauth.invalid_code"
|
||||
MsgOAuthGetUserErr = "oauth.get_user_error"
|
||||
MsgOAuthAccountUsed = "oauth.account_used"
|
||||
)
|
||||
Reference in New Issue
Block a user