0

我有以下代码,它首先根据参数分配区域设置,然后是先前设置的 cookie,然后通过请求HTTP_ACCEPT_LANGUAGE.

def set_locale
  if params[:locale] 
    I18n.locale = params[:locale]
  elsif cookies[:locale]
    I18n.locale = cookies[:locale]
  else 
    I18n.locale = sanitizeLocale(request.env["HTTP_ACCEPT_LANGUAGE"]) # e.g. "en,es;q=0.8,de-de;q=0.5,en-us;q=0.3"
  end
  cookies[:locale] = I18n.locale
end

def sanitizeLocale(locale)
  @locale, lang_weight = cookies[:locale] || begin
    if accept_lang = request.env["HTTP_ACCEPT_LANGUAGE"] # e.g. "en,es;q=0.8,de-de;q=0.5,en-us;q=0.3"
      accept_lang.to_s.split(',').collect {|l| x,y = l.split(';q='); [x.split('-').first, (y||1).to_f]}.sort_by(&:last).reverse.find {|lang, lang_weight| %w[es en it fr de].include?(lang)}
      # returns ["en", 1.0]
    end
  end || 'en' # default
  return @locale
end

我的问题是如何检查params[:locale]给定和cookies[:locale]对照sanitizeLocale. 我很感兴趣仅根据输入获取有效值,例如es en it fr de或默认为 en 。

我一直试图将它的值传递给sanitizeLocale我正在做的类似的事情,HTTP_ACCEPT_LANGUAGE 由于某种原因我无法理解它不起作用,并且en即使params[:locale]给定的值是有效的,也总是默认为it.

4

1 回答 1

0

首先,我们可以稍微简化一下您的 Accept-Language 解析:

def acceptable_langs
  extract_langs = lambda do |l|
    x, y = l.split(';q=')
    [x.split('-').first, -(y || 1).to_f] # the -1 makes sort_by nicer
  end
  known_langs = lambda { |lang| %w[es en it fr de].include?(lang.first) }
  quality = :last
  language = :first
  langs = request.env['HTTP_ACCEPT_LANGUAGE'].to_s
                 .split(',')
                 .map(&extract_langs)
                 .select(&known_langs)
                 .sort_by(&quality)
                 .collect(&:language)
  langs + ['en']
end

to_s照顾nils 和 lambdas 和额外的变量只是为了澄清逻辑。您不必这样做,您真正需要的只是一种返回用户和您的软件都可以接受的语言代码的方法,这些代码由用户的偏好排序。

现在回到set_locale. 您说'en'无论 URL 或 cookie 必须说什么,您都需要语言来匹配 Accept-Langauge(作为后备)。这意味着无论如何您都必须解析 Accept-Language 然后检查params[:locale]cookies[:locale]对照该列表:

def set_locale
  # Figure out what they're asking for with English as the
  # default. Note that `acceptable_langs` always forces English
  # to be in the list.
  asking_for = params[:locale] || cookies[:locale] || 'en'

  # acceptable_langs is always in preference order so we just
  # want the first one that matches our `lang`.
  lang = acceptable_langs.find { |lang| asking_for == lang }

  # Now we have an acceptable language in `lang` (thanks to all
  # the `'en'` fallbacks we sprinkled about).
  I18n.locale = cookies[:locale] = lang
end

您还可以在 cookie 中添加一点“我已经完成了所有这些工作”标志,这样您就可以简单地信任cookies[:locale]是否设置了该标志;不过,可能没有理由过早优化set_locale

于 2012-08-30T19:22:13.477 回答