Zen UI - A minimal interface for e-readers

Contributing to Zen UI

Thank you for your interest in contributing. Zen UI is a small, focused plugin β€” contributions that keep it clean, minimal, and well-behaved are most welcome.

Ways to contribute

Β  Β 
πŸ› Bug report Open an Issue describing what went wrong
πŸ’‘ Feature request Open an Issue with your idea
🌍 Translation Add or improve a .po file in locales/
πŸ”§ Code Fork, branch, change, and open a Pull Request
πŸ“ Documentation Improve the README or add inline comments

Reporting a bug

Open an Issue and include:

If the bug causes a crash, the KOReader log (crash.log or reader.log in the KOReader folder) is very helpful.


Suggesting a feature

Open an Issue describing the feature and why it would be useful. Keep Zen UI’s philosophy in mind β€” features should reduce clutter or add something genuinely useful. Screenshots or mockups are welcome.


Contributing a translation

Translations live in the locales/ folder as standard .po files. No programming knowledge is needed.

Adding a new language

  1. Copy locales/en.po to locales/<lang>.po using the standard locale code β€” for example de.po, ja.po, ko.po.
  2. Open the file in any text editor or a dedicated PO editor such as Poedit.
  3. Update the header fields at the top of the file:
    "Language: de\n"
    
  4. For each entry, fill in the msgstr field with your translation:
    msgid "Quick settings"
    msgstr "Schnelleinstellungen"
    
  5. Submit your file as a Pull Request (see below).

Improving an existing translation

Open the existing .po file for your language, correct or complete the msgstr values, and submit a Pull Request.

Translation guidelines


Contributing code

Setup

Zen UI is a standard KOReader plugin written in Lua. No build system or compilation step is required. The plugin runs directly from source.

To test changes:

  1. Copy the zen_ui.koplugin folder to the plugins/ directory on your device or the KOReader emulator.
  2. Restart KOReader to reload the plugin.

The KOReader emulator is the fastest way to iterate without a physical device.

Static linting (LuaCheck)

Zen UI uses LuaCheck for static analysis.

Install it locally (one-time):

luarocks install luacheck

Run lint checks from the plugin root:

luacheck -q _meta.lua main.lua common config modules

The project config is in .luacheckrc and is aligned with KOReader’s baseline (for globals like G_reader_settings and G_defaults).

Making a change

  1. Fork this repository (click the Fork button at the top right of the GitHub page).
  2. Create a new branch for your change:
    git checkout -b fix/my-bug-description
    
  3. Make your changes.
  4. If you added any new visible text (strings shown in the UI), wrap them with _():
    -- correct
    text = _("Something went wrong.")
    
    -- incorrect β€” not translatable
    text = "Something went wrong."
    
  5. If your change introduces new strings, add entries to locales/en.po:
    msgid "Your new string"
    msgstr ""
    
  6. Commit with a clear message that describes what changed and why:
    git commit -m "Fix progress bar not updating after resume"
    
  7. Push your branch and open a Pull Request against main.

Extracting translatable strings

If you have Python 3 available, you can scan all Lua files for translatable strings and print any that are missing from locales/en.po:

import re, pathlib

strings = set()
pattern = re.compile(r'_\("([^"]+)"\)')
for f in pathlib.Path(".").rglob("*.lua"):
    strings.update(pattern.findall(f.read_text(errors="ignore")))

existing = pathlib.Path("locales/en.po").read_text(errors="ignore")
for s in sorted(strings):
    if f'msgid "{s}"' not in existing:
        print(f'msgid "{s}"\nmsgstr ""\n')

Code style

File structure

zen_ui.koplugin/
β”œβ”€β”€ main.lua                        β€” plugin entry point and lifecycle
β”œβ”€β”€ _meta.lua                       β€” plugin metadata
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ defaults.lua                β€” schema and default values
β”‚   └── manager.lua                 β€” persistence, migration, getters/setters
β”œβ”€β”€ common/
β”‚   └── utils.lua                   β€” shared utilities
β”œβ”€β”€ modules/
β”‚   β”œβ”€β”€ registry.lua                β€” module loader and feature registry
β”‚   β”œβ”€β”€ filebrowser/                β€” file browser patches and layout
β”‚   β”œβ”€β”€ menu/                       β€” menu patches (quick settings, zen mode)
β”‚   └── reader/                     β€” reader patches (clock, status, banner)
β”œβ”€β”€ settings/
β”‚   β”œβ”€β”€ zen_settings.lua            β€” unified settings menu entry
β”‚   β”œβ”€β”€ zen_settings_build.lua      β€” menu tree builder
β”‚   β”œβ”€β”€ zen_settings_apply.lua      β€” apply settings to live state
β”‚   β”œβ”€β”€ zen_settings_updater.lua    β€” update checker and installer
β”‚   └── zen_updater.lua             β€” GitHub release fetcher
β”œβ”€β”€ locales/                        β€” gettext .po translation files
β”œβ”€β”€ icons/                          β€” UI icons
β”œβ”€β”€ CONTRIBUTING.md
β”œβ”€β”€ SECURITY.md
└── README.md

Pull Request checklist

Before submitting, please check:

Thank you for helping make Zen UI better.