Answers.Body: <p>I have changed the above code a little bit because it causes an error when I have for example a website with three active locales and an entry with only one or two active locales.</p>
  
  <p>The error is: Impossible to access an attribute ("locale") on a NULL variable ("")</p>
  
  <p>The expanded if-statement looks now like this:</p>
  
  <pre>{% if localeEntry.locale is defined and localeEntry.locale == locale %}</pre>
  
  <p>And the complete code:</p>
  
  <pre><code>{% set otherLocales = craft.i18n.getSiteLocaleIds()|without(entry.locale) %}
  {% for locale in otherLocales %}
      {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}
      {% if localeEntry.locale is defined and localeEntry.locale == locale %}
          &lt;a href="{{ localeEntry.getUrl() }}"&gt;{{ locale }}&lt;/a&gt;
      {% else %}
          &lt;a href="{{ craft.config.siteUrl[locale] }}"&gt;{{ locale }}&lt;/a&gt;
      {% endif %}
  {% endfor %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-08-11T18:38:31.943Z
Answers.LastActivityDate: 2014-08-11T18:38:31.943Z
Answers.UserDisplayName: Christian Steger
Answers.Body: <p>Thought I would share my language switcher, as it shows languages in their native name.</p>
  
  <pre><code>&lt;nav class="nav nav--locale"&gt;
      &lt;ul&gt;
          {% set locales = craft.i18n.getSiteLocales() %}
  
          {% for locale in locales %}
              {% set entryURL = craft.config.siteUrl[locale.id] %}
  
              {% if entry is defined %}
                  {% set entryLocal = craft.entries.id(entry.id).locale(locale.id).first %}
  
                  {% if entryLocal.getUrl() is defined %}
                      {% set entryURL = entryLocal.getUrl() %}
                  {% endif %}
  
                  &lt;li class="nav__item {% if locale.id == craft.locale %}nav__item--active{% endif %}"&gt;
                      &lt;a href="{{ entryURL }}"&gt;{{ locale.nativeName }}&lt;/a&gt;
                  &lt;/li&gt;
              {% else %}
                  &lt;li class="nav__item {% if locale.id == craft.locale %}nav__item--active{% endif %}"&gt;
                      &lt;a href="{{ entryURL }}"&gt;{{ locale.nativeName }}&lt;/a&gt;
                  &lt;/li&gt;
              {% endif %}
          {% endfor %}
      &lt;/ul&gt;
  &lt;/nav&gt;
  </code></pre>
  
  <p>EDIT: I have fixed an issue when the entry doesn't have the content in all the different locales. This happens when you turn the default locale off in the section settings. In this case the link will take you back to the home page for that language.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-15T17:24:46.603Z
Answers.LastActivityDate: 2015-01-16T09:48:54.420Z
Answers.LastEditDate: 2015-01-16T09:48:54.420Z
Answers.UserDisplayName: Martin
Answers.Body: <p>I've created a plugin which makes it incredibly easy to add language-switching links to your website...</p>
  
  <blockquote>
    <p><a href="https://github.com/lindseydiloreto/craft-languagelink" rel="nofollow noreferrer">Language Link plugin for Craft CMS</a></p>
  </blockquote>
  
  <h3>Standard Usage</h3>
  
  <p>Add this to your <code>_layout</code>, or create a separate template to <code>include</code> in each page:</p>
  
  <pre class="lang-html prettyprint-override"><code>{% if entry is not defined %}
      {% set entry = null %}
  {% endif %}
  
  &lt;ul&gt;
      &lt;li&gt;&lt;a href="{{ craft.languageLink.url('en', entry) }}"&gt;English&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="{{ craft.languageLink.url('es', entry) }}"&gt;Español&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="{{ craft.languageLink.url('fr', entry) }}"&gt;Français&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="{{ craft.languageLink.url('de', entry) }}"&gt;Deutsch&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  </code></pre>
  
  <hr>
  
  <p>This plugin is based on the code I originally <a href="https://craftcms.stackexchange.com/a/8533/45">shared here</a>, taking into account the feedback received from carlcs on that thread. If an entry exists, the plugin will use the proper slug from each locale of an entry (or category, or any other element type). Otherwise, it will simply share the page URI between locales.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-03-09T05:29:53.380Z
Answers.LastActivityDate: 2015-03-09T05:29:53.380Z
Answers.LastEditDate: 2017-04-13T12:51:00.303Z
Answers.UserDisplayName: Lindsey D
Answers.Body: <p>This simple solution has been working brilliantly for me...</p>
  
  <pre class="lang-html prettyprint-override"><code>{% set pageUri = craft.request.url|replace(siteUrl, '') %}
  
  &lt;ul&gt;
      &lt;li&gt;&lt;a href="{{ craft.config.siteUrl['en'] ~ pageUri }}"&gt;English&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="{{ craft.config.siteUrl['fr'] ~ pageUri }}"&gt;Français&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  </code></pre>
  
  <p>The <code>pageUri</code> is basically the current URL, minus the localized <code>siteUrl</code>.</p>
  
  <p>Append the clean <code>pageUri</code> to each localized <code>siteUrl</code>, and voila... whatever page you are currently on will be linked to it's other-language counterpart.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-03-06T00:35:50.817Z
Answers.Text: Yes, something like this works great as long as you don't translate entry slugs.
Answers.UserDisplayName: carlcs
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-03-06T00:36:30.977Z
Answers.Text: Fair point @carlcs! We're not translating those on our site. :)
Answers.UserDisplayName: Lindsey D
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-03-06T00:31:49.453Z
Answers.LastActivityDate: 2015-03-06T00:31:49.453Z
Answers.UserDisplayName: Lindsey D
Answers.Body: <p>I tweaked the version in the answer above by Christian Steger (<a href="https://craftcms.stackexchange.com/a/1794/3835">https://craftcms.stackexchange.com/a/1794/3835</a>). This version, hides the current language from the list of language links, and displays the language links in the target language. </p>
  
  <p>It also allows you to omit any desired languages from the list of language links. This is useful for enabling a locale for use in the control panel without having it appear in the list of language links throughout the site. </p>
  
  <pre><code>{% set currentLocale = craft.i18n.getCurrentLocale() %}
  {# Decide which languages should be omitted from language links #}
  {% set localeExceptions = ["en", currentLocale] %}
  {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(localeExceptions) %}
  
  {% for locale in otherLocales %}
    {% if entry is defined %}
       {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}
    {% endif %}
  
    {% if localeEntry.locale is defined and localeEntry.locale == locale %}
        &lt;a href="{{ localeEntry.getUrl() }}"&gt;{{ craft.i18n.getLocaleById(locale).nativeName }}&lt;/a&gt;
    {% else %}
        &lt;a href="{{ craft.config.siteUrl[locale] }}"&gt;{{ craft.i18n.getLocaleById(locale).nativeName }}&lt;/a&gt;
    {% endif %}
  {% endfor %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-03-24T13:42:28.360Z
Answers.LastActivityDate: 2016-04-27T19:20:35.150Z
Answers.LastEditDate: 2017-04-13T12:51:00.160Z
Answers.UserDisplayName: Justin K
Answers.Body: <p>If you happen to be using the <a href="https://github.com/nystudio107/seomatic/" rel="nofollow noreferrer">SEOmatic</a> plugin for Craft 2.x, it comes with a <a href="https://github.com/nystudio107/seomatic/wiki/15.-Utility-Filters-&amp;-Functions#getlocalizedurls" rel="nofollow noreferrer">getLocalizedUrls()</a> function that:</p>
  
  <blockquote>
    <p>Returns an array of localized URLs for the current page request. This handles elements with localized slugs, etc. This function returns the unique URLs for each language for the current page request, not just the localized site URLs.</p>
  </blockquote>
  
  <p>For <a href="https://github.com/nystudio107/craft-seomatic" rel="nofollow noreferrer">SEOmatic for Craft CMS 3</a>,there's a similarly the <a href="https://github.com/nystudio107/craft-seomatic#helper-functions-seomatichelper" rel="nofollow noreferrer">seomatic.helper.getLocalizedUrls(URI, SITE_ID)</a> helper function:</p>
  
  <blockquote>
    <p>Return a list of localized URLs for a given URI that are in the SITE_ID site's group. Both URI and SITE_ID are optional, and will use the current request's URI and the current site's SITE_ID if omitted.</p>
  </blockquote>
  
  <p>This makes building a language switcher trivial.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2017-07-28T02:21:39.237Z
Answers.LastActivityDate: 2018-07-23T17:46:56.583Z
Answers.LastEditDate: 2018-07-23T17:46:56.583Z
Answers.UserDisplayName: andrew.welch
Answers.Body: <p>Here is my language switcher for Craft CMS 3:</p>
  
  <p><a href="http://craftsnippets.com/articles/universal-language-switcher-for-craft-cms?s=s" rel="nofollow noreferrer">http://craftsnippets.com/articles/universal-language-switcher-for-craft-cms?s=s</a></p>
  
  <p>It works for Entries, categories and other elements with their own URLs and has an option for an automatic appending country flag to language links.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-07T08:08:38.030Z
Answers.LastActivityDate: 2019-07-07T09:43:20.087Z
Answers.LastEditDate: 2019-07-07T09:43:20.087Z
Answers.UserDisplayName: Piotr Pogorzelski
Answers.Body: <p>Here's my take with the latest CraftCMS 3.2 (using sites groups)</p>
  
  <pre><code>{% set swapLinkDone = false %}
  
  {# ——— Loop through all of the site locales, except the current one #}
  {% if entry is defined %}
      {% set otherLocales = craft.app.i18n.siteLocales|filter(locale =&gt; locale.id != craft.app.language) %}
      {% for locale in otherLocales %}
          {% set otherSite = craft.app.sites.allSites|filter(s =&gt; s.language == locale.id and s.groupId == currentSite.groupId)|first %}
          {% if otherSite is defined %}
              {% set localeEntry = craft.entries.id(entry.id).site(otherSite.handle).one %}
              {% if localeEntry is defined and localeEntry.slug != "home" %}
                  &lt;a href="{{ siteUrl(localeEntry.uri, [], null, otherSite.id) }}"&gt;{{ locale.id|t }}&lt;/a&gt;
                  {% set swapLinkDone = true %}
              {% endif %}
          {% endif %}
      {% endfor %}
  {% endif %}
  
  {% if swapLinkDone == false %}
      {% set otherLang = craft.app.language == "en" ? "fr" : "en" %}
      &lt;a href="{{ otherLang == "en" ? "/en" : "/fr" }}"&gt;{{ otherLang|t }}&lt;/a&gt;
  {% endif %}
  
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-23T19:17:19.297Z
Answers.LastActivityDate: 2019-07-23T19:42:50.913Z
Answers.LastEditDate: 2019-07-23T19:42:50.913Z
Answers.UserDisplayName: Alain Duchesneau
Answers.Body: <p>I am building my first multi-language site with Craft as well. This is from a thread over at Google+, so I didn't come up with this myself but it works very well:</p>
  
  <pre><code>{% block locale__switch %}
  
      {# Loop through all of the site locales, except the current one #}
      {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(craft.locale) %}
      {% for locale in otherLocales %}
  
          {# Find the current entry in the other locale #}
          {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}
  
          {# Make sure that it's actually localized to this locale #}
          {% if localeEntry.locale == locale %}
  
              {# Output a link to it #}
              &lt;a href="{{ localeEntry.getUrl() }}"&gt;{{ locale }}&lt;/a&gt;
          {% else %}
  
              {# Output a link to the hompage #}
              &lt;a href="{{ craft.config.siteUrl[locale] }}"&gt;{{ locale }}&lt;/a&gt;
          {% endif %}
  
      {% endfor %}
  {% endblock %}
  </code></pre>
  
  <p>I set this up in a block to implement the switch in various templates. It loops through all the languages minus the current one and outputs the links. It also matches the entries by ID which is why you can have different slugs. Hope it helps.</p>
  
  <p>Yay for the craftcms.stackexchange site!</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T10:39:43.097Z
Answers.Text: This is great...how does it work if there's no matching entry ID in one of the other languages?
Answers.UserDisplayName: Patrick Nesbitt
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T10:48:09.200Z
Answers.Text: Supercool. Thanks. It would be cool to have some sort of explanation of each line becaue I find it quite hard to learn twig. The documentation is scattered across the various craft/twig sites. I added a conditional to check for the homepage because there I don't need the locale.Entry.uri
Answers.UserDisplayName: KSPR
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T11:08:29.377Z
Answers.Text: @Patrick If there is no matching entry in another locale you could link to the homepage of that locale. Just committed an edit to the original answer.
Answers.UserDisplayName: carlcs
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-08-30T12:27:13.700Z
Answers.Text: I get the following error:
  Impossible to access an attribute ("locale") on a null variable
  
  What do I do wrong? I copy/pasted the code you showed.
  
  thanx in advance!
Answers.UserDisplayName: Martijn La Feber
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T10:15:19.197Z
Answers.LastActivityDate: 2014-06-13T12:50:17.623Z
Answers.LastEditDate: 2014-06-13T12:50:17.623Z
Answers.UserDisplayName: portnull
Body: <p>I'm currently building a site with two languages, and I need a language switcher so wherever you enter the website you can switch the language easily.</p>
  
  <p>I've come this far:</p>
  
  <pre><code>{% for locale in craft.i18n.getSiteLocales() %}
      &lt;li {{ locale == craft.i18n.getCurrentLocale() ? 'class="active"' }}&gt;
          &lt;a href="/{{ locale }}/{{ entry.slug }}"&gt;
             {% if loop.first %}DE{% else %}FR{% endif %}
          &lt;/a&gt;
      &lt;/li&gt;
  {% endfor %}
  </code></pre>
  
  <p>The problem here is that <code>{{ entry.slug }}</code> only returns the slug for the current language and doesn't loop trough the languages.</p>
  
  <p>When I'm on french it returns <code>/bonjour</code> twice and on german it returns <code>/hallo</code> twice. Why is that?</p>
  
Tags: <localization><navigation>
Title: How can I build a language switcher?
ThreadText: # How can I build a language switcher?
  
  (Asked by: username_0 on 2014-06-12)
  
  I'm currently building a site with two languages, and I need a language switcher so wherever you enter the website you can switch the language easily.
  
  I've come this far:
  
  ```
  {% for locale in craft.i18n.getSiteLocales() %}
      <li {{ locale == craft.i18n.getCurrentLocale() ? 'class="active"' }}>
          <a href="/{{ locale }}/{{ entry.slug }}">
             {% if loop.first %}DE{% else %}FR{% endif %}
          </a>
      </li>
  {% endfor %}
  
  ```
  
  The problem here is that `{{ entry.slug }}` only returns the slug for the current language and doesn't loop trough the languages.
  
  When I'm on french it returns `/bonjour` twice and on german it returns `/hallo` twice. Why is that?
  
  **Tags:** localization, navigation
  
  
  ---
  
  ## 9 answers
  
  ### Answer by username_9 on 2014-06-12. Score: 29 | Accepted answer
  
  I am building my first multi-language site with Craft as well. This is from a thread over at Google+, so I didn't come up with this myself but it works very well:
  
  ```
  {% block locale__switch %}
  
      {# Loop through all of the site locales, except the current one #}
      {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(craft.locale) %}
      {% for locale in otherLocales %}
  
          {# Find the current entry in the other locale #}
          {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}
  
          {# Make sure that it's actually localized to this locale #}
          {% if localeEntry.locale == locale %}
  
              {# Output a link to it #}
              <a href="{{ localeEntry.getUrl() }}">{{ locale }}</a>
          {% else %}
  
              {# Output a link to the hompage #}
              <a href="{{ craft.config.siteUrl[locale] }}">{{ locale }}</a>
          {% endif %}
  
      {% endfor %}
  {% endblock %}
  
  ```
  
  I set this up in a block to implement the switch in various templates. It loops through all the languages minus the current one and outputs the links. It also matches the entries by ID which is why you can have different slugs. Hope it helps.
  
  Yay for the craftcms.stackexchange site!
  
  > **Comments:**
  > **username_10**: This is great...how does it work if there's no matching entry ID in one of the other languages?  
  > **username_0**: Supercool. Thanks. It would be cool to have some sort of explanation of each line becaue I find it quite hard to learn twig. The documentation is scattered across the various craft/twig sites. I added a conditional to check for the homepage because there I don't need the locale.Entry.uri  
  > **username_4**: @username_10 If there is no matching entry in another locale you could link to the homepage of that locale. Just committed an edit to the original answer.  
  > **username_11**: I get the following error: Impossible to access an attribute ("locale") on a null variable  What do I do wrong? I copy/pasted the code you showed.  thanx in advance!  
  
  ---
  
  ### Answer by username_1 on 2014-08-11. Score: 14
  
  I have changed the above code a little bit because it causes an error when I have for example a website with three active locales and an entry with only one or two active locales.
  
  The error is: Impossible to access an attribute ("locale") on a NULL variable ("")
  
  The expanded if-statement looks now like this:
  
  ```
  {% if localeEntry.locale is defined and localeEntry.locale == locale %}
  ```
  
  And the complete code:
  
  ```
  {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(entry.locale) %}
  {% for locale in otherLocales %}
      {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}
      {% if localeEntry.locale is defined and localeEntry.locale == locale %}
          <a href="{{ localeEntry.getUrl() }}">{{ locale }}</a>
      {% else %}
          <a href="{{ craft.config.siteUrl[locale] }}">{{ locale }}</a>
      {% endif %}
  {% endfor %}
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2015-01-15. Score: 10
  
  Thought I would share my language switcher, as it shows languages in their native name.
  
  ```
  <nav class="nav nav--locale">
      <ul>
          {% set locales = craft.i18n.getSiteLocales() %}
  
          {% for locale in locales %}
              {% set entryURL = craft.config.siteUrl[locale.id] %}
  
              {% if entry is defined %}
                  {% set entryLocal = craft.entries.id(entry.id).locale(locale.id).first %}
  
                  {% if entryLocal.getUrl() is defined %}
                      {% set entryURL = entryLocal.getUrl() %}
                  {% endif %}
  
                  <li class="nav__item {% if locale.id == craft.locale %}nav__item--active{% endif %}">
                      <a href="{{ entryURL }}">{{ locale.nativeName }}</a>
                  </li>
              {% else %}
                  <li class="nav__item {% if locale.id == craft.locale %}nav__item--active{% endif %}">
                      <a href="{{ entryURL }}">{{ locale.nativeName }}</a>
                  </li>
              {% endif %}
          {% endfor %}
      </ul>
  </nav>
  
  ```
  
  EDIT: I have fixed an issue when the entry doesn't have the content in all the different locales. This happens when you turn the default locale off in the section settings. In this case the link will take you back to the home page for that language.
  
  
  ---
  
  ### Answer by username_3 on 2015-03-09. Score: 9
  
  I've created a plugin which makes it incredibly easy to add language-switching links to your website...
  
  > [Language Link plugin for Craft CMS](https://github.com/lindseydiloreto/craft-languagelink)
  
  ### Standard Usage
  
  Add this to your `_layout`, or create a separate template to `include` in each page:
  
  ```html
  {% if entry is not defined %}
      {% set entry = null %}
  {% endif %}
  
  <ul>
      <li><a href="{{ craft.languageLink.url('en', entry) }}">English</a></li>
      <li><a href="{{ craft.languageLink.url('es', entry) }}">Español</a></li>
      <li><a href="{{ craft.languageLink.url('fr', entry) }}">Français</a></li>
      <li><a href="{{ craft.languageLink.url('de', entry) }}">Deutsch</a></li>
  </ul>
  
  ```
  
  ---
  
  This plugin is based on the code I originally [shared here](https://craftcms.stackexchange.com/a/8533/45), taking into account the feedback received from username_4 on that thread. If an entry exists, the plugin will use the proper slug from each locale of an entry (or category, or any other element type). Otherwise, it will simply share the page URI between locales.
  
  
  ---
  
  ### Answer by username_3 on 2015-03-06. Score: 5
  
  This simple solution has been working brilliantly for me...
  
  ```html
  {% set pageUri = craft.request.url|replace(siteUrl, '') %}
  
  <ul>
      <li><a href="{{ craft.config.siteUrl['en'] ~ pageUri }}">English</a></li>
      <li><a href="{{ craft.config.siteUrl['fr'] ~ pageUri }}">Français</a></li>
  </ul>
  
  ```
  
  The `pageUri` is basically the current URL, minus the localized `siteUrl`.
  
  Append the clean `pageUri` to each localized `siteUrl`, and voila... whatever page you are currently on will be linked to it's other-language counterpart.
  
  > **Comments:**
  > **username_4**: Yes, something like this works great as long as you don't translate entry slugs.  
  > **username_3**: Fair point @username_4! We're not translating those on our site. :)  
  
  ---
  
  ### Answer by username_5 on 2016-03-24. Score: 3
  
  I tweaked the version in the answer above by username_1 (<https://craftcms.stackexchange.com/a/1794/3835>). This version, hides the current language from the list of language links, and displays the language links in the target language.
  
  It also allows you to omit any desired languages from the list of language links. This is useful for enabling a locale for use in the control panel without having it appear in the list of language links throughout the site.
  
  ```
  {% set currentLocale = craft.i18n.getCurrentLocale() %}
  {# Decide which languages should be omitted from language links #}
  {% set localeExceptions = ["en", currentLocale] %}
  {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(localeExceptions) %}
  
  {% for locale in otherLocales %}
    {% if entry is defined %}
       {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}
    {% endif %}
  
    {% if localeEntry.locale is defined and localeEntry.locale == locale %}
        <a href="{{ localeEntry.getUrl() }}">{{ craft.i18n.getLocaleById(locale).nativeName }}</a>
    {% else %}
        <a href="{{ craft.config.siteUrl[locale] }}">{{ craft.i18n.getLocaleById(locale).nativeName }}</a>
    {% endif %}
  {% endfor %}
  
  ```
  
  
  ---
  
  ### Answer by username_6 on 2017-07-28. Score: 3
  
  If you happen to be using the [SEOmatic](https://github.com/nystudio107/seomatic/) plugin for Craft 2.x, it comes with a [getLocalizedUrls()](https://github.com/nystudio107/seomatic/wiki/15.-Utility-Filters-&-Functions#getlocalizedurls) function that:
  
  > Returns an array of localized URLs for the current page request. This handles elements with localized slugs, etc. This function returns the unique URLs for each language for the current page request, not just the localized site URLs.
  
  For [SEOmatic for Craft CMS 3](https://github.com/nystudio107/craft-seomatic),there's a similarly the [seomatic.helper.getLocalizedUrls(URI, SITE\_ID)](https://github.com/nystudio107/craft-seomatic#helper-functions-seomatichelper) helper function:
  
  > Return a list of localized URLs for a given URI that are in the SITE\_ID site's group. Both URI and SITE\_ID are optional, and will use the current request's URI and the current site's SITE\_ID if omitted.
  
  This makes building a language switcher trivial.
  
  
  ---
  
  ### Answer by username_7 on 2019-07-07. Score: 2
  
  Here is my language switcher for Craft CMS 3:
  
  <http://craftsnippets.com/articles/universal-language-switcher-for-craft-cms?s=s>
  
  It works for Entries, categories and other elements with their own URLs and has an option for an automatic appending country flag to language links.
  
  
  ---
  
  ### Answer by username_8 on 2019-07-23. Score: 1
  
  Here's my take with the latest CraftCMS 3.2 (using sites groups)
  
  ```
  {% set swapLinkDone = false %}
  
  {# ——— Loop through all of the site locales, except the current one #}
  {% if entry is defined %}
      {% set otherLocales = craft.app.i18n.siteLocales|filter(locale => locale.id != craft.app.language) %}
      {% for locale in otherLocales %}
          {% set otherSite = craft.app.sites.allSites|filter(s => s.language == locale.id and s.groupId == currentSite.groupId)|first %}
          {% if otherSite is defined %}
              {% set localeEntry = craft.entries.id(entry.id).site(otherSite.handle).one %}
              {% if localeEntry is defined and localeEntry.slug != "home" %}
                  <a href="{{ siteUrl(localeEntry.uri, [], null, otherSite.id) }}">{{ locale.id|t }}</a>
                  {% set swapLinkDone = true %}
              {% endif %}
          {% endif %}
      {% endfor %}
  {% endif %}
  
  {% if swapLinkDone == false %}
      {% set otherLang = craft.app.language == "en" ? "fr" : "en" %}
      <a href="{{ otherLang == "en" ? "/en" : "/fr" }}">{{ otherLang|t }}</a>
  {% endif %}
  
  ```
  
  
  ---
  
  