RefugeRestrooms / refugerestrooms

REFUGE restrooms indexes and maps safe restroom locations for trans, intersex, and gender nonconforming individuals.
http://www.refugerestrooms.org
GNU Affero General Public License v3.0
894 stars 261 forks source link

Set locale based on Accept-Language header #420

Closed stardust66 closed 6 years ago

stardust66 commented 6 years ago

This used to be Intimaria#1.

Context

Summary of Changes

The Accept-Language HTTP header indicates the preferred language for request's response. Browsers set this header value based on the user's language preference settings, making it a good first choice when inferring a locale.

Now, the language of the page will change to fit with the preferred language setting of the browser.

Change Setting

Chrome Settings image

screen shot 2018-01-10 at 6 28 37 pm
DeeDeeG commented 6 years ago

Thanks for re-doing this.

I did find out while working on #419 that this breaks if the user requests a locale we don't have.

Here is a screenshot when requesting the ru (Russian) locale: about-russian-locale-no-translations

We need some way of defaulting to something we actually have, probably en, when we don't have the top user-accepted language.

Fortunately there are ways of handling this, such as: https://github.com/iain/http_accept_language That is a gem we can add and then have it select the best locale we provide, selected amongst users' requested locales. I am hoping the gem lets us fall back to a default locale when we match none of the user-accepted languages, but it's not super clear so we would have to test. Seems like most browsers might accept en as the bottom choice, regardless of locale, but we don't want to break if users manually delete the en language in their preferences.

Or if this can be done without installing another gem that's fine by me.

stardust66 commented 6 years ago

I used the gem you suggested. With this, the locale gets set to the correct value and when a locale that we don't support gets requested, it defaults to the value of config.i18n.default_locale which defaults to :en.

We tell rails which locales we supported by setting config.i18n.available_locales.

DeeDeeG commented 6 years ago

Looks good! Going to give it a quick test with the ru locale again just to see what happens.

Also, I'm interested in possibly using language_region_compatible_from(languages). If it does what it says it's supposed to, then that would support zh_ch and zh_tw, whereas compatible_language_from(languages) apparently would treat both as the same thing. Who knows, maybe someday we will have multiple regional versions of the same language.

DeeDeeG commented 6 years ago

Okay, it looks good. This is what I get with the ru locale preferred, followed by es-ES and es, and furthermore, I even deleted en-US and en from my accepted languages. ru-locale-set-got-english

The site still gave me the en locale (verified in developer tools): refuge-lang-equals-en

Edit to clarify: That's good, because on this branch we only have English. English is better than displaying only the translation key names!

DeeDeeG commented 6 years ago

This looks reallly good in further testing. First, I configured the app to believe it supported English, generic Chinese, Chinese specifically for Taiwan [aka traditional Chinese], and Chinese specifically for China [aka simplified Chinese] in config/application.rb.

config.i18n.available_locales = [:en, :zh, 'zh-TW', 'zh-CN']

Here were my results:

Preferred languages What the site gave me Correct behavior?
ru, es-ES, es en ☑️
zh, ru, es-ES, es zh ☑️
zh-CN, zh, ru, es-ES, es zh-CN ☑️
zh-TW, zh-CN, zh, ru, es-ES, es zh-TW ☑️
zh-CN, zh-TW, zh, ru, es-ES, es zh-CN ☑️

Update: more testing

I configured the app to belive it supported only generic English and Chinese specifically for China...

config.i18n.available_locales = [:en, 'zh-CN']

Results:

Preferred languages What the site gave me Correct behavior?
zh-CN, zh-TW, zh, ru, es-ES, es zh-CN ☑️
zh-TW, ru, es-ES, es zh-CN ☑️
zh-TW, ru, es-ES, es, en zh-CN ☑️
en, zh-TW, ru, es-ES, es en ☑️
stardust66 commented 6 years ago

Thanks for all your testing @DeeDeeG!

Intimaria commented 6 years ago

Wow this is fantastic. I admire all of this work!