Going bilingual roughly doubles your content cost and your SEO surface, but it can also double your distribution. The right call depends on what you can sustain week after week, and on whether you set URL structure, hreflang, and sitemaps correctly on day one. Get the technical layer wrong and the second language drags down the first instead of adding to it.
TL;DR
- Default to one language. Ship 100 quality articles in the language you write fastest before you touch the second.
- Bilingual is for reach, not for ad math. US English page RPM sits around $10 CPM with $0.61 CPC; China is roughly $0.11 CPC (Google AdSense rates, 2026). A Chinese audience can be 5-6x less valuable per pageview.
- Plan
/en/and/zh/URLs from article one. Retrofitting a language segment onto flat URLs is a permanent migration headache. - hreflang must be reciprocal. If page A points to B but B does not point back to A, Google ignores the tag entirely (Google: localized versions).
- Never ship raw machine translation. Google’s quality systems detect it and can suppress rankings across both language versions, not just the translated one.
Who this is for
For Chinese-speaking builders aiming at a global audience, the bilingual question shows up in week one. The naive answer is “do both,” but writing 500 articles is hard enough in one language. The honest answer: pick the language you produce best in, ship 100 solid articles, then decide whether to add the second. The decision is half editorial and half technical, and most people only think about the editorial half.
The five-point go/no-go test
Go bilingual only if you can answer yes to most of these:
- You write at native-fluency speed in both languages without leaning on a translation model for the first draft. If one language runs more than 1.5x slower, it is not a co-equal language for the site.
- The topic has comparable demand in both markets. Check Google Keyword Planner / Trends for EN and Baidu Index or Bing Webmaster for ZH. Search intent on the same topic can differ 10x between markets.
- You have editorial capacity for ~2x the work. Editing a translation to human quality costs nearly as much as writing the original; budget 2x, not 1.5x.
- Your monetization survives the lower-value market. Chinese AdSense RPM is a fraction of US English (see the CPM table below), so the second language must earn its keep through reach, affiliate, or product referrals.
- You can maintain hreflang pairs, two sitemaps, and split analytics for the life of the site, not just at launch.
The revenue gap in one table
The single biggest reason “just do both” fails is that not every pageview is worth the same. Approximate Google AdSense figures, 2026:
| Market | Typical CPC | Page RPM range | Relative value |
|---|---|---|---|
| US (English) | ~$0.61 | ~$8-12 | 1.0x (baseline) |
| UK / Canada / Australia (English) | ~$0.50-0.57 | ~$5-9 | ~0.7x |
| China (Chinese) | ~$0.11 | ~$1-3 | ~0.2x |
A bilingual site is worth it when the Chinese half buys you reach (links, shares, app installs, mailing-list signups) that the English half cannot reach on its own. It is rarely worth it for the AdSense math alone.
Quick verdict
Start with one language unless you can write fluently in both and have validated demand on both sides. Add the second language only after the first has clear product-market fit, and only with the URL structure below already in place so the addition is non-breaking.
Before you start
- Confirm your real writing speed in each language with a back-to-back test, not optimism.
- Decide URL structure first — bilingual built on top of single-language URLs is a forever-painful migration.
- Set Search Console and Analytics up to support either path before you commit.
Step by step
-
Audit your writing speed. Draft two 1500-word articles back to back, one per language, untimed-but-honest. Whichever takes more than 1.5x the other should not be your first language for the site.
-
Validate demand separately. Use a keyword tool on each market — Google for EN, Baidu Index or Bing Webmaster for ZH. Same topic can have 10x asymmetric demand.
-
Pick the URL structure before writing a single article. The recommended layout for Astro is:
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
This gives you /en/articles/foo/ and /zh/articles/foo/. Google treats them as separate URLs and only links them through hreflang, so the language segment has to exist from the first commit.
- Configure i18n in
astro.config.mjs. Set the canonical site and the trailing-slash policy once, globally. WithprefixDefaultLocale: true, every URL gets a language prefix including the default, so EN lives at/en/...and not at the bare root. That symmetry is what makes the hreflang and sitemap logic below trivial:
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' },
},
}),
],
});
- Wire hreflang pairs in your layout so EN and ZH versions reference each other. In
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/')}`} />
The x-default should point at the EN version unless your primary audience is Chinese. Two rules Google enforces strictly: every page must list itself plus all alternates (self-referencing), and the relationship must be reciprocal. If /en/foo/ points to /zh/foo/ but /zh/foo/ does not point back, Google drops the annotation entirely. Emitting both links from one shared layout, as above, is how you guarantee reciprocity without hand-editing files.
Sitemap hreflang, HTML <link> hreflang, and HTTP-header hreflang are all equivalent to Google. Pick one method and do not mix them, or you risk conflicting signals. This guide uses the HTML-head method for the page itself plus sitemap annotations as a backstop.
- Generate per-language sitemaps and an index. Output structure:
<!-- /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>
Each per-language sitemap entry should include hreflang annotations:
<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>
- Verify a published pair end-to-end. After deploy:
curl -s https://yourdomain.com/en/articles/foo/ | grep -E 'hreflang|canonical'
curl -s https://yourdomain.com/zh/articles/foo/ | grep -E 'hreflang|canonical'
# both should self-canonical and reference the other language
-
Add EN and ZH as separate properties in Search Console. Use the Domain property for the whole site, then add two URL-prefix properties for
https://yourdomain.com/en/andhttps://yourdomain.com/zh/so you can compare query data without pollution. -
Re-evaluate at article 100. If the second language is dragging output below your minimum cadence, pause it cleanly with
noindex,followrather than deleting:
{frontmatter.lang === 'zh' && pauseZh && (
<meta name="robots" content="noindex,follow" />
)}
Implementation checklist
- URL structure includes a language segment from day one — no retrofitting.
- hreflang pairs are emitted from layout, not edited per file.
- Per-language sitemaps + an index sitemap are submitted to Search Console.
- EN and ZH are separate URL-prefix properties in Search Console.
- Analytics events include a
langdimension so reports can split.
After-launch verification
- Search Console → Coverage: EN and ZH should each show their own indexed counts.
- URL Inspection on a sample article in each language should show the other version as an “alternate page with proper canonical tag”.
- Sitemap index status is “Success” in Search Console for both per-language sitemaps.
curltest confirmshreflangself-reference + cross-reference is present.
Common pitfalls
- Shipping raw machine translation. Google’s quality systems detect unedited machine output and can suppress rankings across both language versions, not just the translated one. The fix is a human editing pass on every translated article. A better model is not a substitute. If you genuinely must publish machine-translated pages, label them honestly with a BCP-47 tag like
lang="en-x-mtfrom-zh"so search engines treat them as machine-translated content. - One URL with a cookie-based language toggle. Google sees a single URL and only the language served to its crawler gets indexed; the other language is effectively invisible. Always use separate URLs per language.
- Missing or broken hreflang. Without reciprocal hreflang, the two versions get treated as competing duplicates. Detection: Search Console reports “Duplicate, Google chose different canonical” between an EN and ZH URL. Validate in the International Targeting report.
- Splitting an already-thin internal-link graph. Keep cross-links explicit. Each article carries a “Related” block in its own language, written for that language, not a literal translation of the other side’s links.
- Budgeting bilingual at 1.5x. Once you count editing and ongoing SEO maintenance it lands closer to 2x. Plan for 2x or the second language will quietly starve the first.
- Forgetting
<html lang="...">. A missing or wrong lang attribute confuses screen readers and Google’s language detection. Set it per page from your layout.
FAQ
- Can I start English-only and add Chinese later?: Yes, and it is usually the right path. Add Chinese once the English site has stable traffic and you know which topics work. Plan the URL structure with
/en/from article one so adding/zh/is non-breaking. - Does Google penalize bilingual sites?: No. With correct reciprocal hreflang and human-quality content, bilingual is fine. What Google penalizes is unedited machine translation, and that penalty can hit both language versions at once.
- Should I use subdomains or subfolders?: Subfolders (
/en/,/zh/) are easier to manage and share one domain’s authority. Use subdomains only with a real operational reason to separate, such as different hosting or teams. - Is bilingual worth it for AdSense revenue?: Rarely on its own. US English page RPM runs roughly $8-12 CPM versus China’s ~$1-3 (2026 AdSense figures), so a Chinese pageview is worth a fraction of an English one. Bilingual pays off through reach, links, and product referrals, not ad math.
- Should I use
zhorzh-CN/zh-Hansin hreflang?: Use plainzhif you serve one written form. If you split Simplified and Traditional, usezh-Hansandzh-Hant(script subtags) rather than region codes likezh-CNandzh-TW, since the difference is the script, not the country. - Where should the language switcher go?: Header or footer, using anchor tags whose targets match your hreflang URLs. Do not auto-redirect by browser language; it confuses crawlers and forces re-indexing on every visit.
Related
- When it makes sense to add a second language
- How to pick a niche that has search demand
- Should a new content site go broad or deep first
- hreflang explained for bilingual sites
- Subdomain vs subdirectory
- Content Site Competitor Analysis Before You Build
- Content Site Monetization Paths: Ads, Affiliates, Products
Tags: #Indie dev #Website planning #Bilingual #hreflang #SEO