Geolocalizzazione dei contenuti in Ruby on Rails

Nella realizzazione di questo sito, ci siamo prefissati l’obiettivo di realizzare un blog bilingue, onde poterci affacciare anche all’utenza extra-italiana.
Rails ha integrata una interfaccia per la localizzazione dei contenuti in grado di gestire le traduzioni attraverso dei file in formato yml; nel nostro caso, per rendere ancora
più semplice la gestione delle traduzioni dei contenuti semistatici, abbiamo deciso di utilizzare l’ottimo localeapp.
Oltre alla traduzione dei contenuti semistatici, gestiamo anche la traduzione dei contenuti dinamici (gli articoli del blog) utilizzando due diversi campi nel database.
Attraverso questa infrastruttura, un visitatore può decidere se vedere il sito localizzato in italiano oppure in inglese semplicemente
accedendo all’indirizzo corretto oppure scegliendolo dal menu popup in alto a sinistra (il simbolo della bandiera).
Tutto ciò premesso, quale lingua vede il visitatore che accede all’indirizzo standard www.azns.it?
Inizialmente abbiamo optato per una impostazione statica del “default locale” in italiano, dopodichè abbiamo deciso di intraprendere una strada diversa: proporre i contenuti del
sito localizzati in italiano, solo per i visitatori provenienti dalla rete italiana.
Ecco come abbiamo fatto:

Installazione delle estensioni necessarie

Per gestire la geolocalizzazione, abbiamo usato la gemma GeoIP
Abbiamo installato la gemma aggiungendo la seguente riga al file gemfile

gem 'geoip'

Quindi abbiamo scaricato i database degli indirizzi IP da maxmind e lo abbiamo scompattato
all’interno della directory /public

Codice per la geolocalizzazione

Tutto il codice necessario per la localizzazione si trova all’interno del file application-controller.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale

  def set_locale
    I18n.locale = extract_locale_from_subdomain || geolocalization #I18n.default_locale
  end

  # Get locale code from request subdomain (like http://it.application.local:3000)
  # You have to put something like:
  #   127.0.0.1 gr.application.local
  # in your /etc/hosts file to try this out locally
  def extract_locale_from_subdomain
    parsed_locale = request.subdomains.first
    unless parsed_locale.nil?
      I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
    else
      nil
    end
  end

  def geolocalization
    c = GeoIP.new('public/GeoIP.dat').country(request.remote_ip)
    if c.country_code3=='ITA'
      'it'
    else
      'en'
    end
  end
end

Commentiamo insieme il codice qui sopra
Ad ogni visualizzazione, viene lanciata la funzione set_locale.

Questa funzione setta la variabile di sistema I18n.locale che è quella che viene utilizzata per capire qual è la lingua di visualizzazione del sito: lo fa lanciando la funzione
extract_locale_from_subdomain che ritorna “it” oppure “en” se l’utente ha scelto una particolare visualizzazione, oppure nil se l’utente ha scelto una lingua non supportata
oppure se sta accendendo alla URL standard “www” (oppure al dominio di secondo livello).

Nel caso in cui questa seconda funzione restituisca nil, normalmente si usa ||I18n.default_locale per settare il locale al valore standard dichiarato nel file di
configurazione dell’applicazione Rails; noi invece lanciamo una terza funzione, geolocalization.

Questa funzione estrae tutti i dati relativi allo stato di appartenenza dell’IP del visitatore con c = GeoIP.new('public/GeoIP.dat').country(request.remote_ip) e restituisce
“it” se si trova in Italia, “en” se si trova all’estero.

La funzione, al momento, è compatibile solo con indirizzi IPv4, in quanto il database pubblico di IPv6 è attualmente incompatibile con la gemma geoip. Pertanto, se state
navigando attraverso un indirizzo IPv6, vedrete questo sito in inglese.