Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h1>TL;DR</h1> <p>This is the kind of things I hate to do over and over again (I'm serving french users, they're easily confused with dots as the decimal separator).</p> <p>I exclusively use the <a href="https://github.com/clemens/delocalize" rel="noreferrer">delocalize gem</a> now, which does the format translation automatically for you. You just have to install the gem and leave your forms as-is, everything should be taken care of for you.</p> <h1>I like to read, give me the long explanation</h1> <p>The basic conversion is quite simple, you have to convert back and forth between the following formats:</p> <ul> <li><p>The backend one, which is usually English, used by your persistent storage (SQL database, NoSQL store, YAML, flat text file, whatever struck your fancy, ...).</p></li> <li><p>The frontend one, which is whatever format your user prefers. I'm going to use French here to stick to the question<sup>*</sup>.</p></li> </ul> <p><sub>* also because I'm quite partial towards it ;-)</sub></p> <p>This means that you have two points where you need to do a conversion:</p> <ol> <li><p><strong>Outbound</strong>: when outputting your HTML, you will need to convert from English to French.</p></li> <li><p><strong>Inbound</strong>: When processing the result of the form POST, you will need to convert back from French to English.</p></li> </ol> <h2>The manual way</h2> <p>Let's say I have the following model, with the <code>rate</code> field as a decimal number with a precision of 2 (eg. <code>19.60</code>):</p> <pre><code>class Tax &lt; ActiveRecord::Base # the attr_accessor isn't really necessary here, I just want to show that there's a database field attr_accessor :rate end </code></pre> <p>The <strong>outbound</strong> conversion step (English => French) can be done by overriding <code>text_field_tag</code>:</p> <pre><code>ActionView::Helpers::FormTagHelper.class_eval do include ActionView::Helpers::NumberHelper alias original_text_field_tag text_field_tag def text_field_tag(name, value = nil, options = {}) value = options.delete(:value) if options.key?(:value) if value.is_a?(Numeric) value = number_with_delimiter(value) # this method uses the current locale to format our value end original_text_field_tag(name, value, options) end end </code></pre> <p>The <strong>inbound</strong> conversion step (French => English) will be handled in the model. We will override the <code>rate</code> attribute writer to replace every French separator with the English one:</p> <pre><code>class Tax &lt; ActiveRecord::Base def rate=(rate) write_attribute(:rate, rate.gsub(I18n.t('number.format.separator'), '.') end end </code></pre> <p>This look nice because there's only one attribute in the example and one type of data to parse, but imagine having to do this for every number, date or time field in your model. That's not my idea of fun.</p> <p>This also is a naïve<sup>*</sup> way of doing the conversions, it does not handle:</p> <ul> <li>Dates</li> <li>Times</li> <li>Delimiters (eg. <code>100,000.84</code>)</li> </ul> <p><sub>* did I already tell you I like French?</sub></p> <h2>Enter delocalize</h2> <p><a href="https://github.com/clemens/delocalize" rel="noreferrer">Delocalize</a> is working on the same principle I outlined above, but does the job much more comprehensively:</p> <ul> <li>It handles <code>Date</code>, <code>Time</code>, <code>DateTime</code> and numbers.</li> <li>You don't have to do anything, just install the gem. It checks your ActiveRecord columns to determine if it's a type that needs conversion and does it automatically.</li> <li>The number conversions are pretty straightforward, but the date ones are really interesting. When parsing the result of a form, it will try the date formats defined in your locale file in descending order and should be able to understand a date formatted like this: <code>15 janvier 2012</code>.</li> <li>Every outbound conversion will be done automatically.</li> <li>It's tested.</li> <li>It's active.</li> </ul> <p>One caveat though: it doesn't handle client-side validations. If you're using them, you will have to figure out how to use i18n in your favourite JavaScript framework.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload