skip to Main Content

I have two news websites, one in Spanish and one in English:

es.example.com // Spanish
example.com // English

But from the main domain (in English) I am integrating a system to be able to show news in another language for example:

example.com/es/url-de-la-noticia/ // Spanish

Based on that URL, I create one ´cookie´ where the language of the URL will be stored, which is the first folder/subfolder or directory ´/es/´:

//I create the cookies automatically for the subdomain and for the URLs in Spanish.
if($FOLDER_LANG === "es" || $SUBDOMAIN_LANG === "es") {
    setcookie ('language', 'es', time()+60*60*24*365, '/', '.example.com');
}

With this parameter, news will be displayed in Spanish for both the site: es.example.com by the subdomain es or by the URLs in Spanish example.com/es/url-de-la-noticia/ = es

//We verify the existence of the cookie
if(isset($_COOKIE['language'])){
    //We print variables of the language in coincidence of the value that the cookie stores
    if($_COOKIE['language']==='en'){
        $website_title = " | Sitio en español";
        $lang = 'es';
        $language = "es";
    }elseif($_COOKIE['language']==='es'){
        $website_title = " | WebSite Ingles";
        $lang = 'en';
        $language = "en";
    }
} else {
    //In case there is no cookie, I show the English language by default.
    $website_title = " | WebSite Ingles";
    $lang = 'en';
    $language = "en";
}

So far everything seems to be working properly.

But the problem arises when I try to change the language through Ajax, although the Ajax code does send and send information, for some reason it does not replace the cookie, that is, if I click on the English language, it does not change it, the change of language.

What I want to achieve is that the language can also be changed, removing or replacing the cookies both on the server side and the client side using ajax:

$(function(){
    var tnum = 'en';
    
    $(document).click( function(e) {
        $('.language, .more_lang').removeClass('active');
    });

    $('.language .current_lang').click(function(e){
        e.stopPropagation();
        $(this).parent().toggleClass('active');
        setTimeout(function(){
            $('.more_lang').toggleClass('active');
        }, 5);
    });

    $('.more_lang .lang').click(function(){
        $(this).addClass('selected').siblings().removeClass('selected');
        $('.more_lang').removeClass('active');

        var img = $(this).find('img').attr('src');
        var lang = $(this).attr('data-value');
        var tnum = lang;

        $('.current_lang .lang-txt').text(lang);
        $('.current_lang img').attr('src', img);

        //if(lang == 'ar'){}
    });
});

$(function() {
    $(".lang").click(function(e) {
        e.preventDefault();
        var language = $(this).attr('data-value');
        var postData={lang: language};

        var request = $.ajax({
            method : 'POST',
            url    : 'language.ini.php',
            data   : postData,
            dataType: "html"
        });
        request.done(function(data) {
            $(".resultado").html(data);
        });
        request.fail(function(jqXHR, textStatus) {
            alert("Ocurrió un error: " + textStatus);
        });
    });
});
body{
    margin:0;
  padding:0;
  color:#444444;
  font-family: 'News Cycle', sans-serif;
}

.language{
  position:fixed;
  z-index:1;
  top:20px;
  left:20px;
  font-size:16px;
  background:#fff;  
  border-radius:4px;
}

.current_lang{
  cursor:pointer;
  text-transform:uppercase;
  overflow:hidden;
}

.lang{
    padding:10px 15px;
}

.lang.selected{
  display:none;
}

.lang img, 
.lang span.lang-txt{
  display:inline-block;
  margin-left:5px;
  vertical-align:middle;
}

.lang span.lang-txt{
   position:relative;
  top:-1px;
  font-weight:700;
}

.lang img{
  width:20px;
  margin-left:0;
}

.lang span span{
  color:#999;
  font-weight:400;
}

.lang span.fa{
  font-size:12px;
  position:relative;
  top:-1px;
  margin-left:3px;
}


/*more lang*/
.more_lang{
  transform:translateY(-20px);
  opacity:0;
  cursor:pointer;
  display:none;
   -webkit-transition: all .3s cubic-bezier(.25, 1.15, .35, 1.15);
    -moz-transition:    all .3s cubic-bezier(.25, 1.15, .35, 1.15);
    -o-transition:      all .3s cubic-bezier(.25, 1.15, .35, 1.15);
    -ms-transition:     all .3s cubic-bezier(.25, 1.15, .35, 1.15);
    transition:         all .3s cubic-bezier(.25, 1.15, .35, 1.15);
}

