Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTL Rendering for Guides #51613

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

RTL Rendering for Guides #51613

wants to merge 11 commits into from

Conversation

jathayde
Copy link
Contributor

@jathayde jathayde commented Apr 19, 2024

rtl_example

Motivation / Background

This PR provides improved 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.

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

@rails-bot rails-bot bot added the docs label Apr 19, 2024
@akhilgkrishnan akhilgkrishnan added the rails foundation Rails Foundation PRs label Apr 19, 2024
@mr3abd
Copy link

mr3abd commented Apr 22, 2024

this comment not related to RTL

but that related by (Translation)
I think should translate words like (Rails) to be like write as you speak not as (Google translation --> (train rails) )
Then I hope to be translated by ريلز, not قضبان

Thanks

@AhmedNadar
Copy link

This is related to translation.

Rails

In Arabic; the word "Rail" refer to different meanings. such as: for clothes, railway system, for safety, for curtains and for support. https://en.bab.la/dictionary/english-arabic/rails
Most translation for "Rails" refer to Railway system or قضبان, where the document header refer to.

There's no direct translation to "Ruby on Rails" among the Arabic speaking Rails developers. The proper usage is writing how the English word sounds, Rails = ريلز
Similar to Ruby = روبي

I noticed, the doc is not consistent on referring to the word "Rails". Sometimes Rails and others ريلز .

Edge

In Arabic, the word "Edge" here means "cliff edge" https://en.bab.la/dictionary/english-arabic/edge
In Rails docs we use the word Edge as "Cutting Edge", and no direct word in Arabic. But we can use مُتَقَدِّم (motaqaddim).
Which has different meaning such as: "advanced, state-of-the-art, cutting-edge, leading-edge, pioneering, innovative."

There a few places where translation could confuse Arabic readers.

CleanShot 2024-04-22 at 10 37 47@2x

@zackbraksa
Copy link

zackbraksa commented Apr 22, 2024

[This comment is not related to RTL]

@AhmedNadar @mr3abd from I can find in the Rails docs:

Note that translations are not submitted to the Rails repository; your work lives in your fork, as described above. This is because, in practice, documentation maintenance via patches is only sustainable in English.

So the Rails repo itself doesn't have Arabic translation bundled in, there might be a semi-official fork somewhere on GitHub, but I'm not aware of it. And so the best place to start for us as Arabic devs is either kick-off an Arabic fork of rails/guides/source (if there is not one already) or contribute to an existing one.

@zackbraksa
Copy link

zackbraksa commented Apr 22, 2024

@jathayde Visually at least, I don't see any issues with the Arabic RTL version. 👍

@carlosantoniodasilva
Copy link
Member

Thanks @mr3abd @AhmedNadar @zackbraksa, indeed we do not intend to make translations available in the guides ourselves, but we're trying to make at least Google Translation do a nicer job, swapping the direction accordingly. If it's going to translate certain words like "Rails" that it maybe should not, there's not much we can do unless it's possible to flag such words in certain ways to tell Translate / automated tools to not translate them -- but even then that'd add a lot of burden to maintaining the guides as they currently are.

That said, we hope that the changes here will make it easier to at least auto-translate the guides via Google or some other tool, and to manually generate them with the appropriate direction set (which was already supported previously), for those who want to work on a fork translating the guides.

@jathayde
Copy link
Contributor Author

As far as translation goes, this is all handled by Google Translate in the browser. We are looking at options to exclude or force certain words, but it may not be doable without API translation (which would be future functionality). Focus for this is UI support for RTL languages and ensuring there's no weird rendering bugs or any best practices we may have missed in RTL support.

@AhmedNadar
Copy link

Regarding RTL layout and for Arabic it is good. No issues.
I will do my best to contribute to translation guide. Google translation is not good. It is ok.

@mr3abd
Copy link

mr3abd commented Apr 22, 2024

@AhmedNadar I'll work too in Arabic content
We can work together on it

Copy link
Member

@carlosantoniodasilva carlosantoniodasilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jathayde, I had a few comments/suggestions below, also think there's a few pieces that might be slightly broken due to the body vs html dir change. Let me know if you have any preference here, we could keep the dir in the body if that makes things easier on the style side of things (also less change), but it's okay to fully move it to the html tag I think.

// Typographic Baseline
// ----------------------------------------------------------------------------

