Rails: changing locale and keeping page parameters - ruby-on-rails

I have a navbar with links to different languages:
<%= link_to t('header.english'), locale: "en" %>
The problem is when user tries to switch language on a page which contains additional parameters in the url. Changing locale at this point reloads the page and strips all the additional parameters.
So, how do I pass all the parameters from the current page to the locale switch link?
For example, when
/page/new?param1=1&param2=2
is open, and user switches the locale,
/page/new?locale=en
is opened, and both additional parameters are stripped away from the url.

If you need locale param to stay in all requests it's good to use this approach:
# app/controllers/application_controller.rb
def default_url_options(options={})
{ locale: I18n.locale }
end
from rails guide

EDIT: THIS IS NOT A GOOD WAY TO DO THIS. See comments below.
The problem is that you are not passing the current params to link_to when you create the locale switcher link.
Change your navbar link to:
<%= link_to t('header.english'), params.merge(locale: "en") %>
See also: Add querystring parameters to link_to

Related

How to keep the query params when changing locale in Rails 6

I am trying to preserve query params when changing locale in Rails 6, I only found the default_url_options method & if I try to pass the params to that it doesn't work throwing unpermitted params passed exception
For example:
A URL having http://localhost:3000/some_path?token=ABcasdjlaweQWd
Should be changed to http://localhost:3000/de/some_path?token=ABcasdjlaweQWd
But currently, it only becomes: http://localhost:3000/some_path & I lose the query params
Keeping things secure is important, so I don't want to hack my way disabling the params filter, but it should be possible to pass the params during language change without big hacks.
Update:
I am changing local by navbar link_to btn (for different locale), for example: link_to url_for( :locale => 'fr' ) that will change locale part of the current url to the french locale for example
What is the correct way to maintain the query params on language change?
Without overriding the default_url_options, a better way is to make the language change button behave differently, so that it won't remove the query params
So instead of this:
= link_to url_for( locale: 'en' )
It should be changed to this, which will keep the params:
= link_to request.params.merge( locale: 'en' )

Link to corresponding path in other locale (rails)

