Переглянути джерело

feat: 完善了国际化功能 和页面

FanLide 2 тижнів тому
батько
коміт
5833a3184b

+ 3 - 0
.gitignore

@@ -26,3 +26,6 @@ dist-ssr
 # Environment files
 .env.local
 .env.*.local
+
+.env.local.example
+.env.local.backup

+ 0 - 0
VANT_TYPE_GUIDE.md → doc/VANT_TYPE_GUIDE.md


+ 4 - 4
src/components/ShopCard.vue

@@ -27,13 +27,13 @@
           {{ shop.rating || '5.0' }}
         </span>
         <span class="divider">|</span>
-        <span>月售 {{ formatSales(shop.monthlySales || 0) }}</span>
+        <span>{{ $t('index.monthlySales', { count: formatSales(shop.monthlySales || 0) }) }}</span>
       </div>
       <div class="shop-delivery">
-        <span class="delivery-time">{{ shop.deliveryTime || '30分钟' }}</span>
+        <span class="delivery-time">{{ shop.deliveryTime || $t('common.duration.minutes', { minutes: 30 }) }}</span>
         <span class="divider">|</span>
-        <span class="delivery-fee">配送 ¥{{ shop.deliveryFee || 0 }}</span>
-        <span v-if="shop.minPrice" class="min-price">起送 ¥{{ shop.minPrice }}</span>
+        <span class="delivery-fee">{{ $t('index.deliveryFee', { fee: shop.deliveryFee || 0 }) }}</span>
+        <span v-if="shop.minPrice" class="min-price">{{ $t('index.minPrice', { price: shop.minPrice }) }}</span>
       </div>
     </div>
   </div>

+ 294 - 83
src/locale/en.json

@@ -4,20 +4,37 @@
     "cancel": "Cancel",
     "success": "Success",
     "error": "Error",
-    "loading": "Loading",
+    "loading": "Loading...",
     "pleaseLogin": "Please login first",
     "selectLanguage": "Select Language",
     "languageChanged": "Language changed",
-    "viewMore": "View More",
+    "viewMore": "More",
     "environment": "Environment",
-    "featureInDevelopment": "Feature in development"
+    "featureInDevelopment": "In Development",
+    "all": "All",
+    "refreshSuccess": "Refresh success",
+    "action": "Action",
+    "viewAll": "View All",
+    "edit": "Edit",
+    "settings": "Settings",
+    "confirmAction": "Confirm Action",
+    "today": "Today",
+    "units": {
+      "tenThousand": "10k",
+      "order": "Order",
+      "table": "Table"
+    },
+    "duration": {
+      "minutes": "{minutes} mins",
+      "hoursMins": "{hours}h {mins}m"
+    }
   },
   "search": {
     "placeholder": "Search shops, dishes"
   },
   "index": {
     "home": "Home",
-    "nearbyHot": "Popular Nearby",
+    "nearbyHot": "Nearby Hot",
     "categories": {
       "japanese": "Japanese",
       "chinese": "Chinese",
@@ -26,70 +43,139 @@
       "dessert": "Dessert",
       "drinks": "Drinks",
       "favorites": "Favorites",
-      "coupons": "Coupons"
+      "coupons": "Coupon Center"
+    },
+    "monthlySales": "{count} sold/mo",
+    "deliveryFee": "Delivery ¥{fee}",
+    "minPrice": "Min ¥{price}",
+    "messages": {
+      "enterKeyword": "Please enter search keyword",
+      "searchResult": "Search: {keyword}",
+      "bannerClick": "Banner clicked: {title}",
+      "categoryClick": "Category: {name}",
+      "viewMoreShops": "View more shops",
+      "nearCurrentLocation": "Near current location",
+      "selectAddress": "Select Delivery Address"
     }
   },
   "menu": {
     "title": "Menu",
-    "currentTable": "Current Table",
-    "people": "People",
-    "closed": "Closed",
-    "distance": "Distance",
-    "dineIn": "Dine In",
-    "takeOut": "Take Out",
-    "selectSpec": "Select Options",
-    "soldOut": "Sold Out",
-    "checkout": "Checkout",
-    "addToCart": "Add to Cart",
-    "clear": "Clear"
+    "searchPlaceholder": "Enter product name",
+    "noMore": "No more items",
+    "empty": "No products",
+    "itemCount": "{count} items",
+    "categories": {
+      "all": "All",
+      "hot": "Hot",
+      "new": "New",
+      "coffee": "Coffee",
+      "tea": "Tea",
+      "milkTea": "Milk Tea",
+      "juice": "Juice",
+      "snack": "Snack",
+      "combo": "Combo"
+    },
+    "sort": {
+      "default": "Default",
+      "priceAsc": "Price: Low to High",
+      "priceDesc": "Price: High to Low",
+      "sales": "Top Sales"
+    },
+    "filter": {
+      "all": "All Products",
+      "discount": "Discounted",
+      "popular": "100+ Sold/mo"
+    },
+    "detail": {
+      "title": "Product Detail",
+      "specs": "Select Specs",
+      "quantity": "Quantity",
+      "noContent": "No content",
+      "sales": "{count} sold/mo",
+      "rating": "{rate}% Positive"
+    },
+    "actions": {
+      "service": "Service",
+      "cart": "Cart",
+      "addCart": "Add to Cart",
+      "buyNow": "Buy Now",
+      "addedToCart": "Added to cart",
+      "emptyCart": "Cart is empty",
+      "selectGoods": "Please select items",
+      "favoriteSuccess": "Added to favorites",
+      "favoriteCancel": "Removed from favorites",
+      "serviceClick": "Contact Service"
+    }
   },
   "cart": {
     "title": "Cart",
     "ordered": "Ordered",
     "items": "Items",
     "clear": "Clear",
-    "checkout": "Checkout",
+    "checkout": "Confirm Order",
     "confirmClear": "Clear cart?",
     "emptyCart": "Please select items first",
     "total": "Total",
-    "amountToPay": "Amount to Pay"
+    "amountToPay": "Payable"
   },
   "order": {
     "title": "Orders",
-    "detail": "Order Details",
-    "orderNumber": "Order Number",
+    "detail": "Order Detail",
+    "orderNumber": "Order No.",
     "orderTime": "Order Time",
     "paymentMethod": "Payment Method",
-    "actualAmount": "Actual Amount",
+    "actualAmount": "Actual Paid",
     "ordered": "Ordered",
     "preparing": "Preparing",
     "delivering": "Delivering",
     "completed": "Completed",
-    "cancelled": "Cancelled"
+    "cancelled": "Cancelled",
+    "applyRefund": "Refund",
+    "payNow": "Pay Now",
+    "confirmReceived": "Confirm Receipt",
+    "confirmReceivedTip": "Have you received the items?",
+    "itemSummary": "Total {count} items, Paid",
+    "tableNumberLabel": "Table No.: ",
+    "currentTable": "Current Table",
+    "people": "People",
+    "booking": "Booking",
+    "orderDetail": "Order Detail",
+    "status": {
+      "unpaid": "Unpaid",
+      "pending": "Pending",
+      "preparing": "Preparing",
+      "completed": "Completed",
+      "cancelled": "Cancelled"
+    },
+    "messages": {
+      "idNotFound": "Order ID not found"
+    },
+    "cancelBooking": "Cancel Booking",
+    "confirmCancelBooking": "Are you sure you want to cancel the booking?"
   },
   "mine": {
-    "title": "My Profile",
+    "title": "Mine",
     "login-benefits": "Login for more benefits",
     "auth-login": "Login",
     "user-id": "User ID",
-    "not-vip": "Non-VIP Member",
-    "view-details": "View Details",
+    "not-vip": "Non-VIP",
+    "view-details": "Details",
     "activate-now": "Activate Now",
-    "coupon": "Coupons",
+    "coupon": "Coupon",
     "points": "Points",
     "balance": "Balance",
-    "history-consumption": "Spending",
+    "history-consumption": "History",
     "my-orders": "My Orders",
     "my-coupons": "My Coupons",
     "switchIdentity": "Switch Role",
-    "personalCenter": "Personal Center",
+    "personalCenter": "Profile",
     "my-services": "My Services",
     "order": {
       "all": "All Orders",
       "unpaid": "Unpaid",
-      "in-progress": "Processing",
+      "in-progress": "In Progress",
       "completed": "Completed",
-      "refund": "Refund"
+      "refund": "Refund/After-sale"
     },
     "coupons": {
       "received": "Received",
@@ -99,48 +185,48 @@
     },
     "services": {
       "address": "Address",
-      "customerService": "Customer Service",
+      "customerService": "Service",
       "feedback": "Feedback"
     }
   },
   "login": {
     "title": "Login",
     "welcome": "Welcome",
-    "phoneLogin": "Phone Verification",
-    "passwordLogin": "Password Login",
+    "phoneLogin": "Phone OTP",
+    "passwordLogin": "Password",
     "orLoginWith": "Or login with",
     "quickLogin": "Quick Login",
     "areaCode": "Area Code",
     "phone": "Phone",
     "password": "Password",
-    "captcha": "Code",
-    "enterPhone": "Enter phone number",
+    "captcha": "OTP",
+    "enterPhone": "Enter phone",
     "enterPassword": "Enter password",
-    "enterCaptcha": "Enter verification code",
-    "getCaptcha": "Get Code",
+    "enterCaptcha": "Enter OTP",
+    "getCaptcha": "Get OTP",
     "loginNow": "Login Now",
-    "invalidPhone": "Invalid phone number format",
+    "invalidPhone": "Invalid phone format",
     "checkAgreement": "Please check the agreement",
-    "autoCreateAccount": "Unregistered phone numbers will automatically create an account after verification",
-    "selectAreaCode": "Select Country Code",
-    "forgotPassword": "Forgot password?",
-    "noAccount": "Don't have an account?",
-    "registerNow": "Register now",
-    "captchaSent": "Verification code sent",
-    "sendFailed": "Failed to send",
-    "currentEnvironment": "Environment",
-    "agreementPrefix": "I have read and agree to",
+    "autoCreateAccount": "New phone numbers will be automatically registered",
+    "selectAreaCode": "Select Area Code",
+    "forgotPassword": "Forgot Password?",
+    "noAccount": "No account?",
+    "registerNow": "Register Now",
+    "captchaSent": "OTP Sent",
+    "sendFailed": "Send Failed",
+    "currentEnvironment": "Current Environment",
+    "agreementPrefix": "I have read and agreed to the",
     "userAgreement": "User Agreement",
     "and": "and",
     "privacyPolicy": "Privacy Policy",
-    "success": "Login successful"
+    "success": "Login Success"
   },
   "merchant": {
     "tabbar": {
       "home": "Home",
-      "order": "Orders",
-      "table": "Tables",
-      "my": "My"
+      "order": "Order",
+      "table": "Table",
+      "my": "Mine"
     },
     "index": {
       "merchantCenter": "Merchant Center",
@@ -150,10 +236,10 @@
       "todayOrders": "Today's Orders",
       "todayRevenue": "Today's Revenue",
       "pendingOrders": "Pending Orders",
-      "pendingMeals": "Pending Meals"
+      "pendingMeals": "Preparing Meals"
     },
     "order": {
-      "title": "Order List",
+      "title": "Orders",
       "status": {
         "all": "All",
         "pending": "Pending",
@@ -168,55 +254,180 @@
       }
     }
   },
