How do you make a language selector and dark mode work together?

53 Views Asked by At

I have written the below script that toggles between two languages and also to make the background change to dark mode, but I am having trouble making the two stay when either one is selected.

So when the dark mode is selected and then English is selected, the dark mode is reset. I would like it so nothing is reset.

Would anyone know a solution?

<!DOCTYPE html>
<html>
  <head>
    <style>
      body.en [lang='it'] {
        display: none;
      }
      body.it [lang='en'] {
        display: none;
      }
      body {
        padding: 25px;
        background-color: white;
        color: black;
        font-size: 25px;
      }
      .dark-mode {
        background-color: black;
        color: white;
      }
      .main-content {
        display: none;
      }
      .main-content:target {
        display: block;
      }
    </style>
  </head>
  <body class="it">

    <p><span lang="en">English</span></p>
    <p><span lang="en">English</span></p>

    <p><span lang="it">Italian</span></p>

    <button onclick="document.body.className='en'">english</button>
    <button onclick="document.body.className='it'">italiano</button>

    <button onclick="myFunction()">Toggle dark mode</button>

    <script>
      function myFunction() {
        var element = document.body;
        element.classList.toggle("dark-mode");
      }
    </script>
    <script>
      document.querySelector('.lang-switch-button').addEventListener('click', function() {
        document.querySelector('body').classList.toggle('en')
        document.querySelector('body').classList.toggle('it')
      })
    </script>
  </body>
</html>
1

There are 1 best solutions below

2
Hordrist On

The problem is that when clicking a language button, you set the body className to the selected language. For exemple, when clicking "italiano", you set the body className to "it" wwith the onclick attribute. However, this erases the "dark-mode" class from the classList.

Indeed, if your body classList is ["dark-mode", "en"], then your body className is "dark-mode en". If you set your body className to "it", then you loose the "dark-mode" class (the body classList becomes ["it"]).

In order to correct that, in the way you are trying to do it, we can add the "lang-switch-button" to your language buttons :

<button class="lang-switch-button">english</button>
<button class="lang-switch-button">italiano</button>

and rewrite your eventListener in the way you were (as I see it), trying to operate it :

<script>

document.querySelectorAll('.lang-switch-button').forEach(function(button){
    button.addEventListener('click', function() {
        document.querySelector('body').classList.toggle('en')
        document.querySelector('body').classList.toggle('it')
    })
})

</script>

NB : be carefull, you have 2 English spans.

Let me know if this worked for you :)


However, this "toggle" method isn't the most effective, as if you click on the "english" button while the page is in english, it switches to italian.

Here is an exemple, among loads of others, of what you can do : -Use the lang attribute on the span, as well as on buttons and body :

<body lang="it">

<p><span lang="en">English</span></p>

<p><span lang="it">Italian</span></p>

<button class="lang-switch-button" lang="en">english</button>
<button class="lang-switch-button" lang=it>italiano</button>


<button onclick="myFunction()">Toggle dark mode</button>

Toggle a "dark" attribute on the body, when clicking the button :

function myFunction() {
var element = document.body;
element.toggleAttribute("dark");
}

And use the "lang" attribute of the buttons, to set the

to hide :

document.querySelectorAll('.lang-switch-button').forEach(function(button){
    var language = button.getAttribute("lang");
    button.addEventListener('click', function() {
        document.querySelector('body').setAttribute("lang", language)
    })
})

CSS adaptation :

body[lang="en"] [lang='it']:not(.lang-switch-button){
display: none;
}
body[lang="it"] [lang='en']:not(.lang-switch-button){
display: none;
}
[dark]{
background-color: black;
color: white;
}

But here is just an idea, among others, and probably not the most optimal.