中英文网站切换,说到底是让同一套业务内容有两种语言入口,并且这两个入口都能被直接打开、被搜索引擎收录、被用户记住。最稳的做法不是在前端点一下按钮就替换文字,而是给每种语言一个独立 URL。Google 搜索中心在多语言站点指南里写得很清楚:不同语言版本要有独立 URL,再用 hreflang 互相标注。比如 www.example.com/zh/ 和 www.example.com/en/,或者 cn.example.com 和 www.example.com。路径方式最常见,权重集中,维护也简单;子域名适合地区差异大、团队分开运营的情况;独立域名适合强本地化,但权重会分散,成本也高。
URL 定了,接着是语言识别。用户第一次进来,浏览器会带 Accept-Language 请求头,里面像 zh-CN,zh;q=0.9,en;q=0.8。服务端或边缘函数可以读这个头,决定跳不跳。但别强行跳,尤其别把用户锁死在一个语言里。常见做法是默认语言放根路径,其他语言放 /en/;用户手动切过之后,用 cookie 或 localStorage 记住选择,下次优先用记住的。这里有个细节,如果服务端根据 Accept-Language 返回不同内容,缓存要加 Vary: Accept-Language,不然 CDN 可能把中文页面发给英文用户。如果按 URL 区分语言,缓存反而简单,直接按路径缓存。
前端翻译层,React 项目常用 react-i18next、next-intl,Vue 用 vue-i18n,Next.js 自己也有国际化路由。翻译文件按语言拆成 zh-CN.json、en.json,键名统一,别在组件里写死中文。日期、货币、数字格式用 Intl.DateTimeFormat、Intl.NumberFormat,这些是浏览器原生 API,比手写格式化靠谱。HTML 根元素要写 lang,比如 ,英文页写 。语言代码别自己编,用 BCP 47,像 zh-CN、zh-TW、en、en-US,RFC 5646 就是干这个的。写错了,屏幕阅读器和搜索引擎都可能理解偏。
切换器本身也有讲究。最好用 链接直接指向对应语言 URL,而不是
后端和数据库这块,别把中文英文硬塞进同一字段。常见做法是主表存 ID、状态、图片,翻译表存 language_code、title、content,或者用 JSON 字段存多语言。查询时按当前语言取,取不到就回退默认语言。CMS 里 WordPress 用 WPML、Polylang,Drupal 有 Language 模块,Shopify 用 Markets,这些工具已经处理了 URL、hreflang 和切换逻辑。自己开发的话,接口要带 Accept-Language 或 lang 参数,返回对应语言,同时把语言写进响应头 Content-Language。

最后别忽略测试。打开中文页,看 canonical 是不是指向自己,hreflang 有没有 en 和 x-default;打开英文页,看 lang 属性、标题、描述是不是英文;用 Search Console 看 hreflang 相关错误和索引情况;用 curl -I 看 Vary 和 Content-Language。百度这边虽然对 hreflang 的依赖没 Google 那么重,但独立 URL、语言标注、sitemap 一样不能少。中英文切换不是翻译完就结束,它是一套 URL、缓存、SEO、前端状态一起配合的工程。把这几个点做顺,用户切得自然,搜索引擎也看得明白。