feat(i18n): add multi-language support (en/zh) across app and server
Implement useLocale composable and shared translation dictionaries Translate public pages, booking flow, and receipt views Store booking locale to send localized WhatsApp notifications
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
formatBookingCurrency
|
||||
} from '~~/shared/booking'
|
||||
import { hasValidFullName, isValidPhoneNumber, normalizeFullName, normalizePhoneNumber } from '~~/shared/auth'
|
||||
import { resolveLocale } from '~~/shared/i18n'
|
||||
|
||||
import { assertBadRequest } from './http'
|
||||
|
||||
@@ -14,6 +15,7 @@ export function parseCreateBookingInput(body: {
|
||||
quantity?: number
|
||||
ticketType?: TicketType
|
||||
personInChargeId?: string
|
||||
locale?: string | null
|
||||
}) {
|
||||
const customerName = normalizeFullName(body.customerName || '')
|
||||
const customerPhone = normalizePhoneNumber(body.customerPhone || '')
|
||||
@@ -21,6 +23,7 @@ export function parseCreateBookingInput(body: {
|
||||
const ticketType = typeof body.ticketType === 'string' ? body.ticketType.trim().toLowerCase() : body.ticketType
|
||||
const quantity = Number(body.quantity)
|
||||
const personInChargeId = (body.personInChargeId || '').trim()
|
||||
const locale = resolveLocale(body.locale)
|
||||
|
||||
assertBadRequest(hasValidFullName(customerName), 'Guest or organizer name must be at least 2 characters')
|
||||
assertBadRequest(isValidPhoneNumber(customerPhone), 'Phone number must include a country code, e.g. +60123456789')
|
||||
@@ -35,7 +38,8 @@ export function parseCreateBookingInput(body: {
|
||||
bookingMode,
|
||||
quantity,
|
||||
ticketType,
|
||||
personInChargeId
|
||||
personInChargeId,
|
||||
locale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +70,21 @@ export function parseBookingPicTransferInput(body: {
|
||||
}
|
||||
|
||||
export function buildBookingMessage(booking: PublicBooking, confirmationUrl: string) {
|
||||
if (booking.locale === 'zh') {
|
||||
return [
|
||||
`我想预订 ${booking.event.title} 的票券。`,
|
||||
'',
|
||||
`姓名:${booking.customerName}`,
|
||||
`联络号码:${booking.customerPhone}`,
|
||||
`座位:${booking.seatCount}`,
|
||||
`票券类别:${booking.ticketLabel || booking.ticketType.toUpperCase()}`,
|
||||
`总价:${formatBookingCurrency(booking.totalPrice, booking.locale)}`,
|
||||
'',
|
||||
'负责人确认链接:',
|
||||
confirmationUrl
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
return [
|
||||
`I'd like to book tickets for the ${booking.event.title}.`,
|
||||
'',
|
||||
@@ -73,7 +92,7 @@ export function buildBookingMessage(booking: PublicBooking, confirmationUrl: str
|
||||
`Phone Number: ${booking.customerPhone}`,
|
||||
`Seats: ${booking.seatCount}`,
|
||||
`Ticket Category: ${booking.ticketLabel || booking.ticketType.toUpperCase()}`,
|
||||
`Total Price: ${formatBookingCurrency(booking.totalPrice)}`,
|
||||
`Total Price: ${formatBookingCurrency(booking.totalPrice, booking.locale)}`,
|
||||
'',
|
||||
'PIC confirmation link:',
|
||||
confirmationUrl
|
||||
|
||||
Reference in New Issue
Block a user