This integration enables translated authentication error messages using your existing @nuxtjs/i18n setup.
pnpm add @nuxtjs/i18n
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n', '@onmax/nuxt-better-auth'],
i18n: {
locales: ['en', 'es'],
defaultLocale: 'en'
}
})
Add error translations to your locale files using the auth.errors.* prefix:
auth:
errors:
USER_NOT_FOUND: "User not found"
INVALID_PASSWORD: "Invalid password"
INVALID_EMAIL_OR_PASSWORD: "Invalid email or password"
EMAIL_NOT_VERIFIED: "Please verify your email first"
SESSION_EXPIRED: "Session expired, please sign in again"
auth:
errors:
USER_NOT_FOUND: "Usuario no encontrado"
INVALID_PASSWORD: "Contraseña incorrecta"
INVALID_EMAIL_OR_PASSWORD: "Email o contraseña incorrectos"
EMAIL_NOT_VERIFIED: "Por favor verifica tu email primero"
SESSION_EXPIRED: "Sesión expirada, inicia sesión de nuevo"
Better Auth errors include a code property that you can translate using useI18n():
<script setup lang="ts">
const { signIn } = useUserSession()
const { t, te } = useI18n()
const error = ref<{ code?: string, message?: string } | null>(null)
async function handleLogin(email: string, password: string) {
await signIn.email(
{ email, password },
{
onError: (ctx) => {
error.value = ctx.error
}
}
)
}
function getErrorMessage(err: { code?: string, message?: string }) {
const key = `auth.errors.${err.code}`
return te(key) ? t(key) : err.message
}
</script>
<template>
<div v-if="error" class="error">{{ getErrorMessage(error) }}</div>
</template>
The getErrorMessage helper checks if a translation exists for the error code. If not, it falls back to the default English message from Better Auth.
For auth config callbacks like sendResetPassword, use @intlify/utils/h3 to detect the user's locale:
@intlify/utils is installed as a dependency of @nuxtjs/i18n, but you need to import it explicitly in server code.import { tryCookieLocale, tryHeaderLocale } from '@intlify/utils/h3'
import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
export default defineServerAuth(() => ({
emailAndPassword: {
enabled: true,
sendResetPassword: async ({ user, url }, request) => {
const locale = tryCookieLocale(request)?.toString()
?? tryHeaderLocale(request)?.toString()
?? 'en'
// Use locale for email content...
}
}
}))
| Code | Default Message |
|---|---|
USER_NOT_FOUND | User not found |
INVALID_PASSWORD | Invalid password |
INVALID_EMAIL_OR_PASSWORD | Invalid email or password |
EMAIL_NOT_VERIFIED | Email not verified |
SESSION_EXPIRED | Session expired |
INVALID_TOKEN | Invalid token |
USER_ALREADY_EXISTS | User already exists |
INVALID_EMAIL | Invalid email |
PASSWORD_TOO_SHORT | Password too short |
RATE_LIMIT_EXCEEDED | Too many requests |