feat: 全站20个模板添加国际化(i18n)支持 - 简体中文/繁体中文/英文三语切换

- 所有18套前端模板 + 管理后台共20个HTML文件添加i18n引擎
- 前端JavaScript方案:I18N_LOCALES翻译字典 + data-i18n属性 + t()函数调用
- 语言切换器UI:下拉菜单选择,匹配各模板主题风格
- 语言持久化:localStorage存储 + URL参数覆盖 + 浏览器语言自动检测
- onLangChange回调:语言切换时动态重新渲染所有内容
- 支持语言:zh-CN(简体中文) / zh-TW(繁体中文) / en(English)
This commit is contained in:
2026-09-09 16:58:40 +08:00
parent 69c59f4fbd
commit a84129330e
20 changed files with 9343 additions and 3855 deletions

View File

@@ -740,6 +740,34 @@ a { color: inherit; text-decoration: none; }
.nav-cta { display: none; }
.section { padding: 40px 0; }
}
/* ===== LANGUAGE SWITCHER ===== */
.lang-switcher{position:relative;margin-left:8px}
.lang-btn{
display:flex;align-items:center;gap:6px;padding:8px 14px;border-radius:12px;
font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;
background:#fff;border:1.5px solid var(--line);
transition:all .25s;
}
.lang-btn:hover{border-color:var(--green);color:var(--green);background:var(--green-mist)}
.lang-btn svg{width:16px;height:16px}
.lang-dropdown{
position:absolute;top:calc(100% + 8px);right:0;min-width:160px;
background:#fff;border:1.5px solid var(--green-100);border-radius:14px;
box-shadow:var(--shadow);overflow:hidden;
opacity:0;transform:translateY(-8px);pointer-events:none;
transition:all .25s;z-index:100;
}
.lang-dropdown.open{opacity:1;transform:none;pointer-events:auto}
.lang-option{
display:flex;align-items:center;gap:10px;padding:12px 16px;
font-size:14px;color:var(--muted);cursor:pointer;transition:all .2s;
}
.lang-option:hover{background:var(--green-mist);color:var(--green-deep)}
.lang-option.active{color:var(--green);font-weight:700}
.lang-option .check{width:16px;height:16px;opacity:0;transition:opacity .2s}
.lang-option.active .check{opacity:1}
</style>
</head>
<body>
@@ -749,16 +777,37 @@ a { color: inherit; text-decoration: none; }
<div class="container nav-inner">
<div class="logo" onclick="scrollToTop()">
<div class="logo-mark" id="logoMark"></div>
<div class="logo-text">绿野<span>鲜送</span></div>
<div class="logo-text" data-i18n="logo_text">绿野<span>鲜送</span></div>
</div>
<div class="search-wrap">
<input id="searchInput" class="search-box" type="text" placeholder="搜索餐厅或美食,如 轻食、寿司、奶茶…" autocomplete="off" />
<input id="searchInput" class="search-box" type="text" data-i18n-placeholder="search_placeholder" placeholder="搜索餐厅或美食,如 轻食、寿司、奶茶…" autocomplete="off" />
<button class="search-btn" id="searchBtn" aria-label="搜索"></button>
</div>
<div class="nav-actions">
<button class="nav-cta" onclick="scrollToRestaurants()">
<span id="navCtaIcon"></span> 立即点餐
<span id="navCtaIcon"></span> <span data-i18n="nav_cta">立即点餐</span>
</button>
<div class="lang-switcher" id="langSwitcher">
<button class="lang-btn" id="langBtn" onclick="toggleLangDropdown()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20z"/></svg>
<span id="langLabel">中文</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:12px;height:12px"><polyline points="6 9 12 15 18 9"/></svg>
</button>
<div class="lang-dropdown" id="langDropdown">
<div class="lang-option" data-lang="zh-CN" onclick="switchLang('zh-CN')">
<svg class="check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
<span>简体中文</span>
</div>
<div class="lang-option" data-lang="zh-TW" onclick="switchLang('zh-TW')">
<svg class="check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
<span>繁體中文</span>
</div>
<div class="lang-option" data-lang="en" onclick="switchLang('en')">
<svg class="check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
<span>English</span>
</div>
</div>
</div>
<button class="cart-btn" id="cartBtn" aria-label="购物车">
<span id="cartBtnIcon"></span>
<span class="cart-badge" id="cartBadge">0</span>
@@ -775,26 +824,26 @@ a { color: inherit; text-decoration: none; }
<div class="container">
<div class="hero-card">
<div class="hero-text">
<span class="hero-tag"><span class="dot"></span> 当日鲜配 · 0 防腐剂</span>
<h1 class="hero-title">新鲜好味 <em>·</em> 绿色送达</h1>
<p class="hero-desc">甄选本地优质餐厅,从农场到餐桌的轻盈之旅。低卡轻食、匠心料理,用一份自然的绿意,点亮每一餐。</p>
<span class="hero-tag"><span class="dot"></span> <span data-i18n="hero_tag">当日鲜配 · 0 防腐剂</span></span>
<h1 class="hero-title"><span data-i18n="hero_title_1">新鲜好味</span> <em>·</em> <span data-i18n="hero_title_2">绿色送达</span></h1>
<p class="hero-desc" data-i18n="hero_desc">甄选本地优质餐厅,从农场到餐桌的轻盈之旅。低卡轻食、匠心料理,用一份自然的绿意,点亮每一餐。</p>
<div class="hero-actions">
<button class="btn-primary" onclick="scrollToRestaurants()">
<span id="heroCtaIcon"></span> 开始点餐
<span id="heroCtaIcon"></span> <span data-i18n="hero_cta1">开始点餐</span>
</button>
<button class="btn-ghost" onclick="scrollToCategories()">浏览分类</button>
<button class="btn-ghost" onclick="scrollToCategories()"><span data-i18n="hero_cta2">浏览分类</span></button>
</div>
<div class="hero-stats">
<div class="hero-stat"><div class="num" id="statRest">12+</div><div class="lbl">精选餐厅</div></div>
<div class="hero-stat"><div class="num">30min</div><div class="lbl">平均送达</div></div>
<div class="hero-stat"><div class="num">4.7★</div><div class="lbl">平均评分</div></div>
<div class="hero-stat"><div class="num" id="statRest">12+</div><div class="lbl" data-i18n="stat_restaurants">精选餐厅</div></div>
<div class="hero-stat"><div class="num">30min</div><div class="lbl" data-i18n="stat_delivery">平均送达</div></div>
<div class="hero-stat"><div class="num">4.7★</div><div class="lbl" data-i18n="stat_rating">平均评分</div></div>
</div>
</div>
<div class="hero-visual">
<div class="hero-bowl" id="heroBowl"></div>
<div class="hero-float f1"><span class="ic" id="floatIc1"></span>低卡轻食</div>
<div class="hero-float f2"><span class="ic" id="floatIc2"></span>新鲜直送</div>
<div class="hero-float f3"><span class="ic" id="floatIc3"></span>绿色包装</div>
<div class="hero-float f1"><span class="ic" id="floatIc1"></span><span data-i18n="float_1">低卡轻食</span></div>
<div class="hero-float f2"><span class="ic" id="floatIc2"></span><span data-i18n="float_2">新鲜直送</span></div>
<div class="hero-float f3"><span class="ic" id="floatIc3"></span><span data-i18n="float_3">绿色包装</span></div>
</div>
</div>
</div>
@@ -806,8 +855,8 @@ a { color: inherit; text-decoration: none; }
<div class="section-head">
<div class="section-title">
<span class="kicker">CATEGORIES</span>
<h2>美食分类</h2>
<p>挑你所爱,一键直达心仪风味</p>
<h2 data-i18n="cat_title">美食分类</h2>
<p data-i18n="cat_desc">挑你所爱,一键直达心仪风味</p>
</div>
</div>
<div class="cat-grid" id="catGrid"></div>
@@ -820,10 +869,10 @@ a { color: inherit; text-decoration: none; }
<div class="section-head">
<div class="section-title">
<span class="kicker">FEATURED</span>
<h2>人气推荐</h2>
<p>本月销量领先,大家都在点</p>
<h2 data-i18n="feat_title">人气推荐</h2>
<p data-i18n="feat_desc">本月销量领先,大家都在点</p>
</div>
<a class="link-more" href="javascript:scrollToRestaurants()">查看全部 →</a>
<a class="link-more" href="javascript:scrollToRestaurants()"><span data-i18n="feat_more">查看全部 →</span></a>
</div>
<div class="featured-scroller" id="featuredScroller"></div>
</div>
@@ -835,27 +884,27 @@ a { color: inherit; text-decoration: none; }
<div class="section-head">
<div class="section-title">
<span class="kicker">RESTAURANTS</span>
<h2>全部餐厅</h2>
<p id="listSubtitle">为你找到附近优质好店</p>
<h2 data-i18n="rest_title">全部餐厅</h2>
<p id="listSubtitle" data-i18n="rest_subtitle">为你找到附近优质好店</p>
</div>
</div>
<div class="toolbar">
<div class="sort-group" id="sortGroup">
<button class="sort-btn active" data-sort="">综合</button>
<button class="sort-btn" data-sort="rating">评分</button>
<button class="sort-btn" data-sort="sales">销量</button>
<button class="sort-btn" data-sort="delivery_time">送达</button>
<button class="sort-btn active" data-sort="" data-i18n="sort_comprehensive">综合</button>
<button class="sort-btn" data-sort="rating" data-i18n="sort_rating">评分</button>
<button class="sort-btn" data-sort="sales" data-i18n="sort_sales">销量</button>
<button class="sort-btn" data-sort="delivery_time" data-i18n="sort_delivery">送达</button>
</div>
<button class="chip-clear" id="chipClear">
<span id="chipClearIcon"></span> <span id="chipClearText">清除筛选</span>
<span id="chipClearIcon"></span> <span id="chipClearText" data-i18n="chip_clear">清除筛选</span>
</button>
<div class="result-info">共 <b id="resultCount">0</b> 家餐厅</div>
<div class="result-info"><span data-i18n="result_prefix">共</span> <b id="resultCount">0</b> <span data-i18n="result_suffix">家餐厅</span></div>
</div>
<div id="restListWrap">
<div class="rest-grid" id="restGrid"></div>
</div>
<div class="load-more-wrap" id="loadMoreWrap" style="display:none">
<button class="load-more" id="loadMoreBtn">加载更多</button>
<button class="load-more" id="loadMoreBtn" data-i18n="load_more">加载更多</button>
</div>
</div>
</section>
@@ -869,7 +918,7 @@ a { color: inherit; text-decoration: none; }
<div class="logo-mark" id="footerLogo"></div>
<div class="logo-text">绿野<span>鲜送</span></div>
</div>
<p>新鲜好味,绿色送达。致力于连接本地优质餐厅与健康食材,让每一餐都自然、轻盈、安心。</p>
<p data-i18n="footer_brand_desc">新鲜好味,绿色送达。致力于连接本地优质餐厅与健康食材,让每一餐都自然、轻盈、安心。</p>
<div class="footer-social" style="margin-top:16px">
<a href="javascript:void(0)" aria-label="微信" id="socialWx"></a>
<a href="javascript:void(0)" aria-label="微博" id="socialWb"></a>
@@ -877,30 +926,30 @@ a { color: inherit; text-decoration: none; }
</div>
</div>
<div class="footer-col">
<h4>关于我们</h4>
<a href="javascript:void(0)">品牌故事</a>
<a href="javascript:void(0)">绿色承诺</a>
<a href="javascript:void(0)">加入我们</a>
<a href="javascript:void(0)">联系合作</a>
<h4 data-i18n="footer_about">关于我们</h4>
<a href="javascript:void(0)"><span data-i18n="footer_story">品牌故事</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_green">绿色承诺</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_join">加入我们</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_partner">联系合作</span></a>
</div>
<div class="footer-col">
<h4>帮助中心</h4>
<a href="javascript:void(0)">下单指南</a>
<a href="javascript:void(0)">配送说明</a>
<a href="javascript:void(0)">退款规则</a>
<a href="javascript:void(0)">常见问题</a>
<h4 data-i18n="footer_help">帮助中心</h4>
<a href="javascript:void(0)"><span data-i18n="footer_guide">下单指南</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_delivery_info">配送说明</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_refund">退款规则</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_faq">常见问题</span></a>
</div>
<div class="footer-col">
<h4>商家合作</h4>
<a href="javascript:void(0)">入驻平台</a>
<a href="javascript:void(0)">商家后台</a>
<a href="javascript:void(0)">营销推广</a>
<a href="javascript:void(0)">开放接口</a>
<h4 data-i18n="footer_biz">商家合作</h4>
<a href="javascript:void(0)"><span data-i18n="footer_platform">入驻平台</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_backend">商家后台</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_marketing">营销推广</span></a>
<a href="javascript:void(0)"><span data-i18n="footer_api">开放接口</span></a>
</div>
</div>
<div class="footer-bottom">
<span>© 2026 绿野鲜送 FreshGreen · 用心连接每一份新鲜</span>
<span>新鲜 · 健康 · 自然 · 轻盈</span>
<span>data-i18n="copyright">© 2026 绿野鲜送 FreshGreen · 用心连接每一份新鲜</span>
<span>data-i18n="copyright_slogan">新鲜 · 健康 · 自然 · 轻盈</span>
</div>
</div>
</footer>
@@ -918,7 +967,7 @@ a { color: inherit; text-decoration: none; }
<div class="cart-drawer" id="cartDrawer">
<div class="cart-drawer-head">
<div class="cart-drawer-title">
<span id="drawerTitleIcon"></span> 购物车 <span class="cnt" id="drawerCount"></span>
<span id="drawerTitleIcon"></span> <span data-i18n="drawer_title">购物车</span> <span class="cnt" id="drawerCount"></span>
</div>
<button class="cart-clear" id="cartClearBtn">
<span id="clearIcon"></span> 清空
@@ -936,15 +985,380 @@ a { color: inherit; text-decoration: none; }
</div>
<div class="cart-bar-text" id="cartBarText">
<div class="cart-bar-total"><small>¥</small><span id="cartBarTotal">0</span></div>
<div class="cart-bar-sub" id="cartBarSub">购物车是空的</div>
<div class="cart-bar-sub" id="cartBarSub" data-i18n="cart_empty">购物车是空的</div>
</div>
<button class="cart-checkout" id="cartCheckoutBtn">去结算</button>
<button class="cart-checkout" id="cartCheckoutBtn" data-i18n="cart_checkout">去结算</button>
</div>
<!-- ===== Toast ===== -->
<div class="toast-wrap" id="toastWrap"></div>
<script>
/* =========================================================
i18n 国际化引擎
========================================================= */
const I18N_LOCALES = {
'zh-CN': {
logo_text: '绿野鲜送',
search_placeholder: '搜索餐厅或美食,如 轻食、寿司、奶茶…',
nav_cta: '立即点餐',
hero_tag: '当日鲜配 · 0 防腐剂',
hero_title_1: '新鲜好味',
hero_title_2: '绿色送达',
hero_desc: '甄选本地优质餐厅,从农场到餐桌的轻盈之旅。低卡轻食、匠心料理,用一份自然的绿意,点亮每一餐。',
hero_cta1: '开始点餐',
hero_cta2: '浏览分类',
stat_restaurants: '精选餐厅',
stat_delivery: '平均送达',
stat_rating: '平均评分',
float_1: '低卡轻食',
float_2: '新鲜直送',
float_3: '绿色包装',
cat_title: '美食分类',
cat_desc: '挑你所爱,一键直达心仪风味',
cat_all: '全部',
feat_title: '人气推荐',
feat_desc: '本月销量领先,大家都在点',
feat_more: '查看全部 →',
rest_title: '全部餐厅',
rest_subtitle: '为你找到附近优质好店',
sort_comprehensive: '综合',
sort_rating: '评分',
sort_sales: '销量',
sort_delivery: '送达',
chip_clear: '清除筛选',
result_prefix: '共',
result_suffix: '家餐厅',
load_more: '加载更多',
footer_brand_desc: '新鲜好味,绿色送达。致力于连接本地优质餐厅与健康食材,让每一餐都自然、轻盈、安心。',
footer_about: '关于我们',
footer_story: '品牌故事',
footer_green: '绿色承诺',
footer_join: '加入我们',
footer_partner: '联系合作',
footer_help: '帮助中心',
footer_guide: '下单指南',
footer_delivery_info: '配送说明',
footer_refund: '退款规则',
footer_faq: '常见问题',
footer_biz: '商家合作',
footer_platform: '入驻平台',
footer_backend: '商家后台',
footer_marketing: '营销推广',
footer_api: '开放接口',
copyright: '© 2026 绿野鲜送 FreshGreen · 用心连接每一份新鲜',
copyright_slogan: '新鲜 · 健康 · 自然 · 轻盈',
drawer_title: '购物车',
cart_clear: '清空',
cart_empty: '购物车是空的',
cart_checkout: '去结算',
status_open: '营业中',
status_closed: '休息',
monthly_sales: 't('monthly_sales')',
delivery_time_suffix: t('delivery_time_suffix'),
min_order_prefix: '起送',
delivery_prefix: '配送',
rating_label: '评分',
all_dishes: '全部菜品',
dish_count_suffix: '道',
no_restaurants: '暂无符合条件的餐厅',
no_restaurants_hint: '试试切换分类或调整搜索关键词',
load_failed: '加载失败',
load_failed_hint: '请检查网络后刷新',
cat_load_failed: '分类加载失败',
menu_load_failed: '菜单加载失败',
loading: '加载中…',
preparing_menu: '正在准备菜单…',
no_dishes: '暂无菜品',
no_dishes_hint: '该餐厅还未上架菜品',
added_to_cart: '已加入',
cart_cleared: '购物车已清空',
cart_empty_warn: '购物车还是空的',
switched_restaurant: '已切换餐厅,购物车已更新',
order_success: '下单成功!共',
order_delivery_hint: '预计 30 分钟送达',
subtotal_with_delivery: '合计 (含配送费',
min_order_warn: '还差',
min_order_reached: '满起送价',
from_restaurant: '来自',
delivery_fee_label: '另需配送费',
meets_min_order: '已满起送价',
cart_drawer_empty: '购物车空空如也',
cart_drawer_empty_hint: '快去挑选心仪美食吧',
items_label: '件',
price_per_serving: '/ 份',
current_filter: '当前筛选:',
no_filter: '为你找到附近优质好店',
clear_prefix: '清除:',
clear_all: '清除筛选',
new_total_label: '新合计',
checkout_btn: '去结算',
},
'en': {
logo_text: 'FreshGreen',
search_placeholder: 'Search restaurants or food, e.g. salad, sushi, bubble tea…',
nav_cta: 'Order Now',
hero_tag: 'Same-Day Delivery · Zero Preservatives',
hero_title_1: 'Fresh Taste',
hero_title_2: 'Green Delivery',
hero_desc: 'Curating local quality restaurants for a light farm-to-table journey. Low-calorie meals, artisan dishes — a touch of natural green for every meal.',
hero_cta1: 'Start Ordering',
hero_cta2: 'Browse Categories',
stat_restaurants: 'Top Restaurants',
stat_delivery: 'Avg Delivery',
stat_rating: 'Avg Rating',
float_1: 'Low-Cal Meals',
float_2: 'Fresh Delivery',
float_3: 'Eco Packaging',
cat_title: 'Food Categories',
cat_desc: 'Find what you love, one tap to your favorite flavor',
cat_all: 'All',
feat_title: 'Popular Picks',
feat_desc: 'Top sellers this month, everyone is ordering',
feat_more: 'View All →',
rest_title: 'All Restaurants',
rest_subtitle: 'Quality restaurants near you',
sort_comprehensive: 'Default',
sort_rating: 'Rating',
sort_sales: 'Sales',
sort_delivery: 'Delivery',
chip_clear: 'Clear Filter',
result_prefix: '',
result_suffix: 'restaurants',
load_more: 'Load More',
footer_brand_desc: 'Fresh taste, green delivery. Connecting local quality restaurants and healthy ingredients for a natural, light, and safe meal every time.',
footer_about: 'About',
footer_story: 'Our Story',
footer_green: 'Green Promise',
footer_join: 'Join Us',
footer_partner: 'Contact',
footer_help: 'Help Center',
footer_guide: 'Ordering Guide',
footer_delivery_info: 'Delivery Info',
footer_refund: 'Refund Policy',
footer_faq: 'FAQ',
footer_biz: 'Partners',
footer_platform: 'Join Platform',
footer_backend: 'Merchant Portal',
footer_marketing: 'Marketing',
footer_api: 'Open API',
copyright: '© 2026 FreshGreen · Connecting freshness with care',
copyright_slogan: 'Fresh · Healthy · Natural · Light',
drawer_title: 'Cart',
cart_clear: 'Clear',
cart_empty: 'Cart is empty',
cart_checkout: 'Checkout',
status_open: 'Open',
status_closed: 'Closed',
monthly_sales: 'sales',
delivery_time_suffix: 'min',
min_order_prefix: 'Min',
delivery_prefix: 'Delivery',
rating_label: 'Rating',
all_dishes: 'All Dishes',
dish_count_suffix: '',
no_restaurants: 'No restaurants found',
no_restaurants_hint: 'Try different categories or search keywords',
load_failed: 'Load Failed',
load_failed_hint: 'Please check your network',
cat_load_failed: 'Failed to load categories',
menu_load_failed: 'Failed to load menu',
loading: 'Loading…',
preparing_menu: 'Preparing menu…',
no_dishes: 'No dishes available',
no_dishes_hint: 'This restaurant has no dishes yet',
added_to_cart: 'Added',
cart_cleared: 'Cart cleared',
cart_empty_warn: 'Cart is still empty',
switched_restaurant: 'Restaurant changed, cart updated',
order_success: 'Order placed! Total',
order_delivery_hint: 'Estimated 30 min delivery',
subtotal_with_delivery: 'Total (incl. delivery',
min_order_warn: 'Still need',
min_order_reached: 'to reach minimum',
from_restaurant: 'From',
delivery_fee_label: 'delivery fee',
meets_min_order: 'Minimum met',
cart_drawer_empty: 'Cart is empty',
cart_drawer_empty_hint: 'Pick some delicious food!',
items_label: 'items',
price_per_serving: '/ serving',
current_filter: 'Filtering:',
no_filter: 'Quality restaurants near you',
clear_prefix: 'Clear: ',
clear_all: 'Clear Filter',
new_total_label: 'New total',
checkout_btn: 'Checkout',
},
'zh-TW': {
logo_text: '綠野鮮送',
search_placeholder: '搜尋餐廳或美食,如 輕食、壽司、奶茶…',
nav_cta: '立即點餐',
hero_tag: '當日鮮配 · 0 防腐劑',
hero_title_1: '新鮮好味',
hero_title_2: '綠色送達',
hero_desc: '甄選本地優質餐廳,從農場到餐桌的輕盈之旅。低卡輕食、匠心料理,用一份自然的綠意,點亮每一餐。',
hero_cta1: '開始點餐',
hero_cta2: '瀏覽分類',
stat_restaurants: '精選餐廳',
stat_delivery: '平均送達',
stat_rating: '平均評分',
float_1: '低卡輕食',
float_2: '新鮮直送',
float_3: '綠色包裝',
cat_title: '美食分類',
cat_desc: '挑你所愛,一鍵直達心儀風味',
cat_all: '全部',
feat_title: '人氣推薦',
feat_desc: '本月銷量領先,大家都在點',
feat_more: '查看全部 →',
rest_title: '全部餐廳',
rest_subtitle: '為你找到附近優質好店',
sort_comprehensive: '綜合',
sort_rating: '評分',
sort_sales: '銷量',
sort_delivery: '送達',
chip_clear: '清除篩選',
result_prefix: '共',
result_suffix: '家餐廳',
load_more: '載入更多',
footer_brand_desc: '新鮮好味,綠色送達。致力於連接本地優質餐廳與健康食材,讓每一餐都自然、輕盈、安心。',
footer_about: '關於我們',
footer_story: '品牌故事',
footer_green: '綠色承諾',
footer_join: '加入我們',
footer_partner: '聯繫合作',
footer_help: '幫助中心',
footer_guide: '下單指南',
footer_delivery_info: '配送說明',
footer_refund: '退款規則',
footer_faq: '常見問題',
footer_biz: '商家合作',
footer_platform: '入駐平台',
footer_backend: '商家後台',
footer_marketing: '行銷推廣',
footer_api: '開放接口',
copyright: '© 2026 綠野鮮送 FreshGreen · 用心連接每一份新鮮',
copyright_slogan: '新鮮 · 健康 · 自然 · 輕盈',
drawer_title: '購物車',
cart_clear: '清空',
cart_empty: '購物車是空的',
cart_checkout: '去結算',
status_open: '營業中',
status_closed: '休息',
monthly_sales: '月售',
delivery_time_suffix: '分鐘',
min_order_prefix: '起送',
delivery_prefix: '配送',
rating_label: '評分',
all_dishes: '全部菜品',
dish_count_suffix: '道',
no_restaurants: '暫無符合條件的餐廳',
no_restaurants_hint: '試試切換分類或調整搜尋關鍵詞',
load_failed: '載入失敗',
load_failed_hint: '請檢查網路後重新整理',
cat_load_failed: '分類載入失敗',
menu_load_failed: '菜單載入失敗',
loading: '載入中…',
preparing_menu: '正在準備菜單…',
no_dishes: '暫無菜品',
no_dishes_hint: '該餐廳還未上架菜品',
added_to_cart: '已加入',
cart_cleared: '購物車已清空',
cart_empty_warn: '購物車還是空的',
switched_restaurant: '已切換餐廳,購物車已更新',
order_success: '下單成功!共',
order_delivery_hint: '預計 30 分鐘送達',
subtotal_with_delivery: '合計 (含配送費',
min_order_warn: '還差',
min_order_reached: '滿起送價',
from_restaurant: '來自',
delivery_fee_label: '另需配送費',
meets_min_order: '已滿起送價',
cart_drawer_empty: '購物車空空如也',
cart_drawer_empty_hint: '快去挑選心儀美食吧',
items_label: '件',
price_per_serving: '/ 份',
current_filter: '當前篩選:',
no_filter: '為你找到附近優質好店',
clear_prefix: '清除:',
clear_all: '清除篩選',
new_total_label: '新合計',
checkout_btn: '去結算',
}
};
const LANG_LABELS = {'zh-CN':'中文','en':'EN','zh-TW':'繁中'};
let currentLang = (function(){
try{
var u=new URLSearchParams(location.search).get('lang');
if(u&&I18N_LOCALES[u]) return u;
}catch(e){}
try{var s=localStorage.getItem('lang');if(s&&I18N_LOCALES[s]) return s;}catch(e){}
var b=navigator.language||navigator.userLanguage||'';
if(b.startsWith('zh-TW')||b.startsWith('zh-Hant')) return 'zh-TW';
if(b.startsWith('zh')) return 'zh-CN';
return 'en';
})();
function t(key){return (I18N_LOCALES[currentLang]&&I18N_LOCALES[currentLang][key])||(I18N_LOCALES['zh-CN'][key])||key;}
function applyI18n(){
document.querySelectorAll('[data-i18n]').forEach(function(el){
var key=el.getAttribute('data-i18n');
if(key==='logo_text'){el.innerHTML=t(key);}
else{el.textContent=t(key);}
});
document.querySelectorAll('[data-i18n-placeholder]').forEach(function(el){
var key=el.getAttribute('data-i18n-placeholder');
el.placeholder=t(key);
});
document.querySelectorAll('[data-i18n-title]').forEach(function(el){
var key=el.getAttribute('data-i18n-title');
el.title=t(key);
});
document.documentElement.lang=currentLang==='zh-TW'?'zh-TW':currentLang==='zh-CN'?'zh-CN':'en';
document.getElementById('langLabel').textContent=LANG_LABELS[currentLang]||currentLang;
document.querySelectorAll('.lang-option').forEach(function(opt){
opt.classList.toggle('active',opt.getAttribute('data-lang')===currentLang);
});
}
function switchLang(lang){
if(!I18N_LOCALES[lang]) return;
currentLang=lang;
try{localStorage.setItem('lang',lang);}catch(e){}
/* --- I18N: language change handler --- */
var onLangChange = function(){
data._idx = {}; buildIdx(); updateFilter(); renderCategories(); renderFeatured(); renderRestaurants(true);
var u = currentRest && restaurants[currentRest];
if(u){
restDetailName.textContent = u.name;
restDetailBadge.textContent = t(u.open?'status_open':'status_closed');
restDetailBadge.className = 'badge '+(u.open?'open':'closed');
restDetailRating.textContent = u.rating;
restDetailSales.textContent = t('monthly_sales')+' '+u.monthly_sales;
}
applyI18n();
};
applyI18n();
if(typeof onLangChange==='function') onLangChange(lang);
document.getElementById('langDropdown').classList.remove('open');
}
function toggleLangDropdown(){
document.getElementById('langDropdown').classList.toggle('open');
}
document.addEventListener('click',function(e){
var sw=document.getElementById('langSwitcher');
if(sw&&!sw.contains(e.target)) document.getElementById('langDropdown').classList.remove('open');
});
/* ============================================================
绿野鲜送 — 前端逻辑
============================================================ */
@@ -1194,7 +1608,7 @@ a { color: inherit; text-decoration: none; }
<div class="rest-info">
<div class="rest-head">
<div class="rest-name">${escapeHtml(r.name)}</div>
<div class="rest-status ${open ? 'open' : 'closed'}">${open ? '营业中' : '休息'}</div>
<div class="rest-status ${open ? 'open' : 'closed'}">${open ? t('status_open') : t('status_closed')}</div>
</div>
<div class="rest-cat">${escapeHtml(r.category_name || '美食')}</div>
${tags.length ? `<div class="rest-tags">${tags.map(t => `<span class="t">${escapeHtml(t)}</span>`).join('')}</div>` : ''}