.language.active .more_lang{
  display:block; 
}

.more_lang.active{
  opacity:1;
   transform:translateY(-0px);
}

.more_lang .lang:hover{
  background:#5766b2;
  color:#fff;
}

.more_lang .lang:hover span{
  color:#fff;
}

.language:hover,
.language.active,
.content a:hover{
  box-shadow:rgba(0,0,0,0.2) 0 5px 15px;  
  -webkit-transition: all 0.3s cubic-bezier(0,.99,.44,.99);
    -moz-transition:    all 0.3s cubic-bezier(0,.99,.44,.99);
    -o-transition:      all 0.3s cubic-bezier(0,.99,.44,.99);
    -ms-transition:     all 0.3s cubic-bezier(0,.99,.44,.99);
    transition:         all 0.3s cubic-bezier(0,.99,.44,.99);
  
}

.language.active .lang{
  border-bottom:1px solid #eaeaea;
}

/*CONTENT*/
.content{
  width:100%;
  max-width:400px;
  position:absolute;
  top:50%;
  left:50%;
  -ms-transform: translateX(-50%) translateY(-50%);
  -webkit-transform: translate(-50%,-50%);
  transform: translate(-50%,-50%);
  border-radius:2px;
  padding:20px;
  -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
  
  text-align:center;
}

.content h1, 
.content h2, 
.content p{
  margin:0;
}

.content p{
   line-height:22px;
  text-align:left;
  margin-top:15px;
}


.content div.ct-img{
  width:150px;
  height:150px;
  overflow:hidden;
  border-radius:50%;
  margin:0 auto 10px;
}

.content div img{
  height:100%;
  position:relative;
  left:-30px;
}

.content a{
  padding: 8px 15px 10px;
   border-radius:4px;
  background:#5766b2;
  color:#fff;
  text-decoration:none;
  display:inline-block;
  margin-top:25px;
  position:relative;
  overflow:hidden;
}

.content a:active{
  transform: scale(0.9);
   -webkit-transform: scale(0.9);
  -moz-transform: scale(0.9);
}

/*RTL*/
body[dir="rtl"] .language{
  right:20px;
  left:auto;
}

body[dir="rtl"] .lang span.fa{
  margin-right:3px;
  margin-left:0;
}

body[dir="rtl"] .lang .lang-txt{
  margin-right:5px;
  margin-left:0;
}

body[dir="rtl"] .content div img{
  left:auto;
  right:-30px;
}


body[dir="rtl"] .content p{
  text-align:right;
}