-  "owner": {
-    "dashboard": "Company Overview",
-    "shops": "Shop Management",
-    "todayData": "Today's Data",
-    "totalRevenue": "Total Revenue",
-    "totalOrders": "Total Orders",
-    "operating": "Operating",
-    "closed": "Closed",
-    "enterShop": "Enter Shop"
-  },
   "admin": {
-    "dashboard": "Admin Dashboard",
-    "users": "User Management",
-    "merchants": "Merchant Management",
-    "searchUser": "Search username/phone",
+    "dashboard": "Admin Dash",
+    "users": "Users",
+    "merchants": "Merchants",
+    "searchUser": "Search user/phone",
     "all": "All",
-    "normalUser": "Normal User",
+    "normalUser": "User",
     "merchant": "Merchant"
   },
   "pos": {
-    "welcome": "POS System",
-    "tables": "Table Management",
-    "orders": "Order Management",
-    "available": "Available",
-    "occupied": "Occupied",
-    "openTable": "Open",
-    "checkout": "Checkout",
-    "acceptOrder": "Accept",
-    "completeOrder": "Complete"
+    "welcome": {
+      "title": "POS System",
+      "welcome": "Welcome to POS System",
+      "initInfo": "Please initialize table info",
+      "shopId": "Shop ID",
+      "enterShopId": "Enter Shop ID",
+      "deskId": "Table ID",
+      "enterDeskId": "Enter Table ID",
+      "deskNumber": "Table No.",
+      "enterDeskNumber": "Enter Table No. (e.g., A01)",
+      "peopleCount": "Guests",
+      "enterPeopleCount": "Enter guest count",
+      "startOrder": "Start Order",
+      "initSuccess": "Init Success",
+      "initFailed": "Init Failed",
+      "devNote": "POS menu in development"
+    },
+    "tables": {
+      "title": "Table Management",
+      "available": "Available",
+      "occupied": "Occupied",
+      "reserved": "Reserved",
+      "tableCapacity": "{capacity}-person",
+      "currentGuests": "Current: {count}",
+      "status": {
+        "available": "Available",
+        "occupied": "Occupied",
+        "reserved": "Reserved",
+        "cleaning": "Cleaning"
+      },
+      "actions": {
+        "open": "Open",
+        "reserve": "Reserve",
+        "order": "Order",
+        "addOrder": "Add Order",
+        "checkout": "Checkout",
+        "transfer": "Transfer",
+        "clear": "Clear",
+        "checkin": "Check-in",
+        "cancelReserve": "Cancel Reserve"
+      },
+      "messages": {
+        "openSuccess": "Table opened",
+        "confirmClearTitle": "Confirm Clear?",
+        "confirmClearMessage": "End the dining session?",
+        "clearSuccess": "Table cleared",
+        "gotoCheckout": "Go to checkout",
+        "addTable": "Add Table"
+      }
+    },
+    "orders": {
+      "title": "Order Management",
+      "status": {
+        "pending": "Pending",
+        "preparing": "Preparing",
+        "completed": "Completed",
+        "cancelled": "Cancelled"
+      },
+      "tableLabel": "Table",
+      "timeLabel": "Time",
+      "empty": "No orders",
+      "messages": {
+        "accepted": "Accepted",
+        "completed": "Completed"
+      }
+    }
+  },
+  "owner": {
+    "dashboard": {
+      "title": "Company Overview",
+      "defaultCompanyName": "My Company",
+      "shopCountSuffix": " Shops",
+      "summary": {
+        "todayData": "Today's Data",
+        "realtimeUpdate": "Real-time Update",
+        "revenue": "Total Revenue",
+        "orders": "Total Orders",
+        "customers": "Customers"
+      },
+      "shops": {
+        "title": "Shops Overview",
+        "operating": "Operating",
+        "resting": "Resting"
+      },
+      "actions": {
+        "reports": "Reports",
+        "shops": "Shops",
+        "staff": "Staff",
+        "finance": "Finance"
+      },
+      "messages": {
+        "settings": "Settings",
+        "staffManagement": "Staff",
+        "financeCenter": "Finance"
+      }
+    },
+    "shops": {
+      "title": "Shop Management",
+      "empty": "No shops",
+      "currentShopLabel": "Current Shop:",
+      "status": {
+        "operating": "Operating",
+        "resting": "Resting",
+        "preparing": "Preparing"
+      },
+      "actions": {
+        "enter": "Enter Shop",
+        "enterManagement": "Manage",
+        "stopOperating": "Stop",
+        "startOperating": "Start"
+      },
+      "messages": {
+        "confirmStatusChange": "Confirm to {action} 「{name}」?",
+        "statusChanged": "{action}ed",
+        "addShop": "Add Shop",
+        "editShop": "Edit Shop: {name}"
+      }
+    },
+    "reports": {
+      "title": "Reports",
+      "dateRange": "Date Range",
+      "avgOrderValue": "Avg Order",
+      "compare": {
+        "title": "Comparison",
+        "shop": "Shop",
+        "revenue": "Revenue",
+        "orders": "Orders",
+        "percent": "Percent"
+      },
+      "trend": {
+        "title": "Trend",
+        "devNote": "Chart in development"
+      }
+    }
   },
+  "available": "Available",
+  "occupied": "Occupied",
+  "openTable": "Open",
+  "checkout": "Checkout",
+  "acceptOrder": "Accept",
+  "completeOrder": "Complete",
   "buffet": {
     "title": "All-You-Can-Eat",
-    "selectPlan": "Select Buffet Plan",
+    "selectPlan": "Select Plan",
     "remaining": "Time Left",
     "pause": "Pause",
     "resume": "Resume",
     "endEarly": "End Early",
-    "timeUp": "Time's up! Thank you",
-    "cannotOrder": "Cannot order now",
-    "confirmOrder": "Confirm Order",
-    "orderSuccess": "Order success!"
+    "timeUp": "Time's up!",
+    "cannotOrder": "Cannot order",
+    "confirmOrder": "Confirm",
+    "orderSuccess": "Success!"
   },
   "role": {
     "customer": "Customer",
+    "guest": "Guest",
     "staff": "Staff",
     "manager": "Manager",
     "owner": "Owner",
-    "admin": "Administrator",
+    "admin": "Admin",
     "switchTitle": "Switch Role",
+    "switchConfirm": "Switch to {role}?",
+    "switchSuccess": "Switched to {role}",
+    "noPermission": "No permission",
     "currentRole": "Current Role"
   }
 }

+ 244 - 33
src/locale/ja.json

@@ -10,7 +10,24 @@
     "languageChanged": "言語を変更しました",
     "viewMore": "もっと見る",
     "environment": "環境",
-    "featureInDevelopment": "開発中"
+    "featureInDevelopment": "開発中",
+    "all": "すべて",
+    "refreshSuccess": "リフレッシュ成功",
+    "action": "操作",
+    "viewAll": "すべて見る",
+    "edit": "編集",
+    "settings": "設定",
+    "confirmAction": "操作確認",
+    "today": "今日",
+    "units": {
+      "tenThousand": "万",
+      "order": "件",
+      "table": "卓"
+    },
+    "duration": {
+      "minutes": "{minutes}分",
+      "hoursMins": "{hours}時間{mins}分"
+    }
   },
   "search": {
     "placeholder": "店舗・料理を検索"
@@ -27,21 +44,68 @@
       "drinks": "ドリンク",
       "favorites": "お気に入り",
       "coupons": "クーポン"
+    },
+    "monthlySales": "月間販売 {count}",
+    "deliveryFee": "配送 ¥{fee}",
+    "minPrice": "¥{price} から配送",
+    "messages": {
+      "enterKeyword": "検索キーワードを入力してください",
+      "searchResult": "検索: {keyword}",
+      "bannerClick": "バナークリック: {title}",
+      "categoryClick": "カテゴリー: {name}",
+      "viewMoreShops": "もっと店舗を見る",
+      "nearCurrentLocation": "現在地付近",
+      "selectAddress": "お届け先を選択"
     }
   },
   "menu": {
-    "title": "注文",
-    "currentTable": "現在のテーブル",
-    "people": "人数",
-    "closed": "営業時間外",
-    "distance": "現在地から",
-    "dineIn": "店内",
-    "takeOut": "持ち帰り",
-    "selectSpec": "オプション選択",
-    "soldOut": "売り切れ",
-    "checkout": "会計へ",
-    "addToCart": "カートに追加",
-    "clear": "クリア"
+    "title": "メニュー",
+    "searchPlaceholder": "商品名を入力してください",
+    "noMore": "これ以上はありません",
+    "empty": "商品がありません",
+    "itemCount": "{count}点のアイテム",
+    "categories": {
+      "all": "すべて",
+      "hot": "人気",
+      "new": "新着",
+      "coffee": "コーヒー",
+      "tea": "お茶",
+      "milkTea": "ミルクティー",
+      "juice": "ジュース",
+      "snack": "スナック",
+      "combo": "セット"
+    },
+    "sort": {
+      "default": "総合順",
+      "priceAsc": "価格の安い順",
+      "priceDesc": "価格の高い順",
+      "sales": "売上順"
+    },
+    "filter": {
+      "all": "すべての商品",
+      "discount": "割引あり",
+      "popular": "月間100+"
+    },
+    "detail": {
+      "title": "商品詳細",
+      "specs": "仕様を選択",
+      "quantity": "数量を選択",
+      "noContent": "内容がありません",
+      "sales": "月間販売 {count}",
+      "rating": "満足度 {rate}%"
+    },
+    "actions": {
+      "service": "サポート",
+      "cart": "カート",
+      "addCart": "カートに入れる",
+      "buyNow": "今すぐ購入",
+      "addedToCart": "カートに追加しました",
+      "emptyCart": "カートは空です",
+      "selectGoods": "商品を選択してください",
+      "favoriteSuccess": "お気に入りに追加",
+      "favoriteCancel": "お気に入り解除",
+      "serviceClick": "サポートに連絡"
+    }
   },
   "cart": {
     "title": "カート",
@@ -65,7 +129,29 @@
     "preparing": "調理中",
     "delivering": "配送中",
     "completed": "完了",
-    "cancelled": "キャンセル"
+    "cancelled": "キャンセル",
+    "applyRefund": "返金申請",
+    "payNow": "今すぐ支払う",
+    "confirmReceived": "受取確認",
+    "confirmReceivedTip": "商品を受け取りましたか?",
+    "itemSummary": "合計{count}点、お支払い",
+    "tableNumberLabel": "テーブル番号: ",
+    "currentTable": "現在のテーブル",
+    "people": "人数",
+    "booking": "予約中",
+    "orderDetail": "注文詳細",
+    "status": {
+      "unpaid": "未払い",
+      "pending": "処理中",
+      "preparing": "調理中",
+      "completed": "完了",
+      "cancelled": "キャンセル"
+    },
+    "messages": {
+      "idNotFound": "注文IDが見つかりません"
+    },
+    "cancelBooking": "予約キャンセル",
+    "confirmCancelBooking": "予約をキャンセルしますか?"
   },
   "mine": {
     "title": "マイページ",
@@ -168,16 +254,6 @@
       }
     }
   },
