Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 8175x 271x 3794x 271x 271x 270x 3780x 3780x 3780x 3780x 3780x 3780x 3780x | // SPDX-FileCopyrightText: 2024-2026 Hack23 AB
// SPDX-License-Identifier: Apache-2.0
/**
* @module Aggregator/Html/Hreflang
* @description Hreflang / language-switcher helpers used by the article
* HTML shell. Produces the canonical per-language filename, the
* `<link rel="alternate" hreflang="…">` set, and the language switcher
* nav rendered in the article header.
*/
import { BASE_URL } from '../../constants/config.js';
import {
ALL_LANGUAGES,
LANGUAGE_FLAGS,
LANGUAGE_NAMES,
getLocalizedString,
} from '../../constants/languages.js';
import { escapeHTML } from '../../utils/file-utils.js';
import type { LanguageCode } from '../../types/index.js';
/**
* Build the canonical filename for an article in a given language. English
* uses the bare stem (`2026-01-15-breaking-en.html`); other languages share
* the same pattern so every language is a first-class variant. Matches the
* existing `news/<date>-<slug>-<lang>.html` convention.
*
* @param articleSlug - Slug of the form `<date>-<type>` (no extension)
* @param lang - Target language code
* @returns Filename string without any directory prefix
*/
export function getArticleFilename(articleSlug: string, lang: LanguageCode): string {
return `${articleSlug}-${lang}.html`;
}
/**
* Build the hreflang `<link rel="alternate">` block for an article.
*
* @param articleSlug - Slug of the form `<date>-<type>` (no extension)
* @returns Newline-joined `<link>` tags for every supported language plus
* an `x-default` fallback pointing at the English variant
*/
export function buildArticleHreflangLinks(articleSlug: string): string {
const entries = ALL_LANGUAGES.map(
(code) =>
` <link rel="alternate" hreflang="${code}" href="${BASE_URL}/news/${getArticleFilename(articleSlug, code)}">`
);
entries.push(
` <link rel="alternate" hreflang="x-default" href="${BASE_URL}/news/${getArticleFilename(articleSlug, 'en')}">`
);
return entries.join('\n');
}
/**
* Build the language-switcher nav block for the article header.
*
* @param articleSlug - Slug of the form `<date>-<type>` (no extension)
* @param current - Language currently being rendered (used for active state)
* @returns HTML fragment containing one `<a class="lang-link">` per language
*/
export function buildLanguageSwitcher(articleSlug: string, current: LanguageCode): string {
return ALL_LANGUAGES.map((code) => {
const flag = getLocalizedString(LANGUAGE_FLAGS, code);
const name = getLocalizedString(LANGUAGE_NAMES, code);
const safeName = escapeHTML(name);
const active = code === current ? ' active' : '';
const ariaCurrent = code === current ? ' aria-current="page"' : '';
const href = getArticleFilename(articleSlug, code);
return `<a href="${href}" class="lang-link${active}" hreflang="${code}" lang="${code}" title="${safeName}" aria-label="${safeName}"${ariaCurrent}>${flag} ${code.toUpperCase()}</a>`;
}).join('\n ');
}
|