Translating tag url's in kirby 4

Hi - I am using tags to filter various pages in Kirby 4, and am trying to use custom url’s without affecting the displayed text for the tag itself.

For example, I have a tag with the value ‘video & photography’ but I want the url for this to read

‘/projects/tag:video-photography’

I had initially thought I could use the following in my blueprint:

options:
 - value: video & photography
   text: video & photography

But now know this won’t have an affect. I have done some digging and read that I can use translations, but can’t find an example of how to do this in the config file, or how it could work with the new translations feature in kirby 4.

Are there any solid examples I can use? Thanks!

Controller:

<?php
return function($page) {

  // fetch the basic set of pages
  $projects = $page->children()->listed()->flip();

  // fetch all tags
  $tags = $projects->pluck('tags', ',', true);

  // add the tag filter
  if($tag = param('tag')) {
    $projects = $projects->filterBy('tags', $tag, ',');
  }

  // apply pagination
  $projects = $projects->paginate(10);
  $pagination = $projects->pagination();

  return compact('projects', 'tags', 'tag', 'pagination');

};

Template:

<!-- tags -->
<div class="container d-flex justify-content-center">
    <?php foreach($tags as $tag): ?>
        <a href="<?= url($page->url(), ['params' => ['tag' => $tag]]) ?>" class="px-2">
        <?= html($tag) ?>
        </a>
    <?php endforeach ?>
</div>

<!-- projects -->
<div class="container">
    <div class="row">
        <?php foreach($projects as $project): ?>
        <div class="col-lg-4">
        <h1><a href="<?= $project->url() ?>"><?= $project->title()->html() ?></a></h1>
        <?= $project->text()->excerpt(300) ?>
        </div>
        <?php endforeach ?>
    </div>
</div>

Translate? Looks more like sluggify to me?

If so, you can use Str::slug($tag), but keep in mind that you need to apply the same logic when filtering in this case.

Well I’d like to use the key value pairs in case I have more complex renaming - however can see there is a new translations feature. Either way I can’t find any documentation at all about key value pairs in either the config file or in the panel (v4) for this purpose and was hoping I could be steered towards something. Thanks

The main problem is that it is not clear what you want to achieve. What do you exactly mean when you say “translate”. For me that means I translate English “hello” to German “hallo”. So that is the first issue.

Then next:

What’s the point here? Value and text are exactly the same. But in general, yes, you can assign text and value to a tags field: Tags | Kirby CMS, paragraph below autocomplete.

I can’t find the link now, but I had read somewhere else on the forum where it was suggested to use kirby 4’s new translation feature via the panel rather than manually adding key value pairs directly in the config.

As for the example of the value and text from my blueprint, this was just an example I wrote out, it should have had something more like this:

options:
 - value: video-photography
   text: video & photography

However it’s a little immaterial as I can’t retrieve the text, only the value, as covered here.

If v4 doesn’t change the approach that’s fine, I just want to find a signle cookbook article/tutorial/post about how to add a map of key value pairs in config for custom tag url’s.

Having said that I can probably get away with the slugify option for now.

i have this for my template but unsure what to do with controller, are you please able to let me know where the Str::slug($tag) needs adding?

thanks so much

template

<?php snippet('head') ?>

<h1>Projects</h1>

<!-- tags -->
<div class="container d-flex justify-content-center">
    <?php foreach($tags as $tag): ?>
        <a href="<?= url($page->url(), ['params' => ['tag' => Str::slug($tag)]]) ?>" class="px-2">
        <?= html($tag) ?>
        </a>
    <?php endforeach ?>
</div>

<!-- projects -->
<div class="container">
    <div class="row">
        <?php foreach($projects as $project): ?>
        <div class="col-lg-4">
        <h1><a href="<?= $project->url() ?>"><?= $project->title()->html() ?></a></h1>
        <?= $project->text()->excerpt(300) ?>
        </div>
        <?php endforeach ?>
    </div>
</div>


<!-- pagination -->
<nav class="pagination">
  <?php if($pagination->hasPrevPage()): ?>
  <a href="<?= $pagination->prevPageUrl() ?>">previous posts</a>
  <?php endif ?>

  <?php if($pagination->hasNextPage()): ?>
  <a href="<?= $pagination->nextPageUrl() ?>">next posts</a>
  <?php endif ?>
</nav>

<?php snippet('footer') ?>

controller:

<?php
return function($page) {

  // fetch the basic set of pages
  $projects = $page->children()->listed()->flip();

  // fetch all tags
  $tags = $projects->pluck('tags', ',', true);

  // add the tag filter
  if($tag = param('tag')) {
    $projects = $projects->filterBy('tags', $tag, ',');
  }

  // apply pagination
  $projects = $projects->paginate(10);
  $pagination = $projects->pagination();

  return compact('projects', 'tags', 'tag', 'pagination');

};

If only I knew what you are referring to…

I’m talking about the language feature in kirby 4 for translations of content:

In several posts this is mentioned as an alternative to querying the blueprint or using key value pairs in the config for mapping values from tags.

Ok, guess you mean the new feature to translate language variables from the Panel.

And of course, you could add your values like value: video-photography there and translate it, so that you could use it later in the frontend. But you would have to do that manually.

That’s right. But it sounds like i’m on a red herring. For now I’m just going back to the drawing board and going to try removing spaces and any ‘&’ symbol. I’m a little stuck on whether to use urldecode or slugify for this. I have attempted to use urldecode for this but it’s not having any effect which is odd - no errors but no change in the url.

<div class="container d-flex justify-content-center">
    <?php foreach($tags as $tag): ?>
        <a href="<?= url($page->url(), ['params' => ['tag' => urldecode($tag)]]) ?>" class="px-2">
        <?= html($tag) ?>
        </a>
    <?php endforeach ?>
</div>

<?php
return function($page) {

  // fetch the basic set of pages
  $projects = $page->children()->listed()->flip();

  // fetch all tags
  $tags = $projects->pluck('tags', ',', true);

  // add the tag filter
  if($tag = urldecode(param('tag'))) {
    $projects = $projects->filterBy('tags', $tag, ',');
  }
  
  // apply pagination
  $projects = $projects->paginate(10);
  $pagination = $projects->pagination();

  return compact('projects', 'tags', 'tag', 'pagination');

};

Here you should normally urlencode, not decode, but that is unnecessary, because Kirby takes care of this automatically when you use the url() function with params.

Hm thanks - still no luck though unfortunately.

Whether it’s either of the following I still get:

“tag:video%20%26%20photography”

for a tag value of “video & photography”

<a href="<?= url($page->url(), ['params' => ['tag' => $tag]]) ?>">

<a href="<?= url($page->url(), ['params' => ['tag' => urlencode($tag)]]) ?>" >

When you expect what?

I’d like “tag:video-photography”

From what I understood this was a job for urldecode rather than slugify but maybe I’m wrong?

No, urlencoding only replaces unsafe characters with url-safe characters, but does not sluggify.

Then we are back to step 1, where you would sluggify and then filter by the sluggified version.

Okay yes I have done this now- I might revisit using the multi-language panel feature another time for more ability to customise tags in the future