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.
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
Can we add this? Where exactly would it go?
I will fix it later today
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:
-
Move enabling and disabling into to GlobalSetting, then people must opt for this extra work on every request.
-
Disable the feature for anon (simplest but not fun)
-
Build a system for reaching into SiteSettings when there is no access to database in a multisite scenario (complicated, but doable)
-
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.
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.
You would reduce it down to the locales discourse supports but it introduces some extra work unconditionally for all anon requests from now on
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
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