-  "owner": {
-    "dashboard": "会社概要",
-    "shops": "店舗管理",
-    "todayData": "本日のデータ",
-    "totalRevenue": "総売上高",
-    "totalOrders": "総注文",
-    "operating": "営業中",
-    "closed": "休業中",
-    "enterShop": "店舗に入る"
-  },
   "admin": {
     "dashboard": "管理画面",
     "users": "ユーザー管理",
@@ -188,16 +264,147 @@
     "merchant": "加盟店"
   },
   "pos": {
-    "welcome": "POSシステム",
-    "tables": "テーブル管理",
-    "orders": "注文管理",
-    "available": "空席",
-    "occupied": "使用中",
-    "openTable": "開席",
-    "checkout": "会計",
-    "acceptOrder": "受注",
-    "completeOrder": "完了"
+    "welcome": {
+      "title": "POSシステム",
+      "welcome": "POSシステムへようこそ",
+      "initInfo": "テーブル情報を初期化してください",
+      "shopId": "店舗ID",
+      "enterShopId": "店舗IDを入力してください",
+      "deskId": "テーブルID",
+      "enterDeskId": "テーブルIDを入力してください",
+      "deskNumber": "テーブル番号",
+      "enterDeskNumber": "テーブル番号を入力してください (例: A01)",
+      "peopleCount": "人数",
+      "enterPeopleCount": "人数を入力してください",
+      "startOrder": "注文を開始する",
+      "initSuccess": "初期化に成功しました",
+      "initFailed": "初期化に失敗しました",
+      "devNote": "POSメニュー機能開発中"
+    },
+    "tables": {
+      "title": "テーブル管理",
+      "available": "空席",
+      "occupied": "使用中",
+      "reserved": "予約済み",
+      "tableCapacity": "{capacity}人席",
+      "currentGuests": "現在: {count}人",
+      "status": {
+        "available": "空席",
+        "occupied": "使用中",
+        "reserved": "予約済み",
+        "cleaning": "清掃中"
+      },
+      "actions": {
+        "open": "開席",
+        "reserve": "予約に設定",
+        "order": "注文",
+        "addOrder": "追加注文",
+        "checkout": "会計",
+        "transfer": "テーブル変更",
+        "clear": "清席",
+        "checkin": "チェックイン開席",
+        "cancelReserve": "予約キャンセル"
+      },
+      "messages": {
+        "openSuccess": "開席に成功しました",
+        "confirmClearTitle": "清席を確認しますか?",
+        "confirmClearMessage": "このテーブルの利用を終了します",
+        "clearSuccess": "清席が完了しました",
+        "gotoCheckout": "会計画面へ移動",
+        "addTable": "テーブル追加"
+      }
+    },
+    "orders": {
+      "title": "注文管理",
+      "status": {
+        "pending": "待機中",
+        "preparing": "調理中",
+        "completed": "完了",
+        "cancelled": "キャンセル済"
+      },
+      "tableLabel": "テーブル",
+      "timeLabel": "時間",
+      "empty": "注文はありません",
+      "messages": {
+        "accepted": "受注しました",
+        "completed": "注文完了"
+      }
+    }
+  },
+  "owner": {
+    "dashboard": {
+      "title": "会社概要",
+      "defaultCompanyName": "マイカンパニー",
+      "shopCountSuffix": " 店舗",
+      "summary": {
+        "todayData": "本日のデータ",
+        "realtimeUpdate": "リアルタイム更新",
+        "revenue": "総売上",
+        "orders": "総注文数",
+        "customers": "来客数"
+      },
+      "shops": {
+        "title": "店舗概況",
+        "operating": "営業中",
+        "resting": "準備中"
+      },
+      "actions": {
+        "reports": "総合レポート",
+        "shops": "店舗管理",
+        "staff": "従業員管理",
+        "finance": "財務センター"
+      },
+      "messages": {
+        "settings": "設定",
+        "staffManagement": "従業員管理",
+        "financeCenter": "財務センター"
+      }
+    },
+    "shops": {
+      "title": "店舗管理",
+      "empty": "店舗はありません",
+      "currentShopLabel": "選択中の店舗:",
+      "status": {
+        "operating": "営業中",
+        "resting": "準備中",
+        "preparing": "準備中"
+      },
+      "actions": {
+        "enter": "店舗に入る",
+        "enterManagement": "管理に入る",
+        "stopOperating": "営業停止",
+        "startOperating": "営業開始"
+      },
+      "messages": {
+        "confirmStatusChange": "「{name}」を{action}してもよろしいですか?",
+        "statusChanged": "{action}しました",
+        "addShop": "店舗追加",
+        "editShop": "店舗編集: {name}"
+      }
+    },
+    "reports": {
+      "title": "総合レポート",
+      "dateRange": "期間選択",
+      "avgOrderValue": "客単価",
+      "compare": {
+        "title": "店舗比較",
+        "shop": "店舗",
+        "revenue": "売上高",
+        "orders": "注文数",
+        "percent": "割合"
+      },
+      "trend": {
+        "title": "営業トレンド",
+        "devNote": "グラフ機能開発中"
+      }
+    }
   },
+  "available": "空席",
+  "occupied": "使用中",
+  "openTable": "開席",
+  "checkout": "会計",
+  "acceptOrder": "受注",
+  "completeOrder": "完了",
   "buffet": {
     "title": "食べ放題モード",
     "selectPlan": "食べ放題プランを選択",
@@ -212,11 +419,15 @@
   },
   "role": {
     "customer": "お客様",
+    "guest": "ゲスト",
     "staff": "スタッフ",
     "manager": "店長",
     "owner": "オーナー",
     "admin": "管理者",
     "switchTitle": "身分切り替え",
+    "switchConfirm": "身分を{role}に切り替えますか?",
+    "switchSuccess": "身分を{role}に切り替えました",
+    "noPermission": "権限がありません",
     "currentRole": "現在の身分"
   }
 }

+ 244 - 33
src/locale/zh-Hans.json

@@ -10,7 +10,24 @@
     "languageChanged": "语言已切换",
     "viewMore": "更多",
     "environment": "环境",
-    "featureInDevelopment": "功能开发中"
+    "featureInDevelopment": "功能开发中",
+    "all": "全部",
+    "refreshSuccess": "刷新成功",
+    "action": "操作",
+    "viewAll": "查看全部",
+    "edit": "编辑",
+    "settings": "设置",
+    "confirmAction": "确认操作",
+    "today": "今日",
+    "units": {
+      "tenThousand": "万",
+      "order": "单",
+      "table": "桌"
+    },
+    "duration": {
+      "minutes": "{minutes}分钟",
+      "hoursMins": "{hours}小时{mins}分"
+    }
   },
   "search": {
     "placeholder": "搜索店铺、菜品"
@@ -27,21 +44,68 @@
       "drinks": "饮品",
       "favorites": "我的收藏",
       "coupons": "领券中心"
+    },
+    "monthlySales": "月售 {count}",
+    "deliveryFee": "配送 ¥{fee}",
+    "minPrice": "起送 ¥{price}",
+    "messages": {
+      "enterKeyword": "请输入搜索关键词",
+      "searchResult": "搜索: {keyword}",
+      "bannerClick": "点击Banner: {title}",
+      "categoryClick": "分类: {name}",
+      "viewMoreShops": "查看更多店铺",
+      "nearCurrentLocation": "当前位置附近",
+      "selectAddress": "选择送餐地址"
     }
   },
   "menu": {
-    "title": "点餐",
-    "currentTable": "当前桌号",
-    "people": "人数",
-    "closed": "已歇业",
-    "distance": "距离您",
-    "dineIn": "自取",
-    "takeOut": "外卖",
-    "selectSpec": "选规格",
-    "soldOut": "已售罄",
-    "checkout": "去结算",
-    "addToCart": "加入购物车",
-    "clear": "清空"
+    "title": "菜单",
+    "searchPlaceholder": "请输入商品名称",
+    "noMore": "没有更多了",
+    "empty": "暂无商品",
+    "itemCount": "{count}件商品",
+    "categories": {
+      "all": "全部",
+      "hot": "热销",
+      "new": "新品",
+      "coffee": "咖啡",
+      "tea": "茶饮",
+      "milkTea": "奶茶",
+      "juice": "果汁",
+      "snack": "小食",
+      "combo": "套餐"
+    },
+    "sort": {
+      "default": "综合排序",
+      "priceAsc": "价格从低到高",
+      "priceDesc": "价格从高到低",
+      "sales": "销量最高"
+    },
+    "filter": {
+      "all": "全部商品",
+      "discount": "有优惠",
+      "popular": "月销100+"
+    },
+    "detail": {
+      "title": "商品详情",
+      "specs": "选择规格",
+      "quantity": "购买数量",
+      "noContent": "暂无内容",
+      "sales": "月销 {count}",
+      "rating": "好评率 {rate}%"
+    },
+    "actions": {
+      "service": "客服",
+      "cart": "购物车",
+      "addCart": "加入购物车",
+      "buyNow": "立即购买",
+      "addedToCart": "已加入购物车",
+      "emptyCart": "购物车是空的",
+      "selectGoods": "请先选择商品",
+      "favoriteSuccess": "收藏成功",
+      "favoriteCancel": "取消收藏",
+      "serviceClick": "联系客服"
+    }
   },
   "cart": {
     "title": "购物车",
@@ -65,7 +129,29 @@
     "preparing": "制作中",
     "delivering": "配送中",
     "completed": "已完成",
-    "cancelled": "已取消"
+    "cancelled": "已取消",
+    "applyRefund": "申请退款",
+    "payNow": "立即支付",
+    "confirmReceived": "确认收货",
+    "confirmReceivedTip": "确定已收到商品吗?",
+    "itemSummary": "共{count}件商品,实付",
+    "tableNumberLabel": "桌号: ",
+    "currentTable": "当前桌号",
+    "people": "人数",
+    "booking": "预约中",
+    "orderDetail": "订单详情",
+    "status": {
+      "unpaid": "待付款",
+      "pending": "待处理",
+      "preparing": "制作中",
+      "completed": "已完成",
+      "cancelled": "已取消"
+    },
+    "messages": {
+      "idNotFound": "订单ID不存在"
+    },
+    "cancelBooking": "取消预约",
+    "confirmCancelBooking": "确定要取消预约吗?"
   },
   "mine": {
     "title": "我的",
@@ -168,16 +254,6 @@
       }
     }
   },
-  "owner": {
-    "dashboard": "公司总览",
-    "shops": "店铺管理",
-    "todayData": "今日数据",
-    "totalRevenue": "总营业额",
-    "totalOrders": "总订单",
-    "operating": "营业中",
-    "closed": "休息中",
-    "enterShop": "进入店铺"
-  },
   "admin": {
     "dashboard": "管理后台",
     "users": "用户管理",
@@ -188,16 +264,147 @@
     "merchant": "商家"
   },
   "pos": {
-    "welcome": "POS系统",
-    "tables": "桌位管理",
-    "orders": "订单管理",
-    "available": "空闲",
-    "occupied": "就餐中",
-    "openTable": "开台",
-    "checkout": "结账",
-    "acceptOrder": "接单",
-    "completeOrder": "完成"
+    "welcome": {
+      "title": "POS系统",
+      "welcome": "欢迎使用POS系统",
+      "initInfo": "请先初始化桌台信息",
+      "shopId": "店铺ID",
+      "enterShopId": "请输入店铺ID",
+      "deskId": "桌台ID",
+      "enterDeskId": "请输入桌台ID",
+      "deskNumber": "桌台号",
+      "enterDeskNumber": "请输入桌台号 (如: A01)",
+      "peopleCount": "就餐人数",
+      "enterPeopleCount": "请输入就餐人数",
+      "startOrder": "开始点餐",
+      "initSuccess": "初始化成功",
+      "initFailed": "初始化失败",
+      "devNote": "POS菜单功能开发中"
+    },
+    "tables": {
+      "title": "桌位管理",
+      "available": "空闲",
+      "occupied": "就餐中",
+      "reserved": "已预约",
+      "tableCapacity": "{capacity}人桌",
+      "currentGuests": "当前: {count}人",
+      "status": {
+        "available": "空闲",
+        "occupied": "就餐中",
+        "reserved": "已预约",
+        "cleaning": "清理中"
+      },
+      "actions": {
+        "open": "开台",
+        "reserve": "设为预约",
+        "order": "点餐",
+        "addOrder": "加餐",
+        "checkout": "结账",
+        "transfer": "换桌",
+        "clear": "清台",
+        "checkin": "签到开台",
+        "cancelReserve": "取消预约"
+      },
+      "messages": {
+        "openSuccess": "开台成功",
+        "confirmClearTitle": "确认清台?",
+        "confirmClearMessage": "将结束该桌的用餐",
+        "clearSuccess": "清台完成",
+        "gotoCheckout": "跳转结账页面",
+        "addTable": "添加桌位"
+      }
+    },
+    "orders": {
+      "title": "订单管理",
+      "status": {
+        "pending": "待处理",
+        "preparing": "制作中",
+        "completed": "已完成",
+        "cancelled": "已取消"
+      },
+      "tableLabel": "桌位",
+      "timeLabel": "时间",
+      "empty": "暂无订单",
+      "messages": {
+        "accepted": "已接单",
+        "completed": "订单完成"
+      }
+    }
+  },
+  "owner": {
+    "dashboard": {
+      "title": "公司总览",
+      "defaultCompanyName": "我的公司",
+      "shopCountSuffix": " 家店铺",
+      "summary": {
+        "todayData": "今日数据",
+        "realtimeUpdate": "实时更新",
+        "revenue": "总营业额",
+        "orders": "总订单",
+        "customers": "顾客数"
+      },
+      "shops": {
+        "title": "店铺概况",
+        "operating": "营业中",
+        "resting": "休息中"
+      },
+      "actions": {
+        "reports": "综合报表",
+        "shops": "店铺管理",
+        "staff": "员工管理",
+        "finance": "财务中心"
+      },
+      "messages": {
+        "settings": "设置",
+        "staffManagement": "员工管理",
+        "financeCenter": "财务中心"
+      }
+    },
+    "shops": {
+      "title": "店铺管理",
+      "empty": "暂无店铺",
+      "currentShopLabel": "当前操作店铺:",
+      "status": {
+        "operating": "营业中",
+        "resting": "休息中",
+        "preparing": "准备中"
+      },
+      "actions": {
+        "enter": "进入店铺",
+        "enterManagement": "进入管理",
+        "stopOperating": "暂停营业",
+        "startOperating": "开始营业"
+      },
+      "messages": {
+        "confirmStatusChange": "确定要{action}「{name}」吗?",
+        "statusChanged": "已{action}",
+        "addShop": "添加店铺",
+        "editShop": "编辑店铺: {name}"
+      }
+    },
+    "reports": {
+      "title": "综合报表",
+      "dateRange": "日期范围",
+      "avgOrderValue": "客单价",
+      "compare": {
+        "title": "店铺对比",
+        "shop": "店铺",
+        "revenue": "营业额",
+        "orders": "订单数",
+        "percent": "占比"
+      },
+      "trend": {
+        "title": "营业趋势",
+        "devNote": "图表功能开发中"
+      }
+    }
   },
