vigetlabs/craft-localeredirector

Browser locale is being forced

Closed this issue · 13 comments

Hi,

The plugin seems to force the browser language. It's impossible to switch languages.
I'm using the latest version of Craft and the plugin on a multi-environment setup.

If you want, I could give you access to the code and/or backend.

I did some debugging. It seems the cookie 'locale' isn't being updated. Eg. When I browse to the homepage, the locale cookie is being set to 'en'. When switching to 'fr', the cookie stays 'en'.

When manually changing the cookie itself to 'de', any page is getting redirected to the german version.

If you have a language switcher menu implemented in your template, which allows users to manually set their language preference (via cookie), then the language setting saved in the cooke will be used by the plugin for redirection.

The language switching html looks like this. And it works like expected.

<ul>
    <li><a href="http://localhost:8888/en/about-us" class="active">English</a></li>
    <li><a href="http://localhost:8888/nl/over-ons" class="">Nederlands</a></li>
    <li><a href="http://localhost:8888/fr/a-propos" class="">Français</a></li>
    <li><a href="http://localhost:8888/de/uber-uns" class="">Deutsch</a></li>
    <li><a href="http://localhost:8888/pl/o-nas" class="">Polski</a></li>
    <li><a href="http://localhost:8888/ru/о-нас" class="">русский</a></li>
</ul>

In the config file:

'siteUrl' => array(
	'nl' => 'http://localhost:8888/nl/',
	'fr' => 'http://localhost:8888/fr/',
	'en' => 'http://localhost:8888/en/',
	'de' => 'http://localhost:8888/de/',
	'pl' => 'http://localhost:8888/pl/',
	'ru' => 'http://localhost:8888/ru/',
)

So everything worked perfectly. Not all sections have a public url configured. So we wrote the language switcher ourselves using twig. Without the need of using cookies.

So, the localeredirector plugin doesn't set cookies, but uses cookie information from another plugin?

The plugin depends on a language preferences first being set by the user (via js). If none have been set (e.g. for the first visit) it will set a cookie based on finding a match between the browser's configured language settings and the locales configured for the site in Craft. On subsequent visits, it will also reset the cookie to the same value, but only for the purposes of extending the expires date.

Hey @DiederikVanHoorebeke

Did you manage to fix this? I got the same issue.

Along with linking to fr/a-propos in the language switcher, you need to set the language cookie to fr via js onclick. Then the plugin will have a cookie to read.

I've used a combination https://github.com/nystudio107/cookies and two small plugins I wrote.

This is my template code:

{% if getCookie( 'locale' ) is empty and entry.id == 12 and not isCrawler() %}
	{% set languateToRedirectTo = getLocaleToRedirectTo() %}
	{% if languateToRedirectTo is empty %} {% set languateToRedirectTo = getPrimaryLanguage() %} {% endif %}
	{{ setCookie( 'locale', languateToRedirectTo ) }}
	{% if languateToRedirectTo != craft.locale %}
		{% set redirectEntry = craft.entries.id(entry.id).locale(languateToRedirectTo).first %}
		{% redirect redirectEntry.getUrl() %}
	{% endif %}
{% else %}
	{{ setCookie( "locale", craft.locale ) }}
{% endif %}

The and entry.id == 12 part in the code makes shure the redirect woks only on the homepage. 12 is the id of the homepage single.

To prevent redirecting crawlers, I created the isCrawler() function, using https://packagist.org/packages/jaybizzle/crawler-detect.

getLocaleToRedirectTo() function is a Twig extension plugin matching the first browser language that exists within the craft locales enabled in the backend:

public function getLocaleToRedirectToFilter()
    {
        $browserLanguages = craft()->request->getBrowserLanguages();
        $craftLanguages = craft()->i18n->getSiteLocaleIds();

        foreach ($browserLanguages as $browserLanguage) {
            if (in_array($browserLanguage, $craftLanguages)) {
                return $browserLanguage;
            }
        }

        return null;
    }

If no results found, it looks for the first locale configured in the backend, using getPrimaryLanguage()

    public function getPrimaryLanguageFilter()
    {
        $craftLanguages = craft()->i18n->getSiteLocaleIds();
        return $craftLanguages[0];
    }

In your template code, it looks like you're doing essentially the same (or similar) thing that the localeredirector plugin is doing: checking for a cookie, finding a language match, setting a cookie, then performing a redirect if necessary. So my initial thought is that the localeredirector plugin and the template code are trying to do the same thing; potentially conflicting and causing issues.

I'd recommend letting the localeredirector plugin handle the detection/matching/cookie, or just roll your own template based detection/redirection since it seems like your needs are fairly custom with restricting to the homepage and detecting/preventing crawlers.

Making sure that the redirect would also work without the use of javascript to set the cookie, I'm using my own template based detection/redirection.

Is there any code example for seeting the language cookie to a locale via onclick?
I am having trouble getting this to work. Probably also worth adding this issue to the documentation.

I did it with this js cookie plugin, but I guess there are a lot of ways do this thing.

$('.lang-switch a').click(function(e){ Cookies.set('locale', $(this).attr('data-lang')); });

I do have an language data attribute on my element.
<li class="nav-item"><a class="nav-link" data-lang="{{ locale }}" href="{{ craft.config.siteUrl[locale] }}">{{ locale }}</a></li>

@bennobo Good call on adding a code sample for setting cookies via js. I have some time today so I'll try to put something together in the readme, or link to some external sources. Otherwise, the js cookie plugin that @thomasvankerckvoorde mentioned is a great start.

Check the readme now. I've added an important notes section with some info on language links and setting cookies.