PHPackages                             nerdcel/kirby-languagerelease - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. nerdcel/kirby-languagerelease

ActiveKirby-plugin[Localization &amp; i18n](/categories/localization)

nerdcel/kirby-languagerelease
=============================

A Kirby CMS plugin to control the release status of language variants with frontend access control

v1.2.2(2w ago)277↓89.7%MITPHPPHP ^8.2CI passing

Since Jan 29Pushed 2w agoCompare

[ Source](https://github.com/nerdcel/kirby-languagerelease)[ Packagist](https://packagist.org/packages/nerdcel/kirby-languagerelease)[ Docs](https://github.com/nerdcel/kirby-languagerelease)[ RSS](/packages/nerdcel-kirby-languagerelease/feed)WikiDiscussions main Synced today

READMEChangelog (7)Dependencies (8)Versions (8)Used By (0)

Kirby Language Release
======================

[](#kirby-language-release)

[![Version](https://camo.githubusercontent.com/34e695c6016bc2a934a96bed696e29b2f2ab562a7134d65a55d00653cd506bea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657273696f6e2d312e302e302d626c75652e737667)](https://github.com/nerdcel/kirby-languagerelease/releases)[![Kirby](https://camo.githubusercontent.com/d5b10246c28851f0e3af9a3089c415e09ad976437e534f17aa3fdd1460826ddf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d352e302b2d626c61636b2e737667)](https://getkirby.com)[![PHP](https://camo.githubusercontent.com/e9b0c005a58eeb6aaac524aaaa3b42d0e30333344a47ff165a0225d4a9916043/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322b2d3737374242342e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

A Kirby CMS plugin that provides granular control over language variant releases with frontend access control and preview capabilities.

[![Kirby Language Release Plugin](screen.png)](screen.png)

⚠️ Important Warning
--------------------

[](#️-important-warning)

**This plugin changes the behavior of your multilingual site immediately after installation!**

Once installed, **all language variants (except the default language) will become inaccessible in the frontend** until they are explicitly released through the Panel. This prevents visitors from accessing unfinished translations.

**Before installing:**

- Back up your site
- Review your current language variants
- Plan which languages should be released immediately after installation

Editors can still access and preview all language variants through the Panel, regardless of their release status.

Features
--------

[](#features)

- ✅ **Release Control**: Individual release status for each language variant of a page
- ✅ **Frontend Access Control**: Unreleased variants are blocked from public access
- ✅ **Preview Mode**: Authenticated editors can preview unreleased variants via Panel
- ✅ **Flexible Behavior**: Choose between 404, redirect, or default content for unreleased pages
- ✅ **Token Validation**: Secure preview mode with session-based authentication
- ✅ **Multilingual Interface**: Translations for DE, EN, ES, FR, IT, NL
- ✅ **Configurable Field Name**: Use custom field names for the release status
- ✅ **Panel Integration**: ViewButton with checkbox interface
- ✅ **Panel Section**: Overview of all language variants and their release status
- ✅ **Page Tree Section**: Hierarchical tree view of all pages with release status per language

Requirements
------------

[](#requirements)

- **Kirby CMS**: 5.0 or higher
- **PHP**: 8.2 or higher

Installation
------------

[](#installation)

### Via Composer (recommended)

[](#via-composer-recommended)

```
composer require nerdcel/kirby-languagerelease
```

### Manual Installation

[](#manual-installation)

1. Download the [latest release](https://github.com/nerdcel/kirby-languagerelease/releases)
2. Extract the ZIP file
3. Copy the `languagerelease` folder to `/site/plugins/`

### Git Submodule

[](#git-submodule)

```
git submodule add https://github.com/nerdcel/kirby-languagerelease.git site/plugins/languagerelease
```

Quick Start
-----------

[](#quick-start)

### 1. Add Field to Your Blueprints (optional)

[](#1-add-field-to-your-blueprints-optional)

Add the release field to your page blueprints:

```
fields:
  languageReleased:
    type: toggle
    label: Language Released
    default: false
```

### 2. Configure Plugin (Optional)

[](#2-configure-plugin-optional)

Create or update `site/config/config.php`:

```
return [
    'nerdcel.languagerelease' => [
        'autoIncludeButton' => true,
        'fieldName' => 'languageReleased', // Field name in your blueprint
        'behavior' => '404', // What to do with unreleased pages: '404', 'redirect', 'default-content'
    ],
];
```

### 3. Release Language Variants

[](#3-release-language-variants)

In the Panel, open a page and switch to a non-default language. You'll see a button to release that language variant in the upper right area next to the language select button.

Panel Section
-------------

[](#panel-section)

The plugin provides a custom Panel section that displays all language variants of a page and their current release status at a glance.

### Add the Section to Your Blueprint

[](#add-the-section-to-your-blueprint)

```
# site/blueprints/pages/default.yml
sections:
  languagerelease:
    type: languagerelease
    label: Language Release Status
```

The section shows a table with:

ColumnDescriptionLanguageThe language name (e.g. "English", "Deutsch")CodeThe language code (e.g. `en`, `de`)Status**Default**, **Released** (green), or **Unreleased** (red)The default language is always marked as "Default" since it does not require release.

### Blueprint Examples

[](#blueprint-examples)

#### Sidebar Section

[](#sidebar-section)

```
columns:
  - width: 2/3
    sections:
      content:
        type: fields
        fields:
          title:
            type: text
          text:
            type: textarea
  - width: 1/3
    sections:
      languagerelease:
        type: languagerelease
        label: Languages
```

#### Full-Width Section

[](#full-width-section)

```
sections:
  languagerelease:
    type: languagerelease
    label: Translation Status
  content:
    type: fields
    fields:
      # your fields...
```

Page Tree Section
-----------------

[](#page-tree-section)

The plugin also provides a **tree section** that displays all pages of the site (including drafts) in a hierarchical tree with their release status across all languages at a glance. This is useful for getting a bird's eye view of the entire site's translation status.

### Add the Tree Section to Your Blueprint

[](#add-the-tree-section-to-your-blueprint)

The tree section is best suited for the `site.yml` blueprint or a dashboard-style page:

```
# site/blueprints/site.yml
sections:
  releasetree:
    type: languagerelease-tree
    label: Translation Overview
```

### What the Tree Shows

[](#what-the-tree-shows)

The tree section renders a table with:

ColumnDescriptionPageHierarchical page tree with expandable/collapsible childrenPer LanguageOne column per language with a colored dot indicating the statusStatus indicators:

- 🔘 **Grey dot** — Default language (always released)
- 🟢 **Green dot** — Released
- 🟡 **Yellow dot** — Translated but not yet released
- 🔴 **Red dot** — No translation

Each page title links to its Panel page, and child pages can be expanded or collapsed.

### Blueprint Examples

[](#blueprint-examples-1)

#### Site Blueprint (Recommended)

[](#site-blueprint-recommended)

```
# site/blueprints/site.yml
columns:
  - width: 1/1
    sections:
      releasetree:
        type: languagerelease-tree
        label: Translation Overview
```

#### Combined with Per-Page Section

[](#combined-with-per-page-section)

You can use both section types together — the tree for a global overview and the per-page section for the current page:

```
# site/blueprints/pages/default.yml
columns:
  - width: 2/3
    sections:
      content:
        type: fields
        fields:
          title:
            type: text
          text:
            type: textarea
  - width: 1/3
    sections:
      languagerelease:
        type: languagerelease
        label: This Page
      releasetree:
        type: languagerelease-tree
        label: All Pages
```

Configuration Options
---------------------

[](#configuration-options)

### Field Name

[](#field-name)

Define which field stores the release status:

```
'nerdcel.languagerelease.fieldName' => 'languageReleased'
```

### Behavior for Unreleased Pages

[](#behavior-for-unreleased-pages)

Choose what happens when visitors try to access unreleased language variants:

#### Option 1: 404 (Default, Recommended)

[](#option-1-404-default-recommended)

```
'nerdcel.languagerelease.behavior' => '404'
```

Shows a 404 error page. Best for SEO and clear communication to search engines.

#### Option 2: Redirect

[](#option-2-redirect)

```
'nerdcel.languagerelease.behavior' => 'redirect'
```

Redirects to the default language (302 redirect). User-friendly but may confuse search engines.

#### Option 3: Default Content

[](#option-3-default-content)

```
'nerdcel.languagerelease.behavior' => 'default-content'
```

Displays content from the default language while keeping the URL. May cause duplicate content issues.

### Environment-Specific Configuration

[](#environment-specific-configuration)

```
'nerdcel.languagerelease' => [
    'autoIncludeButton' => true,
    'fieldName' => 'languageReleased',
    'behavior' => match (option('environment')) {
        'production' => '404',
        'staging' => 'redirect',
        default => 'default-content',
    },
],
```

How It Works
------------

[](#how-it-works)

### Frontend Access Control

[](#frontend-access-control)

```
Visitor requests: example.com/en/page
                        ↓
              Is language released?
                        ↓
        ┌───────────────┴───────────────┐
        ↓                               ↓
      YES ✅                          NO ❌
        ↓                               ↓
   Page displays                  Behavior option:
    normally                     404 / redirect / default

```

### Preview Mode (Panel)

[](#preview-mode-panel)

Editors can preview unreleased pages through the Panel's preview button. The plugin validates preview tokens to ensure only authenticated users can access unreleased content.

**Preview URL Parameters:**

- `?_preview=true&_token=xxx`
- `?version=changes&_token=xxx`

The token is validated server-side, ensuring security.

### Panel Access

[](#panel-access)

All language variants remain fully accessible in the Panel:

- ✅ View all languages
- ✅ Edit all languages
- ✅ Preview unreleased languages
- ✅ No restrictions for editors

Usage in Templates
------------------

[](#usage-in-templates)

### Check Release Status

[](#check-release-status)

```
// Check if current language is released
if (isLanguageReleased($page)) {
    echo 'This page is released';
}

// Filter for released pages only
$pages = $site->children()->filter(fn($p) => isLanguageReleased($p));
```

### Get Field Name

[](#get-field-name)

```
$fieldName = languageReleaseFieldName();
// Returns: 'languageReleased' (or your custom field name)
```

Helper Functions
----------------

[](#helper-functions)

The plugin provides two global helper functions:

### `languageReleaseFieldName(): string`

[](#languagereleasefieldname-string)

Returns the configured field name.

```
$field = languageReleaseFieldName();
```

### `isLanguageReleased(Page $page): bool`

[](#islanguagereleasedpage-page-bool)

Checks if a page's current language variant is released. **When the request is on a Panel or API route (and a user is logged in), this function always returns `true`**, so the Panel can operate without language release filtering. On frontend routes, the check is always applied — even for logged-in users.

```
if (isLanguageReleased($page)) {
    // Language is released (or user is logged into the Panel)
}
```

### `isAuthenticatedPreview(): bool`

[](#isauthenticatedpreview-bool)

Checks if the current request is an authenticated preview.

```
if (isAuthenticatedPreview()) {
    // User is previewing with valid user session
}
```

Translations
------------

[](#translations)

The plugin includes translations for:

- 🇩🇪 German (de)
- 🇬🇧 English (en)
- 🇪🇸 Spanish (es)
- 🇫🇷 French (fr)
- 🇮🇹 Italian (it)
- 🇳🇱 Dutch (nl)

All Panel texts automatically display in the user's selected language.

Security
--------

[](#security)

- ✅ Preview tokens are validated server-side
- ✅ Only authenticated users can preview unreleased content
- ✅ Session-based authentication
- ✅ No bypass mechanisms for unauthenticated users

Troubleshooting
---------------

[](#troubleshooting)

### Issue: All language variants are blocked after installation

[](#issue-all-language-variants-are-blocked-after-installation)

**Solution:** This is expected behavior. Release your language variants through the Panel:

1. Open a page
2. Switch to the language
3. Check the "Release Language Variant" checkbox

### Issue: Preview button doesn't work

[](#issue-preview-button-doesnt-work)

**Solution:** Make sure you're logged into the Panel. The preview requires a valid session.

### Issue: Language Release section is empty

[](#issue-language-release-section-is-empty)

**Solution:** The section loads its data asynchronously from the Kirby API using the `section` mixin. Make sure the built `index.js` is up to date by running `npm run build`. If developing locally, use `npm run dev` for automatic rebuilds.

### Issue: 404 errors on released pages

[](#issue-404-errors-on-released-pages)

**Solution:** Check that the field name in your configuration matches the field in your blueprints.

Example Configurations
----------------------

[](#example-configurations)

### Minimal Configuration (Uses Defaults)

[](#minimal-configuration-uses-defaults)

```
// No configuration needed - uses 'languageReleased' field and '404' behavior
```

### Custom Field Name

[](#custom-field-name)

```
return [
    'nerdcel.languagerelease' => [
        'autoIncludeButton' => true,
        'fieldName' => 'isPublished',
        'behavior' => '404',
    ],
];
```

### User-Friendly Redirects

[](#user-friendly-redirects)

```
return [
    'nerdcel.languagerelease' => [
        'autoIncludeButton' => true,
        'fieldName' => 'languageReleased',
        'behavior' => 'redirect',
    ],
];
```

Development
-----------

[](#development)

### Local Development

[](#local-development)

```
git clone https://github.com/nerdcel/kirby-languagerelease.git
cd kirby-languagerelease
composer install
```

### Frontend Build

[](#frontend-build)

```
npm run build       # Build production assets
npm run dev         # Watch mode for development
```

### Running Tests

[](#running-tests)

```
composer test
```

### Releasing

[](#releasing)

```
composer release:patch   # Bugfix (1.0.1 → 1.0.2)
composer release:minor   # Feature (1.0.1 → 1.1.0)
composer release:major   # Breaking change (1.0.1 → 2.0.0)
```

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for version history.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

MIT License - see [LICENSE](LICENSE) file for details.

Credits
-------

[](#credits)

Developed by [Marcel Hieke](https://marcelhieke.com)

Support
-------

[](#support)

- **Issues**: [GitHub Issues](https://github.com/nerdcel/kirby-languagerelease/issues)
- **Discussions**: [GitHub Discussions](https://github.com/nerdcel/kirby-languagerelease/discussions)

---

Made with ❤️ for the Kirby CMS community

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance93

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~23 days

Recently: every ~16 days

Total

7

Last Release

15d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3840331?v=4)[Marcel Hieke](/maintainers/nerdcel)[@nerdcel](https://github.com/nerdcel)

---

Top Contributors

[![nerdcel](https://avatars.githubusercontent.com/u/3840331?v=4)](https://github.com/nerdcel "nerdcel (15 commits)")

---

Tags

languagetranslationreleasemultilingualpublishkirbykirby-pluginkirby-cms

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nerdcel-kirby-languagerelease/health.svg)

```
[![Health](https://phpackages.com/badges/nerdcel-kirby-languagerelease/health.svg)](https://phpackages.com/packages/nerdcel-kirby-languagerelease)
```

###  Alternatives

[medienbaecker/kirby-modules

Easily add modules to your pages

895.5k1](/packages/medienbaecker-kirby-modules)[johannschopplich/kirby-content-translator

DeepL &amp; AI-powered content translation for Kirby CMS

2010.8k](/packages/johannschopplich-kirby-content-translator)[tractorcow/silverstripe-fluent

Simple localisation for Silverstripe

91437.9k29](/packages/tractorcow-silverstripe-fluent)[belugadigital/kirby-navigation

Kirby 5 field for hierarchical menus with drag &amp; drop level indentation.

8614.7k](/packages/belugadigital-kirby-navigation)[inpsyde/multilingual-press

Simply THE multisite-based free open source plugin for your multilingual websites.

2414.0k1](/packages/inpsyde-multilingual-press)[grommasdietz/kirby-blueprint-areas

Add custom Panel areas via blueprints on Kirby CMS

211.2k](/packages/grommasdietz-kirby-blueprint-areas)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
