Kirby()->language() returns array within plugin


I am using the awesome merx shop plugin.
In config.php I can define several options like so:

  'ww.merx.ordersPage' => 'orders',
  'ww.merx.checkoutPage' => 'checkout',

within the plugin the option is called using

this URL seems to always default to the german version (eg /de/kasse/), regardless of what language is currently used.
I tried adding a parameter to the option function ['language' => kirby()->language()] but the return of the function kirby()->language() is an array and is not the currently selected language.

I can not access $kirby, which is guess is due to the fact that I am working within a plugin.

So the question is two fold:

  • how to I get the current user language within a plugin
  • or how to I get the correct language url for a given site


The url() helper accepts a language code as second parameter:

$languageCode = $kirby->language()->code();
url(option('ww.merx.checkoutPage'), $languageCode)

Call to a member function language() on null within the plugin, or within config.php

Please try again with kirby()->language()->code();. In a plugin, $kirby is not always defined yet.

hm. I am not sure if my text above was wrong or unclear, but hey, people are at least trying to help:

echo kirby()->language()->code()
# de

selected language is it


Kirby\Cms\Language Object
    [code] => de
    [default] => 1
    [direction] => ltr
    [locale] => Array
            [6] => de_CH

    [name] => Deutsch
    [rules] => Array
            [Ä] => AE
            [Ö] => OE
            [Ü] => UE
            [ß] => ss
            [ä] => ae
            [ö] => oe
            [ü] => ue


again, current language is it.

echo $kirby->language()
# it

this is mentioned in my initial post :wink:

Where exactly is url(option('ww.merx.checkoutPage')) used in the plugin?

“deep” inside, or do you need the exact location?
But just kirby()->language()->code() inside config.php leads to the same error

I couldn’t find that line anywhere in the plugin.

/merx/src/payment.php Line 46ff:

    public static function createPayPalPayment(float $total): HttpResponse
        $client = self::getPayPalClient();
        $siteTitle = (string)site()->title();

        $request = new OrdersCreateRequest();
        $applicationContext = array_merge([
            'cancel_url' => url(option('ww.merx.successPage')),
            'return_url' => url(option('ww.merx.successPage')),
            'user_action' => 'PAY_NOW',
            'shipping_preference' => 'NO_SHIPPING',
            'brand_name' => $siteTitle,

edit: this is a different option, but the usage is the same afaik

edit2: if not defined, the default values are set in index.php:

Kirby::plugin('ww/merx', [
    'options' => [
        'successPage' => 'success',
        'ordersPage' => 'orders',
        'currency' => 'EUR',
        'currencySymbol' => '€',
        'email' => '',
        'production' => false,

Pinging @tobiasfabian

so testing a bit more: I created a simple plugin:

Kirby::plugin('eye/test', [
    'hooks' => [
        'route:before' => function ($route, $path, $method) {
            echo kirby()->language();

now the echo results in de, even though <?= $kirby->language() ?> is it

I’ll have a closer look tomorrow.

I assume it has something to do with these lines.
If you want, you can comment them out and see if it works.

Hm no, as the if condition is not triggered: languages is set, as I have a multi-lang setup, and i’ve testet it :wink:
Also here echo kirby()->language()->code(); shows the wrong language

(edit: removed mention)

I think I am narrowing it down:
merx gets called via post route (not using any language prefix)

testing with:

      'pattern' => 'api-test/test',
      'action' => function() {
        echo kirby()->language()->code();exit;

this always shows de, so the default language.
This sort of makes sense, as there is no correct language routing involved.

So now the question is: how to get the language?

Or do I have do to prefix routing in order to let kirby() know which language is selected?

1 Like

There are multiple options:

Either add a (:alpha)-placeholder at the beginning of the pattern 'pattern' => '(:alpha)/api-test/test' and then add a variable in the closure: 'action' => function ($language). Then you should be able to use the $language from the URL in your closure:

      'pattern' => '(:alpha)/api-test/test',
      'action' => function($language) {
        echo $language;exit;

Or use multi-lang setup:

1 Like

This one sounds promising.

I tried this route, which works for me:

'pattern' => 'add',
'language' => '*',      
'method' => 'post',
'action'  => function ($language) {
  $id = get('id');
  $quantity = get('quantity');
  try {
      'id' => $id,
      'quantity' => $quantity,
    $kirby = kirby();
    // dump(kirby()->language());
    return 'success';
  } catch (Exception $ex) {
    return $ex->getMessage();
1 Like

thank you all so much!!!
this works now :slight_smile: