Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions assets/js/languageSuggestion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import * as params from "@params";

const languageSuggestion = (() => {
const supportedLanguages = params.supportedLanguages || [];
const defaultLanguage = "en";
const DISMISSED_KEY = "languageSuggestionDismissed";

const getPreferredLanguage = () => {
const nav = window.navigator;
if (!Array.isArray(nav.languages)) {
return null;
}

for (const language of nav.languages) {
for (const lang of supportedLanguages) {
if (language.toLowerCase().includes(lang)) {
return lang;
}
}
}
return defaultLanguage;
};

const isDismissed = (currentLang, preferredLang) => {
try {
const dismissed = sessionStorage.getItem(DISMISSED_KEY);
if (!dismissed) return false;
const dismissedData = JSON.parse(dismissed);
return (
dismissedData.currentLang === currentLang &&
dismissedData.preferredLang === preferredLang
);
} catch {
return false;
}
};

const setDismissed = (currentLang, preferredLang) => {
try {
sessionStorage.setItem(
DISMISSED_KEY,
JSON.stringify({ currentLang, preferredLang }),
);
} catch {}
};

const init = () => {
const suggestionElement = document.getElementById("language-suggestion");
if (!suggestionElement) return;

const currentLang = suggestionElement.dataset.currentLang;
const preferredLang = getPreferredLanguage();

if (!preferredLang || preferredLang === currentLang) {
return;
}

if (isDismissed(currentLang, preferredLang)) {
return;
}

const translationUrl =
suggestionElement.dataset[
`translation${preferredLang.charAt(0).toUpperCase() + preferredLang.slice(1)}`
];
if (!translationUrl) {
return;
}

const message =
suggestionElement.dataset[
`message${preferredLang.charAt(0).toUpperCase() + preferredLang.slice(1)}`
];
const buttonText =
suggestionElement.dataset[
`buttonText${preferredLang.charAt(0).toUpperCase() + preferredLang.slice(1)}`
];

const messageElement = suggestionElement.querySelector(
".o-language-suggestion__message",
);
if (messageElement && message) {
messageElement.textContent = message;
}

const linkElement = suggestionElement.querySelector(
".o-language-suggestion__link",
);
if (linkElement && buttonText) {
linkElement.href = translationUrl;
linkElement.textContent = buttonText;
linkElement.style.display = "inline-block";
}

suggestionElement.style.display = "block";

const dismissButton = suggestionElement.querySelector(
".o-language-suggestion__dismiss",
);
if (dismissButton) {
dismissButton.addEventListener("click", () => {
suggestionElement.style.display = "none";
setDismissed(currentLang, preferredLang);
});
}
};

return { init, getPreferredLanguage };
})();

document.addEventListener("DOMContentLoaded", () => {
languageSuggestion.init();
});

export default languageSuggestion;
1 change: 1 addition & 0 deletions assets/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ import "./darkmode.js";
import "./search.js";
import "./interactiveMap.js";
import "./expander.js";
import "./languageSuggestion.js";
3 changes: 0 additions & 3 deletions assets/js/mobileMenu.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//import {initWindowOnClick} from './windowOnClickHandling';

function initMobileMenu() {
const menuButton = document.querySelector(".o-nav__menu-button");
const closeButton = document.querySelector(".o-nav__close-button");
Expand All @@ -13,7 +11,6 @@ function initMobileMenu() {
});

window.onclick = (e) => {
//console.log(e.target);
if (e.target.classList.contains("o-header__curtain")) {
closeMobileMenu();
}
Expand Down
44 changes: 44 additions & 0 deletions assets/sass/languageSuggestion.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@import "variables";

.o-language-suggestion {
padding: 1.2rem 1.6rem;
margin-bottom: 1.5rem;
border: 0.2rem solid;
position: relative;

&__message {
margin: 0 0 1rem 0;
padding-right: 3rem;
}

&__actions {
display: flex;
align-items: center;
gap: 1.2rem;
flex-wrap: wrap;
}

&__dismiss {
position: absolute;
top: 1.2rem;
right: 1.2rem;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.4rem;
background: transparent;
border: none;
cursor: pointer;
color: var(--color-body);

&:hover,
&:focus {
color: var(--link-default);
}

svg {
width: 2rem;
height: 2rem;
}
}
}
1 change: 1 addition & 0 deletions assets/sass/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@import "fonts.scss";
@import "navigation.scss";
@import "contentNavigation";
@import "languageSuggestion";
@import "search.scss";
@import "teaser.scss";
@import "footer.scss";
Expand Down
1 change: 1 addition & 0 deletions i18n/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ interactiveMap:
language-switcher:
aria-label: Sprache wechseln
dropdown-label: Verfügbare Sprachen
suggestion: Diese Seite ist in deiner bevorzugten Sprache verfügbar.
menu:
close:
label: Schließen
Expand Down
1 change: 1 addition & 0 deletions i18n/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ interactiveMap:
language-switcher:
aria-label: Switch language
dropdown-label: Available languages
suggestion: This page is available in your preferred language.
menu:
close:
label: Close
Expand Down
1 change: 1 addition & 0 deletions i18n/fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ interactiveMap:
language-switcher:
aria-label: Changer de langue
dropdown-label: Langues disponibles
suggestion: Cette page est disponible dans votre langue préférée.
menu:
close:
label: Fermer
Expand Down
32 changes: 10 additions & 22 deletions layouts/alias.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,22 @@
<noscript>
<meta http-equiv="refresh" content="0; url={{ .Permalink }}" />
</noscript>
<script>
(() => {
const supportedLanguages = [{{ range site.Languages }}"{{ .Lang }}",{{ end }}];
const defaultLanguage = "en";

const getTargetLanguage = () => {
const nav = window.navigator;
if (!Array.isArray(nav.languages)) {
return defaultLanguage;
}

for (const language of nav.languages) {
for (const lang of supportedLanguages) {
if (language.toLowerCase().includes(lang)) {
return lang;
}
}
}
return defaultLanguage;
};
{{ $supportedLanguages := slice }}
{{ range site.Languages }}
{{ $supportedLanguages = $supportedLanguages | append .Lang }}
{{ end }}
{{ $built := resources.Get "js/languageSuggestion.js" | js.Build (dict "format" "esm" "minify" true "params" (dict "supportedLanguages" $supportedLanguages)) }}
<script type="module">
import languageSuggestion from "{{ $built.RelPermalink }}";

(() => {
let targetLocation = '{{ .Permalink }}'
if (window.location.pathname === '/') {
// On root, redirect to the target language root
targetLocation = `/${getTargetLanguage()}/`
targetLocation = `/${languageSuggestion.getPreferredLanguage()}/`
} else if ('{{ relURL .Permalink }}' === '/en/404/'){
// On 404, redirect to the 404 page of the target language
targetLocation = `/${getTargetLanguage()}/404/`
targetLocation = `/${languageSuggestion.getPreferredLanguage()}/404/`
}
window.location.replace(targetLocation);
})();
Expand Down
1 change: 1 addition & 0 deletions layouts/partials/contentNavigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
id="o-aside__content"
aria-label="{{ T "contentNavigation.title" }}"
>
{{ partial "language-suggestion" . }}
<div class="o-single__container">
{{ if eq .Page.Type "operator" }}
<ul aria-label="{{ T "contentNavigation.relatedCountries" }}">
Expand Down
2 changes: 0 additions & 2 deletions layouts/partials/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
new PagefindHighlight({ highlightParam: "highlight" });
</script>

<!-- include a favicon for your site if you have it, else omit the line below
Location of favicon can be in mytheme/static/favicon.ico -->
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="apple-touch-icon" type="image/x-icon" href="/favicon.ico" />
Expand Down
8 changes: 6 additions & 2 deletions layouts/partials/head/js.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{{ $supportedLanguages := slice }}
{{ range site.Languages }}
{{ $supportedLanguages = $supportedLanguages | append .Lang }}
{{ end }}
{{- with resources.Get "js/main.js" }}
{{- if eq hugo.Environment "development" }}
{{- with . | js.Build }}
{{- with . | js.Build (dict "params" (dict "supportedLanguages" $supportedLanguages)) }}
<script src="{{ .RelPermalink }}"></script>
{{- end }}
{{- else }}
{{- $opts := dict "minify" true }}
{{- $opts := dict "minify" true "params" (dict "supportedLanguages" $supportedLanguages) }}
{{- with . | js.Build
$opts | fingerprint
}}
Expand Down
31 changes: 31 additions & 0 deletions layouts/partials/language-suggestion.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<div
id="language-suggestion"
class="o-single__container o-language-suggestion"
style="display: none;"
data-current-lang="{{ site.Language.Lang }}"
{{ range .AllTranslations }}
data-translation-{{ .Language.Lang }}="{{ .RelPermalink }}"
data-language-name-{{ .Language.Lang }}="{{ .Language.LanguageName }}"
{{ end }}
data-message-en="This page is also available in English."
data-message-de="Diese Seite ist auch auf Deutsch verfügbar."
data-message-fr="Cette page est également disponible en français."
data-button-text-en="Switch to English version"
data-button-text-de="Zu deutscher Version wechseln"
data-button-text-fr="Passer à la version française"
>
<button
class="o-language-suggestion__dismiss"
aria-label="{{ T "menu.close.label" }}"
>
{{ partial "icon" "close" }}
</button>
<p class="o-language-suggestion__message"></p>
<div class="o-language-suggestion__actions">
<a
href="#"
class="o-language-suggestion__link a-button"
style="display: none;"
></a>
</div>
</div>
Loading