diff --git a/src/api/request.js b/src/api/request.js new file mode 100644 index 0000000..d30018d --- /dev/null +++ b/src/api/request.js @@ -0,0 +1,64 @@ +import axios from 'axios' +import { ElMessage } from 'element-plus' +import config from '../config' + +const request = axios.create({ + baseURL: config.apiBaseUrl, + timeout: config.requestTimeout, + headers: { + 'Content-Type': 'application/json' + } +}) + +// 请求拦截器 +request.interceptors.request.use( + config => { + // 如果是文件上传,不设置 Content-Type,让浏览器自动设置(包含 boundary) + if (config.data instanceof FormData) { + delete config.headers['Content-Type'] + } + return config + }, + error => { + return Promise.reject(error) + } +) + +// 响应拦截器 +request.interceptors.response.use( + response => { + const data = response.data + + // 如果响应格式是统一的Result格式 + if (data && typeof data === 'object' && 'code' in data) { + if (data.code === '0000') { + // 返回完整对象,让调用方自己处理 + return data + } else { + ElMessage.error(data.message || '请求失败') + return Promise.reject(new Error(data.message || '请求失败')) + } + } + + return data + }, + error => { + console.error('请求错误:', error) + + let message = '请求失败' + if (error.response) { + const data = error.response.data + message = data?.message || `请求失败: ${error.response.status}` + } else if (error.request) { + message = '网络错误,请检查网络连接' + } else { + message = error.message || '请求失败' + } + + ElMessage.error(message) + return Promise.reject(error) + } +) + +export default request + diff --git a/src/i18n/index.js b/src/i18n/index.js new file mode 100644 index 0000000..acb7341 --- /dev/null +++ b/src/i18n/index.js @@ -0,0 +1,137 @@ +import { createI18n } from 'vue-i18n' +import { getLanguageByCurrency, getTranslationsByCurrency } from './locales' + +// 默认中文文本(作为fallback) +const defaultMessages = { + // 商品详情页 + product: { + selectCurrency: '选择货币', + selectSku: '选择商品规格(SKU)', + currentPrice: '现价', + quantity: '数量', + stock: '库存', + buyNow: '立即购买', + addToCart: '加入购物车', + productDetails: '商品详情', + specifications: '规格参数', + outOfStock: '缺货', + confirmPurchase: '确认购买', + cancel: '取消', + unitPrice: '单价', + total: '总计', + confirmPurchaseInfo: '确认购买信息', + sku: 'SKU', + productNotExist: '商品不存在或链接已过期', + linkExpired: '该商品链接可能已失效,请联系商家获取新的商品链接' + }, + // 订单创建页 + order: { + fillOrderInfo: '填写订单信息', + productInfo: '商品信息', + customerInfo: '客户信息', + shippingAddress: '收货地址', + customerName: '客户姓名', + customerPhone: '客户电话', + customerEmail: '客户邮箱', + shippingName: '收货人姓名', + shippingPhone: '收货人电话', + shippingCountry: '收货国家', + addressLine1: '详细地址1', + addressLine2: '详细地址2', + state: '州/省', + city: '城市', + postcode: '邮编', + remark: '备注', + submit: '提交订单', + back: '返回', + pleaseEnter: '请输入', + optional: '可选', + required: '必填', + addressFormat: '地址格式', + phoneCode: '国际区号', + mustMatchId: '需与证件一致,支持当地语言+英文' + }, + // 订单确认页 + confirm: { + orderInfo: '订单信息', + orderNo: '订单号', + orderStatus: '订单状态', + paymentStatus: '支付状态', + payNow: '立即支付', + viewOrder: '查看订单' + }, + // 通用 + common: { + loading: '加载中...', + submit: '提交', + cancel: '取消', + confirm: '确认', + save: '保存', + delete: '删除', + edit: '编辑', + search: '搜索', + reset: '重置', + operation: '操作', + success: '成功', + failed: '失败', + error: '错误', + warning: '警告', + info: '提示' + } +} + +// 创建 i18n 实例 +const i18n = createI18n({ + legacy: false, // 使用 Composition API 模式 + locale: 'zh', // 默认语言 + fallbackLocale: 'zh', // 回退语言 + messages: { + zh: defaultMessages + } +}) + +// 翻译缓存(避免重复请求) +const translationCache = new Map() + +/** + * 根据货币代码加载翻译文本(使用静态翻译,不依赖后端API) + * @param {string} currency 货币代码 + * @returns {Promise} + */ +export async function loadTranslationByCurrency(currency) { + if (!currency) { + return + } + + // 根据货币代码获取语言代码 + const language = getLanguageByCurrency(currency) + + // 检查缓存 + if (translationCache.has(language)) { + const cachedMessages = translationCache.get(language) + i18n.global.setLocaleMessage(language, cachedMessages) + i18n.global.locale.value = language + return + } + + try { + // 从静态翻译文件获取翻译 + const translatedMessages = getTranslationsByCurrency(currency) + + // 缓存翻译结果 + translationCache.set(language, translatedMessages) + + // 设置翻译消息 + i18n.global.setLocaleMessage(language, translatedMessages) + i18n.global.locale.value = language + + console.log(`翻译加载成功,货币: ${currency}, 语言: ${language}`) + } catch (error) { + console.error('加载翻译失败:', error) + // 翻译失败时使用默认中文 + i18n.global.locale.value = 'zh' + } +} + +export default i18n + diff --git a/src/i18n/locales.js b/src/i18n/locales.js new file mode 100644 index 0000000..76f9fc2 --- /dev/null +++ b/src/i18n/locales.js @@ -0,0 +1,1080 @@ +/** + * 静态翻译文本(不依赖后端API) + * 根据国家/货币代码预定义的翻译文本 + */ + +// 中文(默认) +const zh = { + // 订单创建页 + order: { + fillOrderInfo: '填写订单信息', + productInfo: '商品信息', + customerInfo: '客户信息', + shippingAddress: '收货地址', + customerName: '客户姓名', + customerPhone: '客户电话', + customerEmail: '客户邮箱', + shippingName: '收货人姓名', + shippingPhone: '收货人电话', + shippingCountry: '收货国家', + addressLine1: '详细地址1', + addressLine2: '详细地址2', + state: '州/省', + city: '城市', + cityTown: '城市/城镇', + postcode: '邮编', + postcodeHint: '邮编为{0}位数字', + remark: '订单备注', + submit: '提交订单', + back: '返回', + pleaseEnter: '请输入', + optional: '可选', + required: '必填', + addressFormat: '地址格式', + phoneCode: '国际区号', + mustMatchId: '需与证件一致,支持当地语言+英文', + subtotal: '小计', + // 验证错误消息 + validationRequired: '请输入{0}', + validationInvalidPhone: '请输入有效的电话号码', + validationInvalidEmail: '请输入有效的邮箱地址', + validationSelectCountry: '请选择收货国家', + validationPostcodeFormat: '邮编格式不正确,应为{0}位数字', + validationFillComplete: '请填写完整信息', + validationProductMissing: '商品信息缺失,请重新选择商品', + validationOrderCreateFailed: '创建订单失败', + validationOrderCreateRetry: '创建订单失败,请稍后重试', + validationProductParseFailed: '商品信息解析失败', + validationProductInfoMissing: '缺少商品信息', + validationOrderCreateSuccess: '订单创建成功', + // 特殊地址字段 + blockNumber: '组屋号', + unitNumber: '单元号', + barangay: '社区编号', + addressThai: '泰文地址', + province: '省', + district: '市/郡', + ward: '区/坊', + stateMalaysia: '州属', + administrativeArea: '区(Tambon)', + floorUnit: '楼层/单元/代收点', + street: '街道地址', + // 占位符文本 + placeholderAddressLine1: '请输入门牌号、街道、楼栋', + placeholderAddressLine2: '请输入楼层、单元号(可选)', + placeholderBlockNumber: '例如:Blk 123', + placeholderUnitNumber: '例如:#01-234', + placeholderBarangay: '请输入社区编号', + placeholderAddressThai: '请输入泰文地址(支持双语)', + placeholderProvince: '请输入省', + placeholderDistrict: '请输入市/郡', + placeholderWard: '请输入区/坊', + placeholderStateMalaysia: '例如:Selangor(雪兰莪)', + placeholderAdministrativeArea: '请输入区(Tambon)', + placeholderFloorUnit: '楼层、单元号或代收点信息(可选)', + placeholderStreet: '请输入详细街道地址', + placeholderCity: '请输入城市/城镇', + placeholderPostcode: '请输入邮编', + placeholderRemark: '请输入订单备注(可选)', + // 国家特定占位符 + placeholderCityTH: '请输入县 (Amphoe)', + placeholderStateTH: '府 (Changwat)', + placeholderStatePH: '省 (Province)', + placeholderStateOptional: '州/省(可选)', + placeholderProvinceVN: '请输入省 (Tỉnh)', + placeholderDistrictVN: '请输入市/郡 (Thành phố/Huyện)', + placeholderWardVN: '请输入区/坊 (Quận/Phường)' + }, + // 商品详情页 + product: { + selectCurrency: '选择货币和语言', + selectSku: '选择商品规格(SKU)', + currentPrice: '现价', + quantity: '数量', + stock: '库存', + buyNow: '立即购买', + productDetails: '商品详情', + specifications: '规格参数', + outOfStock: '缺货', + confirmPurchase: '确认购买', + cancel: '取消', + unitPrice: '单价', + total: '总计', + confirmPurchaseInfo: '确认购买信息', + sku: 'SKU', + noSkuAvailable: '暂无可用SKU', + selectSkuForPrice: '请选择SKU查看价格', + selectSku: '请选择SKU', + sevenDayReturn: '7天无理由退货', + authenticGuarantee: '正品保证', + expeditedShipping: '极速发货', + imageLoadFailed: '图片加载失败', + noProductDetails: '暂无商品详情', + selectSkuForSpecs: '请先选择SKU查看规格参数', + skuCode: 'SKU编码', + price: '价格', + weight: '重量', + size: '尺寸' + }, + // 订单确认页 + confirm: { + orderInfo: '订单信息', + orderNo: '订单号', + orderStatus: '订单状态', + paymentStatus: '支付状态', + payNow: '立即支付', + orderAmount: '订单金额', + productName: '商品名称', + skuName: 'SKU名称', + quantity: '购买数量', + unitPrice: '单价', + createTime: '创建时间', + recipient: '收货人', + recipientPhone: '收货电话', + shippingAddress: '收货地址', + orderRemark: '订单备注', + back: '返回', + orderNotFound: '订单不存在', + notFilled: '未填写', + addressLine1: '详细地址1', + addressLine2: '详细地址2', + addressIncomplete: '地址信息不完整', + postcodeLabel: '邮编', + // 货币转换提示 + willPayIn: '您将以{0}支付', + actualCost: '实际费用', + approximately: '约', + exchangeRate: '汇率', + rateLockedAt: '汇率锁定时间', + // 订单状态文本 + statusPending: '待支付', + statusPaid: '已支付', + statusShipped: '已发货', + statusCompleted: '已完成', + statusCancelled: '已取消', + // 货币名称 + currencyUSD: '美元', + currencyEUR: '欧元', + currencyGBP: '英镑', + currencyCNY: '人民币', + currencyMYR: '马来西亚林吉特', + currencyVND: '越南盾', + currencyJPY: '日元', + currencyKRW: '韩元', + currencyTHB: '泰铢', + currencySGD: '新加坡元', + currencyHKD: '港币', + currencyPHP: '菲律宾比索' + } +} + +// 英语 +const en = { + order: { + fillOrderInfo: 'Fill Order Information', + productInfo: 'Product Information', + customerInfo: 'Customer Information', + shippingAddress: 'Shipping Address', + customerName: 'Customer Name', + customerPhone: 'Customer Phone', + customerEmail: 'Customer Email', + shippingName: 'Recipient Name', + shippingPhone: 'Recipient Phone', + shippingCountry: 'Shipping Country', + addressLine1: 'Address Line 1', + addressLine2: 'Address Line 2', + state: 'State/Province', + city: 'City', + cityTown: 'City/Town', + postcode: 'Postal Code', + postcodeHint: 'Postal code is {0} digits', + remark: 'Order Remarks', + submit: 'Submit Order', + back: 'Back', + pleaseEnter: 'Please enter', + optional: 'Optional', + required: 'Required', + addressFormat: 'Address Format', + phoneCode: 'Phone Code', + mustMatchId: 'Must match ID, supports local language + English', + // 特殊地址字段 + blockNumber: 'Block Number', + unitNumber: 'Unit Number', + barangay: 'Barangay', + addressThai: 'Thai Address', + province: 'Province', + district: 'District', + ward: 'Ward', + stateMalaysia: 'State', + administrativeArea: 'Administrative Area (Tambon)', + floorUnit: 'Floor/Unit/Collection Point', + street: 'Street Address', + // 占位符文本 + placeholderAddressLine1: 'Please enter house number, street, building', + placeholderAddressLine2: 'Please enter floor, unit number (optional)', + placeholderBlockNumber: 'e.g.: Blk 123', + placeholderUnitNumber: 'e.g.: #01-234', + placeholderBarangay: 'Please enter Barangay', + placeholderAddressThai: 'Please enter Thai address (bilingual supported)', + placeholderProvince: 'Please enter province', + placeholderDistrict: 'Please enter district', + placeholderWard: 'Please enter ward', + placeholderStateMalaysia: 'e.g.: Selangor', + placeholderAdministrativeArea: 'Please enter administrative area (Tambon)', + placeholderFloorUnit: 'Floor, unit number or collection point information (optional)', + placeholderStreet: 'Please enter detailed street address', + placeholderCity: 'Please enter city/town', + placeholderPostcode: 'Please enter postal code', + placeholderRemark: 'Please enter order remarks (optional)', + // 国家特定占位符 + placeholderCityTH: 'Please enter district (Amphoe)', + placeholderStateTH: 'Province (Changwat)', + placeholderStatePH: 'Province', + placeholderStateOptional: 'State/Province (optional)', + placeholderProvinceVN: 'Please enter province (Tỉnh)', + placeholderDistrictVN: 'Please enter city/district (Thành phố/Huyện)', + placeholderWardVN: 'Please enter ward (Quận/Phường)', + subtotal: 'Subtotal', + // 验证错误消息 + validationRequired: 'Please enter {0}', + validationInvalidPhone: 'Please enter a valid phone number', + validationInvalidEmail: 'Please enter a valid email address', + validationSelectCountry: 'Please select shipping country', + validationPostcodeFormat: 'Postcode format is incorrect, should be {0} digits', + validationFillComplete: 'Please fill in complete information', + validationProductMissing: 'Product information is missing, please reselect product', + validationOrderCreateFailed: 'Failed to create order', + validationOrderCreateRetry: 'Failed to create order, please try again later', + validationProductParseFailed: 'Failed to parse product information', + validationProductInfoMissing: 'Product information is missing', + validationOrderCreateSuccess: 'Order created successfully' + }, + product: { + selectCurrency: 'Select Currency and Language', + selectSku: 'Select Product Specification (SKU)', + currentPrice: 'Current Price', + quantity: 'Quantity', + stock: 'Stock', + buyNow: 'Buy Now', + productDetails: 'Product Details', + specifications: 'Specifications', + outOfStock: 'Out of Stock', + confirmPurchase: 'Confirm Purchase', + cancel: 'Cancel', + unitPrice: 'Unit Price', + total: 'Total', + confirmPurchaseInfo: 'Confirm Purchase Information', + sku: 'SKU', + noSkuAvailable: 'No SKU Available', + selectSkuForPrice: 'Please select SKU to view price', + selectSku: 'Please select SKU', + sevenDayReturn: '7-Day Return Policy', + authenticGuarantee: 'Authentic Guarantee', + expeditedShipping: 'Fast Shipping', + imageLoadFailed: 'Image Load Failed', + noProductDetails: 'No Product Details', + selectSkuForSpecs: 'Please select SKU to view specifications', + skuCode: 'SKU Code', + price: 'Price', + weight: 'Weight', + size: 'Size' + }, + confirm: { + orderInfo: 'Order Information', + orderNo: 'Order Number', + orderStatus: 'Order Status', + paymentStatus: 'Payment Status', + payNow: 'Pay Now', + orderAmount: 'Order Amount', + productName: 'Product Name', + skuName: 'SKU Name', + quantity: 'Quantity', + unitPrice: 'Unit Price', + createTime: 'Creation Time', + recipient: 'Recipient', + recipientPhone: 'Recipient Phone', + shippingAddress: 'Shipping Address', + orderRemark: 'Order Remarks', + back: 'Back', + orderNotFound: 'Order not found', + notFilled: 'Not filled', + addressLine1: 'Address Line 1', + addressLine2: 'Address Line 2', + addressIncomplete: 'Address information incomplete', + postcodeLabel: 'Postcode', + // 货币转换提示 + willPayIn: 'You will pay in {0}', + actualCost: 'Actual Cost', + approximately: 'Approximately', + exchangeRate: 'Exchange Rate', + rateLockedAt: 'Rate Locked At', + // 订单状态文本 + statusPending: 'Pending Payment', + statusPaid: 'Paid', + statusShipped: 'Shipped', + statusCompleted: 'Completed', + statusCancelled: 'Cancelled', + // 货币名称 + currencyUSD: 'US Dollar', + currencyEUR: 'Euro', + currencyGBP: 'British Pound', + currencyCNY: 'Chinese Yuan', + currencyMYR: 'Malaysian Ringgit', + currencyVND: 'Vietnamese Dong', + currencyJPY: 'Japanese Yen', + currencyKRW: 'South Korean Won', + currencyTHB: 'Thai Baht', + currencySGD: 'Singapore Dollar', + currencyHKD: 'Hong Kong Dollar', + currencyPHP: 'Philippine Peso' + } +} + +// 马来语(马来西亚) +const may = { + order: { + fillOrderInfo: 'Isi Maklumat Pesanan', + productInfo: 'Maklumat Produk', + customerInfo: 'Maklumat Pelanggan', + shippingAddress: 'Alamat Penghantaran', + customerName: 'Nama Pelanggan', + customerPhone: 'Telefon Pelanggan', + customerEmail: 'E-mel Pelanggan', + shippingName: 'Nama Penerima', + shippingPhone: 'Telefon Penerima', + shippingCountry: 'Negara Penghantaran', + addressLine1: 'Alamat Baris 1', + addressLine2: 'Alamat Baris 2', + state: 'Negeri', + city: 'Bandar', + cityTown: 'Bandar/Pekan', + postcode: 'Poskod', + postcodeHint: 'Poskod adalah {0} digit', + remark: 'Catatan Pesanan', + submit: 'Hantar Pesanan', + back: 'Kembali', + pleaseEnter: 'Sila masukkan', + optional: 'Pilihan', + required: 'Diperlukan', + addressFormat: 'Format Alamat', + phoneCode: 'Kod Telefon', + mustMatchId: 'Mesti sepadan dengan ID, menyokong bahasa tempatan + Inggeris', + // 特殊地址字段 + blockNumber: 'Nombor Blok', + unitNumber: 'Nombor Unit', + barangay: 'Barangay', + addressThai: 'Alamat Thai', + province: 'Wilayah', + district: 'Daerah', + ward: 'Ward', + stateMalaysia: 'Negeri', + administrativeArea: 'Kawasan Pentadbiran (Tambon)', + floorUnit: 'Tingkat/Unit/Titik Kumpulan', + street: 'Alamat Jalan', + // 占位符文本 + placeholderAddressLine1: 'Sila masukkan nombor rumah, jalan, bangunan', + placeholderAddressLine2: 'Sila masukkan tingkat, nombor unit (pilihan)', + placeholderBlockNumber: 'Contoh: Blk 123', + placeholderUnitNumber: 'Contoh: #01-234', + placeholderBarangay: 'Sila masukkan Barangay', + placeholderAddressThai: 'Sila masukkan alamat Thai (dua bahasa disokong)', + placeholderProvince: 'Sila masukkan wilayah', + placeholderDistrict: 'Sila masukkan daerah', + placeholderWard: 'Sila masukkan ward', + placeholderStateMalaysia: 'Contoh: Selangor', + placeholderAdministrativeArea: 'Sila masukkan kawasan pentadbiran (Tambon)', + placeholderFloorUnit: 'Maklumat tingkat, nombor unit atau titik kumpulan (pilihan)', + placeholderStreet: 'Sila masukkan alamat jalan terperinci', + placeholderCity: 'Sila masukkan bandar/pekan', + placeholderPostcode: 'Sila masukkan poskod', + placeholderRemark: 'Sila masukkan catatan pesanan (pilihan)', + // 国家特定占位符 + placeholderCityTH: 'Sila masukkan daerah (Amphoe)', + placeholderStateTH: 'Wilayah (Changwat)', + placeholderStatePH: 'Wilayah', + placeholderStateOptional: 'Negeri/Wilayah (pilihan)', + placeholderProvinceVN: 'Sila masukkan wilayah (Tỉnh)', + placeholderDistrictVN: 'Sila masukkan bandar/daerah (Thành phố/Huyện)', + placeholderWardVN: 'Sila masukkan ward (Quận/Phường)', + subtotal: 'Jumlah Kecil', + // 验证错误消息 + validationRequired: 'Sila masukkan {0}', + validationInvalidPhone: 'Sila masukkan nombor telefon yang sah', + validationInvalidEmail: 'Sila masukkan alamat e-mel yang sah', + validationSelectCountry: 'Sila pilih negara penghantaran', + validationPostcodeFormat: 'Format poskod tidak betul, mestilah {0} digit', + validationFillComplete: 'Sila isi maklumat lengkap', + validationProductMissing: 'Maklumat produk hilang, sila pilih semula produk', + validationOrderCreateFailed: 'Gagal membuat pesanan', + validationOrderCreateRetry: 'Gagal membuat pesanan, sila cuba lagi kemudian', + validationProductParseFailed: 'Gagal menguraikan maklumat produk', + validationProductInfoMissing: 'Maklumat produk hilang', + validationOrderCreateSuccess: 'Pesanan berjaya dibuat' + }, + product: { + selectCurrency: 'Pilih Mata Wang dan Bahasa', + selectSku: 'Pilih Spesifikasi Produk (SKU)', + currentPrice: 'Harga Semasa', + quantity: 'Kuantiti', + stock: 'Stok', + buyNow: 'Beli Sekarang', + productDetails: 'Butiran Produk', + specifications: 'Spesifikasi', + outOfStock: 'Kehabisan Stok', + confirmPurchase: 'Sahkan Pembelian', + cancel: 'Batal', + unitPrice: 'Harga Unit', + total: 'Jumlah', + confirmPurchaseInfo: 'Sahkan Maklumat Pembelian', + sku: 'SKU', + noSkuAvailable: 'Tiada SKU Tersedia', + selectSkuForPrice: 'Sila pilih SKU untuk melihat harga', + selectSku: 'Sila pilih SKU', + sevenDayReturn: 'Polisi Pulangan 7 Hari', + authenticGuarantee: 'Jaminan Asli', + expeditedShipping: 'Penghantaran Pantas', + imageLoadFailed: 'Gagal Memuatkan Imej', + noProductDetails: 'Tiada Butiran Produk', + selectSkuForSpecs: 'Sila pilih SKU untuk melihat spesifikasi', + skuCode: 'Kod SKU', + price: 'Harga', + weight: 'Berat', + size: 'Saiz' + }, + confirm: { + orderInfo: 'Maklumat Pesanan', + orderNo: 'Nombor Pesanan', + orderStatus: 'Status Pesanan', + paymentStatus: 'Status Pembayaran', + payNow: 'Bayar Sekarang', + orderAmount: 'Jumlah Pesanan', + productName: 'Nama Produk', + skuName: 'Nama SKU', + quantity: 'Kuantiti', + unitPrice: 'Harga Unit', + createTime: 'Masa Penciptaan', + recipient: 'Penerima', + recipientPhone: 'Telefon Penerima', + shippingAddress: 'Alamat Penghantaran', + orderRemark: 'Catatan Pesanan', + back: 'Kembali', + orderNotFound: 'Pesanan tidak dijumpai', + notFilled: 'Tidak diisi', + addressLine1: 'Alamat Baris 1', + addressLine2: 'Alamat Baris 2', + addressIncomplete: 'Maklumat alamat tidak lengkap', + postcodeLabel: 'Poskod', + willPayIn: 'Anda akan membayar dalam {0}', + actualCost: 'Kos Sebenar', + approximately: 'Kira-kira', + exchangeRate: 'Kadar Pertukaran', + rateLockedAt: 'Masa Kadar Dikunci', + statusPending: 'Menunggu Pembayaran', + statusPaid: 'Dibayar', + statusShipped: 'Dihantar', + statusCompleted: 'Selesai', + statusCancelled: 'Dibatalkan', + currencyUSD: 'Dolar AS', + currencyEUR: 'Euro', + currencyGBP: 'Pound British', + currencyCNY: 'Yuan China', + currencyMYR: 'Ringgit Malaysia', + currencyVND: 'Dong Vietnam', + currencyJPY: 'Yen Jepun', + currencyKRW: 'Won Korea Selatan', + currencyTHB: 'Baht Thailand', + currencySGD: 'Dolar Singapura', + currencyHKD: 'Dolar Hong Kong', + currencyPHP: 'Peso Filipina' + } +} + +// 菲律宾语 +const fil = { + order: { + fillOrderInfo: 'Punan ang Impormasyon ng Order', + productInfo: 'Impormasyon ng Produkto', + customerInfo: 'Impormasyon ng Customer', + shippingAddress: 'Address ng Pagpapadala', + customerName: 'Pangalan ng Customer', + customerPhone: 'Telepono ng Customer', + customerEmail: 'Email ng Customer', + shippingName: 'Pangalan ng Tatanggap', + shippingPhone: 'Telepono ng Tatanggap', + shippingCountry: 'Bansa ng Pagpapadala', + addressLine1: 'Address Line 1', + addressLine2: 'Address Line 2', + state: 'Estado/Probinsya', + city: 'Lungsod', + postcode: 'Postal Code', + remark: 'Tandaan', + submit: 'Ipasa ang Order', + back: 'Bumalik', + pleaseEnter: 'Mangyaring ipasok', + optional: 'Opsiyonal', + required: 'Kinakailangan', + addressFormat: 'Format ng Address', + phoneCode: 'Phone Code', + mustMatchId: 'Dapat tumugma sa ID, sumusuporta sa lokal na wika + Ingles' + }, + product: { + selectCurrency: 'Pumili ng Currency at Wika', + selectSku: 'Pumili ng Product Specification (SKU)', + currentPrice: 'Kasalukuyang Presyo', + quantity: 'Dami', + stock: 'Stock', + buyNow: 'Bumili Ngayon', + productDetails: 'Mga Detalye ng Produkto', + specifications: 'Mga Specification', + outOfStock: 'Walang Stock', + confirmPurchase: 'Kumpirmahin ang Pagbili', + cancel: 'Kanselahin', + unitPrice: 'Presyo ng Unit', + total: 'Kabuuan', + confirmPurchaseInfo: 'Kumpirmahin ang Impormasyon ng Pagbili', + sku: 'SKU', + noSkuAvailable: 'Walang Available na SKU', + selectSkuForPrice: 'Mangyaring pumili ng SKU para makita ang presyo', + selectSku: 'Mangyaring pumili ng SKU', + sevenDayReturn: '7-Araw na Return Policy', + authenticGuarantee: 'Authentic Guarantee', + expeditedShipping: 'Mabilis na Pagpapadala', + imageLoadFailed: 'Nabigo ang Pag-load ng Larawan', + noProductDetails: 'Walang Detalye ng Produkto', + selectSkuForSpecs: 'Mangyaring pumili ng SKU para makita ang mga specification', + skuCode: 'SKU Code', + price: 'Presyo', + weight: 'Timbang', + size: 'Sukat' + }, + confirm: { + orderInfo: 'Impormasyon ng Order', + orderNo: 'Numero ng Order', + orderStatus: 'Status ng Order', + paymentStatus: 'Status ng Pagbabayad', + payNow: 'Magbayad Ngayon', + orderAmount: 'Halaga ng Order', + productName: 'Pangalan ng Produkto', + skuName: 'Pangalan ng SKU', + quantity: 'Dami', + unitPrice: 'Presyo ng Unit', + createTime: 'Oras ng Paglikha', + recipient: 'Tatanggap', + recipientPhone: 'Telepono ng Tatanggap', + shippingAddress: 'Address ng Pagpapadala', + orderRemark: 'Tandaan ng Order', + back: 'Bumalik', + orderNotFound: 'Hindi natagpuan ang order', + notFilled: 'Hindi napunan', + addressLine1: 'Address Line 1', + addressLine2: 'Address Line 2', + addressIncomplete: 'Hindi kumpleto ang impormasyon ng address', + postcodeLabel: 'Postal Code', + willPayIn: 'Magbabayad ka sa {0}', + actualCost: 'Tunay na Gastos', + approximately: 'Humigit-kumulang', + exchangeRate: 'Rate ng Palitan', + rateLockedAt: 'Oras na Na-lock ang Rate', + statusPending: 'Naghihintay ng Pagbabayad', + statusPaid: 'Bayad na', + statusShipped: 'Naipadala na', + statusCompleted: 'Natapos na', + statusCancelled: 'Nakansela', + currencyUSD: 'US Dollar', + currencyEUR: 'Euro', + currencyGBP: 'British Pound', + currencyCNY: 'Chinese Yuan', + currencyMYR: 'Malaysian Ringgit', + currencyVND: 'Vietnamese Dong', + currencyJPY: 'Japanese Yen', + currencyKRW: 'South Korean Won', + currencyTHB: 'Thai Baht', + currencySGD: 'Singapore Dollar', + currencyHKD: 'Hong Kong Dollar', + currencyPHP: 'Philippine Peso' + } +} + +// 泰语 +const th = { + order: { + fillOrderInfo: 'กรอกข้อมูลคำสั่งซื้อ', + productInfo: 'ข้อมูลสินค้า', + customerInfo: 'ข้อมูลลูกค้า', + shippingAddress: 'ที่อยู่จัดส่ง', + customerName: 'ชื่อลูกค้า', + customerPhone: 'เบอร์โทรลูกค้า', + customerEmail: 'อีเมลลูกค้า', + shippingName: 'ชื่อผู้รับ', + shippingPhone: 'เบอร์โทรผู้รับ', + shippingCountry: 'ประเทศจัดส่ง', + addressLine1: 'ที่อยู่บรรทัด 1', + addressLine2: 'ที่อยู่บรรทัด 2', + state: 'จังหวัด', + city: 'เมือง', + postcode: 'รหัสไปรษณีย์', + remark: 'หมายเหตุ', + submit: 'ส่งคำสั่งซื้อ', + back: 'กลับ', + pleaseEnter: 'กรุณากรอก', + optional: 'ไม่บังคับ', + required: 'จำเป็น', + addressFormat: 'รูปแบบที่อยู่', + phoneCode: 'รหัสโทรศัพท์', + mustMatchId: 'ต้องตรงกับบัตรประชาชน รองรับภาษาท้องถิ่น + อังกฤษ', + // 补充缺失字段 + cityTown: 'เมือง/อำเภอ', + postcodeHint: 'รหัสไปรษณีย์คือ {0} หลัก', + blockNumber: 'หมายเลขบล็อก', + unitNumber: 'หมายเลขหน่วย', + barangay: 'Barangay', + addressThai: 'ที่อยู่ภาษาไทย', + province: 'จังหวัด', + district: 'อำเภอ/เขต', + ward: 'แขวง/ตำบล', + stateMalaysia: 'รัฐ', + administrativeArea: 'พื้นที่บริหาร (Tambon)', + floorUnit: 'ชั้น/หน่วย/จุดรับ', + street: 'ที่อยู่ถนน', + subtotal: 'ยอดรวมย่อย', + // 占位符文本 + placeholderAddressLine1: 'กรุณากรอกเลขที่บ้าน ถนน อาคาร', + placeholderAddressLine2: 'กรุณากรอกชั้น หมายเลขหน่วย (ไม่บังคับ)', + placeholderBlockNumber: 'เช่น: Blk 123', + placeholderUnitNumber: 'เช่น: #01-234', + placeholderBarangay: 'กรุณากรอก Barangay', + placeholderAddressThai: 'กรุณากรอกที่อยู่ภาษาไทย (รองรับสองภาษา)', + placeholderProvince: 'กรุณากรอกจังหวัด', + placeholderDistrict: 'กรุณากรอกอำเภอ/เขต', + placeholderWard: 'กรุณากรอกแขวง/ตำบล', + placeholderStateMalaysia: 'เช่น: Selangor', + placeholderAdministrativeArea: 'กรุณากรอกพื้นที่บริหาร (Tambon)', + placeholderFloorUnit: 'ข้อมูลชั้น หมายเลขหน่วย หรือจุดรับ (ไม่บังคับ)', + placeholderStreet: 'กรุณากรอกที่อยู่ถนนโดยละเอียด', + placeholderCity: 'กรุณากรอกเมือง/อำเภอ', + placeholderPostcode: 'กรุณากรอกรหัสไปรษณีย์', + placeholderRemark: 'กรุณากรอกหมายเหตุคำสั่งซื้อ (ไม่บังคับ)', + placeholderCityTH: 'กรุณากรอกอำเภอ (Amphoe)', + placeholderStateTH: 'จังหวัด (Changwat)', + placeholderStatePH: 'จังหวัด', + placeholderStateOptional: 'รัฐ/จังหวัด (ไม่บังคับ)', + placeholderProvinceVN: 'กรุณากรอกจังหวัด (Tỉnh)', + placeholderDistrictVN: 'กรุณากรอกเมือง/อำเภอ (Thành phố/Huyện)', + placeholderWardVN: 'กรุณากรอกแขวง/ตำบล (Quận/Phường)', + // 验证错误消息 + validationRequired: 'กรุณากรอก {0}', + validationInvalidPhone: 'กรุณากรอกหมายเลขโทรศัพท์ที่ถูกต้อง', + validationInvalidEmail: 'กรุณากรอกอีเมลที่ถูกต้อง', + validationSelectCountry: 'กรุณาเลือกประเทศจัดส่ง', + validationPostcodeFormat: 'รูปแบบรหัสไปรษณีย์ไม่ถูกต้อง ควรเป็น {0} หลัก', + validationFillComplete: 'กรุณากรอกข้อมูลให้ครบถ้วน', + validationProductMissing: 'ข้อมูลสินค้าหายไป กรุณาเลือกสินค้าใหม่', + validationOrderCreateFailed: 'สร้างคำสั่งซื้อล้มเหลว', + validationOrderCreateRetry: 'สร้างคำสั่งซื้อล้มเหลว กรุณาลองใหม่อีกครั้งในภายหลัง', + validationProductParseFailed: 'แยกวิเคราะห์ข้อมูลสินค้าล้มเหลว', + validationProductInfoMissing: 'ข้อมูลสินค้าหายไป', + validationOrderCreateSuccess: 'สร้างคำสั่งซื้อสำเร็จ' + }, + product: { + selectCurrency: 'เลือกสกุลเงินและภาษา', + selectSku: 'เลือกรายละเอียดสินค้า (SKU)', + currentPrice: 'ราคาปัจจุบัน', + quantity: 'จำนวน', + stock: 'สต็อก', + buyNow: 'ซื้อทันที', + productDetails: 'รายละเอียดสินค้า', + specifications: 'ข้อมูลจำเพาะ', + outOfStock: 'หมดสต็อก', + confirmPurchase: 'ยืนยันการซื้อ', + cancel: 'ยกเลิก', + unitPrice: 'ราคาต่อหน่วย', + total: 'รวม', + confirmPurchaseInfo: 'ยืนยันข้อมูลการซื้อ', + sku: 'SKU', + noSkuAvailable: 'ไม่มี SKU ที่ใช้ได้', + selectSkuForPrice: 'กรุณาเลือก SKU เพื่อดูราคา', + selectSku: 'กรุณาเลือก SKU', + sevenDayReturn: 'นโยบายคืนสินค้า 7 วัน', + authenticGuarantee: 'การรับประกันของแท้', + expeditedShipping: 'จัดส่งด่วน', + imageLoadFailed: 'โหลดรูปภาพล้มเหลว', + noProductDetails: 'ไม่มีรายละเอียดสินค้า', + selectSkuForSpecs: 'กรุณาเลือก SKU เพื่อดูข้อมูลจำเพาะ', + skuCode: 'รหัส SKU', + price: 'ราคา', + weight: 'น้ำหนัก', + size: 'ขนาด' + }, + confirm: { + orderInfo: 'ข้อมูลคำสั่งซื้อ', + orderNo: 'หมายเลขคำสั่งซื้อ', + orderStatus: 'สถานะคำสั่งซื้อ', + paymentStatus: 'สถานะการชำระเงิน', + payNow: 'ชำระเงินทันที', + orderAmount: 'จำนวนเงินคำสั่งซื้อ', + productName: 'ชื่อสินค้า', + skuName: 'ชื่อ SKU', + quantity: 'จำนวน', + unitPrice: 'ราคาต่อหน่วย', + createTime: 'เวลาสร้าง', + recipient: 'ผู้รับ', + recipientPhone: 'เบอร์โทรผู้รับ', + shippingAddress: 'ที่อยู่จัดส่ง', + orderRemark: 'หมายเหตุคำสั่งซื้อ', + back: 'กลับ', + orderNotFound: 'ไม่พบคำสั่งซื้อ', + notFilled: 'ไม่ได้กรอก', + addressLine1: 'ที่อยู่บรรทัด 1', + addressLine2: 'ที่อยู่บรรทัด 2', + addressIncomplete: 'ข้อมูลที่อยู่ไม่ครบถ้วน', + postcodeLabel: 'รหัสไปรษณีย์', + willPayIn: 'คุณจะชำระด้วย {0}', + actualCost: 'ค่าใช้จ่ายจริง', + approximately: 'ประมาณ', + exchangeRate: 'อัตราแลกเปลี่ยน', + rateLockedAt: 'เวลาล็อกอัตรา', + statusPending: 'รอการชำระเงิน', + statusPaid: 'ชำระแล้ว', + statusShipped: 'จัดส่งแล้ว', + statusCompleted: 'เสร็จสมบูรณ์', + statusCancelled: 'ยกเลิก', + currencyUSD: 'ดอลลาร์สหรัฐ', + currencyEUR: 'ยูโร', + currencyGBP: 'ปอนด์อังกฤษ', + currencyCNY: 'หยวนจีน', + currencyMYR: 'ริงกิตมาเลเซีย', + currencyVND: 'ดองเวียดนาม', + currencyJPY: 'เยนญี่ปุ่น', + currencyKRW: 'วอนเกาหลีใต้', + currencyTHB: 'บาทไทย', + currencySGD: 'ดอลลาร์สิงคโปร์', + currencyHKD: 'ดอลลาร์ฮ่องกง', + currencyPHP: 'เปโซฟิลิปปินส์' + } +} + +// 越南语 +const vie = { + order: { + fillOrderInfo: 'Điền Thông Tin Đơn Hàng', + productInfo: 'Thông Tin Sản Phẩm', + customerInfo: 'Thông Tin Khách Hàng', + shippingAddress: 'Địa Chỉ Giao Hàng', + customerName: 'Tên Khách Hàng', + customerPhone: 'Số Điện Thoại Khách Hàng', + customerEmail: 'Email Khách Hàng', + shippingName: 'Tên Người Nhận', + shippingPhone: 'Số Điện Thoại Người Nhận', + shippingCountry: 'Quốc Gia Giao Hàng', + addressLine1: 'Địa Chỉ Dòng 1', + addressLine2: 'Địa Chỉ Dòng 2', + state: 'Tỉnh/Thành Phố', + city: 'Thành Phố', + cityTown: 'Thành Phố/Thị Trấn', + postcode: 'Mã Bưu Điện', + postcodeHint: 'Mã bưu điện là {0} chữ số', + remark: 'Ghi Chú', + submit: 'Gửi Đơn Hàng', + back: 'Quay Lại', + pleaseEnter: 'Vui lòng nhập', + optional: 'Tùy chọn', + required: 'Bắt buộc', + addressFormat: 'Định Dạng Địa Chỉ', + phoneCode: 'Mã Điện Thoại', + mustMatchId: 'Phải khớp với ID, hỗ trợ ngôn ngữ địa phương + tiếng Anh', + // 特殊地址字段 + blockNumber: 'Số Block', + unitNumber: 'Số Đơn Vị', + barangay: 'Barangay', + addressThai: 'Địa Chỉ Tiếng Thái', + province: 'Tỉnh', + district: 'Thành Phố/Huyện', + ward: 'Quận/Phường', + stateMalaysia: 'Bang', + administrativeArea: 'Khu Vực Hành Chính (Tambon)', + floorUnit: 'Tầng/Đơn Vị/Điểm Thu Gom', + street: 'Địa Chỉ Đường', + subtotal: 'Tổng Phụ', + // 占位符文本 + placeholderAddressLine1: 'Vui lòng nhập số nhà, đường, tòa nhà', + placeholderAddressLine2: 'Vui lòng nhập tầng, số đơn vị (tùy chọn)', + placeholderBlockNumber: 'Ví dụ: Blk 123', + placeholderUnitNumber: 'Ví dụ: #01-234', + placeholderBarangay: 'Vui lòng nhập Barangay', + placeholderAddressThai: 'Vui lòng nhập địa chỉ tiếng Thái (hỗ trợ song ngữ)', + placeholderProvince: 'Vui lòng nhập tỉnh', + placeholderDistrict: 'Vui lòng nhập thành phố/huyện', + placeholderWard: 'Vui lòng nhập quận/phường', + placeholderStateMalaysia: 'Ví dụ: Selangor', + placeholderAdministrativeArea: 'Vui lòng nhập khu vực hành chính (Tambon)', + placeholderFloorUnit: 'Thông tin tầng, số đơn vị hoặc điểm thu gom (tùy chọn)', + placeholderStreet: 'Vui lòng nhập địa chỉ đường chi tiết', + placeholderCity: 'Vui lòng nhập thành phố/thị trấn', + placeholderPostcode: 'Vui lòng nhập mã bưu điện', + placeholderRemark: 'Vui lòng nhập ghi chú đơn hàng (tùy chọn)', + // 国家特定占位符 + placeholderCityTH: 'Vui lòng nhập huyện (Amphoe)', + placeholderStateTH: 'Tỉnh (Changwat)', + placeholderStatePH: 'Tỉnh', + placeholderStateOptional: 'Tỉnh/Thành Phố (tùy chọn)', + placeholderProvinceVN: 'Vui lòng nhập tỉnh (Tỉnh)', + placeholderDistrictVN: 'Vui lòng nhập thành phố/huyện (Thành phố/Huyện)', + placeholderWardVN: 'Vui lòng nhập quận/phường (Quận/Phường)', + // 验证错误消息 + validationRequired: 'Vui lòng nhập {0}', + validationInvalidPhone: 'Vui lòng nhập số điện thoại hợp lệ', + validationInvalidEmail: 'Vui lòng nhập địa chỉ email hợp lệ', + validationSelectCountry: 'Vui lòng chọn quốc gia giao hàng', + validationPostcodeFormat: 'Định dạng mã bưu điện không đúng, phải là {0} chữ số', + validationFillComplete: 'Vui lòng điền đầy đủ thông tin', + validationProductMissing: 'Thiếu thông tin sản phẩm, vui lòng chọn lại sản phẩm', + validationOrderCreateFailed: 'Tạo đơn hàng thất bại', + validationOrderCreateRetry: 'Tạo đơn hàng thất bại, vui lòng thử lại sau', + validationProductParseFailed: 'Phân tích thông tin sản phẩm thất bại', + validationProductInfoMissing: 'Thiếu thông tin sản phẩm', + validationOrderCreateSuccess: 'Tạo đơn hàng thành công' + }, + product: { + selectCurrency: 'Chọn Tiền Tệ và Ngôn Ngữ', + selectSku: 'Chọn Thông Số Sản Phẩm (SKU)', + currentPrice: 'Giá Hiện Tại', + quantity: 'Số Lượng', + stock: 'Tồn Kho', + buyNow: 'Mua Ngay', + productDetails: 'Chi Tiết Sản Phẩm', + specifications: 'Thông Số Kỹ Thuật', + outOfStock: 'Hết Hàng', + confirmPurchase: 'Xác Nhận Mua', + cancel: 'Hủy', + unitPrice: 'Đơn Giá', + total: 'Tổng', + confirmPurchaseInfo: 'Xác Nhận Thông Tin Mua', + sku: 'SKU', + noSkuAvailable: 'Không có SKU khả dụng', + selectSkuForPrice: 'Vui lòng chọn SKU để xem giá', + selectSku: 'Vui lòng chọn SKU', + sevenDayReturn: 'Chính sách đổi trả 7 ngày', + authenticGuarantee: 'Đảm bảo chính hãng', + expeditedShipping: 'Giao hàng nhanh', + imageLoadFailed: 'Tải hình ảnh thất bại', + noProductDetails: 'Không có chi tiết sản phẩm', + selectSkuForSpecs: 'Vui lòng chọn SKU để xem thông số kỹ thuật', + skuCode: 'Mã SKU', + price: 'Giá', + weight: 'Trọng lượng', + size: 'Kích thước' + }, + confirm: { + orderInfo: 'Thông Tin Đơn Hàng', + orderNo: 'Số Đơn Hàng', + orderStatus: 'Trạng Thái Đơn Hàng', + paymentStatus: 'Trạng Thái Thanh Toán', + payNow: 'Thanh Toán Ngay', + orderAmount: 'Số Tiền Đơn Hàng', + productName: 'Tên Sản Phẩm', + skuName: 'Tên SKU', + quantity: 'Số Lượng', + unitPrice: 'Đơn Giá', + createTime: 'Thời Gian Tạo', + recipient: 'Người Nhận', + recipientPhone: 'Số Điện Thoại Người Nhận', + shippingAddress: 'Địa Chỉ Giao Hàng', + orderRemark: 'Ghi Chú Đơn Hàng', + back: 'Quay Lại', + orderNotFound: 'Không tìm thấy đơn hàng', + notFilled: 'Chưa điền', + addressLine1: 'Địa Chỉ Dòng 1', + addressLine2: 'Địa Chỉ Dòng 2', + addressIncomplete: 'Thông tin địa chỉ không đầy đủ', + postcodeLabel: 'Mã Bưu Điện', + willPayIn: 'Bạn sẽ thanh toán bằng {0}', + actualCost: 'Chi Phí Thực Tế', + approximately: 'Khoảng', + exchangeRate: 'Tỷ Giá', + rateLockedAt: 'Thời Gian Khóa Tỷ Giá', + statusPending: 'Chờ Thanh Toán', + statusPaid: 'Đã Thanh Toán', + statusShipped: 'Đã Giao Hàng', + statusCompleted: 'Hoàn Thành', + statusCancelled: 'Đã Hủy', + currencyUSD: 'Đô La Mỹ', + currencyEUR: 'Euro', + currencyGBP: 'Bảng Anh', + currencyCNY: 'Nhân Dân Tệ', + currencyMYR: 'Ringgit Malaysia', + currencyVND: 'Đồng Việt Nam', + currencyJPY: 'Yên Nhật', + currencyKRW: 'Won Hàn Quốc', + currencyTHB: 'Bạt Thái', + currencySGD: 'Đô La Singapore', + currencyHKD: 'Đô La Hồng Kông', + currencyPHP: 'Peso Philippines' + } +} + +// 印尼语 +const id = { + order: { + fillOrderInfo: 'Isi Informasi Pesanan', + productInfo: 'Informasi Produk', + customerInfo: 'Informasi Pelanggan', + shippingAddress: 'Alamat Pengiriman', + customerName: 'Nama Pelanggan', + customerPhone: 'Telepon Pelanggan', + customerEmail: 'Email Pelanggan', + shippingName: 'Nama Penerima', + shippingPhone: 'Telepon Penerima', + shippingCountry: 'Negara Pengiriman', + addressLine1: 'Alamat Baris 1', + addressLine2: 'Alamat Baris 2', + state: 'Provinsi', + city: 'Kota', + postcode: 'Kode Pos', + remark: 'Catatan', + submit: 'Kirim Pesanan', + back: 'Kembali', + pleaseEnter: 'Silakan masukkan', + optional: 'Opsional', + required: 'Diperlukan', + addressFormat: 'Format Alamat', + phoneCode: 'Kode Telepon', + mustMatchId: 'Harus sesuai dengan ID, mendukung bahasa lokal + Inggris' + }, + product: { + selectCurrency: 'Pilih Mata Uang dan Bahasa', + selectSku: 'Pilih Spesifikasi Produk (SKU)', + currentPrice: 'Harga Saat Ini', + quantity: 'Jumlah', + stock: 'Stok', + buyNow: 'Beli Sekarang', + productDetails: 'Detail Produk', + specifications: 'Spesifikasi', + outOfStock: 'Kehabisan Stok', + confirmPurchase: 'Konfirmasi Pembelian', + cancel: 'Batal', + unitPrice: 'Harga Satuan', + total: 'Total', + confirmPurchaseInfo: 'Konfirmasi Informasi Pembelian', + sku: 'SKU', + noSkuAvailable: 'Tidak Ada SKU Tersedia', + selectSkuForPrice: 'Silakan pilih SKU untuk melihat harga', + selectSku: 'Silakan pilih SKU', + sevenDayReturn: 'Kebijakan Pengembalian 7 Hari', + authenticGuarantee: 'Jaminan Asli', + expeditedShipping: 'Pengiriman Cepat', + imageLoadFailed: 'Gagal Memuat Gambar', + noProductDetails: 'Tidak Ada Detail Produk', + selectSkuForSpecs: 'Silakan pilih SKU untuk melihat spesifikasi', + skuCode: 'Kode SKU', + price: 'Harga', + weight: 'Berat', + size: 'Ukuran' + }, + confirm: { + orderInfo: 'Informasi Pesanan', + orderNo: 'Nomor Pesanan', + orderStatus: 'Status Pesanan', + paymentStatus: 'Status Pembayaran', + payNow: 'Bayar Sekarang', + orderAmount: 'Jumlah Pesanan', + productName: 'Nama Produk', + skuName: 'Nama SKU', + quantity: 'Jumlah', + unitPrice: 'Harga Satuan', + createTime: 'Waktu Pembuatan', + recipient: 'Penerima', + recipientPhone: 'Telepon Penerima', + shippingAddress: 'Alamat Pengiriman', + orderRemark: 'Catatan Pesanan', + back: 'Kembali', + orderNotFound: 'Pesanan tidak ditemukan', + notFilled: 'Tidak diisi', + addressLine1: 'Alamat Baris 1', + addressLine2: 'Alamat Baris 2', + addressIncomplete: 'Informasi alamat tidak lengkap', + postcodeLabel: 'Kode Pos', + willPayIn: 'Anda akan membayar dengan {0}', + actualCost: 'Biaya Aktual', + approximately: 'Sekitar', + exchangeRate: 'Nilai Tukar', + rateLockedAt: 'Waktu Penguncian Nilai Tukar', + statusPending: 'Menunggu Pembayaran', + statusPaid: 'Dibayar', + statusShipped: 'Terkirim', + statusCompleted: 'Selesai', + statusCancelled: 'Dibatalkan', + currencyUSD: 'Dolar AS', + currencyEUR: 'Euro', + currencyGBP: 'Pound Inggris', + currencyCNY: 'Yuan China', + currencyMYR: 'Ringgit Malaysia', + currencyVND: 'Dong Vietnam', + currencyJPY: 'Yen Jepang', + currencyKRW: 'Won Korea Selatan', + currencyTHB: 'Baht Thailand', + currencySGD: 'Dolar Singapura', + currencyHKD: 'Dolar Hong Kong', + currencyPHP: 'Peso Filipina' + } +} + +// 货币代码到语言代码的映射 +const currencyToLanguage = { + 'USD': 'en', + 'SGD': 'en', + 'CNY': 'zh', + 'MYR': 'may', + 'PHP': 'fil', + 'THB': 'th', + 'VND': 'vie', + 'IDR': 'id' +} + +// 语言代码到翻译文本的映射 +const languageMap = { + 'zh': zh, + 'en': en, + 'may': may, + 'fil': fil, + 'th': th, + 'vie': vie, + 'id': id +} + +/** + * 根据货币代码获取语言代码 + */ +export function getLanguageByCurrency(currency) { + return currencyToLanguage[currency?.toUpperCase()] || 'en' +} + +/** + * 根据语言代码获取翻译文本 + */ +export function getTranslations(language) { + return languageMap[language] || en +} + +/** + * 根据货币代码获取翻译文本 + */ +export function getTranslationsByCurrency(currency) { + const language = getLanguageByCurrency(currency) + return getTranslations(language) +} + +export default { + zh, + en, + may, + fil, + th, + vie, + id, + currencyToLanguage, + languageMap, + getLanguageByCurrency, + getTranslations, + getTranslationsByCurrency +} + diff --git a/src/utils/countryConfig.js b/src/utils/countryConfig.js new file mode 100644 index 0000000..4763762 --- /dev/null +++ b/src/utils/countryConfig.js @@ -0,0 +1,166 @@ +/** + * 国家地址配置 + * 定义各国地址字段规则和邮编格式 + */ + +// 货币代码到国家代码的映射 +export const currencyToCountry = { + 'USD': 'US', + 'SGD': 'SG', + 'MYR': 'MY', + 'PHP': 'PH', + 'THB': 'TH', + 'VND': 'VN', + 'CNY': 'CN', + 'GBP': 'GB', + 'EUR': 'DE' +} + +// 国家配置 +export const countryConfigs = { + SG: { + code: 'SG', + name: '新加坡', + nameEn: 'Singapore', + phoneCode: '+65', + postcodeLength: 6, + postcodePattern: /^\d{6}$/, + requiredFields: ['shippingName', 'shippingPhone', 'shippingCountry', 'shippingCity', + 'shippingAddressLine1', 'shippingBlockNumber', 'shippingUnitNumber', 'shippingPostcode'], + specialFields: ['shippingBlockNumber', 'shippingUnitNumber'], + fieldLabels: { + shippingBlockNumber: '组屋号 (Block Number)', + shippingUnitNumber: '单元号 (Unit Number)', + shippingAddressLine1: '详细地址1 (Address Line 1)', + shippingAddressLine2: '详细地址2 (Address Line 2)', + shippingCity: '城市 (City)', + shippingPostcode: '邮编 (Postcode)' + }, + addressFormat: 'Blk 123 Jurong West St 41 #12-345, Singapore 640123' + }, + MY: { + code: 'MY', + name: '马来西亚', + nameEn: 'Malaysia', + phoneCode: '+60', + postcodeLength: 5, + postcodePattern: /^\d{5}$/, + requiredFields: ['shippingName', 'shippingPhone', 'shippingCountry', 'shippingCity', + 'shippingStateMalaysia', 'shippingAddressLine1', 'shippingPostcode'], + specialFields: ['shippingStateMalaysia'], + fieldLabels: { + shippingStateMalaysia: '州属 (State)', + shippingAddressLine1: '详细地址1 (Address Line 1)', + shippingAddressLine2: '详细地址2 (Address Line 2)', + shippingCity: '城市 (City)', + shippingPostcode: '邮编 (Postcode)' + }, + addressFormat: '123 Jalan Abdullah, 05-01 Menara A, Kuala Lumpur, Selangor 50300' + }, + PH: { + code: 'PH', + name: '菲律宾', + nameEn: 'Philippines', + phoneCode: '+63', + postcodeLength: 4, + postcodePattern: /^\d{4}$/, + requiredFields: ['shippingName', 'shippingPhone', 'shippingCountry', 'shippingCity', + 'shippingState', 'shippingBarangay', 'shippingAddressLine1', 'shippingPostcode'], + specialFields: ['shippingBarangay'], + fieldLabels: { + shippingBarangay: 'Barangay(社区编号)', + shippingState: '省 (Province)', + shippingCity: '市 (City)', + shippingAddressLine1: '详细地址1 (Address Line 1)', + shippingAddressLine2: '详细地址2 (Address Line 2)', + shippingPostcode: '邮编 (Postcode)' + }, + addressFormat: '123 Main St, Barangay 12, Manila, Metro Manila 1000' + }, + TH: { + code: 'TH', + name: '泰国', + nameEn: 'Thailand', + phoneCode: '+66', + postcodeLength: 5, + postcodePattern: /^\d{5}$/, + requiredFields: ['shippingName', 'shippingPhone', 'shippingCountry', 'shippingCity', + 'shippingState', 'shippingAddressLine1', 'shippingPostcode', 'shippingAddressThai'], + specialFields: ['shippingAddressThai', 'shippingAdministrativeArea'], + fieldLabels: { + shippingAddressThai: '泰文地址 (Thai Address)', + shippingAddressLine1: '英文地址 (English Address)', + shippingAddressLine2: '详细地址2 (Address Line 2)', + shippingState: '府 (Changwat)', + shippingCity: '县 (Amphoe)', + shippingAdministrativeArea: '区 (Tambon)', + shippingPostcode: '邮编 (Postcode)' + }, + addressFormat: '123 Soi Sukhumvit 101, Khlong Toei, Bangkok 10110' + }, + VN: { + code: 'VN', + name: '越南', + nameEn: 'Vietnam', + phoneCode: '+84', + postcodeLength: 5, + postcodePattern: /^\d{5}$/, + requiredFields: ['shippingName', 'shippingPhone', 'shippingCountry', 'shippingProvince', + 'shippingDistrict', 'shippingWard', 'shippingAddressLine1', 'shippingPostcode'], + specialFields: ['shippingProvince', 'shippingDistrict', 'shippingWard'], + fieldLabels: { + shippingProvince: '省 (Tỉnh)', + shippingDistrict: '市/郡 (Thành phố/Huyện)', + shippingWard: '区/坊 (Quận/Phường)', + shippingAddressLine1: '详细地址1 (Địa chỉ chi tiết 1)', + shippingAddressLine2: '详细地址2 (Địa chỉ chi tiết 2)', + shippingPostcode: '邮编 (Postcode)' + }, + addressFormat: '123 Đường Nguyễn Huệ, Phường Bến Nghé, Quận 1, Thành phố Hồ Chí Minh 70000' + } +} + +/** + * 根据国家代码获取配置 + */ +export function getCountryConfig(countryCode) { + return countryConfigs[countryCode] || null +} + +/** + * 根据货币代码推断国家 + */ +export function getCountryByCurrency(currency) { + return currencyToCountry[currency] || null +} + +/** + * 验证邮编格式 + */ +export function validatePostcode(countryCode, postcode) { + if (!postcode || !postcode.trim()) { + return false + } + const config = getCountryConfig(countryCode) + if (!config) { + return true // 未知国家不验证 + } + return config.postcodePattern.test(postcode.trim()) +} + +/** + * 获取必填字段 + */ +export function getRequiredFields(countryCode) { + const config = getCountryConfig(countryCode) + return config ? config.requiredFields : [] +} + +/** + * 获取特殊字段 + */ +export function getSpecialFields(countryCode) { + const config = getCountryConfig(countryCode) + return config ? config.specialFields : [] +} + diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..eeae2ac --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,32 @@ +/** + * 请求工具函数 + */ + +/** + * 处理API响应 + */ +export function handleResponse(response) { + if (response.code === '0000') { + return response.data + } else { + throw new Error(response.message || '请求失败') + } +} + +/** + * 处理错误 + */ +export function handleError(error) { + if (error.response) { + // 服务器返回了错误响应 + const { data } = error.response + return data?.message || `请求失败: ${error.response.status}` + } else if (error.request) { + // 请求已发出但没有收到响应 + return '网络错误,请检查网络连接' + } else { + // 其他错误 + return error.message || '请求失败' + } +} + diff --git a/src/views/TestPage.vue b/src/views/TestPage.vue new file mode 100644 index 0000000..e146d63 --- /dev/null +++ b/src/views/TestPage.vue @@ -0,0 +1,12 @@ + + + + diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..e7c31ef --- /dev/null +++ b/vite.config.js @@ -0,0 +1,34 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' +import { fileURLToPath } from 'url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + }, + server: { + port: 3000, + proxy: { + '/api': { + target: 'http://127.0.0.1:8082', // 使用 127.0.0.1 而不是 localhost,避免 IPv6 问题 + changeOrigin: true, + secure: false, + ws: true, + timeout: 30000, + configure: (proxy, options) => { + proxy.on('error', (err, req, res) => { + console.error('代理错误:', err.message) + console.error('请确保后端服务已启动在 http://127.0.0.1:8082') + }) + } + } + } + } +}) +