From 9fccdce29dca7b20db4e77f365f71539ee28cfec Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sun, 1 Nov 2026 21:04:17 +0100 Subject: [PATCH 1/3] Always use the left-to-right page direction --- com.woltlab.wcf/templates/documentHeader.tpl | 2 +- wcfsetup/install/files/acp/templates/header.tpl | 2 +- wcfsetup/install/files/acp/templates/rescueMode.tpl | 2 +- .../install/files/lib/data/language/Language.class.php | 9 ++++++++- .../system/form/builder/field/RatingFormField.class.php | 5 ----- wcfsetup/install/lang/de.xml | 3 +-- wcfsetup/install/lang/en.xml | 3 +-- wcfsetup/setup/lang/setup_de.xml | 1 - wcfsetup/setup/lang/setup_en.xml | 1 - wcfsetup/setup/template/header.tpl | 2 +- 10 files changed, 14 insertions(+), 16 deletions(-) diff --git a/com.woltlab.wcf/templates/documentHeader.tpl b/com.woltlab.wcf/templates/documentHeader.tpl index ace9f8605fd..4a10f931b6f 100644 --- a/com.woltlab.wcf/templates/documentHeader.tpl +++ b/com.woltlab.wcf/templates/documentHeader.tpl @@ -1,6 +1,6 @@ diff --git a/wcfsetup/install/files/acp/templates/header.tpl b/wcfsetup/install/files/acp/templates/header.tpl index 5ce59c1fe57..a837e6eda7d 100644 --- a/wcfsetup/install/files/acp/templates/header.tpl +++ b/wcfsetup/install/files/acp/templates/header.tpl @@ -1,6 +1,6 @@ diff --git a/wcfsetup/install/files/acp/templates/rescueMode.tpl b/wcfsetup/install/files/acp/templates/rescueMode.tpl index c863c523dfc..43e2424799a 100644 --- a/wcfsetup/install/files/acp/templates/rescueMode.tpl +++ b/wcfsetup/install/files/acp/templates/rescueMode.tpl @@ -1,5 +1,5 @@ - + diff --git a/wcfsetup/install/files/lib/data/language/Language.class.php b/wcfsetup/install/files/lib/data/language/Language.class.php index d4d1820a838..6d5efdcb3a7 100644 --- a/wcfsetup/install/files/lib/data/language/Language.class.php +++ b/wcfsetup/install/files/lib/data/language/Language.class.php @@ -85,10 +85,12 @@ public function getFixedLanguageCode(): string /** * Returns the page direction of this language. + * + * @deprecated 6.3 Right-to-left languages are no longer supported, the page direction is always `ltr`. */ public function getPageDirection(): string { - return $this->get('wcf.global.pageDirection'); + return 'ltr'; } /** @@ -238,6 +240,11 @@ protected function loadCategory(string $category): bool // include language file @include_once($filename); + if ($category === 'wcf.global') { + // RTL is no longer supported, this overrides language packs that still ship `rtl`. + $this->items['wcf.global.pageDirection'] = 'ltr'; + } + return true; } diff --git a/wcfsetup/install/files/lib/system/form/builder/field/RatingFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/RatingFormField.class.php index 86b4e43422e..abbe18b7a05 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/RatingFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/RatingFormField.class.php @@ -3,7 +3,6 @@ namespace wcf\system\form\builder\field; use wcf\system\form\builder\field\validation\FormFieldValidationError; -use wcf\system\WCF; /** * Implementation of a form field to set the rating of an object. @@ -59,10 +58,6 @@ public function __construct() */ public function getRatings(): array { - if (WCF::getLanguage()->get('wcf.global.pageDirection') === 'rtl') { - return \range($this->maximum, $this->minimum, -1); - } - return \range($this->minimum, $this->maximum); } diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index d9faf42a2d5..dfddd6c23f0 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -3912,8 +3912,6 @@ Dateianhänge: - - @@ -5907,5 +5905,6 @@ Erlaubte Dateiendungen: {', '|implode:$allowedFileExtensions}]]> + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index aef94bb7946..2ef1ae67c6f 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -3858,8 +3858,6 @@ Attachments: - - @@ -5909,5 +5907,6 @@ Allowed extensions: {', '|implode:$allowedFileExtensions}]]> + diff --git a/wcfsetup/setup/lang/setup_de.xml b/wcfsetup/setup/lang/setup_de.xml index ad618846ecb..de1c4e8913f 100644 --- a/wcfsetup/setup/lang/setup_de.xml +++ b/wcfsetup/setup/lang/setup_de.xml @@ -2,7 +2,6 @@ - diff --git a/wcfsetup/setup/lang/setup_en.xml b/wcfsetup/setup/lang/setup_en.xml index cb2ad3f7952..004e94e2d17 100644 --- a/wcfsetup/setup/lang/setup_en.xml +++ b/wcfsetup/setup/lang/setup_en.xml @@ -2,7 +2,6 @@ - diff --git a/wcfsetup/setup/template/header.tpl b/wcfsetup/setup/template/header.tpl index 51ffeeeb910..475d4ddb74e 100644 --- a/wcfsetup/setup/template/header.tpl +++ b/wcfsetup/setup/template/header.tpl @@ -1,5 +1,5 @@ - + {lang}wcf.global.progressBar{/lang} - {lang}wcf.global.title{/lang} From 7228413888c4bad7c679e09cc171e313fb5a87bd Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sun, 1 Nov 2026 21:32:09 +0100 Subject: [PATCH 2/3] Drop the right-to-left stylesheet variant --- .../files/acp/style/acpStyleEditor.css | 21 --- .../files/lib/acp/form/StyleAddForm.class.php | 3 - .../lib/acp/form/StyleEditForm.class.php | 2 - .../acp/form/StyleGlobalValuesForm.class.php | 2 - .../lib/system/style/StyleCompiler.class.php | 25 ---- .../lib/system/style/StyleHandler.class.php | 4 +- .../files/lib/util/StyleUtil.class.php | 130 ------------------ .../files/style/layout/pageHeader/system.scss | 4 - 8 files changed, 2 insertions(+), 189 deletions(-) diff --git a/wcfsetup/install/files/acp/style/acpStyleEditor.css b/wcfsetup/install/files/acp/style/acpStyleEditor.css index 370a6d2a05b..c1fe6f40bbb 100644 --- a/wcfsetup/install/files/acp/style/acpStyleEditor.css +++ b/wcfsetup/install/files/acp/style/acpStyleEditor.css @@ -13,9 +13,6 @@ html[dir="ltr"] #spWindow { margin-right: 40px; } -html[dir="rtl"] #spWindow { - margin-left: 40px; -} #spSidebar { flex: 0 0 300px; } @@ -89,9 +86,6 @@ html[dir="rtl"] #spWindow { html[dir="ltr"] #spHeaderPanel ol.inlineList > li { margin-right: 0; } -html[dir="rtl"] #spHeaderPanel ol.inlineList > li { - margin-left: 0; -} #spHeaderPanel ol.inlineList > li > a { align-items: center; background-color: var(--wcfHeaderMenuLinkBackground); @@ -105,9 +99,6 @@ html[dir="rtl"] #spHeaderPanel ol.inlineList > li { html[dir="ltr"] #spHeaderPanel ol.inlineList > li.active > a::after { margin-left: 5px; } -html[dir="rtl"] #spHeaderPanel ol.inlineList > li.active > a::after { - margin-right: 5px; -} #spHeaderPanel ol.inlineList > li.active > a, #spHeaderPanel ol.inlineList > li:hover > a { background-color: var(--wcfHeaderMenuLinkBackgroundActive); @@ -313,9 +304,6 @@ html[dir="rtl"] #spHeaderPanel ol.inlineList > li.active > a::after { html[dir="ltr"] #spNavigation li:first-child::after { margin-left: 5px; } -html[dir="rtl"] #spNavigation li:first-child::after { - margin-right: 5px; -} /* ### navigation (new page header layouts) ### */ #spWindow:not([data-page-header-layout="classic"]) #spNavigation { @@ -341,9 +329,6 @@ html[dir="rtl"] #spNavigation li:first-child::after { center / contain no-repeat; width: 12px; } -html[dir="rtl"] #spWindow:not([data-page-header-layout="classic"]) #spNavigation li:first-child::after { - transform: scaleX(-1); -} #spWindow:not([data-page-header-layout="classic"]) #spContent { padding-top: 10px; } @@ -416,9 +401,6 @@ html[dir="rtl"] #spWindow:not([data-page-header-layout="classic"]) #spNavigation html[dir="ltr"] #spTable th { text-align: left; } -html[dir="rtl"] #spTable th { - text-align: right; -} #spTable th, #spTable td { padding: 10px; @@ -872,9 +854,6 @@ html[dir="rtl"] #spTable th { html[dir="ltr"] #spContentSidebar { margin-left: 20px; } -html[dir="rtl"] #spContentSidebar { - margin-right: 20px; -} #spContentSidebar .spContentSidebarBox { padding: 20px; background-color: var(--wcfSidebarBackground); diff --git a/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php b/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php index 4937423e280..49c9e0c6a12 100644 --- a/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php @@ -939,9 +939,6 @@ public function save() if (\file_exists($this->styleTestFileDir . '/style.css')) { \unlink($this->styleTestFileDir . '/style.css'); } - if (\file_exists($this->styleTestFileDir . '/style-rtl.css')) { - \unlink($this->styleTestFileDir . '/style-rtl.css'); - } if (\file_exists($this->styleTestFileDir . '/style-preload.json')) { \unlink($this->styleTestFileDir . '/style-preload.json'); } diff --git a/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php b/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php index 79db9085d80..987af9dd8ac 100644 --- a/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php @@ -392,11 +392,9 @@ public function save() if ( $this->styleTestFileDir !== null && \file_exists($this->styleTestFileDir . '/style.css') - && \file_exists($this->styleTestFileDir . '/style-rtl.css') ) { $styleFilename = StyleCompiler::getFilenameForStyle($this->style); \rename($this->styleTestFileDir . '/style.css', $styleFilename . '.css'); - \rename($this->styleTestFileDir . '/style-rtl.css', $styleFilename . '-rtl.css'); if (\file_exists($this->styleTestFileDir . '/style-preload.json')) { \rename($this->styleTestFileDir . '/style-preload.json', $styleFilename . '-preload.json'); } diff --git a/wcfsetup/install/files/lib/acp/form/StyleGlobalValuesForm.class.php b/wcfsetup/install/files/lib/acp/form/StyleGlobalValuesForm.class.php index d0ba56b4377..a9d09e65d67 100644 --- a/wcfsetup/install/files/lib/acp/form/StyleGlobalValuesForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/StyleGlobalValuesForm.class.php @@ -149,11 +149,9 @@ public function save() $defaultStyle !== null && $this->styleTestFileDir !== null && \file_exists($this->styleTestFileDir . '/style.css') - && \file_exists($this->styleTestFileDir . '/style-rtl.css') ) { $styleFilename = StyleCompiler::getFilenameForStyle($defaultStyle); \rename($this->styleTestFileDir . '/style.css', $styleFilename . '.css'); - \rename($this->styleTestFileDir . '/style-rtl.css', $styleFilename . '-rtl.css'); if (\file_exists($this->styleTestFileDir . '/style-preload.json')) { \rename($this->styleTestFileDir . '/style-preload.json', $styleFilename . '-preload.json'); } diff --git a/wcfsetup/install/files/lib/system/style/StyleCompiler.class.php b/wcfsetup/install/files/lib/system/style/StyleCompiler.class.php index ed7ad93083c..431f198d417 100644 --- a/wcfsetup/install/files/lib/system/style/StyleCompiler.class.php +++ b/wcfsetup/install/files/lib/system/style/StyleCompiler.class.php @@ -21,7 +21,6 @@ use wcf\system\WCF; use wcf\util\FileUtil; use wcf\util\StringUtil; -use wcf\util\StyleUtil; use wcf\util\Url; /** @@ -775,27 +774,6 @@ private function compileStylesheet(string $scss, array $variables): string } } - /** - * Converts the given CSS into the RTL variant. - * - * This method differs from StyleUtil::convertCSSToRTL() in that it includes some fixes - * for elements that need to remain LTR. - * - * @see StyleUtil::convertCSSToRTL() - */ - private function convertToRtl(string $css): string - { - $css = StyleUtil::convertCSSToRTL($css); - - // force code boxes to be always LTR - $css .= "\n/* RTL fix for code boxes */\n"; - $css .= ".codeBoxCode { direction: ltr; } \n"; - $css .= ".codeBox .codeBoxCode { padding-left: 7ch; padding-right: 0; } \n"; - $css .= ".codeBox .codeBoxCode > code .codeBoxLine > a { margin-left: -7ch; margin-right: 0; text-align: right; } \n"; - - return $css; - } - /** * Writes the given css into the file with the given prefix. * @@ -806,9 +784,6 @@ private function writeCss(string $filePrefix, string $css, ?array $preloadManife \file_put_contents($filePrefix . '.css', $css); FileUtil::makeWritable($filePrefix . '.css'); - \file_put_contents($filePrefix . '-rtl.css', $this->convertToRtl($css)); - FileUtil::makeWritable($filePrefix . '-rtl.css'); - if ($preloadManifest !== null) { \file_put_contents($filePrefix . '-preload.json', \json_encode($preloadManifest, \JSON_THROW_ON_ERROR)); FileUtil::makeWritable($filePrefix . '-preload.json'); diff --git a/wcfsetup/install/files/lib/system/style/StyleHandler.class.php b/wcfsetup/install/files/lib/system/style/StyleHandler.class.php index facce4108bf..fbdfeeb98ad 100644 --- a/wcfsetup/install/files/lib/system/style/StyleHandler.class.php +++ b/wcfsetup/install/files/lib/system/style/StyleHandler.class.php @@ -143,7 +143,7 @@ public function getStylesheet(bool $isACP = false) if ($isACP) { // ACP - $filename = 'acp/style/style' . (WCF::getLanguage()->get('wcf.global.pageDirection') === 'rtl' ? '-rtl' : '') . '.css'; + $filename = 'acp/style/style.css'; $filemtime = @\filemtime(\WCF_DIR . $filename); if ($filemtime === false) { StyleCompiler::getInstance()->compileACP(); @@ -151,7 +151,7 @@ public function getStylesheet(bool $isACP = false) } } else { // frontend - $filename = 'style/style-' . $this->getStyle()->styleID . (WCF::getLanguage()->get('wcf.global.pageDirection') === 'rtl' ? '-rtl' : '') . '.css'; + $filename = 'style/style-' . $this->getStyle()->styleID . '.css'; $filemtime = @\filemtime(\WCF_DIR . $filename); if ($filemtime === false) { StyleCompiler::getInstance()->compile($this->getStyle()->getDecoratedObject()); diff --git a/wcfsetup/install/files/lib/util/StyleUtil.class.php b/wcfsetup/install/files/lib/util/StyleUtil.class.php index 4aed4b0711f..a29d9c24f62 100644 --- a/wcfsetup/install/files/lib/util/StyleUtil.class.php +++ b/wcfsetup/install/files/lib/util/StyleUtil.class.php @@ -11,136 +11,6 @@ */ final class StyleUtil { - /** - * Matches one value of a shorthand. Whitespace inside a function belongs to the value, - * splitting `calc(1px * -1)` at it would break the declaration. Functions can be nested - * once, e.g. `max(12px, env(foo))`. The quantifiers are possessive, repeating per - * character exhausts the PCRE JIT stack on long values. - */ - private const RTL_VALUE = '((?:[^\s;\}()]++|\((?:[^;\}()]++|\([^;\}()]*+\))*+\))++)'; - - /** - * Matches four values that make up the complete declaration. - */ - private const RTL_FOUR_VALUES = self::RTL_VALUE . '\s+' . self::RTL_VALUE . '\s+' . self::RTL_VALUE . '\s+' - . self::RTL_VALUE . '(?=\s*(?:!important\s*)?[;\}])'; - - /** - * Converts css code from LTR to RTL. - */ - public static function convertCSSToRTL(string $contents): string - { - // parse style attributes - // background - // background-position - $contents = \preg_replace('/background-position:\s*left/', 'wcf-background-position:left', $contents); - $contents = \preg_replace('/background-position:\s*right/', 'background-position:left', $contents); - $contents = \str_replace('wcf-background-position:left', 'background-position:right', $contents); - $contents = \preg_replace_callback('/background-position:\s*([\d\.]+)%/', static function ($matches) { - return 'background-position:' . (100.0 - \floatval($matches[1])) . '%'; - }, $contents); - - // background-image - $contents = \str_replace('-ltr', '-rtl', $contents); - - // (border, margin, padding) left / right - $contents = \str_replace('left:', 'wcf-left:', $contents); - $contents = \str_replace('right:', 'left:', $contents); - $contents = \str_replace('wcf-left:', 'right:', $contents); - - // border-width - $contents = \preg_replace( - '/border-width:\s*' . self::RTL_FOUR_VALUES . '/', - 'border-width:\\1 \\4 \\3 \\2', - $contents - ); - - // (border-left-width, border-right-width) - $contents = \str_replace('border-left-width:', 'wcf-border-left-width:', $contents); - $contents = \str_replace('border-right-width:', 'border-left-width:', $contents); - $contents = \str_replace('wcf-border-left-width:', 'border-right-width:', $contents); - - // border-style - $contents = \preg_replace( - '/border-style:\s*' . self::RTL_FOUR_VALUES . '/', - 'border-style:\\1 \\4 \\3 \\2', - $contents - ); - - // (border-left-style, border-right-style) - $contents = \str_replace('border-left-style:', 'wcf-border-left-style:', $contents); - $contents = \str_replace('border-right-style:', 'border-left-style:', $contents); - $contents = \str_replace('wcf-border-left-style:', 'border-right-style:', $contents); - - // (border-left-color, border-right-color) - $contents = \str_replace('border-left-color:', 'wcf-border-left-color:', $contents); - $contents = \str_replace('border-right-color:', 'border-left-color:', $contents); - $contents = \str_replace('wcf-border-left-color:', 'border-right-color:', $contents); - - // box-shadow - $contents = \preg_replace_callback( - '~box-shadow:\s*(?Pinset)?\s*(?P-)?(?P\d+)~', - static function ($matches) { - return 'box-shadow: ' . $matches['inset'] . ' ' . ($matches['negate'] !== '' ? '' : '-') . $matches['number']; - }, - $contents - ); - - // clear - $contents = \preg_replace('/clear:\s*left/', 'wcf-clear:left', $contents); - $contents = \preg_replace('/clear:\s*right/', 'clear:left', $contents); - $contents = \str_replace('wcf-clear:left', 'clear:right', $contents); - - // float - $contents = \preg_replace('/float:\s*left/', 'wcf-float:left', $contents); - $contents = \preg_replace('/float:\s*right/', 'float:left', $contents); - $contents = \str_replace('wcf-float:left', 'float:right', $contents); - - // margin - $contents = \preg_replace( - '/margin:\s*' . self::RTL_FOUR_VALUES . '/', - 'margin:\\1 \\4 \\3 \\2', - $contents - ); - - // padding - $contents = \preg_replace( - '/padding:\s*' . self::RTL_FOUR_VALUES . '/', - 'padding:\\1 \\4 \\3 \\2', - $contents - ); - - // text-align - $contents = \preg_replace('/text-align:\s*left/', 'wcf-text-align:left', $contents); - $contents = \preg_replace('/text-align:\s*right/', 'text-align:left', $contents); - $contents = \str_replace('wcf-text-align:left', 'text-align:right', $contents); - - // text-shadow - $contents = \preg_replace('/text-shadow:\s*(\d)/', 'text-shadow:-\\1', $contents); - - // border-radius - $contents = \preg_replace( - '/border-radius:\s*' . self::RTL_FOUR_VALUES . '/', - 'border-radius:\\2 \\1 \\4 \\3', - $contents - ); - $contents = \str_replace('border-top-left-radius:', 'wcf-border-top-left-radius:', $contents); - $contents = \str_replace('border-top-right-radius:', 'border-top-left-radius:', $contents); - $contents = \str_replace('wcf-border-top-left-radius:', 'border-top-right-radius:', $contents); - $contents = \str_replace('border-bottom-left-radius:', 'wcf-border-bottom-left-radius:', $contents); - $contents = \str_replace('border-bottom-right-radius:', 'border-bottom-left-radius:', $contents); - $contents = \str_replace('wcf-border-bottom-left-radius:', 'border-bottom-right-radius:', $contents); - - // transform: translateX - return \preg_replace_callback( - '/transform:\s*translateX\((?P-)?(?P\d+)(?P[^\s\)]+)\)/', - static function ($matches) { - return 'transform: translateX(' . ($matches['negate'] !== '' ? '' : '-') . $matches['number'] . $matches['unit'] . ')'; - }, - $contents - ); - } - /** * Compresses css code. */ diff --git a/wcfsetup/install/files/style/layout/pageHeader/system.scss b/wcfsetup/install/files/style/layout/pageHeader/system.scss index 4cb4519cb88..78cb02bb476 100644 --- a/wcfsetup/install/files/style/layout/pageHeader/system.scss +++ b/wcfsetup/install/files/style/layout/pageHeader/system.scss @@ -1083,10 +1083,6 @@ width: 12px; } - html[dir="rtl"] .pageNavigation .breadcrumbs__item:not(:last-child)::after { - transform: scaleX(-1); - } - .pageNavigation .breadcrumbs__item:not(:last-child) .breadcrumbs__link { margin-right: 0; } From 53a012df6dbd9907844e6771bc34539d9b6bda2d Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sun, 1 Nov 2026 22:21:05 +0100 Subject: [PATCH 3/3] Remove the right-to-left handling from the JavaScript components --- ts/WoltLabSuite/Core/Component/MainMenu.ts | 3 ++- ts/WoltLabSuite/Core/Component/Media/Gallery.ts | 11 ++++------- ts/WoltLabSuite/Core/Component/UserMenuDrawer.ts | 5 ++--- ts/WoltLabSuite/Core/Ui/Alignment.ts | 6 ------ .../files/js/WoltLabSuite/Core/Component/MainMenu.js | 3 ++- .../js/WoltLabSuite/Core/Component/Media/Gallery.js | 10 ++++------ .../js/WoltLabSuite/Core/Component/UserMenuDrawer.js | 5 ++--- .../files/js/WoltLabSuite/Core/Ui/Alignment.js | 6 +----- 8 files changed, 17 insertions(+), 32 deletions(-) diff --git a/ts/WoltLabSuite/Core/Component/MainMenu.ts b/ts/WoltLabSuite/Core/Component/MainMenu.ts index d25b3e17113..88cea3db868 100644 --- a/ts/WoltLabSuite/Core/Component/MainMenu.ts +++ b/ts/WoltLabSuite/Core/Component/MainMenu.ts @@ -102,7 +102,8 @@ function isOverflowing(): boolean { // The toggles overlap the edge of their item, therefore the items are measured // instead of relying on the scroll width of the menu. Both edges are checked - // because the items overflow to the left in RTL. + // because a style may center or right-align the items, which then overflow + // to the left as well. return Array.from(menu.children).some((item) => { if ((item as HTMLElement).hidden) { return false; diff --git a/ts/WoltLabSuite/Core/Component/Media/Gallery.ts b/ts/WoltLabSuite/Core/Component/Media/Gallery.ts index 36e037c6ccf..39cd976c586 100644 --- a/ts/WoltLabSuite/Core/Component/Media/Gallery.ts +++ b/ts/WoltLabSuite/Core/Component/Media/Gallery.ts @@ -17,7 +17,7 @@ function getStep(track: HTMLElement, slides: HTMLElement[]): number { return track.clientWidth; } - return Math.abs(slides[1].offsetLeft - slides[0].offsetLeft); + return slides[1].offsetLeft - slides[0].offsetLeft; } function initGallery(gallery: HTMLElement): void { @@ -28,9 +28,6 @@ function initGallery(gallery: HTMLElement): void { const counter = controls.querySelector(".mediaGallery__counter")!; const slides = Array.from(track.querySelectorAll(".mediaGallery__slide")); - // The scroll position is negative for right-to-left languages. - const isRtl = () => window.getComputedStyle(track).direction === "rtl"; - const update = () => { const isScrollable = track.scrollWidth > track.clientWidth + 1; controls.hidden = !isScrollable; @@ -38,7 +35,7 @@ function initGallery(gallery: HTMLElement): void { return; } - const scrollPosition = Math.abs(track.scrollLeft); + const scrollPosition = track.scrollLeft; const index = Math.min(Math.round(scrollPosition / getStep(track, slides)), slides.length - 1); counter.textContent = `${index + 1} / ${slides.length}`; @@ -50,8 +47,8 @@ function initGallery(gallery: HTMLElement): void { track.scrollBy({ left: count * getStep(track, slides) }); }; - previousButton.addEventListener("click", () => scrollBySlides(isRtl() ? 1 : -1)); - nextButton.addEventListener("click", () => scrollBySlides(isRtl() ? -1 : 1)); + previousButton.addEventListener("click", () => scrollBySlides(-1)); + nextButton.addEventListener("click", () => scrollBySlides(1)); track.addEventListener("keydown", (event) => { if (event.target !== track) { diff --git a/ts/WoltLabSuite/Core/Component/UserMenuDrawer.ts b/ts/WoltLabSuite/Core/Component/UserMenuDrawer.ts index 2f3704c1509..7b6895bae79 100644 --- a/ts/WoltLabSuite/Core/Component/UserMenuDrawer.ts +++ b/ts/WoltLabSuite/Core/Component/UserMenuDrawer.ts @@ -162,15 +162,14 @@ function keydown(event: KeyboardEvent, tab: Tab): void { const index = tabs.indexOf(tab); const previous = index === 0 ? tabs.length - 1 : index - 1; const next = index === tabs.length - 1 ? 0 : index + 1; - const isRtl = document.documentElement.dir === "rtl"; let target: number; switch (event.key) { case "ArrowLeft": - target = isRtl ? next : previous; + target = previous; break; case "ArrowRight": - target = isRtl ? previous : next; + target = next; break; case "Home": target = 0; diff --git a/ts/WoltLabSuite/Core/Ui/Alignment.ts b/ts/WoltLabSuite/Core/Ui/Alignment.ts index 51edec0da50..d09e50a0dca 100644 --- a/ts/WoltLabSuite/Core/Ui/Alignment.ts +++ b/ts/WoltLabSuite/Core/Ui/Alignment.ts @@ -9,7 +9,6 @@ import * as Core from "../Core"; import * as DomTraverse from "../Dom/Traverse"; import DomUtil from "../Dom/Util"; -import { getPhrase } from "WoltLabSuite/Core/Language"; import * as Environment from "../Environment"; type HorizontalAlignment = "center" | "left" | "right"; @@ -232,11 +231,6 @@ export function set(element: HTMLElement, referenceElement: HTMLElement, options } } - // in rtl languages we simply swap the value for 'horizontal' - if (getPhrase("wcf.global.pageDirection") === "rtl") { - options.horizontal = options.horizontal === "left" ? "right" : "left"; - } - if (horizontal === null || !horizontal.result) { const horizontalCenter = horizontal; horizontal = tryAlignmentHorizontal(options.horizontal!, elDimensions, refDimensions, refOffsets, windowWidth); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/MainMenu.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/MainMenu.js index 6fa69fc7ef2..ac4fa3cb193 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/MainMenu.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/MainMenu.js @@ -84,7 +84,8 @@ define(["require", "exports", "tslib", "../Ui/CloseOverlay", "../Ui/Screen"], fu const { left, right } = menu.getBoundingClientRect(); // The toggles overlap the edge of their item, therefore the items are measured // instead of relying on the scroll width of the menu. Both edges are checked - // because the items overflow to the left in RTL. + // because a style may center or right-align the items, which then overflow + // to the left as well. return Array.from(menu.children).some((item) => { if (item.hidden) { return false; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Media/Gallery.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Media/Gallery.js index efd7516b6dd..9cdba93e28a 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Media/Gallery.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Media/Gallery.js @@ -17,7 +17,7 @@ define(["require", "exports", "WoltLabSuite/Core/Helper/Selector"], function (re if (slides.length < 2) { return track.clientWidth; } - return Math.abs(slides[1].offsetLeft - slides[0].offsetLeft); + return slides[1].offsetLeft - slides[0].offsetLeft; } function initGallery(gallery) { const track = gallery.querySelector(".mediaGallery__track"); @@ -26,15 +26,13 @@ define(["require", "exports", "WoltLabSuite/Core/Helper/Selector"], function (re const nextButton = controls.querySelector(".mediaGallery__button--next"); const counter = controls.querySelector(".mediaGallery__counter"); const slides = Array.from(track.querySelectorAll(".mediaGallery__slide")); - // The scroll position is negative for right-to-left languages. - const isRtl = () => window.getComputedStyle(track).direction === "rtl"; const update = () => { const isScrollable = track.scrollWidth > track.clientWidth + 1; controls.hidden = !isScrollable; if (!isScrollable) { return; } - const scrollPosition = Math.abs(track.scrollLeft); + const scrollPosition = track.scrollLeft; const index = Math.min(Math.round(scrollPosition / getStep(track, slides)), slides.length - 1); counter.textContent = `${index + 1} / ${slides.length}`; previousButton.disabled = scrollPosition <= 1; @@ -43,8 +41,8 @@ define(["require", "exports", "WoltLabSuite/Core/Helper/Selector"], function (re const scrollBySlides = (count) => { track.scrollBy({ left: count * getStep(track, slides) }); }; - previousButton.addEventListener("click", () => scrollBySlides(isRtl() ? 1 : -1)); - nextButton.addEventListener("click", () => scrollBySlides(isRtl() ? -1 : 1)); + previousButton.addEventListener("click", () => scrollBySlides(-1)); + nextButton.addEventListener("click", () => scrollBySlides(1)); track.addEventListener("keydown", (event) => { if (event.target !== track) { return; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/UserMenuDrawer.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/UserMenuDrawer.js index 69068682bf7..9721dd9c6ef 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/UserMenuDrawer.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/UserMenuDrawer.js @@ -127,14 +127,13 @@ define(["require", "exports", "tslib", "../Ui/User/Menu/Manager", "../Ui/User/Me const index = tabs.indexOf(tab); const previous = index === 0 ? tabs.length - 1 : index - 1; const next = index === tabs.length - 1 ? 0 : index + 1; - const isRtl = document.documentElement.dir === "rtl"; let target; switch (event.key) { case "ArrowLeft": - target = isRtl ? next : previous; + target = previous; break; case "ArrowRight": - target = isRtl ? previous : next; + target = next; break; case "Home": target = 0; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Alignment.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Alignment.js index f3ba422ff5f..9853dcdc7d3 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Alignment.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Alignment.js @@ -5,7 +5,7 @@ * @copyright 2001-2019 WoltLab GmbH * @license GNU Lesser General Public License */ -define(["require", "exports", "tslib", "../Core", "../Dom/Traverse", "../Dom/Util", "WoltLabSuite/Core/Language", "../Environment"], function (require, exports, tslib_1, Core, DomTraverse, Util_1, Language_1, Environment) { +define(["require", "exports", "tslib", "../Core", "../Dom/Traverse", "../Dom/Util", "../Environment"], function (require, exports, tslib_1, Core, DomTraverse, Util_1, Environment) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.set = set; @@ -170,10 +170,6 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Traverse", "../Dom/Uti } } } - // in rtl languages we simply swap the value for 'horizontal' - if ((0, Language_1.getPhrase)("wcf.global.pageDirection") === "rtl") { - options.horizontal = options.horizontal === "left" ? "right" : "left"; - } if (horizontal === null || !horizontal.result) { const horizontalCenter = horizontal; horizontal = tryAlignmentHorizontal(options.horizontal, elDimensions, refDimensions, refOffsets, windowWidth);