All Versions
Latest Version
Avg Release Cycle
16 days
Latest Release
729 days ago

Changelog History
Page 2

  • v3.4.3-rc.1 Changes

    September 08, 2020

    πŸ”‹ Features

    πŸ†• New slugs.maxlength option

    You can now restrict the length of slugs with the new slugs.maxlength option #1821

    // site/config/config.phpreturn ['slugs' =\> [ 'maxlength' =\> 100] ];

    Required fields and when conditions

    Required fields with when conditions now can be left empty, if the when condition does not apply.

    fields: category: type: radiooptions: - Photography - Editorialphotographer: when: category: Photography # the photographer field will now only be required when the category is "Photography" required: true

    Custom drag text for files and pages

    You can now define custom text when files or pages get dragged into textareas. #2735

    // site/config/config.phpreturn ['panel' =\> [ 'kirbytext' =\> [ 'fileDragText' =\> function ($file, $url) { return '(file: ' . $url . ' alt: ' . $page-\>alt() . ')'; }, 'pageDragText' =\> function ($page) { return '(link: ' . $page-\>url() . ' text: ' . $page-\>title() . ')'; }] ] ];

    πŸ‘ Array support for Collection::not()

    When filtering collections, you can now pass an array of IDs or objects to Collection::not()

    $menu = $site-\>children()-\>not(['home', 'error'])// or$a = page('some-page-a');$b = page('some-page-b');$menu = $site-\>children()-\>not([$a, $b]);

    More …

    • πŸ‘ V::alpha($string, $unicode = false) and V::alphanum($string, $unicode = false) can now support unicode characters. This can be activated with the second argument.
    • You can now use Asset objects in panel previews #2746

    ✨ Enhancements

    • 🚚 Commas are now automatically removed from sortBy options in blueprints for enhanced usability. getkirby/ideas#195

      now both versions worksortBy: date desc title descsortBy: date desc, title desc

    • 🍱 We've increased test coverage for our PHP code from 84% to 90% πŸŽ‰

    • We've massively improved our doc block comments and type hints throughout our code base

    • πŸ‘ The file dropdown is now better visually structured with horizontal lines – consistent with the look and feel of the page dropdown. #2787

    • πŸ›  $tableWhitelist in the Database class is now renamed to $tables and a validity check for correct table names is fixed. #2788

    • The beforeSend option for emails can now be predefined in the config #2769

    πŸ› Bug fixes

    • πŸ›  Fixed off-center emoji position in the panel
    • πŸ›  Fixed overflowing text in breadcrumb #2755
    • πŸ›  Fixed broken this.$api.users.list() method (this broke pagination and the role filter in the users view) #2801
    • πŸ“œ Parsedown Extra no longer trims new line characters in some PHP environments
    • πŸ›  Fixed progress bar styling in Firefox #2784
    • πŸ–¨ You can now add pages in pages sections within user blueprints without errors #2771
    • Converting the $site object to string now returns the URL instead of throwing an error #2802
  • v3.4.2 Changes

    August 07, 2020

    πŸš€ This release is a quick patch for an annoying regression in 3.4.1 and a useful bug fix.

    πŸ›  Fixed template switching regression (#2758)

    πŸš€ We broke template switching in 3.4.1 and we are really sorry for it. This patch release will fix this regression. If your projects rely on template switching for pages, you should upgrade!

    πŸ›  Fixed endless loop for users without access to the site view (#2760)

    When you create user roles that don't have access to the site view with

    # /site/blueprints/users/my-role.ymlpermissions: access: site: false

    πŸš€ ... those users will be stuck in an endless loop after login, because they are not allowed to visit the site view, which is the default view. This release will fix this and redirect such users to their own account.

    Summer break

    πŸš€ We wanted to get this release out there before our summer holiday break. We will be back on September 1st with new features, new fixes and new energy. See you soon!

  • v3.4.1 Changes

    August 04, 2020

    πŸ†• New Features

    πŸ†• New Gap field

    The new gap field is a simple layout field to help you organise your fields more visually and create gaps in the field grid.


    fields: category: type: textwidth: 1/2gap: type: gapwidth: 1/4featured: type: togglewidth: 1/4text: - "no" - "yes"

    With conditional fields

    fields: hasHeadline: type: radiooptions: - yes - noheadline: type: textwidth: 1/2when: hasHeadline: yesgap: type: gapwidth: 1/2when: hasHeadline: notext: type: textarea

    Async api library

    πŸ‘ All API methods in the Panel now support async await as an alternative to promise callbacks. This helps to break out of callback hell.

    const page = await this.$api.pages.get("photography");console.log(page.title);

    πŸ†• New beforeSend option for $kirby->email()

    You can now access the phpMailer instance for more fine-grained control in the new beforeSend option:

    $kirby-\>email(['from' =\> '[email protected]', 'to' =\> '[email protected]', 'subject' =\> 'Thank you for your contact request', 'body' =\> 'We will never reply', 'transport' =\> [ 'type' =\> 'smtp', 'host' =\> '', 'port' =\> 465, 'security' =\> true, 'auth' =\> true, 'username' =\> '[email protected]', 'password' =\> 'randomString',], // new feature'beforeSend' =\>function ($mailer) { $mailer-\>SMTPOptions = ['ssl' =\> [ 'verify\_peer' =\> false, 'verify\_peer\_name' =\> false, 'allow\_self\_signed' =\> true] ]; return $mailer; } ]);

    You can also use this new option in email presets in your config file.

    πŸ†• New Dark Mode SVG favicon

    πŸ’» For Dark Mode users, the favicon of the panel will now automatically switch color and adjust to the dark browser bar.


    More new features …

    • πŸ†• New Form::content() method
    • πŸ†• New Vue.$helper.string.camelToKebab(string) helper
    • πŸ†• New Vue.$helper.isComponent(componentName) helper
    • Async store actions

    ✨ Enhancements

    • βž• Added unit tests for LanguageRoutes #2609
    • βž• Added missing hooks unit tests
    • We brought Kirby\Http\Request\Query in line with Kirby\Http\Query #2692

    πŸ›  Fixes

    βͺ We introduced an unintentional breaking change in 3.4.0 that broke plugin options in some third-party plugins. 3.4.1 reverts this breaking change. All plugins that already shipped a fix for this breaking change unfortunately have to roll back that fix as well. We are sorry for the hassle! (You can read more about the issue here: #2697)

    πŸ›  More fixes …

    • πŸ›  Fixed words option for Collection::search() #2698
    • πŸ›  Fixed error page in multilang setup #2609
    • πŸ›  Fixed issues with Umlauts in user email addresses #2600
    • Pass $originalPage in page.duplicate:after hook to fix breaking change
    • Structure fields no longer save unsaveable fields #2702
    • πŸ›  Fixed warning in Account view after logout #2713
    • πŸ›  Fixed warning in Settings view after logout
    • πŸ›  Set fixed types in fields to avoid issues in extended fields #2643
    • translate: false in a child of a structure field no longer saves null on secondary language #1602
    • πŸ›  Fixed certificate issue in Remote::post() requests #2745
    • πŸ›  Fixed unexpected behaviour in Html::tag() method #2743
  • v3.4.1-rc.1

    July 29, 2020
  • v3.4.0 Changes

    July 07, 2020

    πŸ†• New Features

    🍱 Search for files in the Panel πŸŽ‰

    Our global search in the Panel now also searches for files.

    Screen-Recording-2020-06-30-at-15 26 36

    Extensible search

    The Panel search is now also a core component and can be overwritten with your own search logic (#2368):

    Kirby::plugin('distantnative/fuzzy-search', ['components' =\> [ 'search' =\> function (Kirby $kirby, Collection $collection, string $query = null, $params = []) { // ...return $collection; } ] ]);

    🍱 Big hook improvements & wildcard hooks πŸ”₯

    • Hook arguments are now named and magically provided as requested (like in controllers). So it's now possible to just request the arguments the hook needs and in any order. Arguments that are not available will be set to null.
    • Support for wildcard hooks (e.g. page.*:before or page.create:* or *.create:* – all variations are supported!) that will be triggered for all event actions of the given type.
    • πŸ†• New $event object provided as argument for all hooks that contains all information about the triggered event. The $event argument can be used instead of or in addition to the individual hook arguments.

      return ['hooks' => [ 'page.*:before' => function ($page, $event) { var_dump($page); // $pagevar_dump($event->name()); // 'page.create:before'var_dump($event->type()); // 'page'var_dump($event->action()); // 'create'var_dump($event->state()); // 'before'var_dump($event->page()); // $pagevar_dump($event->input()); // $input }] ];

    πŸ’₯ Breaking-changes:

    • ⚑️ The method signature of $app->apply() and $app->trigger() has changed. Instead of a list of arguments, they now receive an associative array with named arguments. $app->apply() now also requires a third argument that tells the method which argument should be modified by the hooks. As both methods are marked for internal use and also not very useful in sites, the only use-case for them so far was hooks defined in plugins. Plugin authors who depend on any of the two changed methods need to update their plugins to support the new signature.
    • πŸ”Œ As the hook arguments are now detected by name and not by order, any hooks that don't use the variable naming as documented in the reference will receive null for those arguments instead.

    πŸ”Œ Hook migration checker plugin

    πŸš€ @lukasbestle has developed a migration checker plugin to help check for broken hooks in your installations. You can find the plugin attached to this release (as an "Asset") or download it from GitHub Gist. Please place the PHP file in site/plugins/migration/index.php and visit any frontend page of your Kirby site to check if you need to migrate some of your hooks. Make sure to delete the plugin again after the migration.

    πŸ†• New Structure Field features

    Duplicate option

    Duplicate option
    0️⃣ Duplicating is enabled by default. To disable, use the following syntax:

    fields: addresses: type: structureduplicate: falsefields: ......

    Prepend new entries

    With the new prepend option for structure fields, you can now add new entries to the top of the list instead of the bottom (getkirby/ideas#203)

    fields: addresses: type: structureprepend: truefields: ......

    πŸ†• New confirmation dialog to revert unsaved changes

    To prevent that unsaved changes can be accidentally deleted with the click of a button, we introduced a new confirmation dialog:
    βͺ Revert unsaved changes

    πŸ‘Œ Support for parentheses in KirbyTags (finally!)

    You can finally write parentheses in KirbyTags. For example:

    (image: my-image.jpg caption: A nice picture (by Ansel Adams))

    A huge Thank-you to @afbora for his StackOverflow hunt in order to find a proper solution.

    πŸ†• New collection filters for dates

    There are now date-specific collection filters that can be used like this:

    $collection-\>filterBy('date', 'date \>=', 'today');

    βœ… The advantage of these filters is that all date formats that can be parsed by PHP are supported (both in the fields and in the test string).

    The added filters are:

    • date ==
    • date !=
    • date >
    • date >=
    • date <
    • date <=
    • date between (or date ..)

    This feature is built on top of our enhanced V::date() validator. You can now also do the following validations with it:

    V::date($dateA, '==', $dateB);V::date($dateA, '!=', $dateB);V::date($dateA, '\>', $dateB);V::date($dateA, '\>=', $dateB);V::date($dateA, '\<', $dateB);V::date($dateA, '\<=', $dateB);

    πŸ‘ $kirby->impersonate(): Support for action function

    It is now possible to pass an action function to $kirby->impersonate(), which will run with the permissions of the impersonated user. The impersonated user is reset after the function has returned:

    $result = $kirby-\>impersonate('kirby', function ($user) { // $this is the $kirby object$email = $user-\>email(); // '[email protected]'return 'this will be returned to $result above'; });

    πŸ†• New permission

    It is now possible to hide files of a specific template from users with a specific role (or to hide files in general) (getkirby/ideas#554)

    πŸ†• New search settings for the multiselect field

    You can now fine-tune the search experience in multiselect fields. This is especially useful if you are providing long lists of options and the result list gets unusable.

    fields: categories: label: Categoriestype: multiselectsearch: # The search starts after entering at least 2 charactersmin: 2# The result list has a limit of 5 entries but can be expandeddisplay: 5options: panel: Paneltemplating: Templatingseo: SEOsecurity: Securityperformance: Performanceanalytics: Analyticsassets: Assetstext: Textforms: Formsutilities: Utilitiesintegrations: Integrationssocial: Social

    πŸ†• New callback method for fields

    It's sometimes useful to modify a field directly in a controller or template. This can now be done with the new callback field method.

    echo $page-\>title()-\>callback(function ($field) { $field-\>value = 'Title: ' . $field-\>value; return $field; });


    πŸ†• New global collectionMethods extension

    Kirby::plugin('your-name/collectionMethods', ['collectionMethods' =\> [ 'toCSV' =\> function () { // write some code to convert the entire // collection to CSV }] ]);

    πŸ”Œ The new toCSV method in this plugin example will now be available for all collections in Kirby (pages, files, users, etc.)

    πŸ†• New servers option

    πŸ‘ To overwrite Kirby's server check you can now set the servers option in your config. This can be used to run the Panel, even though the server setup might not officially be supported by us. It's at your own risk though.

    return ['servers' =\> ['apache', 'nginx', 'symfony'] ];

    πŸ†• New way to access native component handlers

    πŸ“œ When creating your own core components – to manipulate URLs, create thumbnails, parse markdown or more – you can now easily access the native behaviour of Kirby's components with the new $kirby->nativeComponent($componentName) method.

    Kirby::plugin('your-name/url-handler', ['components' =\> [ 'url' =\> function (Kirby $kirby, string $path = null, $options = null) { if (Str::startsWith($path, '@forum')) { return '' . str\_replace('@forum/', '', $path); } return $kirby-\>nativeComponent('url')($kirby, $path, $options); }] ]);

    There's more…

    • πŸ†• New image: icon and image: false options for items in pages or files sections.
    • βž• Added support for embedding YouTube playlists in the youtube and video KirbyTags as well as in Html::youtube() and Html::video() (getkirby/ideas#532)
    • βž• Added support for YouTube options (customizable player) in the youtube and video KirbyTags as well as in Html::video() and Html::youtube() (getkirby/ideas#437)
    • πŸ‘ Form fields now support a simple string as validation rule.
    • πŸ”Œ Permissions: You can now set your own actions in user blueprints and use them in your plugins to check for custom permissions.
    • πŸ†• New Kirby\Data\Xml class and support for XML in Data::encode($data, 'xml') and Data::decode($xml, 'xml')
    • βž• Added .. as an alias for the between collection filter
    • πŸ†• New $page->go() method, which automatically triggers a redirect to the page.
    • πŸ†• New global $kirby->contentToken() method (getkirby/ideas#554)
    • More complex tokens for page drafts and media URLs with the new content.salt option (#2612, getkirby/ideas#554)
    • πŸ†• New F::loadOnce() method (#2394)
    • πŸ‘ F::load(): Support for data variables (#2394)
    • A::nest(): New $ignore parameter
    • πŸ”§ The Remote class can now be configured in your site config with the remote option array.
    • Collection: New case-sensitive mode for custom collections
    • πŸ†• New $allowImpersonation argument for $kirby->user() (#2616)
    • πŸ†• New $props argument for Response::file() & Response::download() to support overrides (e.g. for headers)
    • System: The version and license key are now only available for authenticated users (with permissions if necessary)
    • πŸ†• New $lazy argument for App::instance(). This allows getting the app instance only if the app is already initialized.
    • πŸ‘ modified() methods now support specifying language for file, page and user models:

      $page->modified('c', 'date', 'de');

    • πŸ”Œ Kirby now accepts custom plugin types. This can be used to create plugins for plugins. E.g. the block plugins for the editor. (#2443)

    ✨ Enhancements

    πŸ”¨ Refactored Html and Xml classes

    • Made relevant methods from the Kirby\Toolkit\Html class available in the Kirby\Toolkit\Xml class
    • πŸ”¨ Full refactoring of the Html and Xml classes including tests with 100 % code coverage
      • Improve reliability and consistency of XML parsing and creation (the previous implementation lacked many features and didn't generate correct indentation)
      • Html now inherits from Xml to enable code sharing and access to the parsing and document creation methods in the Html class
      • Correct and improve information in doc blocks
      • Fix email and tel link generation in Html::a()
      • Html::email(): Fix link generation when called without text (the email address was previously not made the link text even though that is what was supposed to happen)
      • Html::tag(): Support for passing null as the $content to explicitly generate a void tag (was already documented like this but not supported)
      • Xml::value(): Proper CDATA support including edge-cases
      • Improve consistency of method arguments

    πŸ”¨ Refactored Database classes

    πŸ”‹ Features

    • πŸ‘ The $database->createTable() method now supports columns with a UNIQUE constraint
    • πŸ‘ The Db::column() and $query->column() database methods now support custom ORDER clauses so that you can order the results by any column and not just by the primary key
    • Database results can now be fetched using a custom callback:

      // prepare a query with the options you need$query = $database->table('simpsons')->fetch(function ($data, $key) { return new Simpson($data); });// this line now executes the query and returns an// array with the return values from your callback$results = $query->all();

    πŸ› Bug fixes

    • The creation of database tables with primary keys using $database->createTable() now works reliably with SQLite (#2234)
    • The Database fail mode is now no longer reset after each query, which makes it more predictable as you can't know how many queries an operation needs internally. You can now enable the fail mode once for the database connection and it will stay that way until it is manually disabled again.
    • Database: The insert ID is now only fetched from the database when an INSERT query was executed to improve compatibility with some database servers (#2347)
    • ⚑️ Database: The internal cache of valid table names is now immediately updated after tables are created or dropped, which enables further queries in the same request

    πŸ”¨ Refactoring

    • πŸ”¨ The Database\Db class and parts of the Database\Sql classes have been refactored, which has changed some internal method signatures.
    • πŸ”¨ We have added a lot of unit tests to the Database classes and will further refactor and improve the classes with 3.5.0.

    πŸ‘ Options: Full support for the dot notation

    πŸ”Œ Options for Kirby and for plugins can be defined as nested arrays or using the dot notation:

    return [// dot notation with a bit of nesting'superwoman.superplugin' =\> [ 'my.option' =\> 'with a value'], // nested arrays'superwoman' =\> ['superplugin' =\> [ 'my' =\> [ 'option' =\> 'with a value'] ] ], ];

    Both variants can now be used fully interchangeably and in any combination.

    πŸ’₯ Breaking-change:

    0️⃣ To ensure proper nesting, Kirby relies on the plugin option default values defined in the plugin using the options extension. If your plugin uses a nested structure in the option defaults, the defaults need to be changed to use the dot notation.

    πŸ”Œ Only options registered in that way can be set in all supported ways (dot notation, fully or partially nested) in the site config. You can read more about this in the reference.

    Whoops facelift


    More enhancements

    • Url::isAbsolute() now also checks for the geo protocol (#2536)
    • Cards: more sensible min-width for size: tiny.
    • You can now replace files with a different mime type but the same extension. (#2519)
    • The options API for fields (checkboxes, radio, multiselect, tags) now uses cURL instead of file_get_contents for enhanced reliability and better error handling (#2330)
    • πŸ‘Œ Improved error handling in our Exif camera class
    • πŸ‘Œ Improved performance of Page::find()
    • πŸ”¨ Refactored error handling with Whoops to handle errors more efficiently and earlier in the app flow.
    • The ready callback is now able to overwrite more options (whoops, debug, home, error, slugs)
    • πŸ‘Œ Improved I18n::translateCount() method (#2430 & #2431)
    • πŸ‘ Cookie: Support for SameSite cookies (#2601)
    • Session: SameSite=Lax for session cookies (#2601)
    • F::load(): Prevent overwriting $fallback (#2394)
    • πŸ‘ Query: Better error handling
    • πŸ‘ Query: Support quote escaping in strings
    • πŸ‘ Query: Full support for nested methods (#2511)
    • πŸ”€ Controller data is now merged safely with with original data (#2559)
    • Bubble up KirbyTag exceptions in debug mode (#2625)
    • βž• Additional Japanese slug rules
    • Field validation is now passed on empty fields (#2592)
    • πŸ“œ Markdown and SmartyPants parsers now accept empty/null values
    • The Remote class now checks for valid TLS certificates in case of HTTPS requests.
    • The Data::decode() and Data::encode() methods are now used throughout Kirby instead of i.e. Yaml::encode(). This allows to create your own data handlers and decoders, which will then be used everywhere.
    • ⚑️ Updated translations
    • ⚑️ Updated PHP version check: Kirby 3.4.0+ supports PHP 7.2 to 7.4. Versions below 7.2 or above 7.4 (= 7.5.0 or greater) are not supported.
    • πŸ‘Œ Improved setup guide in Panel
    • πŸ‘ Better error handling when the Panel cannot be installed
    • Str::template() keeps placeholders in the result string if no value or fallback was passed (#2307)
    • Str::excerpt() allows to pass a $rep that gets added without an additional space to the end of the excerpt. (getkirby/ideas#525)

    πŸ›  Fixes

    • πŸ‘‰ Useless action buttons are no longer displayed in the upload dialog (#2327)
    • πŸ›  Fixed page duplicating issues (#2514 & #2515)
    • Downloads are no longer cached in Chrome (#2513)
    • πŸ‘‰ Use correct page model when creating new pages
    • ⚑️ Models no longer keep old content in memory cache after updates (#2569)
    • πŸ›  Fixed bug in $page->changeTemplate() (#2567)
    • πŸ›  Fixed zero value bug in range field (#2549)
    • The referrer is no longer submitted when clicking on external links in the Panel
    • F::niceSize(): kB is now KB (#2607)
    • πŸ›  File sorting is now fixed for files sections that use "parent" (#2617)
    • route:after is no longer called on $routeβ†’next() (#2418)
    • 0️⃣ Impersonation in API routes is now blocked by default (#2616)
    • πŸ›  Fixed conflicting pagination in files and pages sections
    • πŸ‘‰ User role switching is now more reliable (#2380)
    • The change title dialog no longer closes on mouseup (#2557)
    • πŸ›  Fixed typo in date picker field: Feburary (#2591)


    • 201 commits
    • 39 closed tickets
    • πŸ”€ 80 merged PRs
    • πŸš€ Days since last release: ~2 months

    Contributors (in alphabetical order)

  • v3.4.0-rc.3

    July 06, 2020
  • v3.4.0-rc.2

    July 02, 2020
  • v3.4.0-rc.1

    June 30, 2020
  • v3.3.6 Changes

    April 27, 2020

    πŸš€ While we are busy working on 3.4, this release is a security patch for a minor issue related to .dev domains and reverse proxies.

    About our registration block

    πŸ”’ In order to protect new installations on public servers that don't have an admin account for the Panel yet, we block account registration there by default. This is a security feature, which we implemented years ago in Kirby 2. It helps to avoid that you forget registering your first admin account on a public server.

    πŸ”’ In this case – without our security block – someone else might theoretically be able to find your site, find out it's running on Kirby, find the Panel and then register the account first. It's an unlikely situation, but it's still a certain risk.

    To be able to register the first Panel account on a public server, you have to enforce the installer via a config setting. This helps to push all users to the best practice of registering your first Panel account on your local machine and upload it together with the rest of the site.

    The issue

    As noted by Jukka Rautanen, this installation block still assumed that .dev domains are local domains, which is no longer true. In the meantime, those domains became publicly available. This means that our installation block is no longer working as expected if you use a .dev domain for your Kirby site. We've also used the chance to improve the local installation check if your site is behind a reverse proxy.

    Am I affected?

    You are only affected if:

    1. you use a .dev domain or your site is behind a reverse proxy &
    2. you have not yet registered your first Panel account on the public server &
    3. someone finds your site and tries to login at before you register your first account.

    You are not affected if you have already created one or multiple Panel accounts (no matter if on a .dev domain or behind a reverse proxy).

  • v3.3.5 Changes

    March 17, 2020

    πŸ†• New Features


    You can use the new $page->isPublished() method as the opposite of $page->isDraft(), which will include $page->isListed() and $page->isUnlisted() states. getkirby/ideas#375

    πŸ†• New translation selectors

    🌐 The panel DOM has new CSS multi-lang selectors, which you can use to customize the panel based on the currently selected translation.

    .k-panel[data-translation=en] {}.k-panel[data-translation-default] {}.k-panel:not([data-translation-default]) {}.k-panel:not([data-translation-default]) .k-field:not([data-translate]) {}

    Custom collection for siblings methods

    You can now pass a collection to all sibling methods to get more useful results #2321

    $prevPage = $page-\>prev($page-\>index()-\>listed()-\>filterBy('template', 'text-note')-\>sortBy('date', 'desc') );

    This works for all siblings methods for pages, files and users:

    • indexOf
    • isFirst
    • isLast
    • isNth
    • hasNext
    • hasNextListed ($page)
    • hasNextUnlisted ($page)
    • hasPrev
    • hasPrevListed ($page)
    • hasPrevUnlisted ($page)
    • next
    • nextAll
    • nextListed ($page)
    • nextUnlisted ($page)
    • prev
    • prevAll
    • prevListed ($page)
    • prevUnlisted ($page)


    We've added a new Dir::exists($path) method to the toolkit to keep it consistent with the F class and its F::exists($path) method

    ✨ Enhancements

    • πŸ‘ The textarea field uses CMD + K instead of CMD + L for the link shortcut for better compatibility #1898
    • πŸ‘Œ Improved button labels in picker fields
    • πŸ‘Œ Improved page redirection on for detected languages #2484
    • The uploads option is now checked before accepting dropped files in textareas #2482
    • βž• Added support for late binding in FileActions to enable subclasses of File
    • πŸ‘ Kirby string queries now support numeric parts in the query #2462
    • βœ… We've improved our PHPUnit test speed by a huge margin
    • ⚑️ Updated Czech translation

    πŸ›  Fixes

    • πŸ›  Fixed translation and language issue with routing in multi-lang setups #2428
    • πŸ›  Fixed overflowing cards in narrow columns #1666
    • πŸ›  Fixed z-index issue in sticky columns with dialogs #2477
    • πŸ›  Fixed passing data to kirbytag() helper #2474
    • ⚑️ Cached user data for the authenticated user is now refreshed correctly on $user->update() #2486
    • Empty locales in the language dialog are now reliably caught #2455
    • πŸ›  Fixed overflow for long filenames in dialogs and view titles #2449
    • πŸ›  Fixed upload progress bar #2463
    • πŸ›  Fixed dialog width on mobile #2415
    • πŸ›  Fixed site title on language switch #2396
    • The locale array in language files is now always added in a human-readable way #2426
    • πŸ›  Fixed controller data for content representations if PHP template is not present #2471