上双语,内容成本和 SEO 工作量大致都翻倍,但触达也可能翻倍。选不选,取决于你能不能周复一周地撑下来,以及第一天有没有把 URL 结构、hreflang 和 sitemap 这套技术底子搭对。技术层搭错,第二语言不是加分,而是拖累第一语言。
一句话总结
- 默认只做一种语言。 先用你写得最快的那一种扎扎实实出 100 篇,再碰第二种。
- 双语是为触达,不是为广告账。 美国英文页面 RPM 约 $10 CPM、CPC 约 $0.61;中国大约 $0.11 CPC(Google AdSense,2026 年)。同样一次浏览,中文受众的价值可能只有英文的五分之一到六分之一。
- 第一篇就规划
/en/和/zh/URL。 在扁平 URL 上事后补语言段,是永久性的迁移噩梦。 - hreflang 必须互指。 A 指向 B,但 B 不指回 A,Google 会直接忽略这个标注(Google:本地化版本说明)。
- 绝不直接发机器翻译。 Google 的质量系统能识别,而且可能同时压低两种语言版本的排名,不只是被翻译那一篇。
适合谁看
对面向全球的中文开发者来说,双语问题第一周就会冒出来。朴素答案是”两个都做”,可写 500 篇单语言已经够难了。诚实答案是:先选你能写得最好的那一种,扎实写出 100 篇,再决定要不要加第二种。这个决定一半在编辑层面、一半在技术层面,而大多数人只想到了编辑那一半。
五点 go/no-go 判断
下面几条多数能答”是”,再考虑双语:
- 两种语言都能母语级速度产出,初稿不靠翻译模型。如果一种慢过另一种 1.5 倍以上,它就不该作为站点的并列主语言。
- 题材在两个市场需求相当。EN 用 Google Keyword Planner / Trends,ZH 用 Baidu Index 或 Bing Webmaster。同一题目两边的搜索意图可能差 10 倍。
- 有承担约 2 倍工作量的编辑余力。把翻译改到人写质量,成本几乎等于重写一遍,按 2 倍预算,别按 1.5 倍。
- 变现能扛住更低价值的那个市场。中文 AdSense RPM 只是美国英文的零头(见下方表格),所以第二语言必须靠触达、联盟或产品推广来回本。
- 能长期维护 hreflang 配对、双 sitemap、双 Analytics——是整站生命周期,不是只在上线那阵子。
一张表看清收入差
“两个都做”之所以经常失败,最大的原因是:不是每次浏览都值同样的钱。Google AdSense 近似数据,2026 年:
| 市场 | 典型 CPC | 页面 RPM 区间 | 相对价值 |
|---|---|---|---|
| 美国(英文) | 约 $0.61 | 约 $8-12 | 1.0x(基准) |
| 英 / 加 / 澳(英文) | 约 $0.50-0.57 | 约 $5-9 | 约 0.7x |
| 中国(中文) | 约 $0.11 | 约 $1-3 | 约 0.2x |
双语真正值的时候,是中文那一半帮你换来英文那半够不到的触达——外链、转发、App 安装、邮件订阅。单纯算 AdSense 账,它很少划算。
快速结论
除非你两种语言都能写、而且两个市场的需求都验证过,否则只做一种。等第一种语言跑出明确的产品市场契合度再加第二种,而且要在下面这套 URL 结构已经就位的前提下加,扩展才不会破坏现有结构。
开始前准备
- 用背靠背试写来评估你两种语言的真实写作速度,别凭乐观。
- 第一天就把 URL 结构定好——单语言改双语的迁移成本极高。
- Search Console 和 Analytics 提前按双语形态规划好。
实操步骤
-
评估写作速度。 连续写两篇 1500 字的文章,分别用两种语言,老实计时。超出 1.5 倍那一边,就不该作为站点的主语言。
-
分别验证需求。 用关键词工具查两个市场——Google 看 EN,Baidu Index 或 Bing Webmaster 看 ZH。同一个话题需求差 10 倍是常态。
-
写第一篇之前先定 URL 结构。 Astro 推荐布局:
src/pages/en/articles/[...slug].astro
src/pages/zh/articles/[...slug].astro
src/content/articles/en/<category>/<slug>.mdx
src/content/articles/zh/<category>/<slug>.mdx
输出 /en/articles/foo/ 和 /zh/articles/foo/。Google 把它们视为两个独立 URL,只靠 hreflang 把它们关联起来,所以语言段必须从第一个 commit 就存在。
- 在
astro.config.mjs配 i18n。 全局只配一次 site 和 trailing slash。设prefixDefaultLocale: true后,所有 URL 都带语言前缀(包括默认语言),EN 落在/en/...而不是裸根目录。正是这种对称,让下面的 hreflang 和 sitemap 逻辑变得简单:
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://yourdomain.com',
trailingSlash: 'always',
build: { format: 'directory' },
i18n: {
defaultLocale: 'en',
locales: ['en', 'zh'],
routing: { prefixDefaultLocale: true },
},
integrations: [
sitemap({
i18n: {
defaultLocale: 'en',
locales: { en: 'en-US', zh: 'zh-CN' },
},
}),
],
});
- layout 里写 hreflang 配对,让 EN 和 ZH 互指。
ArticleLayout.astro里:
---
const { translationKey, lang } = Astro.props.article;
const site = Astro.site.toString().replace(/\/$/, '');
const path = Astro.url.pathname;
const otherLang = lang === 'en' ? 'zh' : 'en';
const otherPath = path.replace(`/${lang}/`, `/${otherLang}/`);
---
<link rel="canonical" href={`${site}${path}`} />
<link rel="alternate" hreflang={lang} href={`${site}${path}`} />
<link rel="alternate" hreflang={otherLang} href={`${site}${otherPath}`} />
<link rel="alternate" hreflang="x-default" href={`${site}${path.replace(`/${lang}/`, '/en/')}`} />
x-default 一般指向 EN 版本,除非你的主受众是中文。Google 严格执行两条规则:每个页面必须列出自身加上全部备选版本(自指),而且关系必须互指。如果 /en/foo/ 指向 /zh/foo/,但 /zh/foo/ 不指回来,Google 会把整条标注丢掉。像上面那样从同一个共享 layout 发出两条链接,就能保证互指,不用逐文件手改。
sitemap 里的 hreflang、HTML <link> 的 hreflang、HTTP 头里的 hreflang,对 Google 是等价的。选一种方式,别混用,否则信号会打架。本文用 HTML head 方式做页面本身,再用 sitemap 标注兜底。
- 分语言 sitemap + 一个索引 sitemap。 输出结构:
<!-- /sitemap-index.xml -->
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://yourdomain.com/sitemap-en.xml</loc></sitemap>
<sitemap><loc>https://yourdomain.com/sitemap-zh.xml</loc></sitemap>
</sitemapindex>
每个分语言 sitemap 里的 URL 都带 hreflang 标注:
<url>
<loc>https://yourdomain.com/en/articles/foo/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://yourdomain.com/en/articles/foo/" />
<xhtml:link rel="alternate" hreflang="zh" href="https://yourdomain.com/zh/articles/foo/" />
</url>
- 上线后端到端验证。 部署完:
curl -s https://yourdomain.com/en/articles/foo/ | grep -E 'hreflang|canonical'
curl -s https://yourdomain.com/zh/articles/foo/ | grep -E 'hreflang|canonical'
# 两边都应该 self-canonical 并互指另一种语言
-
Search Console 里 EN 和 ZH 分别建 property。 Domain property 管整站,然后再加两个 URL-prefix property——
https://yourdomain.com/en/和https://yourdomain.com/zh/——查询数据就不会混。 -
写到 100 篇时复盘。 如果第二语言把节奏拖到目标线以下,用
noindex,follow优雅暂停,不要直接删:
{frontmatter.lang === 'zh' && pauseZh && (
<meta name="robots" content="noindex,follow" />
)}
执行检查清单
- URL 第一天就带语言段,永远不要事后补改。
- hreflang 由 layout 统一发,不在每个文件里手写。
- 分语言 sitemap + 索引 sitemap 都已提交 Search Console。
- EN 和 ZH 在 Search Console 是独立 URL-prefix property。
- Analytics 事件带
lang维度,报告可分语言切。
上线后验证
- Search Console → Coverage:EN 和 ZH 应各自有独立 indexed 数。
- 对每种语言抽一篇 URL Inspection——另一语言版本应显示为 “alternate page with proper canonical tag”。
- 两个分语言 sitemap 在 Search Console 都是 Success。
curl测试确认hreflangself + cross 都齐。
容易踩的坑
- 直接发未编辑的机器翻译。 Google 的质量系统能识别未经修改的机翻,而且可能同时压低两种语言版本的排名,不只是被翻译那一篇。修法是每篇都过一遍人工编辑,换更好的模型不能替代。如果确实必须发机翻页面,就用
lang="en-x-mtfrom-zh"这类 BCP-47 标签如实标注,让搜索引擎按机器翻译内容对待。 - 一个 URL + cookie 切换语言。 Google 只看到一个 URL,只有发给爬虫的那种语言被收录,另一种实际隐形。永远按语言分 URL。
- hreflang 缺失或不互指。 没有互指的 hreflang,两个版本会被当成互相竞争的重复页。表现:Search Console 报 “Duplicate, Google chose different canonical”,出现在一对 EN 和 ZH URL 之间。用 International Targeting 报告验证。
- 本来就稀薄的内链图被劈成两半。 内链要显式给。每篇带自己语言的”相关阅读”,为这种语言而写,不是另一边链接的直译。
- 按 1.5 倍估双语工作量。 算上编辑和长期 SEO 维护,实际接近 2 倍。按 2 倍规划,否则第二语言会悄悄饿死第一语言。
- 忘了
<html lang="...">。 lang 属性缺失或写错,读屏软件和 Google 语言识别都会出错。从 layout 里按页面逐个设好。
FAQ
- 能不能先英文,后加中文: 可以,而且通常是对的路。等英文站有稳定流量、确定哪些题目能打之后再加中文。第一篇就规划好
/en/,后面加/zh/才是无破坏的扩展。 - Google 会惩罚双语站吗: 不会。只要 hreflang 互指正确、内容是人写的,双语没问题。Google 惩罚的是未编辑的机器翻译,而且这个惩罚可能同时打到两种语言版本。
- 该用子域名还是子目录: 子目录(
/en/、/zh/)好管理,共用同一个域名的权重。除非运营上确有理由分开(比如不同托管或不同团队),否则别用子域名。 - 为了 AdSense 收入值得做双语吗: 多数情况不值。美国英文页面 RPM 约 $8-12 CPM,中国约 $1-3(2026 年 AdSense 数据),一次中文浏览的价值只是英文的零头。做双语是靠触达、外链和产品推广回本,不是靠广告账。
- hreflang 该写
zh还是zh-CN/zh-Hans: 只供应一种书写形式就写zh。如果区分简体和繁体,用zh-Hans和zh-Hant(字形子标签),而不是zh-CN、zh-TW这类地区码——差异在字形,不在国家。 - 语言切换按钮放哪: header 或 footer,用 a 标签,其目标地址要和 hreflang 的 URL 一致。不要按浏览器语言自动跳转——爬虫会困惑,每次访问都被迫重新索引。