7

Voglio impostare il locale dal browserlocale dei clienti request.env['HTTP_ACCEPT_LANGUAGE'] e dall'URL.Rails I18n set_locale

  1. Se un utente visita un URL (ad esempio: myapp.com) si dovrebbe controllare il HTTP_ACCEPT_LANGUAGE e reindirizzare all'URL destra (ad esempio: myapp.com/en - se il browserlocale è en)

  2. Se un utente sceglie una lingua diversa tramite un menu lingua, dovrebbe cambiare l'URL ad esempio: myapp.com/de.

Qui è la mia cosa ho ottenuto finora:

class ApplicationController < ActionController::Base 
    protect_from_forgery 
    before_filter :set_locale 

private 

    # set the language 
    def set_locale 
    if params[:locale].blank? 
     I18n.locale = extract_locale_from_accept_language_header 
    else 
     I18n.locale = params[:locale] 
    end 
    end 

    # pass in language as a default url parameter 
    def default_url_options(options = {}) 
    {locale: I18n.locale} 
    end 

    # extract the language from the clients browser 
    def extract_locale_from_accept_language_header 
    browser_locale = request.env['HTTP_ACCEPT_LANGUAGE'].try(:scan, /^[a-z]{2}/).try(:first).try(:to_sym) 
    if I18n.available_locales.include? browser_locale 
     browser_locale 
    else 
     I18n.default_locale 
    end 
    end 
end 

Nei miei percorsi il file che ho ottenuto:

Myapp::Application.routes.draw do 
    # set language path 
    scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do 

    root :to => "mycontrollers#new" 
    ... 

    end 

    match '*path', to: redirect("/#{I18n.locale}/%{path}"), constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" } 

    match '', to: redirect("/#{I18n.locale}") 
end 

Il problema è che il routesfile viene eseguito prima e la HTTP_ACCEPT_LANGUAGE ha nessun effetto, perché il parametro url è già impostato quando si tratta del controller.

Qualcuno ha una soluzione per questo? Forse risolverlo con un middleware?

risposta

8

Cambiare alcune cose nei percorsi.

Primo:

scope :path => ":locale" do 
    ... 
end 

Secondo:

vedo ciò che si sta cercando di fare qui:

match '', to: redirect("/#{I18n.locale}") 

Sembra superfluo però.

avrei sbarazzarsi di quella linea e basta modificare il metodo set_locale, in questo modo:

# set the language 
def set_locale 
    if params[:locale].blank? 
    redirect_to "/#{extract_locale_from_accept_language_header}" 
    else 
    I18n.locale = params[:locale] 
    end 
end 
+0

L'application_controller non è chiamato, in caso di partita '' -> così si finisce per non impostazione della localizzazione e senza reindirizzamento. Almeno questo è quello che è successo quando l'ho implementato. –

+0

Ho appena controllato una nuova app Rails (4.1.0) e funziona come previsto. Invece di 'match '', per: redirect ("/# {I18n.locale} ")' dovrai scrivere 'get '', per: redirect ("/# {I18n.locale} ")'. Quella prima richiesta non userà application_controller.rb – etagwerker

+0

Per qualche ragione non funziona per me (testato su 4.0 duro) - comunque ho trovato la seguente soluzione: http://stackoverflow.com/questions/23188986/ applicazione controller-non-essere-eseguito quando si accede-dominio-senza-reindirizzamento –