# Why is RTL class user dependent instead of locale?

**URL:** https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077
**Category:** Development
**Created:** [11 Dicembre 2016, 3:04am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077 "2016-12-11T03:04:10Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![ibnesayeed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ibnesayeed/32/120427_2.png) [@ibnesayeed](https://meta.discourse.org/u/ibnesayeed)
#### Post date: [11 Dicembre 2016, 3:04am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/1 "2016-12-11T03:04:10Z")

</div>

Recently, I [added support for Urdu language](https://meta.discourse.org/t/urdu-language-support-added/53877), which, like Arabic, Hebrew, and Persian, is an RTL (right-to-left) language. To make the software aware of it I added `ur` locale in `rtl_locales` method of the `RTL` model class.

> <https://github.com/discourse/discourse/blob/49fc54aac603fee08a6fb1e8b9610a0537ca9ec2/app/models/rtl.rb#L21-L23>

However, my site’s direction did not change in right-to-left. So, I started investigating what’s wrong? I found that there is a helper method `rtl?` in the `ApplicationHelper` class.

> <https://github.com/discourse/discourse/blob/49fc54aac603fee08a6fb1e8b9610a0537ca9ec2/app/helpers/application_helper.rb#L137-L139>

There seems some duplication of logic. So, I looked into the `RTL` class further and found it confusing because it’s initialization is dependent on a `User` instance.

> <https://github.com/discourse/discourse/blob/49fc54aac603fee08a6fb1e8b9610a0537ca9ec2/app/models/rtl.rb#L1-L7>

This implementation would make perfect sense if RTL is a property independent of the locale in a way that my Arabic may be RTL, but your Arabic may not. However, this is not the case. RTL (or LTR) is the property of the locale, independent of the user. If the `I18n.locale` is assigned a property called `direction` which may hold values `rtl` or `ltr`, with `ltr` being the default (let’s forget about the `ttb` direction for now because that is almost always represented as `ltr` on the web). Alternatively, a method `rtl?` is added to the `I18n.locale` that returns false by default, unless the locale is in the array of RTL locales.

This way, entire RTL class can go away and wherever a locale object is accessible, its direction is also known. We don’t need to know separately if a user’s locale has RTL enabled, we just find the effective locale and apply RTL if applicable.

I know that Discourse does not encourage code refactoring for the sake of refactoring, but being a newbie to the code base I would like to hear the rationale behind why it is the way it is?

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [11 Dicembre 2016, 3:37am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/2 "2016-12-11T03:37:33Z")

</div>

I think the RTL class is used in `UserNotifications` for adding the `rtl` class to emails.

---

<div class="post-metadata">

### Author: ![ibnesayeed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ibnesayeed/32/120427_2.png) [@ibnesayeed](https://meta.discourse.org/u/ibnesayeed)
#### Post date: [11 Dicembre 2016, 3:48am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/3 "2016-12-11T03:48:20Z")

</div>

> [@simon](#):
>
> I think the RTL class is used in UserNotifications for adding the rtl class to emails.

Does this change anything? After all user’s locale or site’s default locale is determined in order to know if it belongs to RTL or not. If the direction was property of the locale, then we wont need this RTL class at all, be it in the email, notification, site’s layout, CSS classes and whatnot.

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [11 Dicembre 2016, 3:53am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/4 "2016-12-11T03:53:34Z")

</div>

> [@ibnesayeed](#):
>
> Does this change anything?

It just means that the class can’t be eliminated without changing a few other things as well. But yes, what you’re saying seems correct to me.

---

<div class="post-metadata">

### Author: ![ibnesayeed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ibnesayeed/32/120427_2.png) [@ibnesayeed](https://meta.discourse.org/u/ibnesayeed)
#### Post date: [11 Dicembre 2016, 4:17am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/5 "2016-12-11T04:17:27Z")

</div>

> [@simon](#):
>
> It just means that the class can’t be eliminated without changing a few other things as well.

Such as, lines 389 and 401

> <https://github.com/discourse/discourse/blob/ad5d16af8ed0257fd14ed54d060946dbda6f8db1/app/mailers/user_notifications.rb#L388-L390>

become (if `direction` property is defined on locale)

```ruby
classes: user.effective_locale.direction

```

or (if `rtl?` method is defined on locale)

```ruby
classes: user.effective_locale.rtl? ? 'rtl' : ''

```

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [11 Dicembre 2016, 4:37am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/6 "2016-12-11T04:37:12Z")

</div>

Yes. I don’t know if this is a change they will want to make, but it’s good you are interested in working on this. I’ve done some work on it in the past. I got involved with it to help set up a forum, but I don’t speak a RTL language. It’s a great way to learn the Discourse code. There are still a few issues in the javascript as well: [RTL interface has wrong position for some of popup boxes](https://meta.discourse.org/t/rtl-interface-has-wrong-position-for-some-of-popup-boxes/51503).

---

<div class="post-metadata">

### Author: ![ibnesayeed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ibnesayeed/32/120427_2.png) [@ibnesayeed](https://meta.discourse.org/u/ibnesayeed)
#### Post date: [11 Dicembre 2016, 4:38am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/7 "2016-12-11T04:38:16Z")

</div>

Also, I noted that in the existing TRL class there is some logic duplicated.

> <https://github.com/discourse/discourse/blob/49fc54aac603fee08a6fb1e8b9610a0537ca9ec2/app/models/rtl.rb#L9-L19>

This chunk can be replaced by the following code.

```ruby
def enabled?
  user.effective_locale.in?(rtl_locales)
end

```

Because `current_user_rtl?` and `site_locale_rtl?` are local methods and not used elsewhere. While the common portion of the two methods (finding the effective locale) is already defined in the `User` class.

> <https://github.com/discourse/discourse/blob/49fc54aac603fee08a6fb1e8b9610a0537ca9ec2/app/models/user.rb#L186-L192>

---

<div class="post-metadata">

### Author: ![ibnesayeed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ibnesayeed/32/120427_2.png) [@ibnesayeed](https://meta.discourse.org/u/ibnesayeed)
#### Post date: [11 Dicembre 2016, 5:00am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/8 "2016-12-11T05:00:35Z")

</div>

> [@simon](#):
>
> I don’t know if this is a change they will want to make, but it’s good you are interested in working on this.

I feel that they might actually be willing to get rid of a class that does not deserve to be a class, because the class itself is not that deep rooted. If we keep the surface methods such as `rtl?` helper method behave the very same way, just change the base implementation without affecting the API then it should be OK. Obviously, we might need some more test cases related to locale direction beyond what is already there.

However, being new to the code base I won’t jump to a conclusion too quickly without hearing from some other people who have better understanding of the code inside out.

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [11 Dicembre 2016, 8:22am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/9 "2016-12-11T08:22:34Z")

</div>

I won’t go so far to say I know the code inside out, but I’ll chip in my ![](https://global.discourse-cdn.com/meta/original/3X/e/d/ed944ccb914c88865820264c68337add7a914982.gif)

I looked to see if any tests might break if `current_user_rtl` or `site_locale_rtl` were removed. I found none and in fact the only place they exist in the Core code is in the models/rtl.rb file.  
So removing them might break some plugins if they are using them, but it shouldn’t break Discourse.

I don’t think “i18n” would need to be used in the proposed `enabled` but I’ve seen it used in other files.

> <https://github.com/discourse/discourse/blob/main/app/services/post_alerter.rb#L336-L344>

> <https://github.com/discourse/discourse/blob/main/app/services/badge_granter.rb#L46-L57>

> <https://github.com/discourse/discourse/blob/main/app/controllers/application_controller.rb#L214-L225>

---

<div class="post-metadata">

### Author: ![ibnesayeed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ibnesayeed/32/120427_2.png) [@ibnesayeed](https://meta.discourse.org/u/ibnesayeed)
#### Post date: [11 Dicembre 2016, 2:15pm UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/10 "2016-12-11T14:15:01Z")

</div>

It looks like `locale` is simply a string, not an object. Hence we can’t attach properties to it. However, there are other ways to specify the direction. One is to add a `direction` or `rtl?` attribute in the `config/locales/names.yml` file. Another possibility is to define `rtl?` method in a place from where it can be called from any part of the application.

> <https://github.com/discourse/discourse/blob/main/config/locales/names.yml>

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [12 Dicembre 2016, 12:01am UTC](https://meta.discourse.org/t/why-is-rtl-class-user-dependent-instead-of-locale/54077/11 "2016-12-12T00:01:01Z")

</div>

For some reason I like the idea of having it in the yml file.

I have no basis for the feeling other than it just seems like the logical best place for it.

I tried hacking the rtl.rb file to

```plaintext
  def enabled?
# site_locale_rtl? || current_user_rtl?
    user.effective_locale.in?(rtl_locales)
  end

# def current_user_rtl?
# SiteSetting.allow_user_locale && user.try(:locale).in?(rtl_locales)
# end

# def site_locale_rtl?
# !SiteSetting.allow_user_locale && SiteSetting.default_locale.in?(rtl_locales)
# end

```

I don’t know Farsi so I could very well not be seeing a glaring issue.  
But the hack did not crash Discourse and I saw no error messages anywhere.  
I did notice that the title was not translated for some pages, but that was true for both hacked and not-hacked.  
And I did not try the `set locale from accept language header` setting nor test emails or many pages at all.

I did test as a site setting desktop and mobile view, and allow user preference desktop and mobile view.

**site default setting desktop**

 ![](https://global.discourse-cdn.com/meta/original/3X/9/a/9aeeb3dfdcd829c43313c1558d33c60bf49fbfd3.png)  
**site default setting mobile**  
 ![](https://global.discourse-cdn.com/meta/original/3X/a/4/a411b8ff6a5c2155e8b922651bd31592d08dd62e.png)  
**user preference desktop**  
 ![](https://global.discourse-cdn.com/meta/original/3X/9/1/9182f5bd943f68fb581ca2cdaba860840a50107b.png)  
**user preference mobile**  
 ![](https://global.discourse-cdn.com/meta/original/3X/6/1/612c6a85734b6325f62a132e47817ab239604a99.png)
