고스트 CMS 다국어 블로그: 5. 홈 링크 다국어 처리

네비게이션바, 푸터, 에러페이지에서 홈링크를 각 언어에 맞는 다국어로 연결하는 방법을 설명한다.



네비게이션바, 푸터, 에러페이지에 home링크가 존재한다. 이 링크는 @site.url로 설정되어있으며 다국어 설정과 상관없이 default 언어의 메인페이지로만 연결되어있다. 이 링크를 현재 활성화된 언어에 맞게 연결되도록 수정해보자.

<a class="gh-head-logo{{#unless @site.logo}} no-image{{/unless}}" href="{{#if (block "lang")}}{{@site.url}}/{{block "lang"}}{{else}}{{@site.url}}{{/if}}">
default.hbs에서 기존에 사용하던 방식처럼 block "lang"을 if문 조건으로 활용해서 처리하면 정상적으로 작동한다.
하지만 이 방식은 error 페이지나 tag 페이지에서는 제대로 동작하지 않는다. 왜냐하면 이 페이지들은 index-ko 또는 index-en을 포함하지 않고 post나 page처럼 명시적으로 "lang"값들을 지정해주지도 않았기 때문이다. 그래서 lang에 의존하지 않기로 했다.
새로운 아이디어는 tag.hbs에서 사용했던 것처럼 localStorage에 저장된 selectedLanguage 값을 가져오고, 해당 값에 따라 URL을 업데이트하는 방식으로 변경하는 것이다.
이건 default에서도, tag에서도, error에서도 해줘야하니 별도의 파일로 만들어서 활용하고자 했다. 이 두 작업을 위한 함수를 각각 만들어, 여러 파일에서 활용할 수 있도록 별도의 util.js 파일에 저장했다.
function getSelectedLanguage() {
return localStorage.getItem("selectedLanguage") || "en";
}
function updateLink(selector, language) {
const element = document.querySelector(selector);
if (element) {
let siteUrl = element.getAttribute("href");
if (!siteUrl.endsWith("/")) {
siteUrl += "/";
}
element.setAttribute("href", `${siteUrl}${language}/`);
}
}
assets/js/util.js
이 함수들을 활용해 @site.url링크가 있는 파일들을 전부 수정해주자.
새로 만든 js파일은 {{asset}}helper를 활용해서 가져오면 된다.
<script type="text/javascript" src="{{asset 'js/util.js'}}"></script>
참조:

전체 코드
전체코드는 여기 github에서 확인 가능하다.
error-404.hbs
가장 아래에 이 코드를 추가해주자.
간단하다. selectedLanguage가져와서 그에 맞게.error-link 의 href를 바꿔주는것이다.
<script type="text/javascript" src="{{asset 'js/util.js'}}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const selectedLanguage = getSelectedLanguage();
if (selectedLanguage !== 'en') {
updateLink('.error-link', selectedLanguage);
}
});
</script>
아무 url이나 입력해서 (e.g. {host}/ko/404error) 홈링크가 {host}/ko/로 잘 연결되는지 확인해보자.


error.hbs
<script type="text/javascript" src="{{asset 'js/util.js'}}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const selectedLanguage = getSelectedLanguage();
if (selectedLanguage !== 'en') {
updateLink('.error-link', selectedLanguage);
updateLink('.site-nav-logo', selectedLanguage);
}
});
</script>
tag.hbs
기존에 구현했던 이 코드를
const selectedLanguage = localStorage.getItem('selectedLanguage') || 'en';
새로 만든 함수로 대체해줬다.
<script type="text/javascript" src="{{asset 'js/util.js'}}"></script>
const selectedLanguage = getSelectedLanguage();
default.hbs
<script type="text/javascript" src="{{asset 'js/util.js'}}"></script>
<script>
function initializeLanguageSelector() {
var selector = document.getElementById('languageSelector');
var currentUrl = window.location.href;
if (!currentUrl.includes('/tag/')) {
var urlLanguage = currentUrl.includes('/ko/') ? 'ko' : 'en';
localStorage.setItem('selectedLanguage', urlLanguage);
selector.value = urlLanguage;
} else {
selector.value = localStorage.getItem('selectedLanguage') || 'en';
}
selector.style.display = 'block';
selector.addEventListener('change', function() {
localStorage.setItem('selectedLanguage', this.value);
if (!currentUrl.includes('/tag/')) {
window.location.href = this.value === 'ko' ? '/ko/' : '/';
}
else {
window.location = window.location.href;
}
});
}
document.addEventListener('DOMContentLoaded', function() {
initializeLanguageSelector();
const selectedLanguage = getSelectedLanguage();
if (selectedLanguage !== 'en') {
updateLink('.gh-head-logo', selectedLanguage);
updateLink('section.copyright a', selectedLanguage);
updateLink('li.nav-home a', selectedLanguage);
}
});
</script>
마치며
이 방식을 이용한다면 block "lang" 방식을 아예 대체할 수도 있다. 그럼에도 불구하고 block "lang" 방식은 SEO 관점에서 html의 lang 속성이 서버 사이드에서 렌더링되는 장점을 가지고 있으므로, (그리고 그닥 중요한 부분이 아니라 생각해서) 그대로 유지하기로 결정했다.