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's 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
Это выглядит хорошо, потому что в примере есть только один атрибут и один тип данных для анализа, но представьте, чтосделать это для каждого поля числа, даты или времени в вашей модели.Это не мое представление о веселье.
Это также наивный * способ делать преобразования, он не обрабатывает:
- Даты
- Times
- Разделители (например,
100,000.84
)
* я уже говорил вам, что мне нравится французский?
Введите delocalize
Делокализация работает по тому же принципу, который я изложил выше, но выполняет работу гораздо более всесторонне:
- Он обрабатывает
Date
, Time
,DateTime
и цифры. - Вам не нужно ничего делать, просто установите драгоценный камень.Он проверяет ваши столбцы ActiveRecord, чтобы определить, требуется ли преобразование этого типа, и выполняет это автоматически.
- Преобразования чисел довольно просты, но даты действительно интересны.При анализе результата формы он будет пытаться использовать форматы даты, определенные в вашем файле локали, в порядке убывания и должен понимать дату, отформатированную следующим образом:
15 janvier 2012
. - Будет выполняться каждое исходящее преобразование.автоматически.
- Он проверен.
- Он активен.
Одно предупреждение: он не обрабатывает проверки на стороне клиента.Если вы используете их, вам придется выяснить, как использовать i18n в вашей любимой среде JavaScript.