MultiLanguage dropdown

I have made select options for couple of languages but It doesn’t work properly. When I select any language it goes to frontpage and display the default selected item. Besides If I change the language from and inner page even then it redirects to the frontpage.

Site URL:
http://modx.kanzlei-bildt.de/

PHP Code

<?php
if ($modx->context->key == 'mgr' || !$modx->getOption( 'friendly_urls' ) || $modx->event->name != 'OnHandleRequest' )
{ return ; }
switch($_REQUEST ["cultureKey"])
    { // English
        case 'en': 
            $modx->switchContext('en');
            break;
        case 'fr': 
            $modx->switchContext('fr');
            break;
        case 'it': 
            $modx->switchContext('it');
            break;
        case 'es': 
            $modx->switchContext('es');
            break;
        case 'pt': 
            $modx->switchContext('pt');
            break;
        // German
        default:  
            $modx->switchContext('web');
            break;
    } 
unset ($_GET ["cultureKey"]);

Javascript Code for select options

const select = document.querySelector(".lang_select");
    const options = document.querySelectorAll(".lang_select option");
    // 1
    select.addEventListener("change", function() {
        const url = this.options[this.selectedIndex].dataset.url;
        console.log(this.options[this.selectedIndex].dataset.url);
        if(url) {
            localStorage.setItem("url", url);
            location.href = url;
        }
    });
   
    if(localStorage.getItem("url")) {
        for(const option of options) {
            const url = option.dataset.url;
            if(url === localStorage.getItem("url")) {
                option.setAttribute("selected", "");
                break;
            }
        }
    }

Your HTML markup for the language select is always

<select class="lang_select">
	<option data-url="/de" selected="">de</option>
	<option data-url="/en">en</option>
	<option data-url="/fr">fr</option>
	...
</select>

When you select an option (like for example english), it always goes to the url /en.

If you want to navigate to a different page, then you either have to change the data-url in your markup or maybe change your javascript code.

How are your different contexts organized? Do they all have the same structure with the same resource-aliases?
And where exactly does $_REQUEST["cultureKey"] get set? In the .htaccess file?


It’s seems that you try to create your own solution for a multilingual MODX site.
Maybe it is a better idea to use an established extra like Babel.

Sorry I forgot to share .htaccess code

# MODX supports Friendly URLs via this .htaccess file. You must serve web
# pages via Apache with mod_rewrite to use this functionality, and you must
# change the file name from ht.access to .htaccess.
#
# Make sure RewriteBase points to the directory where you installed MODX.
# E.g., "/modx" if your installation is in a "modx" subdirectory.
#
# You may choose to make your URLs non-case-sensitive by adding a NC directive
# to your rule: RewriteRule ^(.*)$ index.php?q=$1 [L,QSA,NC]

RewriteEngine On
RewriteBase /


# Prevent rewrite the .well-known directory used by LetsEncrypt by rules below of this rule
RewriteRule "^\.well-known/" - [L]


# Prevent dot directories (hidden directories like .git) to be exposed to the public
# Except for the .well-known directory used by LetsEncrypt a.o
RewriteRule "/\.|^\.(?!well-known/)" - [F]


# Rewrite www.example.com -> example.com -- used with SEO Strict URLs plugin
#RewriteCond %{HTTP_HOST} .
#RewriteCond %{HTTP_HOST} ^www.(.*)$ [NC]
#RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
#
# or for the opposite example.com -> www.example.com use the following
# DO NOT USE BOTH
#
#RewriteCond %{HTTP_HOST} !^$
#RewriteCond %{HTTP_HOST} !^www\. [NC]
#RewriteCond %{HTTP_HOST} (.+)$
#RewriteRule ^(.*)$ https://www.%1/$1 [R=301,L] .


# Force rewrite to https for every host
#RewriteCond %{HTTPS} !=on [OR]
#RewriteCond %{SERVER_PORT} !^443
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]


# Redirect the manager to a specific domain - don't rename the ht.access file
# in the manager folder to use this this rule
#RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
#RewriteCond %{REQUEST_URI} ^/manager [NC]
#RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]


# The Friendly URLs part
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en|fr|it|es|pt)/favicon.ico$ favicon.ico [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en|fr|it|es|pt)/assets(.*)$ assets$2 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en|fr|it|es|pt)/images(.*)$ images$2 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(en|fr|it|es|pt)?/?(.*)$ index.php?cultureKey=$1&q=$2 [L,QSA] 


# For servers that support output compression, you should pick up a bit of
# speed by un-commenting the following lines.

#php_flag zlib.output_compression On
#php_value zlib.output_compression_level 5

And could you please tell me exactly what will I do with Babel and exactly what should I remove or add?
When I use [[BabelLinks]] it displays an unordered list. Could you please tell me how can I get select options?
I request you to write an entire guideline on how to get the select options of all languages.

Set the &tpl property to a custom chunk that outputs an <option> tag instead of a <li>.

https://docs.modx.com/current/en/extras/babel/babellinks

@halftrainedharry
That’s what I did. But I don’t know how the functionality will work. I have written the JS code but that doesn’t work correctly.
Do you have any idea?

    // language dropdown
    const select = document.querySelector(".lang_select");
    const options = document.querySelectorAll(".lang_select option");
    // 1
    select.addEventListener("change", function() {
        const url = this.options[this.selectedIndex].dataset.url;
        console.log(this.options[this.selectedIndex].dataset.url);
        if(url) {
            localStorage.setItem("url", url);
            location.href = url;
        }
    });
    
    // 2
    if(localStorage.getItem("url")) {
        for(const option of options) {
            const url = option.dataset.url;
            if(url === localStorage.getItem("url")) {
                option.setAttribute("selected", "");
                break;
            }
        }
    }

I don’t think that the JS code is the problem.

The data-url attribute of the <option> tags always shows the same content for all pages.
But on a specific page these links should refer to the corresponding pages in the other languages.
For example if you are on the page yourdomain.de/kontakt, then the data-url attributes should be something like /en/contact, /it/contatto etc.

In the manager did you link the resources correctly in the manager page under “Extras” → “Babel”?
What is the content of the template-chunk you use for BabelLinks?

Thank you so much. You made my day. Now the problem is resolved. All the translation pages were unlinked earlier.