+  "available": "空闲",
+  "occupied": "就餐中",
+  "openTable": "开台",
+  "checkout": "结账",
+  "acceptOrder": "接单",
+  "completeOrder": "完成",
   "buffet": {
     "title": "放题模式",
     "selectPlan": "选择放题方案",
@@ -212,11 +419,15 @@
   },
   "role": {
     "customer": "顾客",
+    "guest": "访客",
     "staff": "员工",
     "manager": "店长",
     "owner": "老板",
     "admin": "管理员",
     "switchTitle": "切换身份",
+    "switchConfirm": "确定要切换到{role}身份吗?",
+    "switchSuccess": "已切换到{role}身份",
+    "noPermission": "没有相应权限",
     "currentRole": "当前身份"
   }
 }

+ 257 - 46
src/locale/zh-Hant.json

@@ -4,13 +4,30 @@
     "cancel": "取消",
     "success": "操作成功",
     "error": "操作失敗",
-    "loading": "載中",
-    "pleaseLogin": "請先登",
+    "loading": "載中",
+    "pleaseLogin": "請先登",
     "selectLanguage": "選擇語言",
     "languageChanged": "語言已切換",
     "viewMore": "更多",
     "environment": "環境",
-    "featureInDevelopment": "功能開發中"
+    "featureInDevelopment": "功能開發中",
+    "all": "全部",
+    "refreshSuccess": "刷新成功",
+    "action": "操作",
+    "viewAll": "查看全部",
+    "edit": "編輯",
+    "settings": "設置",
+    "confirmAction": "確認操作",
+    "today": "今日",
+    "units": {
+      "tenThousand": "萬",
+      "order": "單",
+      "table": "桌"
+    },
+    "duration": {
+      "minutes": "{minutes}分鐘",
+      "hoursMins": "{hours}小時{mins}分"
+    }
   },
   "search": {
     "placeholder": "搜尋店舖、菜品"
@@ -23,25 +40,72 @@
       "chinese": "中餐",
       "western": "西餐",
       "fastFood": "快餐",
-      "dessert": "甜",
+      "dessert": "甜",
       "drinks": "飲品",
       "favorites": "我的收藏",
       "coupons": "領券中心"
+    },
+    "monthlySales": "月售 {count}",
+    "deliveryFee": "配送 ¥{fee}",
+    "minPrice": "起送 ¥{price}",
+    "messages": {
+      "enterKeyword": "請輸入搜尋關鍵詞",
+      "searchResult": "搜尋: {keyword}",
+      "bannerClick": "點擊Banner: {title}",
+      "categoryClick": "分類: {name}",
+      "viewMoreShops": "查看更多店舖",
+      "nearCurrentLocation": "當前位置附近",
+      "selectAddress": "選擇送餐地址"
     }
   },
   "menu": {
-    "title": "點餐",
-    "currentTable": "當前桌號",
-    "people": "人數",
-    "closed": "已歇業",
-    "distance": "距離您",
-    "dineIn": "自取",
-    "takeOut": "外賣",
-    "selectSpec": "選規格",
-    "soldOut": "已售罄",
-    "checkout": "去結算",
-    "addToCart": "加入購物車",
-    "clear": "清空"
+    "title": "菜單",
+    "searchPlaceholder": "請輸入商品名稱",
+    "noMore": "沒有更多了",
+    "empty": "暫無商品",
+    "itemCount": "{count}件商品",
+    "categories": {
+      "all": "全部",
+      "hot": "熱銷",
+      "new": "新品",
+      "coffee": "咖啡",
+      "tea": "茶飲",
+      "milkTea": "奶茶",
+      "juice": "果汁",
+      "snack": "小食",
+      "combo": "套餐"
+    },
+    "sort": {
+      "default": "綜合排序",
+      "priceAsc": "價格從低到高",
+      "priceDesc": "價格從高到低",
+      "sales": "銷量最高"
+    },
+    "filter": {
+      "all": "全部商品",
+      "discount": "有優惠",
+      "popular": "月銷100+"
+    },
+    "detail": {
+      "title": "商品詳情",
+      "specs": "選擇規格",
+      "quantity": "購買數量",
+      "noContent": "暫無內容",
+      "sales": "月銷 {count}",
+      "rating": "好評率 {rate}%"
+    },
+    "actions": {
+      "service": "客服",
+      "cart": "購物車",
+      "addCart": "加入購物車",
+      "buyNow": "立即購買",
+      "addedToCart": "已加入購物車",
+      "emptyCart": "購物車是空的",
+      "selectGoods": "請先選擇商品",
+      "favoriteSuccess": "收藏成功",
+      "favoriteCancel": "取消收藏",
+      "serviceClick": "聯繫客服"
+    }
   },
   "cart": {
     "title": "購物車",
@@ -65,12 +129,34 @@
     "preparing": "製作中",
     "delivering": "配送中",
     "completed": "已完成",
-    "cancelled": "已取消"
+    "cancelled": "已取消",
+    "applyRefund": "申請退款",
+    "payNow": "立即支付",
+    "confirmReceived": "確認收貨",
+    "confirmReceivedTip": "確定已收到商品嗎?",
+    "itemSummary": "共{count}件商品,實付",
+    "tableNumberLabel": "桌號: ",
+    "currentTable": "當前桌號",
+    "people": "人數",
+    "booking": "預約中",
+    "orderDetail": "訂單詳情",
+    "status": {
+      "unpaid": "待付款",
+      "pending": "待處理",
+      "preparing": "製作中",
+      "completed": "已完成",
+      "cancelled": "已取消"
+    },
+    "messages": {
+      "idNotFound": "訂單ID不存在"
+    },
+    "cancelBooking": "取消預約",
+    "confirmCancelBooking": "確定要取消預約嗎?"
   },
   "mine": {
     "title": "我的",
-    "login-benefits": "登入獲取更多權益",
-    "auth-login": "授權登入",
+    "login-benefits": "登獲取更多權益",
+    "auth-login": "授權登",
     "user-id": "用戶ID",
     "not-vip": "非VIP用戶",
     "view-details": "查看詳情",
@@ -104,12 +190,12 @@
     }
   },
   "login": {
-    "title": "登",
-    "welcome": "歡迎登",
+    "title": "登",
+    "welcome": "歡迎登",
     "phoneLogin": "手機驗證碼",
-    "passwordLogin": "密碼登",
-    "orLoginWith": "或使用以下方式登",
-    "quickLogin": "一鍵登",
+    "passwordLogin": "密碼登",
+    "orLoginWith": "或使用以下方式登",
+    "quickLogin": "一鍵登",
     "areaCode": "區號",
     "phone": "手機號",
     "password": "密碼",
@@ -118,7 +204,7 @@
     "enterPassword": "請輸入密碼",
     "enterCaptcha": "請輸入驗證碼",
     "getCaptcha": "獲取驗證碼",
-    "loginNow": "立即登",
+    "loginNow": "立即登",
     "invalidPhone": "手機號碼格式不對",
     "checkAgreement": "請勾選下面協議",
     "autoCreateAccount": "未註冊的手機號驗證後自動創建賬號",
@@ -133,7 +219,7 @@
     "userAgreement": "用戶協議",
     "and": "與",
     "privacyPolicy": "隱私政策",
-    "success": "登成功"
+    "success": "登成功"
   },
   "merchant": {
     "tabbar": {
@@ -168,16 +254,6 @@
       }
     }
   },
-  "owner": {
-    "dashboard": "公司總覽",
-    "shops": "店鋪管理",
-    "todayData": "今日數據",
-    "totalRevenue": "總營業額",
-    "totalOrders": "總訂單",
-    "operating": "營業中",
-    "closed": "休息中",
-    "enterShop": "進入店鋪"
-  },
   "admin": {
     "dashboard": "管理後台",
     "users": "用戶管理",
@@ -188,16 +264,147 @@
     "merchant": "商家"
   },
   "pos": {
-    "welcome": "POS系統",
-    "tables": "桌位管理",
-    "orders": "訂單管理",
-    "available": "空閒",
-    "occupied": "就餐中",
-    "openTable": "開台",
-    "checkout": "結賬",
-    "acceptOrder": "接單",
-    "completeOrder": "完成"
+    "welcome": {
+      "title": "POS系統",
+      "welcome": "歡迎使用POS系統",
+      "initInfo": "請先初始化桌台信息",
+      "shopId": "店鋪ID",
+      "enterShopId": "請輸入店鋪ID",
+      "deskId": "桌台ID",
+      "enterDeskId": "請輸入桌台ID",
+      "deskNumber": "桌台號",
+      "enterDeskNumber": "請輸入桌台號 (如: A01)",
+      "peopleCount": "就餐人數",
+      "enterPeopleCount": "請輸入就餐人數",
+      "startOrder": "開始點餐",
+      "initSuccess": "初始化成功",
+      "initFailed": "初始化失敗",
+      "devNote": "POS菜單功能開發中"
+    },
+    "tables": {
+      "title": "桌位管理",
+      "available": "空閒",
+      "occupied": "就餐中",
+      "reserved": "已預約",
+      "tableCapacity": "{capacity}人桌",
+      "currentGuests": "當前: {count}人",
+      "status": {
+        "available": "空閒",
+        "occupied": "就餐中",
+        "reserved": "已預約",
+        "cleaning": "清理中"
+      },
+      "actions": {
+        "open": "開台",
+        "reserve": "設為預約",
+        "order": "點餐",
+        "addOrder": "加餐",
+        "checkout": "結賬",
+        "transfer": "換桌",
+        "clear": "清台",
+        "checkin": "簽到開台",
+        "cancelReserve": "取消預約"
+      },
+      "messages": {
+        "openSuccess": "開台成功",
+        "confirmClearTitle": "確認清台?",
+        "confirmClearMessage": "將結束該桌的用餐",
+        "clearSuccess": "清台完成",
+        "gotoCheckout": "跳轉結賬頁面",
+        "addTable": "添加桌位"
+      }
+    },
+    "orders": {
+      "title": "訂單管理",
+      "status": {
+        "pending": "待處理",
+        "preparing": "製作中",
+        "completed": "已完成",
+        "cancelled": "已取消"
+      },
+      "tableLabel": "桌位",
+      "timeLabel": "時間",
+      "empty": "暫無訂單",
+      "messages": {
+        "accepted": "已接單",
+        "completed": "訂單完成"
+      }
+    }
+  },
+  "owner": {
+    "dashboard": {
+      "title": "公司總覽",
+      "defaultCompanyName": "我的公司",
+      "shopCountSuffix": " 家店舖",
+      "summary": {
+        "todayData": "今日數據",
+        "realtimeUpdate": "實時更新",
+        "revenue": "總營業額",
+        "orders": "總訂單",
+        "customers": "顧客數"
+      },
+      "shops": {
+        "title": "店舖概況",
+        "operating": "營業中",
+        "resting": "休息中"
+      },
+      "actions": {
+        "reports": "綜合報表",
+        "shops": "店舖管理",
+        "staff": "員工管理",
+        "finance": "財務中心"
+      },
+      "messages": {
+        "settings": "設置",
+        "staffManagement": "員工管理",
+        "financeCenter": "財務中心"
+      }
+    },
+    "shops": {
+      "title": "店舖管理",
+      "empty": "暫無店舖",
+      "currentShopLabel": "當前操作店舖:",
+      "status": {
+        "operating": "營業中",
+        "resting": "休息中",
+        "preparing": "準備中"
+      },
+      "actions": {
+        "enter": "進入店舖",
+        "enterManagement": "進入管理",
+        "stopOperating": "暫停營業",
+        "startOperating": "開始營業"
+      },
+      "messages": {
+        "confirmStatusChange": "確定要{action}「{name}」嗎?",
+        "statusChanged": "已{action}",
+        "addShop": "添加店舖",
+        "editShop": "編輯店舖: {name}"
+      }
+    },
+    "reports": {
+      "title": "綜合報表",
+      "dateRange": "日期範圍",
+      "avgOrderValue": "客單價",
+      "compare": {
+        "title": "店舖對比",
+        "shop": "店舖",
+        "revenue": "營業額",
+        "orders": "訂單數",
+        "percent": "占比"
+      },
+      "trend": {
+        "title": "營業趨勢",
+        "devNote": "圖表功能開發中"
+      }
+    }
   },