body[dir="rtl"] .lang span span{
  float:left;
  margin-right:5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="language">
        <div class="current_lang">
            <div class="lang" data-value='en'>
                <img src="https://image.flaticon.com/icons/svg/299/299722.svg">
                <span class="lang-txt">EN</span> 
                <span class="fa fa-chevron-down chevron"></span>
            </div>
        </div>
        <div class="more_lang">    
            <div class="lang selected" data-value='en'>
                <img src="https://image.flaticon.com/icons/svg/299/299722.svg">
                <span class="lang-txt">English<span> (US)</span></span>
            </div>
            <div class="lang" data-value='es'>
                <img src="https://image.flaticon.com/icons/svg/299/299820.svg">
                <span class="lang-txt">Español</span>
            </div>
        </div>
    </div>

The language.ini.php file will be in charge of changing the language, creating their respective cookies.

<?php
    if (isset($_POST['lang'])) {
        $lang = $_POST['lang'] ?: '';
    
        if ($lang === "en") {
            setcookie ('language', 'en', time()+60*60*24*365, '/', 'example.com');
        } elseif ($lang === "es") {
            setcookie ('language', 'es', time()+60*60*24*365, '/', 'es.example.com');
        }
    }
?>

5

Answers


  1. Perhaps J. Mick, using the session storage isn’t the way to take this forward, maybe using HTML Web Storage is a better fit? At least that way, you don’t have to page fresh in order to update cookie values etc, it can be wrote and read straight from JavaScript.

    Here’s a simple example of writing and reading to the storage via JavaScript.
    https://www.w3schools.com/html/tryit.asp?filename=tryhtml5_webstorage_local_clickcount

    Login or Signup to reply.
  2. Cookies can be sent and received for all requests made from your browser, be it AJAX. You would also be able to update the already set cookie using setcookie which your’re already seem to be doing. You can verify the same by looking under Request Headers and Response Headers in Networks tab.

    There might me something else which is causing your issue.

    Login or Signup to reply.
  3. Server-Side Ajax Call (Fix)

    in your language.ini.php you have to change the line:

    setcookie ('language', 'es', time()+60*60*24*365, '/', 'es.example.com');
    

    to :

     setcookie ('language', 'es', time()+60*60*24*365, '/', 'example.com');
    

    because if you specify domain of cookie in header, it will be none host-only cookie and, in your both example.com and es.example.com will be use.

    according to RFC6265

    How Cookies Works

    1. Cookies usually will be requested to set by server-side and browser will save them.

    2. The Browser sends Cookie in every Request.

    3. Server can access cookie from the Request from browser.

    Cookies Are Essential Since Http is Connection-less Protocol, and Server want to Associate a data to a client and use it in next requests .

    A Preferable Scenario (Desired Solution)

    as long as your user decide to view your site in which language they prefer.
    and your server will not doing nothing with it (no controls, no security threads).

    you can use a shortcut .

    Set The Cookie in Your Client-side

    and just remove the language.ini.php file.

    you can do this by pure Javascript and when the user try to navigate in browser. his/her requests will be sent via new cookie which javascript has been set.

    just you have to be aware TO NOT Enable HTTP-Only Flag on Cookie (Which can prevent Js t manipulate Cookie).

    Jquery Example:

    $.cookie('language', '', { expires: 365, path: '/', domain: 'example.com' });
    

    instead of sending an ajax request your js can looks like this:

    $(function() {
        $(".lang").click(function(e) {
            e.preventDefault();
            var language = $(this).attr('data-value');
            $.cookie('language', language, { expires: 365, path: '/', domain: 'example.com' });
    
        });
    });
    
    Login or Signup to reply.
  4. You appear to have multiple UIs for the same thing. You have an English and a Spanish website. Since the domains are different, I would not be surprised if you had different sessions and cookies on the separate domains.

    However, in order to avoid duplicating code and features, at least the underlying logic could be available at a certain URL, exposing an API both to your Spanish and English version.

    Your approach is flawed, because you do not reload the page. However, you could solve it if you had these three parts:

    • API
    • English UI
    • Spanish UI

    Both the English UI and the Spanish UI would use the API in a similar manner and on the level of the API the actual English/Spanish texts would be less relevant, but the API would be the level which would determine the language.

    So, if you click on the English button on the Spanish site or the Spanish button on the English site, then the following should happen:

    • a request is sent to the API
    • the API generates a token for the other language’s site, so the user will not have to manually log in
    • a link, containing that token would be returned to the UI
    • the UI would automatically redirect to the other language’s UI
    • this ensures that the domain is correct and the page is loaded
    • once the other URL is visited, a request is sent to the API
    • the API validates the token
    • if the token was valid, then the user is allowed into the system and the token is destroyed

    This is how I would approach this. At first your API can be very thing, handling only this feature, but ideally it would be great to separate the logic from the two UIs.

    Since this solution would involve sending AJAX requests to the API, which will be on a different URL, you will need to make sure that you have the correct HTML headers that allow your page to send requests to the API without violating the CORS policy of the browser.

    Login or Signup to reply.
  5. Using chrome extensions you can modify easily with javascript api the server cookies or any cookie you want

    https://developers.chrome.com/docs/extensions/reference/cookies/

    This way you can access any cookie
    Unlike regular DOM javascript which will get you access only to non httpOnly cookies for examples.
    https://www.cookiepro.com/knowledge/httponly-cookie/

    When a cookie was created at the server with httpOnly property set to true
    Then this cookie cannot be read from DOM javascript.
    But chrome webextension api do have access to these cookies.

    Let me know if you need any more help or if this helps you…

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search