语言环境切换器。如何使用更改后的语言环境重定向回来?

Locale switcher. How to redirect back with changed locale?

Rails 4.2 申请.

在页面的页脚我有这样的代码:

  footer.footer
    .container
        = form_tag set_locale_path, method: :post, id: 'set_locale' do
          = select_tag "locale", options_for_select(I18n.available_locales, I18n.locale.to_s), onchange: ("$('#set_locale').submit();")

和具有 set_locale 操作的区域设置控制器。

class LocalesController < ApplicationController
  skip_before_filter :authenticate_user!

  def set_locale
    I18n.locale = params[:locale]
    # redirect_to request.referrer
  end
end

我可以通过 request.referrer 访问以前的 url。看起来像:http://localhost:3000/en/users.

有什么方法可以在不 gsubing 引用字符串的情况下更改语言环境?因为如果不是 - 应用程序会将区域设置从引用 url.

切换回 :en

如果不对字符串进行 gsubing,我找不到简单的解决方案。如果使用 get 参数而不是路由的一部分来设置语言环境会更容易。

示例

http://localhost:3000/users?locale=en // Sets the locale to english

在这种情况下,url 将保持不变,但语言环境会发生变化。

这是我在项目中的做法:

before_action :set_locale

def set_locale
  I18n.locale = locale || I18n.default_locale
end

def locale
  return params[:locale] if ["sv", "en"].include? params[:locale]
end

所以我自己一直在处理这个问题。我不想从 URL 中删除该语言,因为如果您使用不同的语言,它确实会影响 SEO。所以我也有 language/locale 作为 url 的一部分所以它看起来像 www.website.com/en/more_url/even_more_url 等等等等

我在其他任何地方都找不到答案,所以这就是我的解决方案。我做了一个创建 url 的服务,如果选择了 none 而不是 URL 的一部分,则换出当前语言或设置它,例如当它的“/”[=13] =]

我只是抓取 URL 的末尾部分并查找语言并根据其长度将它们换出,然后将 URL 构建为字符串然后返回。并在控制器中使用。

它按预期工作,但我不知道如何解决的唯一奇怪的边缘情况是...假设您在一个有表单的页面上。您提交的表单存在验证错误。 Rails 获取 post url 并将浏览器 url 更改为 post URL,这是一种 rails 行为。如果浏览器 url 在表单 URL 上,然后您尝试更改语言,那么您将在 post URL 上使用新语言发出获取请求。所以会导致错误。我想也许你可以添加一个 if 语句只说 运行 这个代码 if request.get 但是那意味着当改变语言时你不能使用 post 请求来设置语言所以它不起作用.

所以你必须希望用户不要提交有错误的 rails 表单然后决定更改语言 LOL(无论如何这看起来都是奇怪的行为)

无论如何,我希望这能帮助那些一直在处理这个问题的人:)

 class LanguageUrlHelper

  def self.get_url(request, locale_param)
    
      uri= URI(request.referer).path 
      long_local_url = "/" + locale_param+ "/"
      short_local_url = "/" + locale_param
      if uri.length > 3  
        if uri.include?("/es/") 
          new_uri = uri.gsub("/es/", long_local_url)
        elsif uri.include?("/en/")
          new_uri = uri.gsub("/en/", long_local_url)
        elsif uri.include?("/pt/")
          new_uri = uri.gsub("/pt/", long_local_url)
        end 
      elsif uri.length <= 3
        if uri  == "/" 
          new_uri = uri.gsub("/", short_local_url)
        elsif uri == "/en"
          new_uri = uri.gsub("/en", short_local_url)
        elsif uri == "/es"
          new_uri = uri.gsub("/es", short_local_url)
        elsif uri == "/pt"
          new_uri = uri.gsub("/pt", short_local_url)
        end
      end 
      new_url = request.base_url + new_uri
      return new_url
    
  end

end 

在你的控制器中添加

redirect_to LanguageUrlHelper.get_url(request, params[:locale])

我上面写的答案不是最好的方法我有一个更新的方法,我最终使用它我认为解决了多个问题。取决于您真正想要翻译您的应用程序的程度。

在我的事业中,我想确保我翻译了内容和 url,这使得它对用户和营销目的更友好,例如,如果您正在做登陆页面或其他事情。

