✨ Closed #148, add multiple lananguages support.
This commit is contained in:
parent
0b8bdc0e00
commit
60b14e65e9
@ -29,7 +29,143 @@
|
|||||||
font-size: $font-size-smallest;
|
font-size: $font-size-smallest;
|
||||||
}
|
}
|
||||||
|
|
||||||
.google-translate {
|
.i18n-translate {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
font-size: $font-size-largest;
|
||||||
|
margin: auto 0;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-select, .lang-options {
|
||||||
|
|
||||||
|
.flag-icon {
|
||||||
|
background-size: cover;
|
||||||
|
width: 30px;
|
||||||
|
height: 20px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-icon-zh-cn {
|
||||||
|
background-image: url("/imgs/flags/zh-CN.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-icon-en-us {
|
||||||
|
background-image: url("/imgs/flags/en-US.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-icon-fr-fr {
|
||||||
|
background-image: url("/imgs/flags/fr-FR.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-select {
|
||||||
|
|
||||||
|
.flag-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-select {
|
||||||
|
margin-left: 16px;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.25;
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
font-size: $font-size-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
justify-content: center;
|
||||||
|
width: 140px;
|
||||||
|
|
||||||
|
/* &:hover {
|
||||||
|
+ .lang-options {
|
||||||
|
display: block;
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
.selected-language {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-options {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-top: none;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
display: block;
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-option {
|
||||||
|
padding: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
padding-left: 14px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--selection-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-name {
|
||||||
|
margin: 0 16px 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* select {
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
option {
|
||||||
|
font-size: $font-size-small;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right center;
|
||||||
|
padding-right: 30px;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-icon-zh-cn {
|
||||||
|
background-image: url("../imgs/flags/zh-CN.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-icon-en-us {
|
||||||
|
background-image: url("../imgs/flags/en-US.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-icon-fr-fr {
|
||||||
|
background-image: url("../imgs/flags/fr-FR.png");
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
/* .google-translate {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.fa {
|
.fa {
|
||||||
@ -37,7 +173,7 @@
|
|||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
@if $footer_vendors_enable {
|
@if $footer_vendors_enable {
|
||||||
.vendors-list {
|
.vendors-list {
|
||||||
|
@ -60,6 +60,7 @@ NexT.boot.registerEvents = function() {
|
|||||||
NexT.boot.refresh = function() {
|
NexT.boot.refresh = function() {
|
||||||
|
|
||||||
NexT.utils.fmtSiteInfo();
|
NexT.utils.fmtSiteInfo();
|
||||||
|
NexT.utils.registerLangSelect();
|
||||||
|
|
||||||
if (!NexT.CONFIG.page.isPage) return;
|
if (!NexT.CONFIG.page.isPage) return;
|
||||||
|
|
||||||
|
@ -499,22 +499,59 @@ NexT.utils = {
|
|||||||
const isSubPath = !NexT.CONFIG.root.startsWith(target.pathname) && location.pathname.startsWith(target.pathname);
|
const isSubPath = !NexT.CONFIG.root.startsWith(target.pathname) && location.pathname.startsWith(target.pathname);
|
||||||
target.classList.toggle('menu-item-active', target.hostname === location.hostname && (isSamePath || isSubPath));
|
target.classList.toggle('menu-item-active', target.hostname === location.hostname && (isSamePath || isSubPath));
|
||||||
});
|
});
|
||||||
},
|
},*/
|
||||||
|
|
||||||
registerLangSelect: function() {
|
registerLangSelect: function() {
|
||||||
const selects = document.querySelectorAll('.lang-select');
|
let selects = document.getElementById('lang-select');
|
||||||
selects.forEach(sel => {
|
if (!selects) return;
|
||||||
sel.value = NexT.CONFIG.page.lang;
|
|
||||||
sel.addEventListener('change', () => {
|
let selected = selects.querySelector('#lang-selected');
|
||||||
const target = sel.options[sel.selectedIndex];
|
let selectedVal = selected.querySelectorAll('span');
|
||||||
document.querySelectorAll('.lang-select-label span').forEach(span => {
|
let flagIcon = selectedVal[0];
|
||||||
span.innerText = target.text;
|
let langName = selectedVal[1];
|
||||||
});
|
let selectIcon = selected.querySelector('i');
|
||||||
// Disable Pjax to force refresh translation of menu item
|
|
||||||
window.location.href = target.dataset.href;
|
|
||||||
|
let options = selects.querySelectorAll('#lang-options>div');
|
||||||
|
let optionsDom = options[0].parentNode;
|
||||||
|
options.forEach(option => {
|
||||||
|
option.addEventListener('click', () => {
|
||||||
|
let langCode = option.getAttribute('lang-code');
|
||||||
|
flagIcon.className = 'flag-icon flag-icon-'+langCode;
|
||||||
|
langName.innerHTML = option.getAttribute('lang-name');
|
||||||
|
selectIcon.className = 'fa fa-chevron-down';
|
||||||
|
optionsDom.style.opacity = '0';
|
||||||
|
optionsDom.style.transform = 'translateY(-10px)';
|
||||||
|
|
||||||
|
const currentUrl = window.location.href;
|
||||||
|
const newUrl = currentUrl.replace(/(\/[^\/]+)?(\/[^\/]+)?$/, `/${langCode}$1$2`);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
optionsDom.style.display = 'none';
|
||||||
|
window.location.href = newUrl;
|
||||||
|
}, 300);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},*/
|
|
||||||
|
selected.addEventListener('mouseenter', function() {
|
||||||
|
selectIcon.className = 'fa fa-chevron-up';
|
||||||
|
optionsDom.style.display = 'block';
|
||||||
|
optionsDom.style.opacity = '1';
|
||||||
|
optionsDom.style.transform = 'translateY(0)';
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
optionsDom.addEventListener('mouseleave', function() {
|
||||||
|
selectIcon.className = 'fa fa-chevron-down';
|
||||||
|
optionsDom.style.opacity = '0';
|
||||||
|
optionsDom.style.transform = 'translateY(-10px)';
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
optionsDom.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
registerSidebarTOC: function () {
|
registerSidebarTOC: function () {
|
||||||
const toc = document.getElementById('TableOfContents');
|
const toc = document.getElementById('TableOfContents');
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
{{ $ft := .Site.Params.footer }}
|
{{ $ft := .Site.Params.footer }}
|
||||||
{{ if $ft.translate }}
|
<div class="i18n-translate">
|
||||||
<div id="gtranslate" class="google-translate">
|
|
||||||
<i class="fa fa-language"></i>
|
<i class="fa fa-language"></i>
|
||||||
<div id="google_translate_element"></div>
|
<div id="lang-select" class="lang-select">
|
||||||
|
<div id="lang-selected" class="selected-option">
|
||||||
|
<span class="flag-icon flag-icon-{{$.Site.Language.Lang}}"></span>
|
||||||
|
<span class="selected-language">{{ .Site.Language.LanguageName }}</span>
|
||||||
|
<i class="fa fa-chevron-down"></i>
|
||||||
|
</div>
|
||||||
|
<div id="lang-options" class="lang-options">
|
||||||
|
{{ range .Site.Languages }}
|
||||||
|
<div class="lang-option" lang-code="{{ .Lang }}" lang-name="{{ .LanguageName }}">
|
||||||
|
<span class="flag-icon flag-icon-{{ .Lang }}"></span>
|
||||||
|
<span class="lang-name">{{ .LanguageName }}</span>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
©
|
©
|
||||||
<span itemprop="copyrightYear">
|
<span itemprop="copyrightYear">
|
||||||
|
@ -105,11 +105,6 @@
|
|||||||
{{ $nextjs = $nextjs | append $lawt }}
|
{{ $nextjs = $nextjs | append $lawt }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .Site.Params.footer.translate }}
|
|
||||||
{{ $translate := resources.Get "js/3rd/others/translate.js" }}
|
|
||||||
{{ $nextjs = $nextjs | append $translate }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
|
|
||||||
{{ $nextjs = $nextjs | resources.Concat "js/main.js"}}
|
{{ $nextjs = $nextjs | resources.Concat "js/main.js"}}
|
||||||
{{ if hugo.IsProduction }}
|
{{ if hugo.IsProduction }}
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
"lazyload" .Site.Params.lazyload
|
"lazyload" .Site.Params.lazyload
|
||||||
"motion" .Site.Params.motion
|
"motion" .Site.Params.motion
|
||||||
"i18n" (dict
|
"i18n" (dict
|
||||||
|
"enable" .Site.Params.footer.translate
|
||||||
"placeholder" (T "Search.placeholder")
|
"placeholder" (T "Search.placeholder")
|
||||||
"empty" (T "Search.empty")
|
"empty" (T "Search.empty")
|
||||||
"hits_time" (T "Search.time")
|
"hits_time" (T "Search.time")
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
<i class="fas fa-comments"></i>
|
<i class="fas fa-comments"></i>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .Site.Params.footer.translate }}
|
|
||||||
<div id="goto-gtranslate" class="button" title="{{ T "ToolBtns.lang" }}">
|
<div id="goto-gtranslate" class="button" title="{{ T "ToolBtns.lang" }}">
|
||||||
<i class="fas fa-globe"></i>
|
<i class="fas fa-globe"></i>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
|
||||||
<div id="toggle-theme" class="button" title="{{ T "ToolBtns.theme" }}">
|
<div id="toggle-theme" class="button" title="{{ T "ToolBtns.theme" }}">
|
||||||
<i class="fas fa-adjust"></i>
|
<i class="fas fa-adjust"></i>
|
||||||
</div>
|
</div>
|
||||||
|
1
static/css/google-translate.min.css
vendored
1
static/css/google-translate.min.css
vendored
File diff suppressed because one or more lines are too long
BIN
static/imgs/flags/en-US.png
Normal file
BIN
static/imgs/flags/en-US.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
static/imgs/flags/fr-FR.png
Normal file
BIN
static/imgs/flags/fr-FR.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 596 B |
BIN
static/imgs/flags/zh-CN.png
Normal file
BIN
static/imgs/flags/zh-CN.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 617 B |
Loading…
Reference in New Issue
Block a user