+  "available": "空閒",
+  "occupied": "就餐中",
+  "openTable": "開台",
+  "checkout": "結賬",
+  "acceptOrder": "接單",
+  "completeOrder": "完成",
   "buffet": {
     "title": "放題模式",
     "selectPlan": "選擇放題方案",
@@ -212,11 +419,15 @@
   },
   "role": {
     "customer": "顧客",
+    "guest": "訪客",
     "staff": "員工",
-    "manager": "店",
+    "manager": "店",
     "owner": "老板",
     "admin": "管理員",
     "switchTitle": "切換身份",
+    "switchConfirm": "確定要切換到{role}身份嗎?",
+    "switchSuccess": "已切換到{role}身份",
+    "noPermission": "沒有相應權限",
     "currentRole": "當前身份"
   }
 }

+ 50 - 29
src/views/index/index.vue

@@ -1,15 +1,18 @@
 <template>
   <div class="index-page">
-    <!-- 顶部栏 -->
+    <!-- 顶部栏:包含位置选择、语言切换和搜索框 -->
     <div class="top-bar">
       <div class="top-row">
+        <!-- 位置展示与点击触发选择 -->
         <div class="location-bar" @click="showLocationPicker = true">
           <van-icon name="location-o" />
           <span class="location-text">{{ currentLocation }}</span>
           <van-icon name="arrow-down" size="12" />
         </div>
+        <!-- 语言切换组件 -->
         <LanguageSwitcher compact />
       </div>
+      <!-- 搜索组件 -->
       <SearchBar
         v-model="searchKeyword"
         :placeholder="t('search.placeholder') || '搜索店铺、菜品'"
@@ -74,7 +77,7 @@
         <!-- Loading -->
         <div v-if="loading" class="loading-more">
           <van-loading type="spinner" size="24" />
-          <span>加载中...</span>
+          <span>{{ $t('common.loading') }}</span>
         </div>
       </div>
     </van-pull-refresh>
@@ -89,7 +92,7 @@
     <!-- 位置选择弹窗 -->
     <van-popup v-model:show="showLocationPicker" position="bottom" round>
       <van-area
-        title="选择送餐地址"
+        :title="$t('index.messages.selectAddress')"
         :area-list="areaList"
         @confirm="handleLocationConfirm"
         @cancel="showLocationPicker = false"
@@ -111,12 +114,13 @@ import LanguageSwitcher from '@/components/LanguageSwitcher.vue'
 const router = useRouter()
 const appStore = useAppStore()
 
