Skip to content

Commit

Permalink
Talks locale links (#196)
Browse files Browse the repository at this point in the history
This improves how talks in the other language are displayed.

Up until now, you could have a talk in English on a `.cz` site and vice
versa which I think caused some troubles for search engines and people
alike. So now when the talk is in English, you'll have a `.com` link in
the list of talks together with a flag icon and a language name. Also,
HTTP redirects will take you where you're supposed to be, English talks
on `.com` site etc., when you're not.

Also, if there's an other locale talk, and it's correctly paired with
the original locale talk using `key_translation_group`, you'll have a
link in the header directly to the talk in the other locale.

Follow-up to #194 #192
  • Loading branch information
spaze authored Aug 14, 2023
2 parents 45d1c74 + a12a6cb commit 1c87bc0
Show file tree
Hide file tree
Showing 27 changed files with 335 additions and 38 deletions.
1 change: 1 addition & 0 deletions site/app/Admin/Presenters/TalksPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public function __construct(
public function renderDefault(): void
{
$this->template->pageTitle = $this->translator->translate('messages.title.talks');
$this->template->defaultLocale = $this->translator->getDefaultLocale();
$this->template->upcomingTalks = $this->talks->getUpcoming();
$this->template->talks = $this->talks->getAll();
}
Expand Down
12 changes: 7 additions & 5 deletions site/app/Admin/Presenters/templates/Talks/default.latte
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{define #itemTalk, MichalSpacekCz\Talks\Talk $item, bool $upcoming}
<li><a n:href="Talks:talk $item->getId()"><strong n:tag-if="$upcoming">{$item->getTitle()}</strong></a>
{define #itemTalk, MichalSpacekCz\Talks\Talk $item, bool $upcoming, string $defaultLocale}
<li>
<a n:href="Talks:talk $item->getId()"><strong n:tag-if="$upcoming">{$item->getTitle()}</strong></a>
<small n:if="$item->getLocale() !== $defaultLocale">{icon flag} {_"messages.locales.{$item->getLocale()}"}</small>
<small><strong class="date">{$item->getDate()|localeDay}</strong>, {$item->getEvent()}</small>
<span n:if="$item->isHasSlides()" title="{_messages.label.slides}">{icon images}</span>
<span n:if="$item->getVideo()->getVideoHref()" title="{_messages.label.videorecording}">{icon camera-video}</span>
<small>(<a n:href="slides $item->getId()">upravit slajdy</a>)</small>
</li>
</li>
{/define}

{define #content}
Expand All @@ -19,11 +21,11 @@
<ol reversed>
{foreach $upcomingTalks as $item}
{var $upcoming = true}
{include #itemTalk, item: $item, upcoming: $upcoming}
{include #itemTalk, item: $item, upcoming: $upcoming, defaultLocale: $defaultLocale}
{/foreach}
{foreach $talks as $item}
{var $upcoming = false}
{include #itemTalk, item: $item, upcoming: $upcoming}
{include #itemTalk, item: $item, upcoming: $upcoming, defaultLocale: $defaultLocale}
{/foreach}
</ol>
{/define}
52 changes: 52 additions & 0 deletions site/app/Application/LocaleLink.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
declare(strict_types = 1);

namespace MichalSpacekCz\Application;

class LocaleLink
{

public function __construct(
private readonly string $locale,
private readonly string $languageCode,
private readonly string $languageName,
private readonly string $url,
) {
}


public function getLocale(): string
{
return $this->locale;
}


public function getLanguageCode(): string
{
return $this->languageCode;
}


public function getLanguageName(): string
{
return $this->languageName;
}


public function getUrl(): string
{
return $this->url;
}


public function withUrl(string $url): self
{
return new self(
$this->getLocale(),
$this->getLanguageCode(),
$this->getLanguageName(),
$url,
);
}

}
15 changes: 12 additions & 3 deletions site/app/Application/LocaleLinkGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ class LocaleLinkGenerator implements LocaleLinkGeneratorInterface
private const DEFAULT_PARAMS = '*';


/**
* @param array<string, array{code:string, name:string}> $languages
*/
public function __construct(
private readonly RouterFactory $routerFactory,
private readonly IRequest $httpRequest,
private readonly IPresenterFactory $presenterFactory,
private readonly LinkGenerator $linkGenerator,
private readonly Translator $translator,
private readonly array $languages,
) {
}

Expand All @@ -35,7 +39,7 @@ public function __construct(
*
* @param string $destination destination in format "[[[module:]presenter:]action] [#fragment]"
* @param array<string, array<string, string|null>> $params of locale => [name => value]
* @return array<string, string> of locale => URL
* @return array<string, LocaleLink> of locale => URL
* @throws InvalidLinkException
*/
public function links(string $destination, array $params = []): array
Expand All @@ -48,7 +52,12 @@ public function links(string $destination, array $params = []): array
}
if (count($router->getRouters())) {
$linkGenerator = new LinkGenerator($router, $this->httpRequest->getUrl(), $this->presenterFactory);
$links[$locale] = $linkGenerator->link($destination, $this->getParams($params, $locale));
$links[$locale] = new LocaleLink(
$locale,
$this->languages[$locale]['code'],
$this->languages[$locale]['name'],
$linkGenerator->link($destination, $this->getParams($params, $locale)),
);
}
}
}
Expand Down Expand Up @@ -97,7 +106,7 @@ public function allLinks(string $destination, array $params = []): array
}
return array_merge(
[$locale => $this->linkGenerator->link($destination, $this->getParams($params, $locale))],
$links,
array_map(fn(LocaleLink $localeLink): string => $localeLink->getUrl(), $links),
);
}

Expand Down
2 changes: 1 addition & 1 deletion site/app/Application/LocaleLinkGeneratorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface LocaleLinkGeneratorInterface
/**
* @param string $destination destination in format "[[[module:]presenter:]action] [#fragment]"
* @param array<string, array<string, string|null>> $params of locale => [name => value]
* @return array<string, string> of locale => URL
* @return array<string, LocaleLink> of locale => URL
* @throws InvalidLinkException
*/
public function links(string $destination, array $params = []): array;
Expand Down
2 changes: 1 addition & 1 deletion site/app/Articles/Blog/BlogPosts.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public function enrich(BlogPost $post): void
$post->href = $this->linkGenerator->link('Www:Post:', $params);
} else {
$links = $this->localeLinkGenerator->links('Www:Post:', $this->localeLinkGenerator->defaultParams($params));
$post->href = $links[$post->locale];
$post->href = $links[$post->locale]->getUrl();
}
}

Expand Down
5 changes: 5 additions & 0 deletions site/app/Form/TalkFormFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public function create(callable $onSuccess, ?Talk $talk = null): Form
$form = $this->factory->create();
$allTalks = $this->getAllTalksExcept($talk ? (string)$talk->getAction() : null);

$form->addInteger('translationGroup', 'Skupina překladů:')
->setRequired(false);
$form->addSelect('locale', 'Jazyk:', $this->locales->getAllLocales())
->setRequired('Zadejte prosím jazyk')
->setPrompt('- vyberte -');
Expand Down Expand Up @@ -112,6 +114,7 @@ public function create(callable $onSuccess, ?Talk $talk = null): Form
$this->talks->update(
$talk->getId(),
$values->locale,
$values->translationGroup,
$values->action,
$values->title,
$values->description,
Expand Down Expand Up @@ -145,6 +148,7 @@ public function create(callable $onSuccess, ?Talk $talk = null): Form
} else {
$talkId = $this->talks->add(
$values->locale,
$values->translationGroup,
$values->action,
$values->title,
$values->description,
Expand Down Expand Up @@ -185,6 +189,7 @@ public function setTalk(Form $form, Talk $talk, SubmitButton $submit): void
$values = [
'action' => $talk->getAction(),
'locale' => $talk->getLocaleId(),
'translationGroup' => $talk->getTranslationGroupId(),
'title' => $talk->getTitleTexy(),
'description' => $talk->getDescriptionTexy(),
'date' => $talk->getDate()->format('Y-m-d H:i'),
Expand Down
21 changes: 21 additions & 0 deletions site/app/Talks/Talk.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ class Talk
public function __construct(
private readonly int $id,
private readonly int $localeId,
private readonly string $locale,
private readonly ?int $translationGroupId,
private readonly ?string $action,
private readonly ?string $url,
private readonly Html $title,
private readonly string $titleTexy,
private readonly ?Html $description,
Expand Down Expand Up @@ -55,12 +58,30 @@ public function getLocaleId(): int
}


public function getLocale(): string
{
return $this->locale;
}


public function getTranslationGroupId(): ?int
{
return $this->translationGroupId;
}


public function getAction(): ?string
{
return $this->action;
}


public function getUrl(): ?string
{
return $this->url;
}


public function getTitle(): Html
{
return $this->title;
Expand Down
13 changes: 13 additions & 0 deletions site/app/Talks/TalkFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

namespace MichalSpacekCz\Talks;

use Contributte\Translation\Translator;
use MichalSpacekCz\Application\LocaleLinkGeneratorInterface;
use MichalSpacekCz\Formatter\TexyFormatter;
use MichalSpacekCz\Media\Exceptions\ContentTypeException;
use MichalSpacekCz\Media\VideoFactory;
use Nette\Application\UI\InvalidLinkException;
use Nette\Database\Row;

class TalkFactory
Expand All @@ -14,19 +17,29 @@ class TalkFactory
public function __construct(
private readonly TexyFormatter $texyFormatter,
private readonly VideoFactory $videoFactory,
private readonly Translator $translator,
private readonly LocaleLinkGeneratorInterface $localeLinkGenerator,
) {
}


/**
* @throws ContentTypeException
* @throws InvalidLinkException
*/
public function createFromDatabaseRow(Row $row): Talk
{
if ($this->translator->getDefaultLocale() !== $row->locale && $row->action) {
$links = $this->localeLinkGenerator->links('Www:Talks:talk', $this->localeLinkGenerator->defaultParams(['name' => $row->action]));
$url = isset($links[$row->locale]) ? $links[$row->locale]->getUrl() : null;
}
return new Talk(
$row->id,
$row->localeId,
$row->locale,
$row->translationGroupId,
$row->action,
$url ?? null,
$this->texyFormatter->format($row->title),
$row->title,
$row->description ? $this->texyFormatter->formatBlock($row->description) : null,
Expand Down
31 changes: 31 additions & 0 deletions site/app/Talks/TalkLocaleUrls.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
declare(strict_types = 1);

namespace MichalSpacekCz\Talks;

use Nette\Database\Explorer;

class TalkLocaleUrls
{

public function __construct(
private readonly Explorer $database,
) {
}


/**
* @return array<string, string> locale => action
*/
public function get(Talk $talk): array
{
if (!$talk->getTranslationGroupId()) {
return [];
}
return $this->database->fetchPairs(
'SELECT l.locale, t.action FROM talks t JOIN locales l ON t.key_locale = l.id_locale WHERE t.key_translation_group = ?',
$talk->getTranslationGroupId(),
);
}

}
Loading

0 comments on commit 1c87bc0

Please sign in to comment.