1 2 3 4 5
if self.location_type.to_s == 'point' breaker = self.lang == 'fr' ? 'proximite' : 'near' else breaker = self.lang == 'fr' ? 'dans' : 'in' end
Refactorings
No refactoring yet !
danielharan
October 11, 2007, October 11, 2007 19:37, permalink
Assuming you are only working with two languages...
1 2 3 4 5
if self.location_type.to_s == 'point' breaker = {'fr' => 'proximite', 'en' =>'near' }[self.lang] else breaker = {'fr' => 'dans', 'en' => 'in' }[self.lang] end
Gary Haran
October 11, 2007, October 11, 2007 19:55, permalink
in the middle of all of this I had to add another else... a coworker mentionned this example
1 2 3 4 5 6 7 8 9
p = Proc.new { |en, fr| lang.to_s == "en" ? en : fr } breaker = case location_type when 'point' p.call('near', 'proximite') when 'street' p.call('on', 'sur') else p.call('in', 'dans') end
macournoyer
October 11, 2007, October 11, 2007 20:25, permalink
what about puting the localisation stuff in a yaml file ?
Yaml data file
1 2 3 4 5 6 7 8 9
point: en: near fr: proximite street: en: on fr: sur default: en: in fr: dans
Code
1 2 3
texts = File.open("path/to/text.yaml") { |file| YAML.load(file) } breaker = (texts[location_type] || texts['default'])[lang.to_s]
Frahugo
October 12, 2007, October 12, 2007 01:13, permalink
I'm using a Globalite plugin. I love it because it is a simple way to achieve what Marc-André just suggested. You install the plug-in, put your localized strings in Yaml files, set the current language in your controller and voila. You then the l() method on a symbol. The localized strings are read once and cached in memory (you havae to restart the server if you modify the files, but in production mode, we want that to avoid always reading files).
lang/ui/fr.yml
1 2 3
point: proximite nopoint: dans happy: Nous adorons tous Ruby on Rails
lang/ui/en.yml
1 2 3
point: near nopoint: in happy: We all love Ruby on Rails
Controller
1 2 3
Globalite.language = self.lang.to_sym # This could be in a before_filter in application.rb key = self.location_type.to_sym breaker = key.l( :nopoint.l ) # If no key found for location_type, defaults to key :nopoint
michiel
October 12, 2007, October 12, 2007 01:37, permalink
YAML solutions break down when the text isn't static. I use procs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# in helper TIME_REMAINING_TODAY = { :en => "%s of practice remaining today", :nl => "nog %s te oefenen vandaag", :de => "noch %s zu üben heute", :fr => "encore %s de pratique aujourd'hui", } define_message :time_remaining_today do |time, lang| sprintf(TIME_REMAINING_TODAY[lang], i_distance_of_time_in_words(time, lang)) end # in model (doesn't know or care about user language) return time_remaining_today(interval) # in controller @msg = model.calc_time # in view <%= @msg[@user.lang] %>
Hampton
October 12, 2007, October 12, 2007 18:41, permalink
So, I was the mystery coworker with the Proc
I thought of this solution. Its a bit dense and confusing... however, its *very* editable, almost without thought. We could easily want to specify new location_types later... or change translations... or even add another language. This solution has those as "pros", but I wouldn't use it just because its too dense.
BUUUUT, the super short was is really fun. Notice the way I am handling the language-array lookup! I'll be impressed if people can figure out how it works at all.
1 2 3 4 5 6 7 8 9
breaker = ( { :point => {:en => 'near', :fr => 'proximite'}, :street => {:en => 'on', :fr => 'sur'} }[location_type] || {:en => 'in', :fr => 'dans'} # default )[lang] # Crazy Short version breaker = ({:point => %w(near proximite), :street => %w(on sur)}[location_type] || %w(in dans))[lang.to_s <=> "en"]
With all the magic surrounding ruby I can't help but think that there are shorter and more readable ways to do this.