docs(readme): update README for clarity and consistency

- Translated sections from German to English for better accessibility.
- Enhanced the structure by clearly defining the workspace relationship and local development instructions.
- Improved descriptions for Docker setup and deployment processes to ensure users understand the requirements and context.
- Updated links and formatting for consistency throughout the document.

This commit aims to improve the overall clarity and usability of the README documentation.
This commit is contained in:
Marvin
2026-04-10 02:12:06 +02:00
parent 66b8446d19
commit 8d8fda49c4
227 changed files with 498 additions and 2496 deletions

View File

@@ -147,7 +147,14 @@ body {
color: var(--color-on-surface);
}
.navbar__item .navbar__link {
.navbar__items--right {
display: flex;
align-items: center;
gap: 0.45rem;
}
.navbar__item .navbar__link,
.navbar__item.navbar__link {
font-family: var(--font-headline);
font-weight: 500;
letter-spacing: 0.06em;
@@ -157,11 +164,13 @@ body {
transition: color 0.25s ease;
}
.navbar__item .navbar__link:hover {
.navbar__item .navbar__link:hover,
.navbar__item.navbar__link:hover {
color: var(--color-on-surface);
}
.navbar__item .navbar__link--active {
.navbar__item .navbar__link--active,
.navbar__item.navbar__link--active {
color: var(--color-primary);
box-shadow: inset 0 -2px 0 0 var(--color-primary);
}
@@ -175,41 +184,40 @@ body {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
min-width: 2.25rem;
min-height: 2.25rem;
padding: 0;
border-radius: 999px;
backdrop-filter: blur(12px);
background: rgba(0, 30, 28, 0.65);
box-shadow: inset 0 0 0 1px rgba(15, 81, 76, 0.15);
}
.nav-icon-only {
color: transparent;
}
.nav-icon-only::before {
font-size: 0.95rem;
.nav-right-icon.nav-icon-only {
color: var(--color-on-surface-variant);
}
.nav-link-mods::before {
content: '🧩';
.nav-right-icon.nav-icon-only:hover,
.nav-right-icon.nav-icon-only:focus-visible {
color: var(--color-on-surface);
}
.nav-link-discord::before {
content: '💬';
.nav-icon-svg {
flex-shrink: 0;
display: block;
color: currentColor;
}
.nav-link-support::before {
content: '🛟';
}
.nav-link-github::before {
content: '⌁';
}
.nav-locale::before {
content: '🌐';
.nav-icon-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Editorial bleed + hero (homepage) */
@@ -423,11 +431,7 @@ body {
/* Doc canvas — editorial bleed (wiki layout alignment); no hard section borders */
.theme-doc-wrapper {
background: linear-gradient(
180deg,
var(--color-surface-container-low) 0%,
var(--color-background) 42%
);
background: linear-gradient(180deg, var(--color-surface-container-low) 0%, var(--color-background) 42%);
}
.theme-doc-root .theme-doc-sidebar-container {
@@ -562,27 +566,22 @@ body {
color: var(--color-primary);
}
.footer-link-icon {
position: relative;
padding-left: 1.4rem;
.footer-link-with-icon {
display: inline-flex;
align-items: center;
gap: 0.4rem;
}
.footer-link-icon::before {
position: absolute;
left: 0;
opacity: 0.9;
.footer-icon-svg {
flex-shrink: 0;
opacity: 0.85;
color: rgba(192, 252, 246, 0.45);
transition: color 0.2s ease, opacity 0.2s ease;
}
.footer-link-github::before {
content: '⌁';
}
.footer-link-discord::before {
content: '💬';
}
.footer-link-support::before {
content: '🛟';
.footer__link-item:hover .footer-icon-svg {
opacity: 1;
color: var(--color-primary);
}
.button.button--primary {

View File

@@ -36,12 +36,12 @@ export const sharedWorkflowLinksEn: HomepageDocLink[] = [
{
title: 'End-user docs',
description: 'Install, update, and troubleshooting paths.',
link: '/wiki/legacy/wiki-import/EndUser/End-User-Release',
link: '/wiki/guides/players/overview',
},
{
title: 'Mod developer docs',
description: 'Setup, debugging, and hook integration.',
link: '/wiki/legacy/wiki-import/ModDevs/Mod-Developer-Debug',
link: '/wiki/guides/mod-developers/overview',
},
{
title: 'Repo inventory',
@@ -95,12 +95,12 @@ export const sharedWorkflowLinksDe: HomepageDocLink[] = [
{
title: 'Endnutzer-Doku',
description: 'Installation, Updates und Fehlerbehebung.',
link: '/wiki/legacy/wiki-import/EndUser/End-User-Release',
link: '/wiki/guides/players/overview',
},
{
title: 'Mod-Entwickler-Doku',
description: 'Setup, Debugging und Hook-Integration.',
link: '/wiki/legacy/wiki-import/ModDevs/Mod-Developer-Debug',
link: '/wiki/guides/mod-developers/overview',
},
{
title: 'Repo-Inventar',

View File

@@ -0,0 +1,63 @@
/**
* Swizzled: community footer links use react-icons instead of emoji/CSS pseudo-elements.
*/
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import isInternalUrl from '@docusaurus/isInternalUrl';
import IconExternalLink from '@theme/Icon/ExternalLink';
import type {Props} from '@theme/Footer/LinkItem';
import {FaDiscord, FaGithub, FaLifeRing} from 'react-icons/fa6';
const footerIconProps = {
className: 'footer-icon-svg',
'aria-hidden': true as const,
size: 14,
};
function getFooterIcon(className?: string): ReactNode | null {
if (!className) {
return null;
}
if (className.includes('footer-link-github')) {
return <FaGithub {...footerIconProps} />;
}
if (className.includes('footer-link-discord')) {
return <FaDiscord {...footerIconProps} />;
}
if (className.includes('footer-link-support')) {
return <FaLifeRing {...footerIconProps} />;
}
return null;
}
export default function FooterLinkItem({item}: Props): ReactNode {
const {to, href, label, prependBaseUrlToHref, className, ...props} = item;
const toUrl = useBaseUrl(to);
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
const icon = getFooterIcon(className);
return (
<Link
className={clsx('footer__link-item', className)}
{...(href
? {
href: prependBaseUrlToHref ? normalizedHref : href,
}
: {
to: toUrl,
})}
{...props}>
{icon ? (
<span className="footer-link-with-icon">
{icon}
<span>{label}</span>
</span>
) : (
label
)}
{href && !isInternalUrl(href) && <IconExternalLink />}
</Link>
);
}

View File

@@ -0,0 +1,132 @@
/**
* Swizzled: language control uses react-icons; compact desktop label matches icon-only navbar style.
*/
import React, {type ReactNode} from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import {useAlternatePageUtils} from '@docusaurus/theme-common/internal';
import {translate} from '@docusaurus/Translate';
import {mergeSearchStrings, useHistorySelector} from '@docusaurus/theme-common';
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem';
import type {Props} from '@theme/NavbarItem/LocaleDropdownNavbarItem';
import {IoLanguage} from 'react-icons/io5';
import styles from './styles.module.css';
function useLocaleDropdownUtils() {
const {
siteConfig,
i18n: {localeConfigs},
} = useDocusaurusContext();
const alternatePageUtils = useAlternatePageUtils();
const search = useHistorySelector((history) => history.location.search);
const hash = useHistorySelector((history) => history.location.hash);
const getLocaleConfig = (locale: string) => {
const localeConfig = localeConfigs[locale];
if (!localeConfig) {
throw new Error(
`Docusaurus bug, no locale config found for locale=${locale}`,
);
}
return localeConfig;
};
const getBaseURLForLocale = (locale: string) => {
const localeConfig = getLocaleConfig(locale);
const isSameDomain = localeConfig.url === siteConfig.url;
if (isSameDomain) {
return `pathname://${alternatePageUtils.createUrl({
locale,
fullyQualified: false,
})}`;
}
return alternatePageUtils.createUrl({
locale,
fullyQualified: true,
});
};
return {
getURL: (locale: string, options: {queryString: string | undefined}) => {
const finalSearch = mergeSearchStrings(
[search, options.queryString],
'append',
);
return `${getBaseURLForLocale(locale)}${finalSearch}${hash}`;
},
getLabel: (locale: string) => {
return getLocaleConfig(locale).label;
},
getLang: (locale: string) => {
return getLocaleConfig(locale).htmlLang;
},
};
}
export default function LocaleDropdownNavbarItem({
mobile,
dropdownItemsBefore,
dropdownItemsAfter,
queryString,
className,
...props
}: Props): ReactNode {
const utils = useLocaleDropdownUtils();
const {
i18n: {currentLocale, locales},
} = useDocusaurusContext();
const localeItems = locales.map((locale): LinkLikeNavbarItemProps => {
return {
label: utils.getLabel(locale),
lang: utils.getLang(locale),
to: utils.getURL(locale, {queryString}),
target: '_self',
autoAddBaseUrl: false,
className:
locale === currentLocale
? mobile
? 'menu__link--active'
: 'dropdown__link--active'
: '',
};
});
const items = [...dropdownItemsBefore, ...localeItems, ...dropdownItemsAfter];
const dropdownLabel = mobile
? translate({
message: 'Languages',
id: 'theme.navbar.mobileLanguageDropdown.label',
description: 'The label for the mobile language switcher dropdown',
})
: utils.getLabel(currentLocale);
const iconOnlyDesktop =
!mobile && String(className ?? '').includes('nav-icon-only');
const label: ReactNode = (
<>
<IoLanguage
className={iconOnlyDesktop ? styles.iconOnly : styles.iconLanguage}
aria-hidden
/>
{mobile || !iconOnlyDesktop ? (
dropdownLabel
) : (
<span className="nav-icon-sr-only">{dropdownLabel}</span>
)}
</>
);
return (
<DropdownNavbarItem
{...props}
className={className}
mobile={mobile}
label={label}
items={items}
/>
);
}

View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
.iconLanguage {
vertical-align: middle;
margin-right: 5px;
color: currentColor;
flex-shrink: 0;
}
.iconOnly {
vertical-align: middle;
margin-right: 0;
color: currentColor;
flex-shrink: 0;
}

View File

@@ -0,0 +1,117 @@
/**
* Swizzled: icon-only navbar links use react-icons instead of CSS/emoji pseudo-elements.
*/
import React, {type ReactNode} from 'react';
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import isInternalUrl from '@docusaurus/isInternalUrl';
import {isRegexpStringMatch} from '@docusaurus/theme-common';
import IconExternalLink from '@theme/Icon/ExternalLink';
import type {Props} from '@theme/NavbarItem/NavbarNavLink';
import clsx from 'clsx';
import {FaDiscord, FaGithub, FaLifeRing, FaPuzzlePiece} from 'react-icons/fa6';
const navIconProps = {
className: 'nav-icon-svg',
'aria-hidden': true as const,
size: 18,
};
function getNavIcon(className?: string): ReactNode | null {
if (!className) {
return null;
}
if (className.includes('nav-link-mods')) {
return <FaPuzzlePiece {...navIconProps} />;
}
if (className.includes('nav-link-discord')) {
return <FaDiscord {...navIconProps} />;
}
if (className.includes('nav-link-support')) {
return <FaLifeRing {...navIconProps} />;
}
if (className.includes('nav-link-github')) {
return <FaGithub {...navIconProps} />;
}
return null;
}
function isIconOnlyClass(className?: string) {
return Boolean(className?.includes('nav-icon-only'));
}
export default function NavbarNavLink({
activeBasePath,
activeBaseRegex,
to,
href,
label,
html,
isDropdownLink,
prependBaseUrlToHref,
className,
...props
}: Props): ReactNode {
const toUrl = useBaseUrl(to);
const activeBaseUrl = useBaseUrl(activeBasePath);
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
const cls = clsx(className);
const navIcon = getNavIcon(cls);
const iconOnly = isIconOnlyClass(cls) && Boolean(navIcon);
const isExternalLink = Boolean(label && href && !isInternalUrl(href));
const linkContentProps = html
? {dangerouslySetInnerHTML: {__html: html}}
: iconOnly && navIcon
? {
children: (
<>
{navIcon}
{typeof label === 'string' || typeof label === 'number' ? (
<span className="nav-icon-sr-only">{label}</span>
) : (
label
)}
</>
),
}
: {
children: (
<>
{label}
{isExternalLink && (
<IconExternalLink
{...(isDropdownLink && {width: 12, height: 12})}
/>
)}
</>
),
};
if (href) {
return (
<Link
href={prependBaseUrlToHref ? normalizedHref : href}
className={className}
{...props}
{...linkContentProps}
/>
);
}
return (
<Link
to={toUrl}
isNavLink
className={className}
{...((activeBasePath || activeBaseRegex) && {
isActive: (_match, location) =>
activeBaseRegex
? isRegexpStringMatch(activeBaseRegex, location.pathname)
: location.pathname.startsWith(activeBaseUrl),
})}
{...props}
{...linkContentProps}
/>
);
}