为此,您需要添加“route_translator”gem

在应用程序控制器中添加为私有方法(这需要在之前的操作中调用。)

def set_current_url_and_params

    set_params = params.except("authenticity_token", "controller","action")
    @path = ""
    @current_page_params = set_params.to_unsafe_h
    Rails.application.routes.router.recognize(request) do |route, matches, param|
      @path = route.name
      break
    end 
    
end

它所做的是设置 @path 变量,该变量具有您当前所在的路径。这将在视图中使用,例如,如果您的菜单是这样,您可以切换语言。

像这样:

=button_to  "ES", set_location_path(locale:'es', current_path:@path, current_page_params:@current_page_params), class: "btn btn-primary-soft btn-block mb-1"
=button_to  "EN", set_location_path(locale:'en', current_path:@path, current_page_params:@current_page_params), class: "btn btn-primary-soft btn-block mb-1"

此按钮向设置“语言环境”的端点发送 post 请求。它还将发送我们在应用程序控制器中设置的current_path。

在您的路由文件中,您将使用我上面提到的 gem。

localized do 
 get "register"=> "users#new", :as=> :new_user
end

gem 会根据您要使用的 locales/languages 为您创建一些新路径。 所以在这个例子中它创建了

new_user_en
new_user_es
new_user_pt

现在假设您在 new_user_en_path

块设置了这个所以现在它知道你在哪里。它知道命名路由,它会给你一个字符串“new_user_en”

Rails.application.routes.router.recognize(request) do |route, matches, param|
   @path = route.name
   break
end 

当发送更改语言环境的请求时,您还使用@path(带有字符串值)发送它,您需要获取并处理它。我使用了与其他答案相同的服务和方法,但进行了一些更改后使用这个更好。

class LanguageUrlHelper
  #you need to include url helpers in service for this to work

  class << self
   include Rails.application.routes.url_helpers
  end
  


  def self.get_url(request, params)
    
    prefix_path = params[:current_path]
    locale = "_"+ params[:locale]
    
    if prefix_path.include?("_es")
      new_path = prefix_path.gsub("_es", locale)
    elsif prefix_path.include?("_en")
      new_path = prefix_path.gsub("_en", locale)
    elsif prefix_path.include?("_pt")
      new_path = prefix_path.gsub("_pt", locale)
    else
      new_path = prefix_path + locale
    end 


    
    url = eval("#{new_path}_path(params.to_unsafe_h)")
    
   end
end

在更改语言环境操作控制器中添加

def set_locale
   I18n.locale = params[:locale] || I18n.default_locale
   http_accept_language.compatible_language_from(I18n.available_locales)
   session[:currency] = params[:currency]
   flash[:success] = t("application_controller.set_location.success")
   redirect_to LanguageUrlHelper.get_url(request, params)
end

get_url 的作用是换出包含区域设置的 url_helper 路径的最后一位,并将其更改为您想要的新区域。

例如,如果我想要西班牙语,它会抓取 new_user_en 并将其更改为 new_user_es。

然后我对其进行插值,然后评估给我实际 URL 的方法。 用这条线

url = eval("#{new_path}_path(params.to_unsafe_h)")

您还需要确保发送当前页面参数(如果有的话),因此我还将当前参数存储在一个变量中,并在按钮中传递,该按钮也会传递到该服务中。

此外,这对于它的工作很重要,@path 需要从一开始就设置,添加“_en”等需要是真实路径。所以你需要确保根路径也使用 gem 所以你必须添加(显然使用你自己的)这给你 root_en_path 等等等等

root :to => 'landing_pages#buyers'
localized do 
 root :to => 'landing_pages#buyers'
end 

所以做这一切

例如,如果您在

domain.com/en/new_user 并想将其更改为西班牙语,现在将其更改为 域。com/es/nuevo_usario 并重定向到该页面,该页面恰好是您在翻译 URL 时已经在的翻译页面。

这比使用 regex 或 gsubing url 好得多,后者对我来说似乎更脆弱。我希望这对那些一直试图搞乱翻译的人有所帮助。我找不到任何解决这个问题的东西,花了很多时间试图弄明白:)