Multi-lang site and google search console, duplicate without user-selected canonical

I checked the google searched console and notice the following:

  • Duplicate without user-selected canonical

The site uses the sitemap from the cookbook: https://getkirby.com/docs/cookbook/content/sitemap

Also, as you can see google decided to set .com/details and .com/contact as duplicates and not the secondary language version.

All pages are translated. There is a …com/sitemap.xml that has been added to the search console. There is no …com/fr/sitemap.xml

Any suggestions on how to fix this?

Google suggests to choose canonical URLs, but does that mean secondary languages won’t get indexed? https://support.google.com/webmasters/answer/139066

This cookbook page is only for ONE language websites.
But you can use one of the plugins, which supports multi language websites, look at https://getkirby.com/plugins?category=seo

1 Like

I don’t think you have to worry about duplicate content as long as you have real translated pages, see also these Google documents (then canonical links are not necessary)
https://support.google.com/webmasters/answer/182192?hl=en
https://support.google.com/webmasters/answer/189077

1 Like

Thanks!

Hint:
Follow @texnixe’s second link https://support.google.com/webmasters/answer/189077 and open the accordion “Sitemap”.
There we can read, that we have to link to ALL (!!!) languages by using
‘<xhtml:link rel=“alternate” hreflang=" … ">’ …

This is missing in the cookbook article.

If we search for an older article here in the forum, we can read a discussion about this…

Thanks @anon77445132, almost done! Here’s my current sitemap.xml that works with both single and multi-lang setups.

What I’m trying to fix is the lastmod date. How do I check if a secondary language .txt file exists? Something like (this doesn’t work):

<?php if ($p->contentFile($language->code())): ?>
  <lastmod><?php echo F::modified($p->contentFile($language->code()), 'c') ?></lastmod>
<?php else: ?>
  <lastmod><?= $p->modified('c') ?></lastmod>
<?php endif ?>

:point_up_2: Fixed, code below is updated.

Full code:

<?= '<?xml version="1.0" encoding="utf-8"?>'; ?>
<?php if (kirby()->languages()->count() > 1): ?>
  <urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="https://www.w3.org/1999/xhtml">

    <?php foreach ($pages as $p): ?>
      <?php if (in_array($p->uri(), $ignore)) continue ?>

        <?php foreach(kirby()->languages() as $language): ?>
          <url>
            <loc><?= html($p->url($language->code())) ?></loc>

            <?php foreach(kirby()->languages() as $languageAlt): ?>

              <xhtml:link rel="alternate" hreflang="<?php echo $languageAlt->code() ?>" href="<?= $p->url($languageAlt->code()) ?>"/>

            <?php endforeach ?>

            <?php if ($p->translation($language->code())->exists()): ?>
              <lastmod><?php echo F::modified($p->contentFile($language->code()), 'c') ?></lastmod>
            <?php else: ?>
              <lastmod><?= $p->modified('c') ?></lastmod>
            <?php endif ?>

            <priority><?= ($p->isHomePage()) ? 1 : number_format(0.5 / $p->depth(), 1) ?></priority>
          </url>
        <?php endforeach ?>

    <?php endforeach ?>

  </urlset>
<?php else: ?>
  <urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">

    <?php foreach ($pages as $p): ?>
      <?php if (in_array($p->uri(), $ignore)) continue ?>
        <url>
          <loc><?= html($p->url()) ?></loc>
          <lastmod><?= $p->modified('c') ?></lastmod>
          <priority><?= ($p->isHomePage()) ? 1 : number_format(0.5 / $p->depth(), 1) ?></priority>
        </url>
    <?php endforeach ?>

  </urlset>
<?php endif ?>

I’ve also added the following to the header:

<?php if ($kirby->languages()->count() > 1): ?>
  <?php foreach($kirby->languages() as $language): ?>

    <link rel="alternate" hreflang="<?php echo $language->code() ?>" href="<?= $page->url($language->code()) ?>">

  <?php endforeach ?>
<?php endif ?>
1 Like

You can check if a translation exists with $page->translation()->exists().

Hmm still doesn’t work :thinking: when a secondary language hasn’t been edited the .txt file doesn’t exist yet, it falls back to the primary language file. I need to check if the .txt file exists or not.

Yes, and with $page->translation($languageCode)->exists() you can check if a .txt file in the given language exists.

1 Like

Excellent! That works :raised_hands: :raised_hands: