# Okhp3 I18N Page Sync

> Detect which pages on a static site are missing a translation, or have a translation that has fallen behind a changed English source, by reusing the site's own generated search index as the page inventory. Reports drift and names the exact-pair okhp3-translation-en-us-<pair> skill that owns each flagged route. Never drafts, edits, or publishes a translated page itself, and never fails a build over a page the site has not declared in scope for translation.

- Skill: `okhp3/okhp3-i18n-page-sync` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add okhp3/okhp3-i18n-page-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/okhp3/okhp3-i18n-page-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: OKHP3 (https://skillmd.com/u/okhp3)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/okhp3/okhp3-i18n-page-sync

---


# okhp3-i18n-page-sync

**OverKill Hill P³** · [overkillhill.com](https://overkillhill.com) · [github.com/OKHP3](https://github.com/OKHP3)

Keeps a multi-language static site honest about which pages actually have a
current translation, the same way a search-index builder already scours a
site and catalogs every page: this skill reuses that same generated index as
its page inventory rather than inventing a second, competing way to discover
content, and adds one persisted ledger to tell "never translated" apart from
"translated, but the English source moved on since."

It is deliberately a detector, not a translator. Detection is safe to run
unattended in CI on every push; translation is not, because it produces
prose that needs the voice, dictionary, and register-mediation gates the
`language-mediation` family's exact-pair skills already enforce. Keeping
these as two skills, run in sequence, is the same non-negotiable boundary
the `language-mediation` family draws between register mediation and
regional-language translation: detection and translation are two stages,
never one compounded skill.

## Scope

| In scope | Out of scope |
|---|---|
| Reading a site's generated search index as the English page inventory | Crawling the filesystem or a live site to discover pages itself |
| Comparing each in-scope page's source hash against a persisted ledger, per configured target locale | Deciding what "in scope" means; that is an explicit, owner-set config field |
| A read-only `--report`/`--check` mode safe for CI, and an explicit `--adopt` mode that only ever records a baseline | Drafting, editing, or publishing any translated page content |
| Naming the exact-pair `okhp3-translation-en-us-<pair>` skill responsible for each flagged route | Performing that translation itself, or any specialist-register simplification |

## Required inputs

- The site's own generated search index (a JSON file the consuming site already builds, commonly at a path like assets/data/search-index.json; the exact path is set by that site's own `search_index` config field, not fixed by this package), already current. This skill does not build or refresh it.
- `i18n/sync.config.json` in the consuming repository (see `references/config-schema.md`). Its absence is a valid, expected state for a site that has not started translating yet: every mode exits 0 and says so.
- One `okhp3-translation-en-us-<pair>` skill per configured target locale, available to whoever acts on the drift report.

## Procedure

1. Load `i18n/sync.config.json`. If it does not exist, stop here and report "not configured" with exit code 0. This is not an error state.
2. Load the site's search index and take its `entries[].url` values as the candidate page list, excluding any URL containing `#` (a fragment, not a page) and any URL already under a configured target locale's root.
3. If `in_scope_routes` is set, narrow the candidate list to exactly those routes. A route never listed there can never appear in a drift report, no matter how long its translation has lagged. This is what makes a partial pilot rollout safe to run in CI without failing the build over content nobody has committed to translating.
4. For each in-scope English page and each configured target locale, compare the target file's presence and the ledger's recorded `synced_source_sha256` against the current source-page bytes to classify it `missing`, `stale`, `needs_baseline` (a translation exists but was never confirmed in the ledger), or `in_sync`.
5. Also report `orphan`: a ledger entry whose English source page no longer appears in the search index at all. This is a warning, not build-breaking drift; a page can be legitimately retired.
6. In `--check` mode (the one wired into CI), exit 1 only when `missing` or `stale` routes exist. `needs_baseline` and `orphan` are surfaced but never fail the build; they need a one-time `--adopt` or a human decision, not an emergency.
7. Never translate. For every `missing` or `stale` route, name the exact `okhp3-translation-en-us-<pair>` skill from the config and stop. Handing that route to the named translation skill is a separate step. A first baseline uses `--adopt`; replacing a stale baseline requires the deliberate `--adopt --refresh-stale --routes "<route>"` acknowledgement after review-confirmed content lands.

## Format-adapter boundary

This skill assumes a page is exactly the file at `<locale-root>/<route-path>/index.html` (or `index.html` at the site root). A site whose routing does not follow that convention needs its own discovery adapter before this skill's route-to-path mapping applies; this package does not attempt to be a general static-site router.

## Controlled automation

The GitHub Action built around this skill (see `templates/`) runs `--check` on every push and pull request against `main`, and fails the job on real drift so it shows up the same way any other site-validation failure does. It performs no writes, opens no pull request, and calls no external API: the only remediation path out of a failing check is a human or an agent session running the named translation skill and then `--adopt`. This keeps the automation boundary the `language-mediation` family already documents intact: automation may detect and flag, but drafting and publishing stay explicit, reviewed, human-initiated steps.

## Quality and review gates

This skill has nothing to say about translation quality; it only proves source-byte freshness for a translated file. Passing `--check` is not evidence that a translation is accurate, current in tone, reviewed, structurally release-ready, indexed, or published. Those claims belong to separate review and release stages.

## Companion release boundary

Once the matching exact-pair skill has a reviewed HTML candidate, hand it to
`okhp3-i18n-page-release` for static-page release validation. That separate
stage verifies the declared BCP-47 `html lang`, self-canonical URL, public
alternate cluster, staging state, and optional rendered-language evidence. Do
not add those checks here: this package's source-hash result must remain a
small, deterministic answer to a different question, "has the declared source
changed since this target was confirmed?"

## Output contract

Return `Configured` (yes/no), `Missing routes` (route, locale, skill to run), `Stale routes` (route, locale, skill to run), `Needs-baseline routes`, `Orphaned routes`, and `Check result`. Describe `in_sync` as source-byte freshness. When routes are flagged, name the next action explicitly: which translation skill, then `--adopt` for a first baseline or `--adopt --refresh-stale --routes "<route>"` for a reviewed stale refresh.

## Resource routing

- Read `references/config-schema.md` before writing or editing a consuming site's `i18n/sync.config.json`.
- Copy `templates/i18n-page-sync-workflow.yml` into a consuming repository's `.github/workflows/` to wire this into CI. It requires no secrets and calls no external service.
- Run `scripts/i18n-page-sync.py --help` before using it directly. Use `--mode report` to preview drift, `--mode check` to verify a repository the way CI does, and `--mode adopt` only for a baseline or an explicit `--refresh-stale --routes` review-confirmed refresh.
- Route a reviewed localized HTML target to `okhp3-i18n-page-release` before
  classifying it as indexable or treating technical metadata as release-ready.

## Evaluation and release

`evals/evals.json` covers missing/stale detection, the never-translates-itself boundary, out-of-scope routes never failing a build, an explicit route-limited stale refresh, and an unconfigured site being a clean no-op. Version `1.2.0` additionally distinguishes source-byte freshness from release readiness and routes reviewed HTML candidates to the distinct release stage. This is a fully deterministic script over structured JSON and file hashes; its ten-test local suite plus the Foundry structural validator are structural evidence only. There is no language-quality dimension here requiring a native-review holdout.

## About

Built by [Jamie Hill](https://overkillhill.com) · [OverKill Hill P³](https://overkillhill.com)
Published at [github.com/OKHP3](https://github.com/OKHP3)
Part of the [OKHP3/skillz](https://github.com/OKHP3/skillz) Agent Skill library.
MIT License -- free to use, fork, and adapt. A nod to the source is appreciated.

