#48 ✓resolved
Josh H

Conforming Validation Code to i18n

Reported by Josh H | November 7th, 2007 @ 09:15 PM

It's really cool that DataMapper includes support for localization in the validation code. A group of developers of Rails i18n plugins is working on a standard API for i18n plugins for Rails, and we've got a proposal for doing validation translation in Rails that looks a lot like what DataMapper has, but with slightly different syntax.

I think it would be great if the API embraced other ORMs like DataMapper too, and if DataMapper conformed to the as-of-yet unpublished i18n API. It's mostly a matter of changing the String interpolation syntax. I'd be glad to fill in you with the details and maybe have you join our discussion if you're interested.

Josh Harvey

Globalize for Rails



Comments and changes to this ticket

  • Sam Smoot

    Sam Smoot November 8th, 2007 @ 12:15 AM

    • State changed from “new” to “open”

    Sounds great. Contact me any time by gmail (account: ssmoot) or in the #datamapper IRC channel. I'm really curious to find out what syntax differences you guys came together on, and if it might work for DataMapper.

  • Sam Smoot

    Sam Smoot December 28th, 2007 @ 10:49 PM

    Josh, any news on a final API? I'm hoping to ping Jay on this in the next few days, and it would be great to bring this stuff to his attention.

  • Josh H

    Josh H December 29th, 2007 @ 09:02 AM

    It's almost done, and probably all the questions relevant to validation code are settled. I sent you an invite to the i18n patch google group.

    Basically, the idea is to use symbols, with a #.t method which receives any necessary arguments. String interpolation is done with @{{}}@, as in liquid (but this is only present in the translations, not in the symbols). Pluralization is done by passing an integer to #.t. Translations are stored in YAML files.

    I'd be happy to elaborate.


  • Josh H

    Josh H December 29th, 2007 @ 09:04 AM

    The interpolation syntax is {{replace_me}}, without the @ characters.

  • Sam Smoot

    Sam Smoot December 29th, 2007 @ 11:09 AM

    Josh, thanks for the invite, I'll take a good long look at it. :-)

    Right off the bat I have a question though... how do you manage reordering position of arguments? Do you pass a Hash to #t?


    "{{attribute}} must be at least {{min}} characters long".t(
      :attribute => "name",
      :min => 5

    The performance of using a Hash for arguments vs a sprintf concerns me a bit, but it might not be a big deal I suppose.

  • Josh H

    Josh H December 29th, 2007 @ 11:21 AM

    Yep, you'd use a Hash. Passing ordered arguments would be very problematic for i18n, since the order of the arguments might be different in different languages. I think any small performance hit would be justified in supporting multiple translations. I also think the actual translation would dwarf the performance hit of sprintf vs hash.

    Since we'd be using symbols, the way we'd do this is:

    :too_short.t 5, :attribute => "name"

    The actual translation ("{attribute}} must be at least {{count}} characters long") would be supplied in the YAML file. (There would probably be another version for count == 1: "{attribute}} must be at least one character long".)

  • Sam Smoot

    Sam Smoot December 29th, 2007 @ 11:00 PM

    Ahh, you're right about the performance worry of course. Non issue I'm sure.

    Gotta say, I'm not really a fan of Symbol#t vs String#t, but I'll live I suppose.

    I would prefer it if we ended up supporting both. I could imagine strong arguments either way. Of course I'm sure you have more experience putting this stuff into practice, but that's my humble suggestion. :-)

    Agree about the ordering of arguments being different for different languages. That's why I suggested sprintf. Perhaps like me until a couple months ago when wycats showed me, you're unaware that sprintf can reorder arguments?

    In the existing DM code:

    # Formats String for easy translation. Replaces an arbitrary number of 
    # values using numeric identifier replacement.
    #   "%s %s %s" % %w(one two three) #=> "one two three"
    #   "%3$s %2$s %1$s" % %w(one two three) #=> "three two one"
    def t(*values)
      self.class::translate(self) % values

    This was just a quick idea of how it might be done. I'm sure your group's version has had a lot more peer review, so don't think I'm suggesting this is a superior method. Just an idea you might not have been aware of? Or just as likely... you dismissed for some good reason that hasn't occurred to me yet. :-)

    I've gotta admit, I'm not the biggest fan of the reordering syntax. Then again, it scores big points with me that it's built right into Ruby, no additional effort required.

  • Josh H

    Josh H December 30th, 2007 @ 02:28 AM

    Thanks for the thoughtful comments, Sam. The truth is we had bloody battles on the symbol vs string thing, and a few people (like me) changed to the symbol side in the end. I also didn't mention that String is also supported, mostly because we want to encourage the Symbol syntax, especially for all "official" stuff. If you're not convinced on the Symbol thing, I'd be glad to dig up our discussions on it and try to convince you :).

    We took a look at the sprintf syntax, but we decided it's just too confusing to keep track of which terms map to which numbers, and we wanted to stick with the hash syntax. Also, as you noted, the syntax itself is damn confusing.

  • Dan Kubb (dkubb)
  • Sam Smoot
  • Dan Kubb (dkubb)

    Dan Kubb (dkubb) November 30th, 2008 @ 02:25 AM

    • Milestone cleared.
    • State changed from “open” to “resolved”
    • Assigned user cleared.

    I know there's been some discussion in Lighthouse on this, but the last comment was almost a year ago, and there hasn't been any activity since.

    Perhaps this would be something more appropriate for the mailing list? I'm sure the Ruby i18n landscape has changed quite a bit with Rails adding an i18n layer, and Merb planning to at some point. Opening up the discussion on the mailing list might be a better place to get the ball rolling on this if anyone is interested in taking this up.

    For now I'm going to close this, but once we figure out the precise steps or things that need to change in DM we can open tickets for those specific tasks/issues later.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »