Rails:将区域设置适当地设置为IP地址

时间:2017-03-11 11:00:11

标签: ruby-on-rails ruby internationalization locale geocoding

我正在尝试使用request.location (geocoder gem),将区域设置适当地设置为客户端 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

我在这里做错了什么?

1 个答案:

答案 0 :(得分:6)

默认情况下,请求之间不会记住

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