I have a multi-lingual application in Ruby on Rails 4. For that I use the following domains:
Swedish: exempel.se
English: example.com
French: fr.example.com
Spanish: es.example.com
I want to be able to link to the corresponding path in another corresponding locale. For example if I am at www.exempel.se/denna-bloggpost I want to be able to easily link to (English/Spanish/French) to e.g. www.example.com/this-here-blog-post and es.example.com/este-posto-de-bloggo (sorry, can't speak Spanish :)).
I understand this is done with link_to 'Spanish', locale => :es but this gives me the url www.exempel.se/denna-bloggpost?locale=es which is not what I want. I expect to access es.example.com/esto-posto-de-bloggo
It seems like default_url_options has something to do with this but I can't make it work.
How do I solve this?
Edit (2017-03-30): I will also need this solution for hreflang in the section.
I am using the route_translator gem.
I have seen several solutions for this but they all include solutions with ?locale=en or are just to simplified (like, only working for one single controller). What I am hoping for is a solution that would do something like this:
<% I18n.available_locales.each |locale| do %>
<% I18n.t(this route e.g. /denna-bloggpost) #=> /este-posto-de-bloggo, /this-blog-post, /le-post-du-blog %>
<% end %>
You can use the locale-specific routes that route_translator generates for you. Run rake routes to see what these are. And then:
# Create links for every other locale
<% (I18n.available_locales - I18n.locale).each |locale| do %>
# Example URL helper here - replace with your own!
<%= Rails.application.routes.url_helpers.send("posts_#{locale}_url",
'denna-bloggpost') %>
<% end %>
In order to create such a dynamic mapping, you must presumably have something like this defined in your application config:
APP_CONFIG = {
# ...
base_urls: {
se: 'exempel.se',
en: 'example.com',
fr: 'fr.example.com',
es: 'es.example.com'
}
# ...
}
(It wouldn't necessarily need to be in this format, of course; this is just an example.)
In the locale switching menu, you can then define your links like this:
link_to("French", "#{APP_CONFIG[:base_urls][:fr]}#{request.env['PATH_INFO']}")
In order to actually set the locale in your application, you could then place something like this in your ApplicationController:
class ApplicationController
before_action :set_locale
def set_locale
I18n.locale = APP_CONFIG[:base_urls].key(request.host) || I18n.default_locale
end
end
For more information, see here: http://guides.rubyonrails.org/i18n.html#managing-the-locale-across-requests
This question is addressed a number of times and many ways. Yet the simplest approach in my opinion is
<%= link_to "ру", request.params.merge( locale: 'ru' ) %>

Rails erb templating, link element visibility to action in yield?

In application.html.erb file, can I link HTML elements visibility to actions that are inside the <%= yield %> tag ?
For example if I have a header element and want to display a text there if <%= yield %> is displaying a specific action?
You can use the current_page? helper to determine if you're on a specific page (as identified with the given path parameters, etc.) and branch accordingly.
Or, if you need a more broad stroke you can use controller_name and/or action_name to get the current controller's name and the current action's name and branch accordingly.
Lastly, you can inspect params[:controller] or params[:action], which are sometimes more revealing than the above.

Can I Set Up Routes That Include The Locale & Default the Locale In The Route When It Is Not Provided?

I currently have routing that requires the locale (i.e. /en, /fr, etc.). At some point I have used all of the statements below in routes.rb:
scope "/:locale", locale: /#{I18n.available_locales.join("|")}/ do
scope "/:locale", defaults: { :locale => "en" } do
scope "/:locale" do
I know that if I do the following if the route does not include the locale that it will point to the English version of the website. However it does not set the locale like I want once the page is displayed. If I go to the French version by clicking my locale logic the first link will display the French version of the page with /fr in the link. However if I click another link on the French page the locale goes back to English with the locale excluded from the link.
scope "(/:locale)", defaults: { :locale => "en" } do
Here is the code for my locale links in my application where a user can click on a flag image or text to change the locale:
<%= link_to_unless_current image_tag("english.jpg", alt: "#{t :english}"), locale: "en" %> <%= link_to_unless_current "#{t :english}", locale: "en" %>
<%= link_to_unless_current image_tag("french.jpg", alt: "#{t :french}"), locale: "fr" %> <%= link_to_unless_current "#{t :french}", locale: "fr" %>
What I would like to do is to prevent a 500 system error if by chance someone has an link saved before the website was localized. For example if they have http://mywebsite.com/video it would display the English version of the website and set the locale to "en".
Here is the code I have in application_controller.rb.
before_filter :set_locale
def default_url_options(options={})
{ :locale => I18n.locale }
end
private
def set_locale
I18n.locale = (params[:locale] if params[:locale].present?) || cookies[:locale] || 'en'
cookies[:locale] = I18n.locale if cookies[:locale] != I18n.locale.to_s
end
I'm not finding anything on this particular issue other than to use the routing-filter gem. I was using the gem but until there is a production version of the gem for Rails 4 I have no option but to figure this routing issue out.
Any help would be appreciated.
i find your question rather confusing... so my answer will refer to some parts of you code. maybe that gives you enough context to fix your problems.
do not use 3 routes for locale
one route is enough, please read the guides for internationlization.
i think that you will have to go with the optional approach as you want to support legacy urls:
scope "(/:locale)" {}
use the config.default_locale option
in the configuration you can configure fallbacks for localization.
don't mix default_url_options and cookies
if you are using cookies to keep track of your locale, you can can skip the default_url_options, you will have to keep the unlocalized versions anyways for backward compatibility.
if you MUST have urls like domain.com/en/something do it the other way around. avoid using cookies, use the URL everywhere and redirect people coming in from a legacy url.

Link back to page visited before form

I have a listing page, then a form, then a thank you page. I need to put a link on the thank you page that takes the user back to the page they were on before the form which always varies. I've tried using this:
= link_to "Back", :back
But this only takes them back to the previous page, so the form.
Try this
<%= link_to 'Back', url_for(:back) %>
# if request.env["HTTP_REFERER"] is set to "http://www.example.com"
# => http://www.example.com
here is more details.
Well, you can set a method in the form page to collect that url. The basic idea is to use a custom session variable to store previous url and keep it to next session.
Suppose your form's action is SomeController#new, then
class SomeController < ApplicationController
after_action "save_my_previous_url", only: [:new]
def save_my_previous_url
# session[:previous_url] is a Rails built-in variable to save last url.
session[:my_previous_url] = URI(request.referer || '').path
end
end
Then in the thank you page, you can get this my_previous_url by
session[:my_previous_url]
This should be able to suit your case, the previous url two pages ago.
Disclaimer: This is not verified. Idea only.
Add
Session belongs to controller. It is not a helper you can use directly in view. You need to define an instance variable in controller and then you can use it in view. Like this
# Controller
#back_url = session[:my_previous_url]
# View
<%= link_to "Back", #back_url %>
You can use the example from Rails API:
<%= link_to "Back", :back %>
Rails API Doc for link_to
Using a :back Symbol instead of an options hash will generate a link to the referrer (a JavaScript back link will be used in place of a referrer if none exists).
Since you saying,it might be different page before form, probably request_url can help you. you can save your request_url in a param and redirect to param_url if there is.
here is a source that you can take for reference.
http://programming-tut.blogspot.com/2010/06/ruby-on-rails-request-url.html
If use in Controller, you can direct use like this:
def some_action
# some code
redirect_to :back
end
This works for me:
In controller from previous view:
cookies[:original_referrer] = request.orignal_url
to set a cookie on the browser with the URL of the originating page
In the controller from the current view:
redirect_to cookies[:original_referrer]

Resources