Improve RTL Rendering for Guides (#51613)

Improve RTL language support, specifically focused on Arabic (MSA), Farsi, and Hebrew languages, including custom fonts for those languages, a javascript to detect auto-translation and shift the dir attribute, and other cleanup based on volunteer feedback.

Co-authored-by: Carlos Antonio da Silva <carlosantoniodasilva@gmail.com>
This commit is contained in:
John Athayde 2024-06-07 13:00:52 -04:00 committed by GitHub
parent bc727a04b7
commit 7dbe81710e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 102 additions and 27 deletions

@ -186,4 +186,15 @@
}
})
});
// Observe the HTML tag for Google Translate CSS class, to swap our lang direction LTR/RTL.
var observer = new MutationObserver(function(mutations, _observer) {
each(mutations, function(mutation) {
if (mutation.type === "attributes" && mutation.attributeName == "class") {
mutation.target.dir = mutation.target.classList.contains("translated-rtl") ? "rtl" : "ltr";
}
})
});
observer.observe(document.querySelector("html"), { attributeFilter: ["class"] });
}).call(this);

@ -17,6 +17,7 @@ body.guide {
-webkit-tap-highlight-color:rgba(38, 27, 35, 0);
// ----------------------------------------------------------------------------
// Typographic Baseline
// ----------------------------------------------------------------------------
@ -57,7 +58,6 @@ body.guide {
margin: 0 0 0.75em 0; // Space after paragraph
text-align: left;
} // p
// Links
@ -259,12 +259,6 @@ body.guide {
}
} // dd
} // dl
// :where(&[dir="ltr"]) dd { margin-left: 1.5em; }
// :where(&[dir="rtl"]) dd { margin-right: 1.5em; }
// :where(&[dir="ltr"]) :is(dd) { margin-left: 0; padding-left: 0; }
// :where(&[dir="rtl"]) :is(dd) { margin-right: 0; padding-right: 0; }
li {
margin-bottom: 0.5em;
@ -274,7 +268,7 @@ body.guide {
pre, code {
font-size: 1rem;
font-family: "IBM Plex Mono", "Anonymous Pro", "Inconsolata", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
font-family: "IBM Plex Mono", "Anonymous Pro", "Inconsolata", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace !important;
line-height: 1.5;
margin: 1em 0;
overflow: auto;
@ -322,14 +316,17 @@ body.guide {
.wrapper {
padding: 1em;
:where(body[dir="ltr"]) & { text-align: left; }
:where(body[dir="rtl"]) & { text-align: right; }
text-align: left;
@include media('>desktop') { // 1024
max-width: calc(55rem + 420px);
margin: 0 auto;
padding-right: 470px;
:where(html[dir="rtl"]) & {
padding-right: 1.5em;
padding-left: 470px;
}
}
} // .wrapper
@ -584,8 +581,8 @@ body.guide {
z-index: 15;
padding-bottom: 0.125em;
:where(body[dir="ltr"]) & { background-position: right top; padding-right: 1em; }
:where(body[dir="rtl"]) & { background-position: left top; padding-left: 1em; }
:where(html[dir="ltr"]) & { background-position: right top; padding-right: 1em; }
:where(html[dir="rtl"]) & { background-position: left top; padding-left: 1em; }
}
@ -604,8 +601,8 @@ body.guide {
max-width: 1000px;
z-index: 10;
:where(body[dir="ltr"]) & { left: auto; right: 50px; }
:where(body[dir="rtl"]) & { left: 50px; right: auto; }
:where(html[dir="ltr"]) & { left: auto; right: 50px; }
:where(html[dir="rtl"]) & { left: 50px; right: auto; }
&.visible {
display: block !important;
@ -706,6 +703,11 @@ body.guide {
right: 50px;
max-height: calc(100vh - 200px);
width: 400px;
:where(html[dir="rtl"]) & {
right: auto;
left: 50px;
}
}
&.guide-index {
@ -714,11 +716,20 @@ body.guide {
@include media('>desktop-ultra-wide') {
right: calc(30vw - 400px);
:where(html[dir="rtl"]) & {
right: auto;
left: calc(30vw - 400px);
}
}
@include media('>desktop-hd') { // 1920
right: calc(40vw - 400px);
:where(html[dir="rtl"]) & {
right: auto;
left: calc(40vw - 400px);
}
}
h3.chapter img {
@ -820,6 +831,11 @@ body.guide {
background-color: $stop-bkgnd;
opacity: 0;
transition: opacity 0.2s ease-in-out;
:where(html[dir="rtl"]) & {
right: -3.5em;
left: unset;
}
}
a.active::after {
@ -838,6 +854,11 @@ body.guide {
background-color: $rf-brand;
opacity: 0;
transition: opacity 0.2s ease-in-out;
:where(html[dir="rtl"]) & {
right: -3em;
left: unset;
}
}
a.active::before {
@ -852,4 +873,40 @@ body.guide {
}
}
} // body.guide
} // body.guide
html[dir="rtl"] {
body.guide {
direction: rtl;
p, table th, .wrapper,
#guides .guides-section-container .guides-section {
text-align: right;
}
} // body.guide
&:lang(ar), &:lang(fa) {
body.guide {
h1, h2, h3, h4, h5, h6, p, dl, dd, dt, ul, ol, li,
header#page_header nav#feature_nav .header-logo a {
font-family: "Noto Sans Arabic", sans-serif !important;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
font-variation-settings: "wdth" 100;
}
} // body.guide
} // &:lang(ar), &:lang(fa)
&:lang(he), &:lang(iw) {
body.guide {
h1, h2, h3, h4, h5, h6, p, dl, dd, dt, ul, ol, li,
header#page_header nav#feature_nav .header-logo a {
font-family: "Heebo", sans-serif !important;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
}
} // body.guide
} // &:lang(he), &:lang(iw)
} // html[dir="rtl"]

@ -8,21 +8,22 @@
/* Same bottom margin for special boxes than for regular paragraphs, this way
intermediate whitespace looks uniform. */
.interstitial {
.interstitial,
dl dd .interstitial {
background-repeat: no-repeat;
background-size: 36px 36px;
border-radius: $base-border-radius;
border: 2px solid $gray-500;
border-style: solid !important;
border-width: 2px !important;
min-height: calc(36px + 1.2em);
min-height: calc(36px + 1.5em);
margin: 2em auto;
padding: 0.75em !important;
position: relative;
// Padding and spacing for LTR vs RTL langauge defaults
:where(body[dir="ltr"]) & { background-position: 10px 10px; padding-right: 1em !important; padding-left: 56px !important; }
:where(body[dir="rtl"]) & { background-position: calc(100% - 10px) 10px; padding-right: 56px !important; padding-left: 1em !important; }
:where(html[dir="ltr"]) & { background-position: 10px 10px; padding-right: 1em !important; padding-left: 56px !important; }
:where(html[dir="rtl"]) & { background-position: calc(100% - 10px) 10px; padding-right: 56px !important; padding-left: 1em !important; }
/* Remove bottom margin of paragraphs in special boxes, otherwise they get a
spurious blank area below with the box background. */
@ -39,6 +40,8 @@ intermediate whitespace looks uniform. */
background-color: $gray-900;
min-height: auto; // remove if icon is restored
padding-left: 1em !important; // remove if icon is restored
direction: ltr !important;
text-align: left !important;
pre {margin: 0;}
@ -52,9 +55,9 @@ intermediate whitespace looks uniform. */
padding: 0.25em 0.5em !important;
position: absolute;
bottom: 10px;
:where(body[dir="ltr"]) & { right: 10px; }
:where(body[dir="rtl"]) & { left: 10px; }
right: 10px;
text-transform: uppercase;
width: auto;
} // button.clipboard-button
} // &.code
@ -92,5 +95,4 @@ intermediate whitespace looks uniform. */
&.kindle {
padding-top: 1em !important;
}
} // .interstitial
} // .interstitial

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html dir="<%= @direction %>" lang="en">
<head>
<meta charset="utf-8">
@ -25,10 +25,15 @@
<meta property="og:image" content="https://avatars.githubusercontent.com/u/4223" />
<meta property="og:type" content="website" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@100..900&family=Noto+Sans+Arabic:wght@100..900&display=swap" rel="stylesheet">
<meta name="theme-color" content="#C81418">
</head>
<body dir="<%= @direction %>" class="guide">
<body class="guide">
<nav id="topNav" aria-label="Secondary">
<div class="wrapper">
<strong class="more-info-label">More at <a href="https://rubyonrails.org/">rubyonrails.org:</a> </strong>