Sometimes it can be useful to set your application locale based upon the request IP. You can easily achieve this using Geocoder
. Among the many things Geocoder
does, it can also tell the location
of a request
.
First, add Geocoder
to your Gemfile
# Gemfile
gem 'geocoder'
Geocoder
adds location
and safe_location
methods to the standard Rack::Request
object so you can easily look up the location of any HTTP request by IP address. You can use this methods in a before_action
in your ApplicationController
:
class ApplicationController < ActionController::Base
before_action :set_locale_from_request
def set_locale_from_request
country_code = request.location.data["country_code"] #=> "US"
country_sym = country_code.underscore.to_sym #=> :us
# If request locale is available use it, otherwise use I18n default locale
if I18n.available_locales.include? country_sym
I18n.locale = country_sym
end
end
Beware that this will not work in development
and test
environments, as things like 0.0.0.0
and localhost
are valid valid Internet IP addresses.
Geocoder
is very powerful and flexible, but needs to be configured to work with a geocoding service (see more details); many of which place limits on usage. It's also worth bearing in mind that calling an external service on every request could impact performance.
To address these, it can also be worth considering:
Using a gem like GeoIP
(see here) allows lookups to happen against a local datafile. There may be a trade-off in terms of accuracy, as these datafiles need to be kept up-to-date.
Pages served through CloudFlare have the option of being geocoded transparently, with the country code being added to the header (HTTP_CF_IPCOUNTRY
). More detail can be found here.