New option: auto-select language by HTTP header

Thanks for the link, I wanted to request that, too (however it will probably not help much in my case) …

Yes, that’s exactly what I need.

Huh. What about caching the last “known” language? This obviously needs to be a different field from the user preference.
Or better yet, have a heuristic based on how often you access the forum with a specific language? That’s increasing complexity a lot, however a simple solution could be to store an array with “known” languages and a weighting (value between 0 and 1), which is updated every time a user logs in: increase weighting for the current language and decrease it for the other ones in the array … well, not that simple.

Or just cache the language the HTTP header field contains and once the user visits with a different language, show a prompt saying something like “We are having trouble identifying your main language. Please choose your preferred language from the list below:” and let that update the user preference. Then we know for sure and the user is informed / will not be surprised if the language changes because he was on vacation for too long …

Another option would be to update the user’s locale preference from their HTTP headers on login.

I think the best/simplest solution for doing this in a plugin is to ask the user to confirm their language preferences from the locale select input. If you are concerned that your users won’t be able to find that in their preferences, it could be added to the header for users who have not yet confirmed their language.

Actually, it looks like all system emails are sent in the forum’s default language (they use config.locale)


    # discourse/lib/freedom_patches/translate_accelerator.rb

    def translate(key, *args)
      load_locale(config.locale) unless @loaded_locales.include?(config.locale)
      return translate_no_cache(key, *args) if args.length > 0

      @cache ||= LruRedux::ThreadSafeCache.new(LRU_CACHE_SIZE)
      k = "#{key}#{config.locale}#{config.backend.object_id}"

      @cache.getset(k) do
        translate_no_cache(key).freeze
      end
    end
 

Other than dealing with that, this plugin should do close to what you are looking for.

The logic is that if the site-settings allow user locales:

  • if there is no logged in user use the local from the accept-language headers
  • if there is a logged in user and the user has selected their preferred language in the Discourse preferences, use that language
  • if there is a logged in user and the user has not selected a preferred language, use the language from the accept-language header

https://github.com/scossar/variable-language

4 Likes

I’ll try that plugin and report back here, thanks a lot!

Uh-oh, that should be fixed to use the user’s preference if it was selected, @eviltrout .

I’m sorry but there is an error somewhere:

Started GET "/" for x.x.x.x at 2015-11-19 13:44:56 +0000
Processing by CategoriesController#index as HTML
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `ensure_all_loaded!' for I18n:Module)
/var/www/discourse/plugins/variable-language/plugin.rb:35:in `set_locale'

I added the plugin in the container configuration file:

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - mkdir -p plugins
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/scossar/variable-language.git

… and rebuilt the container. Afterwards, I received a 500 (see log above).

May you have a look at that, please?

I think you need to update your version of discourse. ensure_all_loaded! was recently added.

Here’s the main method that the plugin is overriding from application_controller.rb

  def set_locale
    I18n.locale = current_user.try(:effective_locale) || SiteSetting.default_locale
    I18n.ensure_all_loaded!
  end

I’m on 1.4.2. Was this added in 1.5?

Yes, before that it was using I18n.fallbacks.ensure_loaded!. If you can’t update to 1.5 you could probably get the plugin to work by changing its set_locale method to this:

    def set_locale
      if SiteSetting.allow_user_locale
        if !current_user
          I18n.locale = locale_from_http_header
        else
          if current_user.preferred_locale?
            I18n.locale = current_user.preferred_locale
          else
            I18n.locale = locale_from_http_header
          end
        end
      else
        I18n.locale = SiteSetting.default_locale
      end
      I18n.fallbacks.ensure_loaded!
    end

I haven’t tested this though.

1 Like

Thanks, I think I can wait until 1.5, hoping it will release around New Year.

On the other hand, would it be possible to make the plugin downwards-compatible by checking for the existance of ensure_all_loaded and falling back to fallbacks.ensure_loaded otherwise?

Don’t get your hopes up, unless you are celebrating New Year’s Day in March. :wink:

2 Likes

What about it , content wise ?
I wouldn’t recommend a website layout in French when the content is Arabic. Which is very likely to happen.

That depends on what you want or how your community is structured. Especially when your community is private.

It might not make sense for most discussion forums, but it makes sense for forums that are providing a service to clients who may speak different languages.

1 Like

Sure, I’ll do that in the next couple of days. Also, I found a problem with the plugin where it is causing an error when the site is accessed without the accept-language headers being set. I’ll fix that too.

2 Likes

I’ve updated this. I haven’t tested it on 1.4.2. Let me know if there are any problems. You may need to clear your browser cache to get a new locale from the headers.

There is an issue with the login_required_welcome_message being cached in the first locale that accesses it. I assume that’s not a problem if you are using SSO.

1 Like

I’m using this now on 1.4.2/3, works perfectly. Thanks a lot! :+1:

1 Like

It’s been a while. I was called to a case of Discourse not upgrading to the latest v2.4.1 and I traced it to this extension based on the error message during the upgrade attempt:

Gem::LoadError: can’t activate http_accept_language-2.0.5, already activated http_accept_language-2.1.1

… and I found this line in the repo:

gem ‘http_accept_language’, ‘2.0.5’

While I don’t know Ruby, this lead me to think there was a dependency conflict. I managed to upgrade to Discourse v2.3.10, which was successful. Then I commented out the plugin line in the container config and was able to upgrade to the latest stable of Discourse.

Now, I have not tracked the development of Discourse for a while, but recent comments led me to my first question, and if that is not the case, there is an obvious second question:

  1. Is the extension still needed, or is its functionality now covered by the Discourse “core” satisfactorily?
  2. If not, would it be possible to update the extension to make it compatible with Discourse v2.4+, and maybe even make it an “official” extension?

Thank you & all the best!

Edit: scossar/variable-language#1

1 Like

Did we regress here @david?

I don’t think this plugin is needed any more - it hasn’t been touched in years. Try using the core set locale from accept language header site setting.

@simon should we add a note to the README and archive the GitHub repo?

3 Likes

This plugin is no longer required: https://github.com/scossar/variable-language. I had actually forgotten that I made it. The plugin’s functionality has been added to core with the set locale from accept language header site setting.

I’ll remove the plugin from my Github repo and remove any references to it from Meta. Thanks for bringing this to my attention!

4 Likes