# OINK 1.5.0 — Read translations side by side

> Compare a page with its translation in an opt-in bilingual view, with scroll sync by shared headings.

---

LLMS index: [llms.txt](/llms.txt)

---

OINK 1.5.0 adds an opt-in Bilingual View for multilingual sites. Readers,
authors, and translators can open a page beside one of its existing
translations and keep both panes aligned near the same section. The feature is
off by default, so sites that do not enable it keep the exact same rendered
pages and outputs as before. This documentation site is now running on OINK
1.5.0 with Bilingual View enabled across its Docs and blog pages—press
B or click **Open bilingual view** at the top of this page to try
it right now.

**v1\.5\.0 · 2026-11-04**
- [View release](https://github.com/pgsty/oink/releases/tag/v1.5.0)
- [Source · tar\.gz](https://github.com/pgsty/oink/archive/refs/tags/v1.5.0.tar.gz)
- [Source · zip](https://github.com/pgsty/oink/archive/refs/tags/v1.5.0.zip)
- [pgsty\/oink](https://github.com/pgsty/oink)

## Bilingual View {#bilingual-view}

Enable it with a single site setting:

```yaml {title="hugo.yaml"}
params:
  ui:
    compare: true
```

Every Docs, Book, and blog page that has a published HTML translation on the
same origin then shows **Open bilingual view** beside the page actions. Readers
can also launch **Bilingual View** from the command palette or press
B when keyboard navigation is enabled. The current page stays on
the reading-start side while the other pane loads a translation selected from
the target-language menu.

**Sync Scroll** matches shared visible heading IDs and interpolates smoothly
between them. Even when one translation is longer or includes an extra
subsection, both panes stay aligned section by section. Partial matches use the
available anchors and display an approximate-sync note; when two pages share no
usable headings, the reader estimates position from overall reading progress. If
heading IDs are duplicated or appear in a different order across languages,
**Sync Scroll** turns off automatically while leaving both panes open for
independent reading. Keep explicit `{#id}` anchors aligned across translations,
as described in the [multilingual guide](/docs/customize/i18n/#anchors), for the
best experience.

Bilingual View loads the two existing HTML pages inside same-origin frames only
when a reader opens it. Each pane keeps its own language, text direction, tabs,
tables, diagrams, footnotes, and interactive components while suppressing
duplicate shell navigation, search, comments, and analytics. No language-pair
pages, new layouts, or extra output formats are generated at build time. Print,
Markdown, and feed outputs remain unchanged.

## Responsive reading and accessibility {#narrow}

On viewports narrower than `900px`, the reader switches to a compact toolbar row
and a language switcher bar that displays one retained pane at a time. The
switcher bar also holds the target-language menu so pane titles are not
repeated. Even on short, high-zoom viewports (`320 × 256` CSS pixels, roughly
400% browser zoom), at least `160px` of vertical reading space remains visible
without horizontal scrolling.

Right-to-left host pages place the current page on the right (the reading-start
side) and the target translation on the left. Resizing across the `900px`
breakpoint moves the target-language menu between the desktop pane header and
the mobile switcher bar without losing keyboard focus, menu state, or the
active pane. Forced-colors mode highlights the active pane with a clear border,
and the `B` shortcut and `aria-keyshortcuts` attribute are exposed only when
keyboard navigation is enabled and a translation target exists.

## Language and analytics boundaries {#before-enabling}

Individual languages can opt out by setting `compare: false` under
`languages.<lang>.params.ui`. An opted-out language never displays the
Bilingual View button and is never offered as a target language from other
pages. Pages without a same-origin translation, unpublished drafts,
language-home fallbacks, and translations hosted on external domains are
excluded automatically.

Custom scripts added through `hooks/head-end.html` execute inside each pane
frame. Analytics snippets placed there should skip pane loads by checking
`window.OinkComparePane`, as shown in
[Analytics and SEO](/docs/admin/analytics/#bilingual-view). Theme-managed
analytics (`services.googleAnalytics.id` and `params.analytics.*`) skips panes
automatically; when `params.ui.compare: true` is active, OINK renders Google
Analytics through its own pane-aware template rather than Hugo's built-in
`google_analytics.html` partial.

If your site sends a Content Security Policy, allow same-origin frames with
`frame-src 'self'` and make sure your server does not block same-origin framing
with `X-Frame-Options: DENY` or `frame-ancestors 'none'`. See the
[deployment guide](/docs/admin/deploy/#csp) for details.

## Browser navigation and history {#history}

Opening Bilingual View pushes a single browser history entry. Clicking
**Close**, pressing Escape, or using browser **Back** closes the
reader and restores your scroll position and focus on the host page. If an
interactive component such as a diagram viewer or expanded table is open inside
a pane, Escape closes that inner dialog first before closing
Bilingual View.

Reloading the page while Bilingual View is open—or returning to it with browser
**Forward**—reopens the reader on the existing history entry rather than pushing
a duplicate record, so a single **Back** step always returns to regular reading.
In-page `#anchor` links scroll within their pane without adding history entries,
links to other pages on the site exit Bilingual View and navigate normally, and
external links open outside the frame.

## Upgrade {#upgrade}

Use **Hugo Extended 0.168.0** and **Go 1.27.3**. Theme styles continue to
compile with Hugo's built-in LibSass.

```sh
hugo mod get github.com/pgsty/oink@v1.5.0
hugo mod tidy
hugo --environment production --minify --printPathWarnings
```

Commit the updated `go.mod` and `go.sum`. Refresh vendored or copied theme
files separately. Keep Hugo's LibSass deprecation warning visible and review
other diagnostics; do not enable `--panicOnWarning` or
`HUGO_PANICONWARNING`.

Existing content and configuration need no migration. The new interface labels
are translated in all 32 catalogs. The [upgrade guide](/docs/admin/upgrade/#preparing-1-5)
covers validation, CSP, analytics, and rollback.

---

Backlinks:

- [Releases](/blog/release/)
- [Docs](/docs/)
- [Introduction](/docs/about/)
- [Contributing](/docs/about/contributing/)
- [Upgrade](/docs/admin/upgrade/)
