Skip to content

dshushin/nvim.bilingual

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nvim.bilingual

Neovim plugin + pandoc tool for writing bilingual legal documents in markdown with parallel two-column export to PDF and Word.

Built for legal contracts where text in two languages must appear side by side with synchronized sections.

Example

Write in markdown with fenced divs — export to PDF and Word with a single command:

Markdown source (Neovim)

Bilingual markdown source in Neovim

PDF output (LuaLaTeX + paracol)

PDF output — English / Arabic bilingual contract

Word output (DOCX tables)

DOCX output — English / Arabic bilingual contract

Features

  • Parallel columns — two languages side by side, sections aligned
  • Page-break support — columns flow naturally across pages (no gaps)
  • RTL support — Arabic, Hebrew with automatic font switching
  • Contract templates — ready-made skeletons for EN-RU, EN-AR, EN-HE
  • Syntax highlighting — colored markers for bilingual blocks, concealing support
  • Block folding — fold bilingual sections with preview from both columns
  • Quick section insert — keymap to add bilingual blocks without typing tags
  • Export from nvim:Bilingual pdf / :Bilingual docx
  • Professional PDF — LuaLaTeX with PT Serif, paracol, proper typography
  • Word export — clean DOCX with two-column tables

Requirements

  • Neovim >= 0.10
  • pandoc >= 3.0 — brew install pandoc
  • LuaLaTeX (for PDF) — brew install --cask mactex or brew install basictex

Fonts (bundled on macOS):

  • PT Serif, Helvetica Neue, Menlo
  • Geeza Pro (Arabic), Arial Hebrew (Hebrew)

Installation

vim-plug

Plug '/path/to/nvim.bilingual'

lazy.nvim

{ dir = "/path/to/nvim.bilingual" }

No setup() call needed — the plugin loads automatically.

Quick Start

1. Create a new contract

:Bilingual new

A menu appears with language pairs:

Language pair:
> English / Russian
  English / Arabic
  English / Hebrew

Select one — a new buffer opens with a full contract template (~10 articles).

Or specify the pair directly:

:Bilingual new en-ru
:Bilingual new en-ar
:Bilingual new en-he

2. Add sections

Press <leader>bs in a markdown file to insert an empty bilingual section at the cursor:

::: {.bilingual}
::: {.col}

:::
::: {.col}

:::
:::

If the file already contains RTL content (Arabic/Hebrew), the second column automatically gets dir=rtl lang=ar/he.

3. Export

:Bilingual pdf        " export to PDF
:Bilingual docx       " export to Word
:Bilingual            " export both

Output goes to ~/Documents/bilingual-exports/.

Or from the command line:

./export.sh document.md           # PDF + DOCX
./export.sh document.md --pdf     # PDF only
./export.sh document.md --docx    # DOCX only

Markdown Syntax

Wrap bilingual sections in ::: {.bilingual} with two ::: {.col} children:

---
title:
  - "Sale and Purchase Agreement"
  - "Договор купли-продажи"
date: "February 26, 2026"
---

::: {.bilingual}
::: {.col}
### Article 1. Definitions

"Agreement" means this Sale and Purchase Agreement.
:::
::: {.col}
### Статья 1. Определения

«Договор» означает настоящий Договор купли-продажи.
:::
:::

Text outside .bilingual blocks spans the full page width — useful for signatures, document headers, and notes.

RTL languages

Add dir=rtl and lang= to the .col div:

::: {.bilingual}
::: {.col}
### Article 1. Definitions
:::
::: {.col dir=rtl lang=ar}
### المادة 1. التعريفات
:::
:::
Attribute Effect
dir=rtl Right-to-left text direction
lang=ar Arabic font (Geeza Pro)
lang=he Hebrew font (Arial Hebrew)

Font switching is automatic — PT Serif is the main font with Geeza Pro (Arabic) and Arial Hebrew (Hebrew) as fallbacks via luaotfload. When LuaLaTeX encounters Arabic or Hebrew characters, it switches to the appropriate font automatically. This means Arabic text in document titles also renders correctly.

Editing RTL in Neovim

For better display of Arabic/Hebrew in the editor, enable terminal bidi:

" init.vim
set termbidi
-- init.lua
vim.opt.termbidi = true

This delegates bidirectional text rendering to the terminal. With termbidi, Arabic and Hebrew characters display in correct reading order. However, terminals always start lines from the left margin — full RTL paragraph alignment is not available. For correct RTL layout, use the PDF/DOCX export.

