mirror of https://github.com/rails/rails
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:
parent
bc727a04b7
commit
7dbe81710e
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue