Ответ 1
TL; DR
Это то, что мне не нравится делать снова и снова (я служу французским пользователям, их легко путать с точками как разделитель с десятичной запятой).
Я использую delocalize gem, который автоматически преобразует формат для вас. Вам просто нужно установить драгоценный камень и оставить свои формы как есть, все должно заботиться о вас.
Мне нравится читать, дайте мне длинное объяснение
Базовое преобразование довольно простое, вам нужно конвертировать туда и обратно между следующими форматами:
-
Бэкэнд, который обычно используется на английском языке, используется вашим постоянным хранилищем (база данных SQL, хранилище NoSQL, YAML, текстовый файл, все, что поразило ваше воображение,...).
-
Внешний интерфейс, который является тем форматом, который предпочитает ваш пользователь. Я собираюсь использовать французский здесь, чтобы придерживаться вопроса *.
* также потому, что я отношусь к нему частично, -)
Это означает, что у вас есть две точки, где вам нужно сделать преобразование:
-
Исходящие: при выводе вашего HTML вам нужно будет преобразовать с английского языка на французский.
-
Входящие. При обработке результата формы POST вам нужно будет перевести обратно с французского на английский.
Ручной способ
Скажем, у меня есть следующая модель с полем rate
как десятичное число с точностью 2 (например, 19.60
):
class Tax < ActiveRecord::Base
# the attr_accessor isn't really necessary here, I just want to show that there a database field
attr_accessor :rate
end
Шаг преобразования исходящий (английский = > французский) можно сделать, переопределив text_field_tag
:
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
В модели будет обрабатываться шаг входящего преобразования (французский = > английский). Мы заменим атрибут атрибута rate
, чтобы заменить каждый французский разделитель на английский:
class Tax < ActiveRecord::Base
def rate=(rate)
write_attribute(:rate, rate.gsub(I18n.t('number.format.separator'), '.')
end
end
Это выглядит хорошо, потому что в этом примере используется только один атрибут и один тип данных для анализа, но представьте, что вам нужно сделать это для каждого числа, даты или времени в вашей модели. Это не моя идея веселья.
Это также наивный способ выполнения конверсий * который не обрабатывается:
- Даты
- Времена
- Разделители (например,
100,000.84
)
* Я уже говорил, что мне нравится французский?
Введите делокализацию
Delocalize работает над тем же принципом, который я изложил выше, но делает работу гораздо более всесторонне:
- Он обрабатывает
Date
,Time
,DateTime
и числа. - Вам не нужно ничего делать, просто установите драгоценный камень. Он проверяет ваши столбцы ActiveRecord, чтобы определить, является ли он типом, который нуждается в преобразовании, и делает это автоматически.
- Конверсии чисел довольно просты, но даты действительно интересны. При анализе результата формы он будет пытаться использовать формат даты, определенный в вашем файле локали, в порядке убывания и должен понимать дату, отформатированную следующим образом:
15 janvier 2012
. - Каждое исходящее преобразование будет выполнено автоматически.
- Он протестирован.
- Он активен.
Одно предупреждение: оно не обрабатывает проверки на стороне клиента. Если вы используете их, вам нужно будет выяснить, как использовать i18n в своей любимой структуре JavaScript.