:root {
font-family: Inter, sans-serif;
font-family: Inter, "Noto Sans Arabic", "Heebo", sans-serif;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seemed to break when there were two languages listed in one line. Split lines in c022085 and removed this in 9182dad

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few more mentions of "Noto Sans Arabic", "Heebo" still spread in the CSS, should they also be moved down to the specific lang blocks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up in 91ddfcc

@@ -17,19 +17,27 @@ body.guide {

-webkit-tap-highlight-color:rgba(38, 27, 35, 0);

// ----------------------------------------------------------------------------
html.translated-rtl & {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we eliminate the usage of .translated-rtl from the CSS, and rely on the dir alone?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c022085


:where(body[dir="ltr"]) & { text-align: left; }
:where(body[dir="rtl"]) & { text-align: right; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have moved these to the html tag, so we're not modifying the body anymore. Do you prefer to change the body instead?

It's a simple change to the JS to target the body, change line 111:

// from
mutation.target.dir = 
// to
document.querySelector("body").dir = 

For instance, I believe some of these changes broke a few things like the icon positions:

Details

Screenshot 2024-04-23 at 11 00 51
Screenshot 2024-04-23 at 11 01 02

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c022085


// :where(&[dir="ltr"]) :is(dd) { margin-left: 0; padding-left: 0; }
// :where(&[dir="rtl"]) :is(dd) { margin-right: 0; padding-right: 0; }
// :where(&[dir="rtl"]) :is(dd),
// html.translated-rtl :is(dd) { margin-right: 0; padding-right: 0; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove these commented pieces.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c022085

}

html.translated-rtl:lang("he", "iw") {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just use the lang, or rather a combination of dir and lang, and avoid .translated-* in the css.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c022085

<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">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will these cause the fonts to be downloaded upfront, or just they're actually referenced/needed? (i.e. for those specific languages, assuming we make the change to only refer to them there)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They load on page load. Not sure how we could only include that font for dir changed pages. Is there a technique you'd suggest?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jathayde well, simple erb -> if can do the work.

<% if @direction == "rtl" %>
  <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">
<% endif %>

Also, you can use unicode-range and system fonts without using 3rd party fonts.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@idangoldman unfortunately because we may swap dir on-the-fly with a google translation trigger, it won't work to embed that conditional via ERB.

We'd have to do it via JS and manually append the link tags when the translation changes.

I don't know much/enough about those system fonts for this though, @jathayde do you / have you tried?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlosantoniodasilva yeah fair point...

After looking into the codebase, I saw that all the currently used fonts in the guides are declaired as @font-face in guides/assets/stylesrc/style.scss.

@jathayde, what about adding the new fonts support into that file as @font-face with specific unicode-range, that way the fonts will be used (downloaded) only if characters on the unicode-range are presented on the screen.

Stay with me, it's a bit long ->

/* RTL Fonts Support for Arabic */
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:100; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Thin.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:100; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-ThinItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:200; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-ExtraLight.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:200; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-ExtraLightItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:300; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Light.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:300; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-LightItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:400; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Regular.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:400; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Italic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:500; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Medium.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:500; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-MediumItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:600; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-SemiBold.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:600; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-SemiBoldItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:700; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Bold.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:700; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-BoldItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:800; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-ExtraBold.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:800; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-ExtraBoldItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:normal; font-weight:900; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-Black.woff2?v=4.0") format("woff2"); }
@font-face { font-family:"Noto Sans Arabic"; font-style:italic; font-weight:900; font-display:swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; src:url("https://rubyonrails.org/assets/fonts/NotoSansArabic-BlackItalic.woff2?v=4.0") format("woff2"); }

/* RTL Fonts Support for Hebrew */
@font-face { font-family:Heebo; font-style:normal; font-weight:100; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Thin.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:100; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-ThinItalic.woff2?v=4.0") format("woff2"); }`
@font-face { font-family:Heebo; font-style:normal; font-weight:200; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-ExtraLight.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:200; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-ExtraLightItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:300; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Light.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:300; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-LightItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:400; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Regular.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:400; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Italic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:500; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Medium.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:500; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-MediumItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:600; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-SemiBold.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:600; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-SemiBoldItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:700; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Bold.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:700; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-BoldItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:800; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-ExtraBold.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:800; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-ExtraBoldItalic.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:normal; font-weight:900; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-Black.woff2?v=4.0") format("woff2"); }
@font-face { font-family:Heebo; font-style:italic; font-weight:900; font-display:swap; unicode-range: U+0590-05FF, U+FB1D-FB4F; src:url("https://rubyonrails.org/assets/fonts/Heebo-BlackItalic.woff2?v=4.0") format("woff2"); }

One thing, I haven't found how the fonts are generated/downloaded/stored on rubyonrails.org.

Another thing, Inter, Noto Sans Arabic, Heebo font face declaration can become more readable with writing a mixin inputs a map of the fonts options and outputs the above.

References:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Playing with this right now and the only issue I've got is that Google bypasses this step for you when you serve from their CDN. We could download and host the fonts, but without doing that, I don't see a clear way to limit to unicode ranges. @carlosantoniodasilva do we want to try and serve these from our domain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think we could leverage a variable font to reduce the @font-face calls instead of needing 18 declarations for each weight/style combo.

@jathayde
Copy link
Contributor Author

@carlosantoniodasilva anything else we need to address here?

@carlosantoniodasilva
Copy link
Member

@jathayde my apologies, I got side tracked with some personal & work stuff, but I'll take a look and get back to you soon.

Copy link
Member

@carlosantoniodasilva carlosantoniodasilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jathayde thanks for the updates here, I had a few more minor suggestions before we ship it.


:where(html[dir="ltr"]) & { text-align: left; }
:where(html[dir="rtl"]) & { text-align: right; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More of thinking out loud, to hear your thoughts: would it work / make sense to style left by default, and use the dir=rtl tag to swap right, rather than having the two explicitly called out throughout the styles? In other words, by default (without thinking about "dir") it is listed there / it works... when we swap is that the extra dir is taken into account for changing stuff.

I don't mind it this way, just something that crossed my mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here, but the arguments for both methods:

Keeping as is:

  1. Pro: Clarity of what parameters are being addressed and how they change
  2. Con: If dir is not defined, it falls back to the cascade and works up the tree until it finds a declaration or the browser default.

Moving to only defining the override is effectively the opposite. I stuck with the method that was previously employed in the guides build, and I do like the visual clarity of the elements that change being spelled out next to each other, but it's not a hill I would die defending.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these that are not related to page layout are now at the bottom.

p {
text-align: right;
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is similar/related to the font declarations at the bottom, and those also use body.guide, let's try and group them together.

How about something like this at the bottom:

html[dir="rtl"] {
  body.guide {
    // these declarations
  }

  &:lang("ar"), &:lang("fa") {
    body.guide { 
      // ... font declarations 
    }
  }

  &:lang("foo")...
}

So we have less spread changes related to dir=rtl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done this where the items are simple. Where things are layout related or media query I've left them in place as it seems more logical and easier to understand. ae881dc

@@ -135,7 +146,7 @@ body.guide {
} // h1

h2 {
font-family: 'Calibre', sans-serif;
font-family: 'Calibre', "Noto Sans Arabic", "Heebo", sans-serif;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the other fonts I mentioned, I think these would be covered by the declarations at the bottom.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up in 91ddfcc

@@ -439,7 +449,7 @@ body.guide {
background-repeat: no-repeat;
background-position: top center;
display: inline-block;
font-family: 'Calibre', sans-serif;
font-family: 'Calibre', "Noto Sans Arabic", "Heebo", sans-serif;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another font declaration... not sure if a is covered by those already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up in 91ddfcc

@@ -22,7 +22,8 @@ intermediate whitespace looks uniform. */

// 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(body[dir="rtl"]) &,
html.translated-rtl & { background-position: calc(100% - 10px) 10px; padding-right: 56px !important; padding-left: 1em !important; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably the .translated-rtl from here as well, and switch from body to html on the declarations above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 196635c

@idangoldman
Copy link

Hi @jathayde and @carlosantoniodasilva

@MohammadYounes made RTLCSS (Website), a wonderful library automating the process of supporting RTL Web UIs by generating a RTL css file base on a LTR css file.

The generated style-rtl.css file can be added easiely as parf of the observer in guides/assets/javascripts/guides.js like so:

var googleTranslateLanguageSwitch = new MutationObserver(function (mutations, _observer) {
  each(mutations, function (mutation) {
    if (mutation.type === "attributes" && mutation.attributeName == "class") {
      const isRTLbyGoogleTranslate = mutation.target.classList.contains("translated-rtl");

      mutation.target.dir = isRTLbyGoogleTranslate
        ? "rtl"
        : "ltr";

      if (isRTLbyGoogleTranslate && !document.getElementById("rtl-style")) {
          const rtlStyle = document.createElement("link");
          rtlStyle.id = "rtl-style";
          rtlStyle.rel = "stylesheet";
          rtlStyle.href = "style-rtl.css";

          document.head.appendChild(rtlStyle);
      } else {
        document.getElementById("rtl-style")?.remove();
      }
    }
  });
});

googleTranslateLanguageSwitch.observe(document.querySelector("html"), {
  attributeFilter: ["class"],
});

I'm sure the above example can be rewritten in a more readable way 🫣

Also, RTLCSS comes with various options of configuration, including taking care of edge cases, custom rules, and generation flows of RTL css files.

After successful implementation for style.css, the RTL support can be expanded twards print.css and epub.css.

@jathayde
Copy link
Contributor Author

jathayde commented May 7, 2024 via email

@idangoldman
Copy link

Enjoy your travels John! Feel free to ping me with follow-ups.

@jathayde
Copy link
Contributor Author

Some missed issues with interstitial padding due to body vs html dir call fixed in 196635c

@jathayde
Copy link
Contributor Author

@carlosantoniodasilva I think I've resolved everything - if you want to check and mark resolved as you see fit, we can see if there's anything else floating and get this finished up.

@carlosantoniodasilva carlosantoniodasilva added this to the 7.2.0 milestone May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs rails foundation Rails Foundation PRs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants