Multilingual Ghost CMS Blog: 3. Adding a Language Selector

Multilingual Ghost CMS Blog: 3. Adding a Language Selector

I finished the basic setup for a multilingual blog. I used the / and /ko/ paths to separate posts by language. Right now, you can only move from the English page to the Korean page, or vice versa, by manually entering the URL. For user convenience, let's add a UI for selecting the language.

0.0.3 · sanghunka/ghost-multilingual-theme@f5a2d86
Add language selector

default.hbs

  • Add a language-selector div below <div class="gh-head-actions">.
<div class="gh-head-actions">
    <div class="language-selector">
        <svg aria-hidden="true" class="icon-language" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
            <path d="M12 22q-2.05 0-3.875-.788-1.825-.787-3.187-2.15-1.363-1.362-2.15-3.187Q2 14.05 2 12q0-2.075.788-3.887.787-1.813 2.15-3.175Q6.3 3.575 8.125 2.787 9.95 2 12 2q2.075 0 3.887.787 1.813.788 3.175 2.151 1.363 1.362 2.15 3.175Q22 9.925 22 12q0 2.05-.788 3.875-.787 1.825-2.15 3.187-1.362 1.363-3.175 2.15Q14.075 22 12 22Zm0-2.05q.65-.9 1.125-1.875T13.9 16h-3.8q.3 1.1.775 2.075.475.975 1.125 1.875Zm-2.6-.4q-.45-.825-.787-1.713Q8.275 16.95 8.05 16H5.1q.725 1.25 1.812 2.175Q8 19.1 9.4 19.55Zm5.2 0q1.4-.45 2.487-1.375Q18.175 17.25 18.9 16h-2.95q-.225.95-.562 1.837-.338.888-.788 1.713ZM4.25 14h3.4q-.075-.5-.113-.988Q7.5 12.525 7.5 12t.037-1.012q.038-.488.113-.988h-3.4q-.125.5-.188.988Q4 11.475 4 12t.062 1.012q.063.488.188.988Zm5.4 0h4.7q.075-.5.113-.988.037-.487.037-1.012t-.037-1.012q-.038-.488-.113-.988h-4.7q-.075.5-.112.988Q9.5 11.475 9.5 12t.038 1.012q.037.488.112.988Zm6.7 0h3.4q.125-.5.188-.988Q20 12.525 20 12t-.062-1.012q-.063-.488-.188-.988h-3.4q.075.5.112.988.038.487.038 1.012t-.038 1.012q-.037.488-.112.988Zm-.4-6h2.95q-.725-1.25-1.813-2.175Q16 4.9 14.6 4.45q.45.825.788 1.712.337.888.562 1.838ZM10.1 8h3.8q-.3-1.1-.775-2.075Q12.65 4.95 12 4.05q-.65.9-1.125 1.875T10.1 8Zm-5 0h2.95q.225-.95.563-1.838.337-.887.787-1.712Q8 4.9 6.912 5.825 5.825 6.75 5.1 8Z"></path>
        </svg>
        <select id="languageSelector">
            <option value="en">English</option>
            <option value="ko">한국어</option>
        </select>
    </div>

  • Add the script between {{ghost_foot}} and </body>.
{{ghost_foot}}

<script>
    function initializeLanguageSelector() {
        var selector = document.getElementById('languageSelector');
        var currentUrl = window.location.href;
        
        var urlLanguage = currentUrl.includes('/ko/') ? 'ko' : 'en';
        localStorage.setItem('selectedLanguage', urlLanguage);
        selector.value = urlLanguage;
        
        selector.style.display = 'block';
        selector.addEventListener('change', function() {
            localStorage.setItem('selectedLanguage', this.value);
            window.location.href = this.value === 'ko' ? '/ko/' : '/';
        });
    }
    
    initializeLanguageSelector();
</script>
</body>

Line 8: Identify the language through the URL.

Line 9: It stores the value specified in the selector in localStorage for use.

Line 10: Set the selector's value to match the detected language.

Line 13: When the value of the Language selector changes, it redirects.

assets/built/screen.css

If you stop here, the dropdown looks too ugly. Let's refine it a bit with CSS to make it look nicer.

Add the code below to the very end of the assets/built/screen.css file.

.language-selector {
    display: flex;
    align-items: center;
    background-color: #ffffff; /* Light background */
    border: 1px solid #e5e5e5; /* Gray border */
    border-radius: 5px;
    padding: 5px 10px;
}

.language-selector .icon-language {
    fill: #333333; /* Dark gray icon */
    margin-right: 10px;
    width: 24px;
    height: 24px;
}

#languageSelector {
    padding: 8px 30px 8px 12px; /* Increase right padding to prevent overlap of arrow and text */
    background-color: #ffffff; /* Background color */
    color: #333333; /* Text color */
    border: none;
    cursor: pointer;
    -webkit-appearance: none; /* Remove default styling */
    -moz-appearance: none;
    appearance: none;
    background-image: url('data:image/svg+xml;utf8,<svg fill="%23333333" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M5.516 7.548c.436-.446 1.043-.481 1.576 0l2.908 2.681 2.908-2.681c.533-.481 1.141-.446 1.576 0 .436.445.408 1.197 0 1.615l-4.241 3.896c-.41.375-1.141.375-1.551 0l-4.241-3.896c-.408-.418-.436-1.17 0-1.615z"/></svg>'); /* Custom dropdown arrow, gray */
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 12px;
}

Result

Issue

The tag page still does not work properly.

On the tag page (https://{host}/tag/news/), posts appear regardless of language. I'll cover this issue in the next post.

Next post

Multilingual Ghost CMS Blog: 4. Making Tag Pages Multilingual
Let's go to the news tag page.