Note on RTL in editors: No terminal or markdown editor fully supports RTL paragraph alignment for pandoc fenced divs. Arabic/Hebrew character order displays correctly in Typora and Terminal.app, but text remains left-aligned. Ghostty, iTerm2, and Neovide show reversed characters. For correct RTL layout with right-to-left alignment, use the PDF/DOCX export — the editor is for writing, the export is for reading.

The plugin also provides syntax highlighting for bilingual blocks and folding (zc to fold, zo to open, zM/zR for all). Set conceallevel=1 for a compact view that replaces ::: {.bilingual} markers with minimal glyphs.

CriticMarkup (Track Changes)

Mark changes directly in markdown using CriticMarkup syntax:

The price shall be {--USD 50,000--}{++USD 75,000++}.
This Agreement {~~shall~>may~~} be terminated.
{>>Consider adding force majeure clause here<<}
Syntax Meaning Redline rendering
{++text++} Addition Green underline
{--text--} Deletion Red strikethrough
{~~old~>new~~} Substitution Red strikethrough + green underline
{>>comment<<} Comment Yellow italic in brackets
{==text==} Highlight Yellow background

Export modes

:Bilingual pdf          " redline — show changes (default)
:Bilingual accept pdf   " clean — accept all changes
:Bilingual accept       " clean PDF + DOCX

From the command line:

./export.sh document.md --pdf             # redline
./export.sh document.md --pdf --accept    # clean version

Commands

Command Description
:Bilingual new Create contract from template (interactive menu)
:Bilingual new en-ru Create EN-RU contract directly
:Bilingual new en-ar Create EN-AR contract (Arabic RTL)
:Bilingual new en-he Create EN-HE contract (Hebrew RTL)
:Bilingual section Insert empty bilingual section at cursor
:Bilingual pdf Export current file to PDF
:Bilingual docx Export current file to DOCX
:Bilingual Export to both PDF and DOCX
:Bilingual accept Export clean version (accept all changes)
:Bilingual accept pdf Clean PDF only
:Bilingual redline Export with visible changes (default)

All commands have tab-completion.

Keymaps

Key Mode Action
<leader>bs Normal Insert bilingual section at cursor
<leader>ba Visual Mark selection as addition {++...++}
<leader>bd Visual Mark selection as deletion {--...--}
<leader>bc Visual Add comment {>>...<<}

Active only in markdown/mdx files.

Contract Templates

Three templates are included, each with ~10 articles:

Template Languages Jurisdiction
en-ru English + Russian configurable
en-ar English + Arabic (RTL) UAE
en-he English + Hebrew (RTL) Israel

Each template includes: definitions, subject, price and payment, term and termination, representations and warranties, liability, confidentiality, force majeure, governing law, general provisions, and signature blocks.

All placeholder values are marked with [___] for easy find-and-replace.

How It Works

PDF (LaTeX)

  1. Pandoc reads markdown and applies the Lua filter (filter/bilingual.lua)
  2. The filter collects consecutive .bilingual blocks into paracol environments
  3. Each section pair uses \switchcolumn* for vertical synchronization
  4. luaotfload fallback auto-switches fonts for Arabic/Hebrew characters
  5. paracol handles page breaks within parallel columns — no empty gaps
  6. LuaLaTeX with babel (bidi=basic) renders the final PDF with correct paragraph-level bidirectional text

DOCX (Word)

  1. Same Lua filter, but generates two-column tables instead of paracol
  2. RTL content is wrapped in Div elements with dir="rtl" attribute
  3. Pandoc converts to DOCX with proper table formatting

Examples

File Languages
example/contract.md English + Russian
example/contract-ar.md English + Arabic (RTL)
example/contract-he.md English + Hebrew (RTL)
./export.sh example/contract.md
./export.sh example/contract-ar.md
./export.sh example/contract-he.md

Project Structure

nvim.bilingual/
├── plugin/bilingual.lua             -- bootstrap, commands
├── lua/bilingual/
│   └── init.lua                     -- new, section, export, keymaps
├── after/syntax/
│   └── markdown.vim                 -- bilingual block highlighting + conceal
├── filter/
│   └── bilingual.lua                -- pandoc Lua filter (paracol + tables)
├── templates/
│   ├── bilingual.latex              -- LaTeX template (fonts, paracol, babel bidi)
│   └── contracts/
│       ├── en-ru.md                 -- English / Russian template
│       ├── en-ar.md                 -- English / Arabic template
│       └── en-he.md                 -- English / Hebrew template
├── example/
│   ├── contract.md                  -- EN-RU example
│   ├── contract-ar.md               -- EN-AR example (RTL)
│   └── contract-he.md               -- EN-HE example (RTL)
├── assets/                          -- screenshots for README
├── export.sh                        -- CLI export script
└── README.md

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors