2017-03-11 9 views
2

request.location(geocoder gem)을 사용하여 로케일을 클라이언트 IP 주소에 적절히 설정하려고합니다. 레일 : 로케일을 적절하게 IP 주소로 설정합니다.


내가있어 무엇 :

응용 프로그램/컨트롤러/application_controller.rb

before_action :set_locale 

private 

def set_locale 
    # get location with geocoder 
    location = request.location 

    # set locale through URL 
    if params.has_key?(:locale) 
     I18n.locale = params[:locale] || I18n.default_locale 
    # set locale through user preference 
    elsif current_user && current_user.locale.present? 
     I18n.locale = current_user.try(:locale) || I18n.default_locale 
    # set locale through geocoder detection of location 
    elsif location.present? && location.country_code.present? && I18n.available_locales.include?(location.country_code) 
     if location.country_code.include? "-" 
      I18n.locale = location.country_code 
     else 
      I18n.locale = location.country_code.downcase 
     end 
    # set locale through HTTP detection of location 
    elsif (request.env["HTTP_ACCEPT_LANGUAGE"] || "en").scan(/^[a-z]{2}/).first.present? && I18n.available_locales.include?((request.env["HTTP_ACCEPT_LANGUAGE"] || "en").scan(/^[a-z]{2}/).first) 
     I18n.locale = (request.env["HTTP_ACCEPT_LANGUAGE"] || "en").scan(/^[a-z]{2}/).first 
    end 
end 


설정/application.rb

# i18n Translations 
## load the subfolders in the locales 
config.i18n.load_path += Dir["#{Rails.root.to_s}/config/locales/**/**/**/**/**/*.{rb,yml}"] 
## set default locale 
config.i18n.default_locale = 'en' 
## provide locale fallbacks 
config.i18n.enforce_available_locales = false 
config.i18n.fallbacks = { 
    'de-AT' => 'de', 'de-CH' => 'de', 'de-DE' => 'de', 
    'en-AU' => 'en', 'en-CA' => 'en', 'en-GB' => 'en', 'en-IE' => 'en', 'en-IN' => 'en', 'en-NZ' => 'en', 'en-US' => 'en', 'en-ZA' => 'en' 
} 

매개 변수 params[:locale]을 사용하면 모든 것이 잘 작동합니다. 그러나 매개 변수가 없으면 항상 기본값은 en입니다.

내가 뭘 잘못하고 있니?

답변

4

I18n.locale은 기본적으로 요청간에 기억되지 않습니다. 세션에 저장하여 직접 구현해야합니다. I18n.locale를 설정하면, 당신은 사용할 수 있습니다

session[:locale] = I18n.locale 

와 다음을 다시 끌어 :

I18n.locale = params[:locale] || session[:locale] || I18n.default_locale 
# explicit params take precedence 
# otherwise use the remembered session value 
# fallback to the default for new users 

(!) 참고 :이 항상 실행되지 않도록 당신의 location = request.location 이동하는 것이 좋습니다. 데이터를 사용하지 않더라도 모든 요청에 ​​작은 성능 저하 (및 지오 코딩 서비스 조회)가 발생합니다.

예로서

, 여기 당신이 할 수있는한 방법입니다 :

def set_locale 
    # explicit param can always override existing setting 
    # otherwise, make sure to allow a user preference to override any automatic detection 
    # then detect by location, and header 
    # if all else fails, fall back to default 
    I18n.locale = params[:locale] || user_pref_locale || session[:locale] || location_detected_locale || header_detected_locale || I18n.default_locale 

    # save to session 
    session[:locale] = I18n.locale 
end 

# these could potentially do with a bit of tidying up 
# remember to return `nil` to indicate no match 

def user_pref_locale 
    return nil unless current_user && current_user.locale.present? 
    current_user.locale 
end 

def location_detected_locale 
    location = request.location 
    return nil unless location.present? && location.country_code.present? && I18n.available_locales.include?(location.country_code) 
    location.country_code.include?("-") ? location.country_code : location.country_code.downcase 
end 

def header_detected_locale 
    return nil unless (request.env["HTTP_ACCEPT_LANGUAGE"] || "en").scan(/^[a-z]{2}/).first.present? && I18n.available_locales.include?((request.env["HTTP_ACCEPT_LANGUAGE"] || "en").scan(/^[a-z]{2}/).first) 
    (request.env["HTTP_ACCEPT_LANGUAGE"] || "en").scan(/^[a-z]{2}/).first 
end 
+0

이상한입니다 나는 다음과 같은 추가하면'세션 [: 로케일] =의 PARAMS [: 로케일] 새로운 로케일이 설정되면 세션 데이터를 업데이트하기 위해 params [: locale]! = session [: locale]'이 실행되면 요청이있을 때마다 응용 프로그램이'en'으로 폴백합니다. 레일이이 매개 변수를 백그라운드에서 설정합니까? – jonhue

+0

@jonhue :'session'은 요청 사이에 기억되지만,'params'는'locale'을 포함하거나 포함하지 않을 수도 있습니다. 모든 페이지에 포함 시키려면 URL을 생성 할 때 컨트롤러에서보기로 전달해야합니다. 가장 좋은 방법은'params [: locale]'을 기존 설정의 명시 적 one-off override *로 처리하고, 그렇지 않으면 항상'session [: locale]'에 의존합니다. – gwcodes

+0

우연히도, 이에 대한 코드 샘플은 I18n 문서 섹션 (http://stackoverflow.com/documentation/ruby-on-rails/2772/i18n-internationalization/9336/set-locale-through-requests#t=201703111203188547129)을 참조하십시오. 더 완전한 설명을주기 위해서 – gwcodes