Say I want to localize my app for English and Japanese visitors.  How  
do I know which language to use for each HTTP request?  Here''s a way  
to negotiate the best choice.
What you do with the negotiated language is up to you: use it to  
choose a message dictionary, to decide how to format numbers and  
dates, to set preferred units of measurement, etc.  Drop this into  
lib/negotiate_request_language.rb and follow your nose.
# Mix in to your controller to transparently negotiate a language to
# each request.
#
#   require ''negotiate_request_language''
#
#   class ApplicationController < ActionController::Base
#     # Figure out which of these languages the visitor wants.
#     # Use the lang method to retrieve the matching language.
#     accepts_languages ''en'', ''ja''
#
#     def index
#       render_text greeting
#     end
#
#     protected
#       def greeting
#         case lang
#           when ''en'': ''and a good day to you
sir''
#           when ''ja'': ''konnichiwa''
#           else '':-)''
#         end
#       end
#   end
#
# Further reading on language negotiation:
#   http://www.cs.tut.fi/~jkorpela/multi/
#   http://ppewww.ph.gla.ac.uk/~flavell/www/lang-neg.html
module ActionController
   class Base
     def self.accepts_languages(*langs)
       include NegotiateRequestLanguage
       self.accepted_languages = langs.flatten
     end
   end
end
module NegotiateRequestLanguage
   # Look for language in this order.  Expects a corresponding
   # accept_lang_from_#{method} method.
   ACCEPT_LANG_METHODS = [
     :params,
     :cookie,
     :header,
     :environment,
     :failsafe
   ]
   def self.append_features(base)
     super
     base.cattr_accessor :accepted_languages
     base.send :before_filter, :negotiate_language
     base.helper_method :lang
   end
   protected
     attr_reader :lang
     # Check whether we accept a language.
     def accepts_lang?(lang)
       accepted_languages.include? lang
     end
     # Negotiate a language to the HTTP request.  Search for a request
     # parameter, a cookie, the Accept-Language HTTP header, and the  
LANG
     # environment variable.  Fall back to ''en''.
     def negotiate_language
       ACCEPT_LANG_METHODS.find { |m| @lang = send("accept_lang_from_# 
{m}") }
     end
   private
     # Look for lang in query params (could be from a custom route.)   
If found,
     # set a long-lived cookie to pin the match.
     def accept_lang_from_params
       if lang = params[:lang].downcase and accepts_lang?(lang)
         cookies[''lang''] = { :value => lang, :expires =>
10.years.from_now }
         lang
       end
     end
     # If lang cookie is present, check whether we have a match.
     # If the language is not accepted, clear the cookie.
     def accept_lang_from_cookie
       if lang = cookies[''lang''].downcase
         if accepts_lang?(lang)
           lang
         else
           cookies[''lang''] = nil
         end
       end
     end
     # Look for languages in the Accept-Language HTTP header.
     def accept_lang_from_header
       if header = request.env[''HTTP_ACCEPT_LANGUAGE'']
         accept = header.split('','')
         lang = accept.shift.to_s.strip.downcase
         # Take the preferred language if accepted.
         if accepts_lang?(lang)
           lang
         # Otherwise, parse the quality string and pick the best.
         else
           best = accept.inject([nil, 0.0]) do |best, pref|
             lang, quality = pref.split('';'')
             lang = lang.strip.downcase
             if md = /q=(.+)/.match(quality)
               quality = md.captures.first.to_f
             else
               quality = 1.0
             end
             if (best.nil? or quality > best[1]) and accepts_lang?(lang)
               best = [lang, quality]
             end
           end
           if best and accepts_lang?(best[0])
             best[0]
           end
         end
       end
     end
     # Look in the environment for a default language if all else fails.
     def accept_lang_from_environment
       ENV[''LANG''] if
accepts_lang?(ENV[''LANG''])
     end
     # And go to ''en'' if the environment fails too.
     def accept_lang_from_failsafe
       ''en''
     end
end
I extracted this from code that uses Locale objects instead of  
language strings, so beware bugs.  I have test cases that could be  
adapted also if you''d like to extend it further.
Best,
jeremy
On Tuesday 14 June 2005 10:52, Jeremy Kemper wrote:> Say I want to localize my app for English and Japanese visitors. How > do I know which language to use for each HTTP request? Here''s a way > to negotiate the best choice.Jeremy, would you mind to integrate your code with the "Translating" tutorial? Specifically the localize method at http://manuals.rubyonrails.com/read/chapter/88 Michael -- Michael Schuerig They tell you that the darkness mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org Is a blessing in disguise http://www.schuerig.de/michael/ --Janis Ian, From Me To You
One of the things that has surprised me about Rails is how robust it is. In light of that, I find its lack of i18n support to be a curious gaping hole. I realize I can download get-text, install it and use that, but come on, this is Rails. Anymore it tires me out just thinking of how painful such mundane work would be. Let me sit for a moment... I suppose I can deal with get-text or something else of its ilk, but I''m still puzzled: Why doesn''t Rails have i18n support? Thanks, david
Just in case anyone didn''t know - i18n = internationalization (or internationalisation), i.e. i + 18 letters + n. I think it''s a stupid way to write it, but that might just be me :) -DF On 7/14/05, David Geary <sabreware-ihVZJaRskl1bRRN4PJnoQQ@public.gmane.org> wrote:> One of the things that has surprised me about Rails is how robust it > is. In light of that, I find its lack of i18n support to be a curious > gaping hole. I realize I can download get-text, install it and use > that, but come on, this is Rails. Anymore it tires me out just > thinking of how painful such mundane work would be. Let me sit for a > moment... > > I suppose I can deal with get-text or something else of its ilk, but > I''m still puzzled: Why doesn''t Rails have i18n support? > > Thanks, > > > david > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
thank you so much for clearing that up.... I was just about to write that very question.... --Alan On 14-Jul-05, at 12:00 AM, David Felstead wrote:> Just in case anyone didn''t know - > > i18n = internationalization (or internationalisation), i.e. i + 18 > letters + n. > > I think it''s a stupid way to write it, but that might just be me :) > > -DF > > On 7/14/05, David Geary <sabreware-ihVZJaRskl1bRRN4PJnoQQ@public.gmane.org> wrote: > >> One of the things that has surprised me about Rails is how robust it >> is. In light of that, I find its lack of i18n support to be a curious >> gaping hole. I realize I can download get-text, install it and use >> that, but come on, this is Rails. Anymore it tires me out just >> thinking of how painful such mundane work would be. Let me sit for a >> moment... >> >> I suppose I can deal with get-text or something else of its ilk, but >> I''m still puzzled: Why doesn''t Rails have i18n support? >> >> Thanks, >> >> >> david >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> >> > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >