Swedish? meta just showed me the UI in Swedish

I opened my browser, clicked ‘log out’ on the drop-down menu (because my browser doesn’t recover Discourse sessions properly when I log in), and got the anonymous home page. The buttons and top header were in Swedish (“Logga in” instead of “Login”). I do not have Swedish selected in my browser and never have.

1 Like

I’m not sure if this is related, but I’ve noticed on meta that when, as an anonymous use, I change my browser’s language preference, I often need to refresh the page several times before the new locale file is served. Does this have anything to do with the locale file being served through a CDN? On my own forum, without a CDN, the new locale file is served on the first request.

This is a strong indicator that anonymous cache middlewere has a missing cache buster for locales

2 Likes

Can we add this? Where exactly would it go?

I will fix it later today

4 Likes

OK this is fiendish to fix and I am not sure what to do:

Trivially we can add env['HTTP_ACCEPT_LANGUAGE'] to:

https://github.com/discourse/discourse/blob/master/lib/middleware/anonymous_cache.rb#L48

Trouble is that our anonymous cache will automatically become much less efficient, every permutation out there of accept language will force a new entry in the cache.

The anon cache middleware is VERY early in the stack, at that point we don’t even have safe access to Site Settings, so we can’t even figure out if this feature is enabled.

So now, the existence of this feature is forcing us to do extra work for every anon request. Some options:

  1. Move enabling and disabling into to GlobalSetting, then people must opt for this extra work on every request.

  2. Disable the feature for anon (simplest but not fun)

  3. Build a system for reaching into SiteSettings when there is no access to database in a multisite scenario (complicated, but doable)

  4. Just shove the accpet header and deal with a terrible anon cache … mine is HTTP_ACCEPT_LANGUAGE: en-US,en;q=0.8,he;q=0.6 very few have this.

Only 2) is easy, so @codinghorror we need to decide what amount of effort we need to invest here.

I estimate its half a day to a day to get 1 or 3 to work perfectly.

5 Likes

Another option would be to reduce the header to the “top supported language” and cache key off that. So you have ~20-30 variations max, and you might need to keep them around even if the feature’s off.

1 Like

You would reduce it down to the locales discourse supports but it introduces some extra work unconditionally for all anon requests from now on

1 Like

Given that the cost here is so extreme we are

  • doing nothing at the moment, leaving the feature default off

  • marking the feature as EXPERIMENTAL in the site setting copy description

cc: @simon

3 Likes

It wouldn’t be as bad if a global setting was added and the accept-language header was parsed before it was used in the cache_key. Something like this?

# lib/anonymous_locale.rb

class AnonymousLocale
  def self.locale(accept_language_header)
    if GlobalSetting.locale_from_header
      begin
        require 'http_accept_language' unless defined? HttpAcceptLanguage
        available_locales = I18n.available_locales.map { |locale| locale.to_s.gsub(/_/, '-') }
        parser = HttpAcceptLanguage::Parser.new(accept_language_header)
        parser.language_region_compatible_from(available_locales).gsub(/-/, '_')
      rescue
        I18n.default_locale
      end
    else
      I18n.default_locale
    end
  end
end

And then in anonymous_cache:

def cache_key
  @cache_key ||= "ANON_CACHE_#{@env["HTTP_ACCEPT"]}_#{AnonymousLocale.locale(@env["HTTP_ACCEPT_LANGUAGE"])}_#{@env["HTTP_HOST"]}#{@env["REQUEST_URI"]}|m=#{is_mobile?}|c=#{is_crawler?}"
end
2 Likes