A continuation of Janady13/crawler-signal-reference / framework-html-meta-content-language.md. The complete source identity, every recorded occurrence, and linked equations are on its first page.
Source transcript · continued
Download complete source text ↓1,822 lines · 57.7 KB
21. [ ] Marshallese pages: `<html lang="mh">`.
22. [ ] hreflang reciprocity en-US and mh.
23. [ ] x-default points to English.
24. [ ] UTF-8 chain verified end to end (per framework-html-meta-charset.md).
25. [ ] Mixed content sections have `lang="mh"` on Marshallese elements.
### Federal subcontractor
26. [ ] If multi language required: full hreflang implementation.
27. [ ] BCP 47 codes correctly formatted.
28. [ ] Documentation per contract requirements.
### Browser and accessibility
29. [ ] Screen readers correctly identify document language.
30. [ ] Spell check applies appropriate language rules.
31. [ ] Font rendering appropriate for language.
### Tooling and process
32. [ ] `language-audit.sh` script in `/usr/local/bin/`.
33. [ ] Pre deploy check verifies html lang present.
34. [ ] Pre deploy check verifies no deprecated http-equiv.
### Documentation
35. [ ] Per client language decision documented in project notes.
A site that passes all 35 has correctly configured language signaling for browsers, search engines, accessibility tools, and (where applicable) multi language audiences.
---
## 17. COMMON PITFALLS
Thirteen patterns to recognize and avoid.
**Pitfall 1: Missing `<html lang>` attribute.**
Symptom: page renders but no language signal for browsers or search engines.
Why it breaks: html lang is the primary signal.
Fix: add `<html lang="en-US">` (or appropriate BCP 47).
**Pitfall 2: Using deprecated http-equiv instead of html lang.**
Symptom: page has `<meta http-equiv="content-language" content="en-US">` but no html lang.
Why it breaks: Google ignores the meta since 2010.
Fix: replace with `<html lang="en-US">`.
**Pitfall 3: Both http-equiv meta and html lang present.**
Symptom: redundant signals.
Why it breaks: no harm but legacy CMS smell.
Fix: remove the meta tag; keep html lang.
**Pitfall 4: Wrong BCP 47 format.**
Symptom: `en_US` (underscore) instead of `en-US` (hyphen).
Why it breaks: BCP 47 uses hyphens; underscores invalid.
Fix: use hyphens.
**Pitfall 5: Just `en` without region.**
Symptom: `<html lang="en">` without region.
Why it breaks: less specific; may produce regional mismatches.
Fix: use `en-US` for US-based content.
**Pitfall 6: Mismatch between html lang and HTTP Content-Language.**
Symptom: html says `en-US`, HTTP says `es`.
Why it breaks: conflicting signals.
Fix: align both.
**Pitfall 7: Multi language site without hreflang.**
Symptom: English and Spanish versions exist but no hreflang links.
Why it breaks: Google can't determine which version is for which audience.
Fix: add reciprocal hreflang links.
**Pitfall 8: hreflang without reciprocity.**
Symptom: English page lists Spanish; Spanish page doesn't list English.
Why it breaks: Google requires bidirectional confirmation.
Fix: each version must list all others.
**Pitfall 9: Marshallese content untagged within English page.**
Symptom: `<p>Yokwe!</p>` (Marshallese text) inside English page without `lang="mh"`.
Why it breaks: screen reader pronounces with English rules.
Fix: `<p lang="mh">Yokwe!</p>`.
**Pitfall 10: Inconsistent language across same language pages.**
Symptom: homepage `<html lang="en-US">`; about page `<html lang="en">`; services page `<html lang="en-US">`.
Why it breaks: fragmented signal.
Fix: standardize to one canonical code (typically `en-US` for US clients).
**Pitfall 11: WordPress migration left http-equiv tag.**
Symptom: hand coded Bubbles site has WordPress era meta http-equiv.
Why it breaks: stale tag; signals WordPress legacy via Wappalyzer.
Fix: remove during migration cleanup.
**Pitfall 12: hreflang URL doesn't match canonical.**
Symptom: hreflang says `https://example.com/es/` but canonical says `https://example.com/es/page/`.
Why it breaks: Google may use wrong canonical.
Fix: align hreflang URL with canonical URL.
**Pitfall 13: UTF-8 chain broken for Marshallese.**
Symptom: Marshallese characters render as mojibake despite `lang="mh"`.
Why it breaks: lang attribute doesn't fix encoding.
Fix: ensure full UTF-8 chain per framework-html-meta-charset.md.
---
## 18. DIAGNOSTIC COMMANDS
Reference of commands useful for language signaling investigation.
### Inspect a single URL
```bash
# Get html lang attribute
curl -s https://example.com/ | grep -oE '<html[^>]+lang="[^"]+"' | head -1
# Get meta http-equiv content-language (should be absent)
curl -s https://example.com/ | grep -c 'meta http-equiv="content-language"'
# Get hreflang
curl -s https://example.com/ | grep -oE 'link rel="alternate" hreflang="[^"]+"' | head -5
# Get HTTP Content-Language header
curl -sI https://example.com/ | grep -i "content-language"
```
### Verify reciprocity
```bash
# For multi language sites, verify each version lists all others
for url in https://example.com/ https://example.com/es/ https://example.com/mh/; do
echo "=== $url ==="
HREFLANGS=$(curl -s "$url" | grep -oE 'hreflang="[^"]+"' | sort -u)
echo "$HREFLANGS"
echo ""
done
```
### Find deprecated http-equiv tags
```bash
# Across all client sites
for site_dir in /var/www/sites/*/; do
SITE=$(basename "$site_dir")
INDEX="$site_dir/index.html"
if [ -f "$INDEX" ]; then
if grep -q 'meta http-equiv="content-language"' "$INDEX"; then
echo "DEPRECATED TAG: $SITE"
grep 'meta http-equiv="content-language"' "$INDEX" | head -1
fi
fi
done
```
### Bulk audit
```bash
language-audit.sh
```
### Lighthouse SEO audit
```bash
# Lighthouse checks for html lang attribute
lighthouse https://example.com/ \
--only-audits=document-has-html-lang,html-has-lang \
--output=json --output-path=/tmp/lh.json --quiet
python3 -c "
import json
with open('/tmp/lh.json') as f:
data = json.load(f)
for audit_id, audit in data.get('audits', {}).items():
if 'lang' in audit_id:
print(f'{audit_id}: {audit.get(\"score\")} - {audit.get(\"title\")}')
"
```
### Google Search Console verification
For multi language sites, use Search Console > International Targeting report:
* Confirms hreflang implementation.
* Shows any reciprocity errors.
* Lists language/region targeting.
### Browser verification
In Chrome DevTools:
1. Open the page.
2. Console: `document.documentElement.lang`.
3. Should return the html lang value.
For accessibility:
* Use ChromeVox extension or similar.
* Verify screen reader announces page language.
* Verify language switches are detected.
### After language changes
```bash
nginx -t && systemctl reload nginx
systemctl restart fastapi-sidecar
# Verify
language-audit.sh
```
---
## 19. CROSS-REFERENCES
* [framework-http-content-headers.md](framework-http-content-headers.md): the HTTP `Content-Language:` response header is the canonical server side layer for language signaling.
* [framework-html-meta-charset.md](framework-html-meta-charset.md): UTF-8 chain is critical for languages with special characters (Marshallese-Voices case study in both frameworks).
* [framework-html-meta-description.md](framework-html-meta-description.md): description per language; Marshallese-Voices respectful local context.
* [framework-html-meta-viewport.md](framework-html-meta-viewport.md): order in head.
* [framework-html-meta-color-scheme.md](framework-html-meta-color-scheme.md): order in head.
* [framework-html-meta-referrer.md](framework-html-meta-referrer.md): order in head.
* [UNIVERSAL-RANKING-FRAMEWORK.md](UNIVERSAL-RANKING-FRAMEWORK.md): language and international targeting are part of the broader ranking framework.
* [SEO-BUILD-REFERENCE.md](SEO-BUILD-REFERENCE.md) v2.4: the build playbook including language signaling per client.
* W3C HTML5 lang attribute: https://www.w3.org/TR/html52/dom.html#the-lang-and-xml-lang-attributes
* Google deprecation announcement (2010): https://developers.google.com/search/blog/2010/03/working-with-multilingual-websites
* Google Search Central on language targeting: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites
* MDN meta http-equiv=content-language: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
* IETF BCP 47: https://tools.ietf.org/html/bcp47
* IANA Language Subtag Registry: https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
* W3C Internationalization on language tags: https://www.w3.org/International/articles/language-tags/
* Marshallese language (Wikipedia): https://en.wikipedia.org/wiki/Marshallese_language
---
## APPENDIX A: ONE PAGE QUICK REFERENCE
For the person who just wants the answer.
### The Bubbles rule
**Use `<html lang="en-US">` (or appropriate BCP 47). Skip `<meta http-equiv="content-language">`. Use hreflang for multi language sites.**
### The canonical patterns
```html
<!-- Standard single language (most Bubbles clients) -->
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<!-- ... no http-equiv content-language ... -->
</head>
```
```html
<!-- Multi language (Marshallese-Voices pattern) -->
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<link rel="alternate" hreflang="en-US" href="https://example.com/">
<link rel="alternate" hreflang="mh" href="https://example.com/mh/">
<link rel="alternate" hreflang="x-default" href="https://example.com/">
</head>
```
### The forbidden pattern (legacy)
```html
<!-- Deprecated by Google in 2010; redundant with html lang -->
<meta http-equiv="content-language" content="en-US">
```
### Five rules to memorize
1. **`<html lang="en-US">` (or other BCP 47) on every page.**
2. **Skip `<meta http-equiv="content-language">` (Google deprecated 2010).**
3. **Use BCP 47 format with hyphen (`en-US` not `en_US`).**
4. **Multi language: hreflang reciprocity + x-default.**
5. **Mixed language sections: `lang="..."` on the specific elements.**
### Five commands every operator should know
```bash
# 1. Check html lang
curl -s URL | grep -oE '<html[^>]+lang="[^"]+"' | head -1
# 2. Check for deprecated tag (should be 0)
curl -s URL | grep -c 'meta http-equiv="content-language"'
# 3. Check hreflang
curl -s URL | grep -oE 'rel="alternate" hreflang="[^"]+"'
# 4. Audit across all sites
language-audit.sh
# 5. Apply changes
nginx -t && systemctl reload nginx
```
### Three end to end tests
```bash
# 1. html lang present and valid BCP 47
URL=https://example.com/
LANG=$(curl -s "$URL" | grep -oE '<html[^>]+lang="[^"]+"' | head -1 | sed 's/.*lang="\([^"]*\)".*/\1/')
if [[ "$LANG" =~ ^[a-z]+(-[A-Z]+)?$ ]]; then
echo "OK: lang=$LANG (valid BCP 47)"
else
echo "FAIL: lang=$LANG (invalid or missing)"
fi
# 2. No deprecated http-equiv
HAS_LEGACY=$(curl -s "$URL" | grep -c 'meta http-equiv="content-language"')
[ "$HAS_LEGACY" = "0" ] && echo "OK: no deprecated tag" || echo "FAIL: $HAS_LEGACY legacy tags"
# 3. For multi language: hreflang reciprocity verified
# (Manual check; see Section 18)
```
If all three pass AND screen reader correctly identifies language AND search engines correctly classify content by language, the language signaling layer is correctly wired.
---
End of framework-html-meta-content-language.md.