-const activeTab = ref(0)
-const refreshing = ref(false)
-const loading = ref(false)
-const searchKeyword = ref('')
-const currentLocation = ref('东京都渋谷区')
-const showLocationPicker = ref(false)
+// --- 响应式状态 ---
+const activeTab = ref(0)              // 底部导航当前激活项
+const refreshing = ref(false)         // 下拉刷新状态
+const loading = ref(false)            // 加载更多状态
+const searchKeyword = ref('')         // 搜索关键词
+const currentLocation = ref('东京都渋谷区') // 当前位置显示文本
+const showLocationPicker = ref(false)  // 是否显示位置选择弹窗
 
 // Mock数据
 const areaList = ref({
@@ -142,6 +146,7 @@ const bannerList = ref([
 
 const { t } = useI18n()
 
+// 金刚区分类列表(使用 computed 配合 i18n 实现动态语言切换)
 const categories = computed(() => [
   { id: '1', name: t('index.categories.japanese'), icon: 'fire-o', color: '#ff6b6b' },
   { id: '2', name: t('index.categories.chinese'), icon: 'hot-o', color: '#ee0a24' },
@@ -189,39 +194,50 @@ const recommendShops = ref<Shop[]>([
   }
 ])
 
+/**
+ * 处理下拉刷新逻辑
+ */
 const onRefresh = async () => {
-  // 模拟刷新
+  // 模拟 API 请求刷新数据
   await new Promise(resolve => setTimeout(resolve, 1000))
   refreshing.value = false
-  showToast('刷新成功')
+  showToast(t('common.refreshSuccess'))
 }
 
 const handleSearch = (keyword: string) => {
   if (!keyword.trim()) {
-    showToast('请输入搜索关键词')
+    showToast(t('index.messages.enterKeyword'))
     return
   }
-  showToast(`搜索: ${keyword}`)
+  showToast(t('index.messages.searchResult', { keyword }))
 }
 
 const handleBannerClick = (banner: any) => {
-  showToast(`点击Banner: ${banner.title}`)
+  showToast(t('index.messages.bannerClick', { title: banner.title }))
 }
 
+/**
+ * 处理分类项点击
+ */
 const handleCategoryClick = (category: any) => {
   if (category.id === '7') {
-    // 我的收藏
+    // 点击“我的收藏”跳转到个人中心
     router.push('/mine')
   } else if (category.id === '8') {
-    // 领券中心
-    showToast('领券中心')
+    // 点击“领券中心
+    showToast(t('index.categories.coupons'))
   } else {
-    showToast(`分类: ${category.name}`)
+    // 其他分类显示 toast 提示
+    showToast(t('index.messages.categoryClick', { name: category.name }))
   }
 }
 
+/**
+ * 处理店铺点击跳转
+ * 会切换 store 状态为店铺模式
+ */
 const handleShopClick = (shop: Shop) => {
-  // 进入店铺模式
+  // 切换 App 状态:进入特定店铺模式(隐藏全局导航等)
   appStore.enterShopMode({
     id: shop.id,
     name: shop.name,
@@ -230,6 +246,7 @@ const handleShopClick = (shop: Shop) => {
     status: 'operating'
   })
   
+  // 跳转到该店铺的菜单页
   router.push({
     path: '/menu',
     query: { shopId: shop.id }
@@ -237,7 +254,7 @@ const handleShopClick = (shop: Shop) => {
 }
 
 const handleViewMore = () => {
-  showToast('查看更多店铺')
+  showToast(t('index.messages.viewMoreShops'))
 }
 
 const handleLocationConfirm = (values: any) => {
@@ -245,38 +262,42 @@ const handleLocationConfirm = (values: any) => {
   showLocationPicker.value = false
 }
 
+/**
+ * 请求浏览器地理位置权限并获取坐标
+ */
 const requestLocation = async () => {
   try {
     if ('geolocation' in navigator) {
+      // 通过浏览器 API 获取经纬度
       const position = await new Promise<GeolocationPosition>((resolve, reject) => {
         navigator.geolocation.getCurrentPosition(resolve, reject, {
-          enableHighAccuracy: false,
-          timeout: 5000,
-          maximumAge: 300000
+          enableHighAccuracy: false, // 是否高精度(由于可能耗时较长,这里通常设为 false)
+          timeout: 5000,             // 超时时间
+          maximumAge: 300000         // 缓存时长
         })
       })
       
       const { latitude, longitude } = position.coords
       
-      // 调用反向地理编码获取地址
+      // 异步导入地理编码工具(按需加载)
       const { reverseGeocode, formatAddress } = await import('@/utils/geocoding')
+      // 调用逆地理编码服务(优先后端,降级 Nominatim)
       const geocodeResult = await reverseGeocode(latitude, longitude)
       
       if (geocodeResult) {
-        // 根据当前语言格式化地址
+        // 格式化并更新地址显示
         const formattedAddress = formatAddress(geocodeResult, appStore.lang)
         currentLocation.value = formattedAddress
       } else {
-        // 编码失败,显示通用文本
-        currentLocation.value = '当前位置附近'
+        // 如果解析失败,显示兜底文案
+        currentLocation.value = t('index.messages.nearCurrentLocation')
       }
       
-      // 存储位置到store
+      // 将坐标同步到全局 Store
       appStore.setLocation({ latitude, longitude })
     }
   } catch (error) {
     console.log('用户拒绝了位置权限或定位失败', error)
-    // 使用默认位置(不更改 currentLocation)
   }
 }
 

+ 16 - 14
src/views/menu/detail.vue

@@ -2,7 +2,7 @@
   <div class="detail-page">
     <!-- 导航栏 -->
     <van-nav-bar
-      title="商品详情"
+      :title="$t('menu.detail.title')"
       fixed
       left-arrow
       @click-left="handleBack"
@@ -59,14 +59,14 @@
           <div class="goods-desc">{{ goods.desc }}</div>
           
           <div class="goods-stats">
-            <div class="stat-item">月销 {{ goods.sales || 0 }}</div>
-            <div class="stat-item">好评率 {{ goods.rating || 100 }}%</div>
+            <div class="stat-item">{{ $t('menu.detail.sales', { count: goods.sales || 0 }) }}</div>
+            <div class="stat-item">{{ $t('menu.detail.rating', { rate: goods.rating || 100 }) }}</div>
           </div>
         </div>
 
         <!-- 规格选择 -->
         <div class="specs-card" v-if="goods.specs && goods.specs.length">
-          <div class="card-title">选择规格</div>
+          <div class="card-title">{{ $t('menu.detail.specs') }}</div>
           <div class="specs-list">
             <div
               v-for="spec in goods.specs"
@@ -82,14 +82,14 @@
 
         <!-- 购买数量 -->
         <div class="quantity-card">
-          <div class="card-title">购买数量</div>
+          <div class="card-title">{{ $t('menu.detail.quantity') }}</div>
           <van-stepper v-model="quantity" min="1" max="99" />
         </div>
 
         <!-- 商品详情 -->
         <div class="detail-card">
-          <div class="card-title">商品详情</div>
-          <div class="detail-content" v-html="goods.detail || '暂无内容'"></div>
+          <div class="card-title">{{ $t('menu.detail.title') }}</div>
+          <div class="detail-content" v-html="goods.detail || $t('menu.detail.noContent')"></div>
         </div>
       </template>
 
@@ -99,15 +99,15 @@
 
     <!-- 底部操作栏 -->
     <van-action-bar>
-      <van-action-bar-icon icon="chat-o" text="客服" @click="contactService" />
+      <van-action-bar-icon icon="chat-o" :text="$t('menu.actions.service')" @click="contactService" />
       <van-action-bar-icon
         icon="cart-o"
-        text="购物车"
+        :text="$t('menu.actions.cart')"
         :badge="cartStore.cartCount || ''"
         @click="goToCart"
       />
-      <van-action-bar-button type="warning" text="加入购物车" @click="handleAddCart" />
-      <van-action-bar-button type="danger" text="立即购买" @click="handleBuyNow" />
+      <van-action-bar-button type="warning" :text="$t('menu.actions.addCart')" @click="handleAddCart" />
+      <van-action-bar-button type="danger" :text="$t('menu.actions.buyNow')" @click="handleBuyNow" />
     </van-action-bar>
   </div>
 </template>
@@ -115,6 +115,7 @@
 <script setup lang="ts">
 import { ref, computed, onMounted } from 'vue'
 import { useRouter, useRoute, type LocationQueryValue } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast, showImagePreview } from 'vant'
 import { useCartStore } from '@/store/index'
 import { getGoodsDetail, type Goods } from '@/api/goods'
@@ -122,6 +123,7 @@ import { getGoodsDetail, type Goods } from '@/api/goods'
 const router = useRouter()
 const route = useRoute()
 const cartStore = useCartStore()
+const { t } = useI18n()
 
 const loading = ref(true)
 const isFavorite = ref(false)
@@ -208,7 +210,7 @@ const handleShare = () => {
 
 const toggleFavorite = () => {
   isFavorite.value = !isFavorite.value
-  showToast(isFavorite.value ? '收藏成功' : '取消收藏')
+  showToast(isFavorite.value ? t('menu.actions.favoriteSuccess') : t('menu.actions.favoriteCancel'))
 }
 
 const selectSpec = (id: number | string) => {
@@ -223,7 +225,7 @@ const previewImages = (index: number) => {
 }
 
 const contactService = () => {
-  showToast('联系客服')
+  showToast(t('menu.actions.serviceClick'))
 }
 
 const goToCart = () => {
@@ -238,7 +240,7 @@ const handleAddCart = () => {
     image: goods.value.images?.[0] || '',
     quantity: quantity.value
   })
-  showToast('已加入购物车')
+  showToast(t('menu.actions.addedToCart'))
 }
 
 const handleBuyNow = () => {

+ 34 - 31
src/views/menu/menu.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="menu-page">
     <!-- 导航栏 -->
-    <van-nav-bar title="菜单" fixed left-arrow @click-left="$router.back()">
+    <van-nav-bar :title="$t('menu.title')" fixed left-arrow @click-left="$router.back()">
       <template #right>
         <van-icon name="search" size="18" @click="showSearch = true" />
       </template>
@@ -11,7 +11,7 @@
     <van-search
       v-show="showSearch"
       v-model="searchKeyword"
-      placeholder="请输入商品名称"
+      :placeholder="$t('menu.searchPlaceholder')"
       show-action
       @search="handleSearch"
       @cancel="showSearch = false"
@@ -63,7 +63,7 @@
               v-else
               v-model:loading="loading"
               :finished="finished"
-              :finished-text="goodsList.length > 0 ? '没有更多了' : ''"
+              :finished-text="goodsList.length > 0 ? $t('menu.noMore') : ''"
               @load="onLoad"
             >
               <div v-if="goodsList.length > 0" class="goods-list">
@@ -77,7 +77,7 @@
               </div>
 
               <!-- 空状态 -->
-              <van-empty v-else description="暂无商品" />
+              <van-empty v-else :description="$t('menu.empty')" />
             </van-list>
           </van-pull-refresh>
         </div>
@@ -92,10 +92,10 @@
       </div>
       <div class="cart-info">
         <div class="cart-price">¥{{ cartStore.cartTotal.toFixed(2) }}</div>
-        <div class="cart-text">{{ cartStore.cartCount }}件商品</div>
+        <div class="cart-text">{{ $t('menu.itemCount', { count: cartStore.cartCount }) }}</div>
       </div>
       <van-button type="primary" round class="checkout-btn" @click.stop="goToCheckout">
-        去结算
+        {{ $t('menu.actions.checkout') || $t('common.checkout') }}
       </van-button>
     </div>
 
@@ -110,6 +110,7 @@
 <script setup lang="ts">
 import { ref, computed, onMounted, watch } from 'vue'
 import { useRouter, useRoute } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast } from 'vant'
 import { useCartStore } from '@/store/index'
 import { getGoodsList, getGoodsCategories } from '@/api/index'
@@ -120,39 +121,41 @@ const router = useRouter()
 const route = useRoute()
 const cartStore = useCartStore()
 
+const { t } = useI18n()
+
 // 搜索
 const showSearch = ref(false)
 const searchKeyword = ref('')
 
 // 分类
 const activeCategory = ref(0)
-const categoryList = ref([
-  { id: 0, name: '全部', icon: 'apps-o' },
-  { id: 1, name: '热销', badge: 'HOT', icon: 'fire-o' },
-  { id: 2, name: '新品', badge: 'NEW', icon: 'gift-o' },
-  { id: 3, name: '咖啡', icon: 'coffee-o' },
-  { id: 4, name: '茶饮', icon: 'hot-o' },
-  { id: 5, name: '奶茶', icon: 'bag-o' },
-  { id: 6, name: '果汁', icon: 'peer-pay' },
-  { id: 7, name: '小食', icon: 'goods-collect-o' },
-  { id: 8, name: '套餐', icon: 'label-o' }
+const categoryList = computed(() => [
+  { id: 0, name: t('menu.categories.all'), icon: 'apps-o' },
+  { id: 1, name: t('menu.categories.hot'), badge: 'HOT', icon: 'fire-o' },
+  { id: 2, name: t('menu.categories.new'), badge: 'NEW', icon: 'gift-o' },
+  { id: 3, name: t('menu.categories.coffee'), icon: 'coffee-o' },
+  { id: 4, name: t('menu.categories.tea'), icon: 'hot-o' },
+  { id: 5, name: t('menu.categories.milkTea'), icon: 'bag-o' },
+  { id: 6, name: t('menu.categories.juice'), icon: 'peer-pay' },
+  { id: 7, name: t('menu.categories.snack'), icon: 'goods-collect-o' },
+  { id: 8, name: t('menu.categories.combo'), icon: 'label-o' }
 ])
 
 // 排序和筛选
 const sortType = ref(0)
-const sortOptions = [
-  { text: '综合排序', value: 0 },
-  { text: '价格从低到高', value: 1 },
-  { text: '价格从高到低', value: 2 },
-  { text: '销量最高', value: 3 }
-]
+const sortOptions = computed(() => [
+  { text: t('menu.sort.default'), value: 0 },
+  { text: t('menu.sort.priceAsc'), value: 1 },
+  { text: t('menu.sort.priceDesc'), value: 2 },
+  { text: t('menu.sort.sales'), value: 3 }
+])
 
 const filterType = ref(0)
-const filterOptions = [
-  { text: '全部商品', value: 0 },
-  { text: '有优惠', value: 1 },
-  { text: '月销100+', value: 2 }
-]
+const filterOptions = computed(() => [
+  { text: t('menu.filter.all'), value: 0 },
+  { text: t('menu.filter.discount'), value: 1 },
+  { text: t('menu.filter.popular'), value: 2 }
+])
 
 // 商品列表
 const goodsList = ref([])
@@ -299,7 +302,7 @@ const loadGoodsList = async (reset = false) => {
     }
   } catch (error) {
     console.error('加载商品列表失败:', error)
-    showToast('加载失败')
+    showToast(t('common.loadFailed'))
   } finally {
     loading.value = false
     refreshing.value = false
@@ -349,13 +352,13 @@ const addToCart = (goods) => {
     price: parseFloat(goods.price),
     quantity: 1
   })
-  showToast('已加入购物车')
+  showToast(t('menu.actions.addedToCart'))
 }
 
 // 去购物车
 const goToCart = () => {
   if (cartStore.cartCount === 0) {
-    showToast('购物车是空的')
+    showToast(t('menu.actions.emptyCart'))
     return
   }
   router.push('/cart')
@@ -364,7 +367,7 @@ const goToCart = () => {
 // 去结算
 const goToCheckout = () => {
   if (cartStore.cartCount === 0) {
-    showToast('请先选择商品')
+    showToast(t('menu.actions.selectGoods'))
     return
   }
   router.push('/cart')

+ 1 - 1
src/views/mine/mine.vue

@@ -362,7 +362,7 @@ const handleAvatarClick = () => {
       clearTimeout(avatarTapTimer.value)
     }
     // 三次点击头像的隐藏功能
-    showToast('彩蛋功能')
+    showToast(t('common.featureInDevelopment'))
   }
 }
 

+ 2 - 2
src/views/order/detail.vue

@@ -164,7 +164,7 @@
               <img :src="orderData.appShopDeskVO?.image" class="goods-image" />
               <div class="goods-info">
                 <div class="goods-title">{{ orderData.appShopDeskVO?.title }}</div>
-                <div class="goods-spec">桌号: {{ orderData.appShopDeskVO?.number }}</div>
+                <div class="goods-spec">{{ $t('order.tableNumberLabel') }}{{ orderData.appShopDeskVO?.number }}</div>
               </div>
               <div class="goods-price-info">
                 <div class="goods-quantity">×1</div>
@@ -310,7 +310,7 @@ const loadOrderDetail = async () => {
   try {
     const orderId = route.query.id
     if (!orderId) {
-      showToast('订单ID不存在')
+      showToast(t('order.messages.idNotFound'))
       router.back()
       return
     }

+ 4 - 4
src/views/order/order.vue

@@ -142,7 +142,7 @@
                   {{ formatTime(item.createTime) }}
                 </div>
                 <div class="order-total">
-                  <span>{{ getGoodsCount(item.cartInfo) }}件商品,实付</span>
+                  <span>{{ $t('order.itemSummary', { count: getGoodsCount(item.cartInfo) }) }}</span>
                   <span class="price">¥{{ item.payPrice }}</span>
                 </div>
               </div>
@@ -216,9 +216,9 @@ const orderTypeTabs = ref([
 // 订单状态 Tab (普通订单)
 const statusTabs = ref([
   { type: -1, name: t('merchant.order.status.all') },
-  { type: 0, name: t('merchant.order.status.unpaid') },
-  { type: 1, name: t('merchant.order.status.pending') },
-  { type: 4, name: t('merchant.order.status.completed') },
+  { type: 0, name: t('order.status.unpaid') },
+  { type: 1, name: t('order.status.pending') },
+  { type: 4, name: t('order.status.completed') },
   { type: -3, name: t('order.applyRefund') }
 ])
 

+ 24 - 21
src/views/owner/dashboard.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="owner-dashboard">
-    <van-nav-bar title="公司总览" fixed placeholder>
+    <van-nav-bar :title="$t('owner.dashboard.title')" fixed placeholder>
       <template #right>
         <van-icon name="setting-o" size="20" @click="goToSettings" />
       </template>
@@ -23,8 +23,8 @@
           </div>
         </div>
         <div class="company-info">
-          <h2>{{ company?.name || '我的公司' }}</h2>
-          <p>{{ shopCount }} 家店铺</p>
+          <h2>{{ company?.name || $t('owner.dashboard.defaultCompanyName') }}</h2>
+          <p>{{ shopCount }}{{ $t('owner.dashboard.shopCountSuffix') }}</p>
         </div>
       </div>
     </div>
@@ -32,13 +32,13 @@
     <!-- 今日汇总 -->
     <div class="summary-section">
       <div class="section-title">
-        <span>今日数据</span>
-        <span class="update-time">实时更新</span>
+        <span>{{ $t('owner.dashboard.summary.todayData') }}</span>
+        <span class="update-time">{{ $t('owner.dashboard.summary.realtimeUpdate') }}</span>
       </div>
       <div class="summary-cards">
         <div class="summary-card primary">
           <div class="card-value">¥{{ formatNumber(summary?.totalRevenue || 0) }}</div>
-          <div class="card-label">总营业额</div>
+          <div class="card-label">{{ $t('owner.dashboard.summary.revenue') }}</div>
           <div class="card-trend" :class="{ up: (summary?.comparedToYesterday || 0) > 0 }">
             <van-icon :name="(summary?.comparedToYesterday || 0) > 0 ? 'arrow-up' : 'arrow-down'" />
             {{ Math.abs(summary?.comparedToYesterday || 0) }}%
@@ -46,11 +46,11 @@
         </div>
         <div class="summary-card">
           <div class="card-value">{{ summary?.totalOrders || 0 }}</div>
-          <div class="card-label">总订单</div>
+          <div class="card-label">{{ $t('owner.dashboard.summary.orders') }}</div>
         </div>
         <div class="summary-card">
           <div class="card-value">{{ summary?.totalCustomers || 0 }}</div>
-          <div class="card-label">顾客数</div>
+          <div class="card-label">{{ $t('owner.dashboard.summary.customers') }}</div>
         </div>
       </div>
     </div>
@@ -58,8 +58,8 @@
     <!-- 店铺列表 -->
     <div class="shops-section">
       <div class="section-title">
-        <span>店铺概况</span>
-        <span class="view-all" @click="goToShopList">查看全部</span>
+        <span>{{ $t('owner.dashboard.shops.title') }}</span>
+        <span class="view-all" @click="goToShopList">{{ $t('common.viewAll') }}</span>
       </div>
       <div class="shop-list">
         <div
@@ -72,13 +72,13 @@
             <div class="shop-name">
               {{ shop.shopName }}
               <van-tag :type="shop.status === 'operating' ? 'success' : 'default'">
-                {{ shop.status === 'operating' ? '营业中' : '休息中' }}
+                {{ shop.status === 'operating' ? $t('owner.dashboard.shops.operating') : $t('owner.dashboard.shops.resting') }}
               </van-tag>
             </div>
             <div class="shop-stats">
               <span>¥{{ formatNumber(shop.todayRevenue) }}</span>
               <span class="divider">|</span>
-              <span>{{ shop.todayOrders }}</span>
+              <span>{{ shop.todayOrders }}{{ $t('common.units.order') }}</span>
             </div>
           </div>
           <div class="shop-tables">
@@ -88,7 +88,7 @@
                 :style="{ width: `${(shop.occupiedTables / shop.totalTables) * 100}%` }"
               ></div>
             </div>
-            <span class="tables-text">{{ shop.occupiedTables }}/{{ shop.totalTables }}</span>
+            <span class="tables-text">{{ shop.occupiedTables }}/{{ shop.totalTables }}{{ $t('common.units.table') }}</span>
           </div>
           <van-icon name="arrow" class="arrow" />
         </div>
@@ -99,19 +99,19 @@
     <div class="quick-actions">
       <div class="action-item" @click="goToReports">
         <van-icon name="chart-trending-o" size="24" />
-        <span>综合报表</span>
+        <span>{{ $t('owner.dashboard.actions.reports') }}</span>
       </div>
       <div class="action-item" @click="goToShopList">
         <van-icon name="shop-o" size="24" />
-        <span>店铺管理</span>
+        <span>{{ $t('owner.dashboard.actions.shops') }}</span>
       </div>
       <div class="action-item" @click="goToStaffList">
         <van-icon name="friends-o" size="24" />
-        <span>员工管理</span>
+        <span>{{ $t('owner.dashboard.actions.staff') }}</span>
       </div>
       <div class="action-item" @click="goToFinance">
         <van-icon name="balance-o" size="24" />
-        <span>财务中心</span>
+        <span>{{ $t('owner.dashboard.actions.finance') }}</span>
       </div>
     </div>
   </div>
@@ -120,7 +120,10 @@
 <script setup lang="ts">
 import { ref, computed, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast } from 'vant'
+
+const { t } = useI18n()
 import { useCompanyStore } from '@/store/modules/company'
 
 const router = useRouter()
@@ -133,13 +136,13 @@ const shopSummaries = computed(() => companyStore.companySummary?.shopSummaries
 
 const formatNumber = (num: number) => {
   if (num >= 10000) {
-    return (num / 10000).toFixed(1) + '万'
+    return (num / 10000).toFixed(1) + t('common.units.tenThousand')
   }
   return num.toLocaleString()
 }
 
 const goToSettings = () => {
-  showToast('设置')
+  showToast(t('common.settings'))
 }
 
 const goToShopList = () => {
@@ -156,11 +159,11 @@ const goToReports = () => {
 }
 
 const goToStaffList = () => {
-  showToast('员工管理')
+  showToast(t('owner.dashboard.messages.staffManagement'))
 }
 
 const goToFinance = () => {
-  showToast('财务中心')
+  showToast(t('owner.dashboard.messages.financeCenter'))
 }
 
 onMounted(async () => {

+ 17 - 14
src/views/owner/reports.vue

@@ -1,37 +1,37 @@
 <template>
   <div class="owner-reports">
-    <van-nav-bar title="综合报表" left-arrow @click-left="goBack" fixed placeholder />
+    <van-nav-bar :title="$t('owner.reports.title')" left-arrow @click-left="goBack" fixed placeholder />
 
     <!-- 日期范围选择 -->
     <div class="date-picker">
-      <van-cell title="日期范围" :value="dateRangeText" is-link @click="showDatePicker = true" />
+      <van-cell :title="$t('owner.reports.dateRange')" :value="dateRangeText" is-link @click="showDatePicker = true" />
     </div>
 
     <!-- 汇总卡片 -->
     <div class="summary-cards">
       <div class="summary-card">
-        <div class="card-label">总营业额</div>
+        <div class="card-label">{{ $t('owner.reports.compare.revenue') }}</div>
         <div class="card-value">¥{{ formatNumber(reportData.totalRevenue) }}</div>
       </div>
       <div class="summary-card">
-        <div class="card-label">总订单</div>
+        <div class="card-label">{{ $t('owner.reports.compare.orders') }}</div>
         <div class="card-value">{{ reportData.totalOrders }}</div>
       </div>
       <div class="summary-card">
-        <div class="card-label">客单价</div>
+        <div class="card-label">{{ $t('owner.reports.avgOrderValue') }}</div>
         <div class="card-value">¥{{ avgOrderValue }}</div>
       </div>
     </div>
 
     <!-- 店铺对比 -->
     <div class="section">
-      <div class="section-title">店铺对比</div>
+      <div class="section-title">{{ $t('owner.reports.compare.title') }}</div>
       <div class="compare-table">
         <div class="table-header">
-          <span class="col-name">店铺</span>
-          <span class="col-revenue">营业额</span>
-          <span class="col-orders">订单数</span>
-          <span class="col-percent">占比</span>
+          <span class="col-name">{{ $t('owner.reports.compare.shop') }}</span>
+          <span class="col-revenue">{{ $t('owner.reports.compare.revenue') }}</span>
+          <span class="col-orders">{{ $t('owner.reports.compare.orders') }}</span>
+          <span class="col-percent">{{ $t('owner.reports.compare.percent') }}</span>
         </div>
         <div
           v-for="shop in shopComparison"
@@ -53,11 +53,11 @@
 
     <!-- 趋势图(简化版)-->
     <div class="section">
-      <div class="section-title">营业趋势</div>
+      <div class="section-title">{{ $t('owner.reports.trend.title') }}</div>
       <div class="trend-chart">
         <div class="chart-placeholder">
           <van-icon name="chart-trending-o" size="48" color="#ddd" />
-          <p>图表功能开发中</p>
+          <p>{{ $t('owner.reports.trend.devNote') }}</p>
         </div>
       </div>
     </div>
@@ -74,6 +74,9 @@
 <script setup lang="ts">
 import { ref, computed } from 'vue'
 import { useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+
+const { t } = useI18n()
 
 const router = useRouter()
 
@@ -84,7 +87,7 @@ const dateRangeText = computed(() => {
   if (startDate && endDate) {
     return `${startDate.toLocaleDateString()} ~ ${endDate.toLocaleDateString()}`
   }
-  return '今日'
+  return t('common.today')
 })
 
 // 模拟数据
@@ -106,7 +109,7 @@ const shopComparison = ref([
 
 const formatNumber = (num: number) => {
   if (num >= 10000) {
-    return (num / 10000).toFixed(1) + '万'
+    return (num / 10000).toFixed(1) + t('common.units.tenThousand')
   }
   return num.toLocaleString()
 }

+ 22 - 16
src/views/owner/shops.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="owner-shops">
-    <van-nav-bar title="店铺管理" left-arrow @click-left="goBack" fixed placeholder>
+    <van-nav-bar :title="$t('owner.shops.title')" left-arrow @click-left="goBack" fixed placeholder>
       <template #right>
         <van-icon name="add-o" size="20" @click="addShop" />
       </template>
@@ -43,10 +43,10 @@
 
           <div class="shop-actions">
             <van-button size="small" plain type="primary" @click.stop="enterShop(shop)">
-              进入店铺
+              {{ $t('owner.shops.actions.enter') }}
             </van-button>
             <van-button size="small" plain @click.stop="editShop(shop)">
-              编辑
+              {{ $t('common.edit') }}
             </van-button>
             <van-button
               size="small"
@@ -54,20 +54,20 @@
               :type="shop.status === 'operating' ? 'warning' : 'success'"
               @click.stop="toggleStatus(shop)"
             >
-              {{ shop.status === 'operating' ? '暂停营业' : '开始营业' }}
+              {{ shop.status === 'operating' ? $t('owner.shops.actions.stopOperating') : $t('owner.shops.actions.startOperating') }}
             </van-button>
           </div>
         </div>
 
-        <van-empty v-if="shops.length === 0" description="暂无店铺" />
+        <van-empty v-if="shops.length === 0" :description="$t('owner.shops.empty')" />
       </div>
     </van-pull-refresh>
 
     <!-- 当前选中店铺指示 -->
     <div v-if="selectedShop" class="current-shop-bar">
-      <span>当前操作店铺: <strong>{{ selectedShop.name }}</strong></span>
+      <span>{{ $t('owner.shops.currentShopLabel') }} <strong>{{ selectedShop.name }}</strong></span>
       <van-button size="small" type="primary" @click="enterSelectedShop">
-        进入管理
+        {{ $t('owner.shops.actions.enterManagement') }}
       </van-button>
     </div>
   </div>
@@ -76,7 +76,10 @@
 <script setup lang="ts">
 import { ref, computed, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast, showConfirmDialog } from 'vant'
+
+const { t } = useI18n()
 import { useCompanyStore, type Shop, type ShopStatus } from '@/store/modules/company'
 
 const router = useRouter()
@@ -99,9 +102,9 @@ const getStatusType = (status: ShopStatus): 'success' | 'warning' | 'default' =>
 
 const getStatusText = (status: ShopStatus) => {
   const texts: Record<ShopStatus, string> = {
-    operating: '营业中',
-    closed: '休息中',
-    preparing: '准备中'
+    operating: t('owner.shops.status.operating'),
+    closed: t('owner.shops.status.resting'),
+    preparing: t('owner.shops.status.preparing')
   }
   return texts[status]
 }
@@ -131,22 +134,25 @@ const enterSelectedShop = () => {
 }
 
 const editShop = (shop: Shop) => {
-  showToast(`编辑店铺: ${shop.name}`)
+  showToast(t('owner.shops.messages.editShop', { name: shop.name }))
 }
 
 const addShop = () => {
-  showToast('添加店铺')
+  showToast(t('owner.shops.messages.addShop'))
 }
 
 const toggleStatus = async (shop: Shop) => {
-  const newStatus = shop.status === 'operating' ? '暂停营业' : '开始营业'
+  const actionText = shop.status === 'operating' 
+    ? t('owner.shops.actions.stopOperating') 
+    : t('owner.shops.actions.startOperating')
+  
   try {
     await showConfirmDialog({
-      title: '确认操作',
-      message: `确定要${newStatus}「${shop.name}」吗?`
+      title: t('common.confirmAction'),
+      message: t('owner.shops.messages.confirmStatusChange', { action: actionText, name: shop.name })
     })
     // TODO: 调用API更新状态
-    showToast(`已${newStatus}`)
+    showToast(t('owner.shops.messages.statusChanged', { action: actionText }))
   } catch {
     // 用户取消
   }

+ 21 - 18
src/views/pos/orders.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="pos-orders">
-    <van-nav-bar title="订单管理" fixed placeholder />
+    <van-nav-bar :title="$t('pos.orders.title')" fixed placeholder />
 
     <van-tabs v-model:active="activeTab" sticky @change="onTabChange">
-      <van-tab title="全部" />
-      <van-tab title="待处理" />
-      <van-tab title="制作中" />
-      <van-tab title="已完成" />
+      <van-tab :title="$t('common.all')" />
+      <van-tab :title="$t('pos.orders.status.pending')" />
+      <van-tab :title="$t('pos.orders.status.preparing')" />
+      <van-tab :title="$t('pos.orders.status.completed')" />
     </van-tabs>
 
     <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
@@ -18,11 +18,11 @@
           </div>
           <div class="order-info">
             <div class="info-row">
-              <span class="label">桌位:</span>
+              <span class="label">{{ $t('pos.orders.tableLabel') }}:</span>
               <span class="value">{{ order.tableName }}</span>
             </div>
             <div class="info-row">
-              <span class="label">时间:</span>
+              <span class="label">{{ $t('pos.orders.timeLabel') }}:</span>
               <span class="value">{{ formatTime(order.createTime) }}</span>
             </div>
           </div>
@@ -35,14 +35,14 @@
           <div class="order-footer">
             <span class="amount">¥{{ order.amount }}</span>
             <van-button v-if="order.status === 'pending'" size="small" type="primary" @click.stop="acceptOrder(order)">
-              接单
+              {{ $t('merchant.order.actions.accept') }}
             </van-button>
             <van-button v-if="order.status === 'preparing'" size="small" type="success" @click.stop="completeOrder(order)">
-              完成
+              {{ $t('merchant.order.actions.complete') }}
             </van-button>
           </div>
         </div>
-        <van-empty v-if="filteredOrders.length === 0" description="暂无订单" />
+        <van-empty v-if="filteredOrders.length === 0" :description="$t('pos.orders.empty')" />
       </div>
     </van-pull-refresh>
   </div>
@@ -51,8 +51,11 @@
 <script setup lang="ts">
 import { ref, computed } from 'vue'
 import { useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast } from 'vant'
 
+const { t } = useI18n()
+
 const router = useRouter()
 
 interface OrderItem {
@@ -119,12 +122,12 @@ const getStatusType = (status: string) => {
 
 const getStatusText = (status: string) => {
   const texts: Record<string, string> = {
-    pending: '待处理',
-    preparing: '制作中',
-    completed: '已完成',
-    cancelled: '已取消'
+    pending: t('pos.orders.status.pending'),
+    preparing: t('pos.orders.status.preparing'),
+    completed: t('pos.orders.status.completed'),
+    cancelled: t('pos.orders.status.cancelled')
   }
-  return texts[status]
+  return texts[status] || status
 }
 
 const formatTime = (timestamp: number) => {
@@ -139,7 +142,7 @@ const onTabChange = () => {
 const onRefresh = () => {
   setTimeout(() => {
     refreshing.value = false
-    showToast('刷新成功')
+    showToast(t('common.refreshSuccess'))
   }, 1000)
 }
 
@@ -149,12 +152,12 @@ const viewOrder = (order: Order) => {
 
 const acceptOrder = (order: Order) => {
   order.status = 'preparing'
-  showToast('已接单')
+  showToast(t('pos.orders.messages.accepted'))
 }
 
 const completeOrder = (order: Order) => {
   order.status = 'completed'
-  showToast('订单完成')
+  showToast(t('pos.orders.messages.completed'))
 }
 </script>
 

+ 35 - 29
src/views/pos/tables.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="pos-tables">
-    <van-nav-bar title="桌位管理" fixed placeholder>
+    <van-nav-bar :title="$t('pos.tables.title')" fixed placeholder>
       <template #right>
         <van-icon name="add-o" size="20" @click="showAddTable" />
       </template>
@@ -10,21 +10,21 @@
     <div class="stats-bar">
       <div class="stat-item">
         <span class="stat-value available">{{ availableCount }}</span>
-        <span class="stat-label">空闲</span>
+        <span class="stat-label">{{ $t('pos.tables.available') }}</span>
       </div>
       <div class="stat-item">
         <span class="stat-value occupied">{{ occupiedCount }}</span>
-        <span class="stat-label">就餐中</span>
+        <span class="stat-label">{{ $t('pos.tables.occupied') }}</span>
       </div>
       <div class="stat-item">
         <span class="stat-value reserved">{{ reservedCount }}</span>
-        <span class="stat-label">已预约</span>
+        <span class="stat-label">{{ $t('pos.tables.reserved') }}</span>
       </div>
     </div>
 
     <!-- 楼层筛选 -->
     <van-tabs v-model:active="currentFloor" sticky>
-      <van-tab v-for="floor in floors" :key="floor" :title="floor === 0 ? '全部' : `${floor}F`" />
+      <van-tab v-for="floor in floors" :key="floor" :title="floor === 0 ? $t('common.all') : `${floor}F`" />
     </van-tabs>
 
     <!-- 桌位列表 -->
@@ -43,13 +43,13 @@
           </van-tag>
         </div>
         <div class="table-info">
-          <span>{{ table.capacity }}人桌</span>
+          <span>{{ $t('pos.tables.tableCapacity', { capacity: table.capacity }) }}</span>
           <span v-if="table.status === 'occupied'" class="duration">
             {{ formatDuration(table.startTime) }}
           </span>
         </div>
         <div v-if="table.guestCount" class="guest-count">
-          当前: {{ table.guestCount }}人
+          {{ $t('pos.tables.currentGuests', { count: table.guestCount }) }}
         </div>
       </div>
     </div>
@@ -60,7 +60,7 @@
       :title="selectedTable?.name"
       :actions="tableActions"
       @select="onActionSelect"
-      cancel-text="取消"
+      :cancel-text="$t('common.cancel')"
     />
   </div>
 </template>
@@ -68,8 +68,11 @@
 <script setup lang="ts">
 import { ref, computed } from 'vue'
 import { useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast, showConfirmDialog } from 'vant'
 
+const { t } = useI18n()
+
 const router = useRouter()
 
 interface Table {
@@ -117,25 +120,25 @@ const tableActions = computed(() => {
 
   if (table.status === 'available') {
     return [
-      { name: '开台', value: 'open' },
-      { name: '设为预约', value: 'reserve' }
+      { name: t('pos.tables.actions.open'), value: 'open' },
+      { name: t('pos.tables.actions.reserve'), value: 'reserve' }
     ]
   }
 
   if (table.status === 'occupied') {
     return [
-      { name: '点餐', value: 'order' },
-      { name: '加餐', value: 'addOrder' },
-      { name: '结账', value: 'checkout' },
-      { name: '换桌', value: 'transfer' },
-      { name: '清台', value: 'clear', color: '#ee0a24' }
+      { name: t('pos.tables.actions.order'), value: 'order' },
+      { name: t('pos.tables.actions.addOrder'), value: 'addOrder' },
+      { name: t('pos.tables.actions.checkout'), value: 'checkout' },
+      { name: t('pos.tables.actions.transfer'), value: 'transfer' },
+      { name: t('pos.tables.actions.clear'), value: 'clear', color: '#ee0a24' }
     ]
   }
 
   if (table.status === 'reserved') {
     return [
-      { name: '签到开台', value: 'checkin' },
-      { name: '取消预约', value: 'cancelReserve', color: '#ee0a24' }
+      { name: t('pos.tables.actions.checkin'), value: 'checkin' },
+      { name: t('pos.tables.actions.cancelReserve'), value: 'cancelReserve', color: '#ee0a24' }
     ]
   }
 
@@ -166,10 +169,10 @@ const getTagType = (status: string): 'success' | 'warning' | 'danger' | 'primary
 
 const getStatusText = (status: string) => {
   const texts: Record<string, string> = {
-    available: '空闲',
-    occupied: '就餐中',
-    reserved: '已预约',
-    cleaning: '清理中'
+    available: t('pos.tables.status.available'),
+    occupied: t('pos.tables.status.occupied'),
+    reserved: t('pos.tables.status.reserved'),
+    cleaning: t('pos.tables.status.cleaning')
   }
   return texts[status] || status
 }
@@ -177,10 +180,10 @@ const getStatusText = (status: string) => {
 const formatDuration = (startTime?: number) => {
   if (!startTime) return ''
   const minutes = Math.floor((Date.now() - startTime) / 1000 / 60)
-  if (minutes < 60) return `${minutes}分钟`
+  if (minutes < 60) return t('common.duration.minutes', { minutes })
   const hours = Math.floor(minutes / 60)
   const mins = minutes % 60
-  return `${hours}小时${mins}分`
+  return t('common.duration.hoursMins', { hours, mins })
 }
 
 const handleTableClick = (table: Table) => {
@@ -195,7 +198,7 @@ const onActionSelect = async (action: { value: string }) => {
 
   switch (action.value) {
     case 'open':
-      showToast('开台成功')
+      showToast(t('pos.tables.messages.openSuccess'))
       table.status = 'occupied'
       table.startTime = Date.now()
       break
@@ -203,22 +206,25 @@ const onActionSelect = async (action: { value: string }) => {
       router.push({ path: '/menu', query: { table: table.name } })
       break
     case 'checkout':
-      showToast('跳转结账页面')
+      showToast(t('pos.tables.messages.gotoCheckout'))
       break
     case 'clear':
-      await showConfirmDialog({ title: '确认清台?', message: '将结束该桌的用餐' })
+      await showConfirmDialog({ 
+        title: t('pos.tables.messages.confirmClearTitle'), 
+        message: t('pos.tables.messages.confirmClearMessage') 
+      })
       table.status = 'available'
       table.startTime = undefined
       table.guestCount = undefined
-      showToast('清台完成')
+      showToast(t('pos.tables.messages.clearSuccess'))
       break
     default:
-      showToast(`操作: ${action.value}`)
+      showToast(`${t('common.action')}: ${action.value}`)
   }
 }
 
 const showAddTable = () => {
-  showToast('添加桌位')
+  showToast(t('pos.tables.messages.addTable'))
 }
 </script>
 

+ 21 - 19
src/views/pos/welcome.vue

@@ -1,44 +1,44 @@
 <template>
   <div class="pos-welcome">
-    <van-nav-bar title="POS系统" left-arrow @click-left="goBack" />
+    <van-nav-bar :title="$t('pos.welcome.title')" left-arrow @click-left="goBack" />
 
     <div class="welcome-content">
-      <h1>欢迎使用POS系统</h1>
-      <p>请先初始化桌台信息</p>
+      <h1>{{ $t('pos.welcome.welcome') }}</h1>
+      <p>{{ $t('pos.welcome.initInfo') }}</p>
 
       <van-form @submit="handleSubmit">
         <van-cell-group inset>
           <van-field
             v-model="formData.shopId"
             name="shopId"
-            label="店铺ID"
-            placeholder="请输入店铺ID"
-            :rules="[{ required: true, message: '请输入店铺ID' }]"
+            :label="$t('pos.welcome.shopId')"
+            :placeholder="$t('pos.welcome.enterShopId')"
+            :rules="[{ required: true, message: $t('pos.welcome.enterShopId') }]"
           />
 
           <van-field
             v-model="formData.deskId"
             name="deskId"
-            label="桌台ID"
-            placeholder="请输入桌台ID"
-            :rules="[{ required: true, message: '请输入桌台ID' }]"
+            :label="$t('pos.welcome.deskId')"
+            :placeholder="$t('pos.welcome.enterDeskId')"
+            :rules="[{ required: true, message: $t('pos.welcome.enterDeskId') }]"
           />
 
           <van-field
             v-model="formData.deskNumber"
             name="deskNumber"
-            label="桌台号"
-            placeholder="请输入桌台号 (如: A01)"
-            :rules="[{ required: true, message: '请输入桌台号' }]"
+            :label="$t('pos.welcome.deskNumber')"
+            :placeholder="$t('pos.welcome.enterDeskNumber')"
+            :rules="[{ required: true, message: $t('pos.welcome.enterDeskNumber') }]"
           />
 
           <van-field
             v-model="formData.peopleCount"
             name="peopleCount"
             type="number"
-            label="就餐人数"
-            placeholder="请输入就餐人数"
-            :rules="[{ required: true, message: '请输入就餐人数' }]"
+            :label="$t('pos.welcome.peopleCount')"
+            :placeholder="$t('pos.welcome.enterPeopleCount')"
+            :rules="[{ required: true, message: $t('pos.welcome.enterPeopleCount') }]"
           />
         </van-cell-group>
 
@@ -50,7 +50,7 @@
             native-type="submit"
             :loading="loading"
           >
-            开始点餐
+            {{ $t('pos.welcome.startOrder') }}
           </van-button>
         </div>
       </van-form>
@@ -61,7 +61,9 @@
 <script setup lang="ts">
 import { ref } from 'vue'
 import { useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
 import { showToast } from 'vant'
+const { t } = useI18n()
 import { usePosStore } from '@/store/modules/pos'
 
 const router = useRouter()
@@ -85,16 +87,16 @@ const handleSubmit = () => {
     })
 
     showToast({
-      message: '初始化成功',
+      message: t('pos.welcome.initSuccess'),
       icon: 'success'
     })
 
     setTimeout(() => {
-      showToast('POS菜单功能开发中')
+      showToast(t('pos.welcome.devNote'))
       loading.value = false
     }, 1000)
   } catch (error) {
-    showToast('初始化失败')
+    showToast(t('pos.welcome.initFailed'))
     loading.value = false
   }
 }