2017-07-09 08:06:36 -04:00
|
|
|
# frozen_string_literal: true
|
2017-06-30 01:00:04 -04:00
|
|
|
require_relative "../core_ext/string/multibyte"
|
|
|
|
require_relative "../i18n"
|
2009-11-07 14:23:21 -05:00
|
|
|
|
|
|
|
module ActiveSupport
|
|
|
|
module Inflector
|
2010-04-14 10:12:07 -04:00
|
|
|
# Replaces non-ASCII characters with an ASCII approximation, or if none
|
|
|
|
# exists, a replacement character which defaults to "?".
|
|
|
|
#
|
2012-09-12 14:46:33 -04:00
|
|
|
# transliterate('Ærøskøbing')
|
2010-04-14 10:12:07 -04:00
|
|
|
# # => "AEroskobing"
|
|
|
|
#
|
|
|
|
# Default approximations are provided for Western/Latin characters,
|
|
|
|
# e.g, "ø", "ñ", "é", "ß", etc.
|
|
|
|
#
|
|
|
|
# This method is I18n aware, so you can set up custom approximations for a
|
|
|
|
# locale. This can be useful, for example, to transliterate German's "ü"
|
|
|
|
# and "ö" to "ue" and "oe", or to add support for transliterating Russian
|
|
|
|
# to ASCII.
|
|
|
|
#
|
|
|
|
# In order to make your custom transliterations available, you must set
|
|
|
|
# them as the <tt>i18n.transliterate.rule</tt> i18n key:
|
|
|
|
#
|
|
|
|
# # Store the transliterations in locales/de.yml
|
|
|
|
# i18n:
|
|
|
|
# transliterate:
|
2010-05-03 09:25:28 -04:00
|
|
|
# rule:
|
2010-05-03 09:16:38 -04:00
|
|
|
# ü: "ue"
|
|
|
|
# ö: "oe"
|
2010-04-14 10:12:07 -04:00
|
|
|
#
|
|
|
|
# # Or set them using Ruby
|
2012-09-12 14:46:33 -04:00
|
|
|
# I18n.backend.store_translations(:de, i18n: {
|
|
|
|
# transliterate: {
|
|
|
|
# rule: {
|
|
|
|
# 'ü' => 'ue',
|
|
|
|
# 'ö' => 'oe'
|
2010-04-14 10:12:07 -04:00
|
|
|
# }
|
|
|
|
# }
|
|
|
|
# })
|
|
|
|
#
|
2012-09-14 23:44:06 -04:00
|
|
|
# The value for <tt>i18n.transliterate.rule</tt> can be a simple Hash that
|
|
|
|
# maps characters to ASCII approximations as shown above, or, for more
|
|
|
|
# complex requirements, a Proc:
|
2010-04-14 10:12:07 -04:00
|
|
|
#
|
2012-09-12 14:46:33 -04:00
|
|
|
# I18n.backend.store_translations(:de, i18n: {
|
|
|
|
# transliterate: {
|
2012-09-14 23:44:06 -04:00
|
|
|
# rule: ->(string) { MyTransliterator.transliterate(string) }
|
2010-04-14 10:12:07 -04:00
|
|
|
# }
|
|
|
|
# })
|
|
|
|
#
|
|
|
|
# Now you can have different transliterations for each locale:
|
|
|
|
#
|
|
|
|
# I18n.locale = :en
|
2012-09-12 14:46:33 -04:00
|
|
|
# transliterate('Jürgen')
|
2010-04-14 10:12:07 -04:00
|
|
|
# # => "Jurgen"
|
|
|
|
#
|
|
|
|
# I18n.locale = :de
|
2012-09-12 14:46:33 -04:00
|
|
|
# transliterate('Jürgen')
|
2010-04-14 10:12:07 -04:00
|
|
|
# # => "Juergen"
|
2015-07-26 14:59:12 -04:00
|
|
|
def transliterate(string, replacement = "?".freeze)
|
2017-01-16 13:49:44 -05:00
|
|
|
raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
|
|
|
|
|
2010-05-10 09:46:37 -04:00
|
|
|
I18n.transliterate(ActiveSupport::Multibyte::Unicode.normalize(
|
|
|
|
ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
|
2016-08-06 13:38:33 -04:00
|
|
|
replacement: replacement)
|
2009-11-07 14:23:21 -05:00
|
|
|
end
|
|
|
|
|
2012-09-14 23:44:06 -04:00
|
|
|
# Replaces special characters in a string so that it may be used as part of
|
|
|
|
# a 'pretty' URL.
|
2009-11-07 14:23:21 -05:00
|
|
|
#
|
2015-01-03 20:44:16 -05:00
|
|
|
# parameterize("Donald E. Knuth") # => "donald-e-knuth"
|
|
|
|
# parameterize("^trés|Jolie-- ") # => "tres-jolie"
|
2015-10-07 08:16:38 -04:00
|
|
|
#
|
|
|
|
# To use a custom separator, override the `separator` argument.
|
|
|
|
#
|
|
|
|
# parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
|
|
|
|
# parameterize("^trés|Jolie-- ", separator: '_') # => "tres_jolie"
|
|
|
|
#
|
|
|
|
# To preserve the case of the characters in a string, use the `preserve_case` argument.
|
|
|
|
#
|
|
|
|
# parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
|
|
|
|
# parameterize("^trés|Jolie-- ", preserve_case: true) # => "tres-Jolie"
|
|
|
|
#
|
2016-11-14 07:14:23 -05:00
|
|
|
def parameterize(string, separator: "-", preserve_case: false)
|
2015-10-07 17:43:58 -04:00
|
|
|
# Replace accented chars with their ASCII equivalents.
|
2009-11-07 14:23:21 -05:00
|
|
|
parameterized_string = transliterate(string)
|
2015-10-07 17:43:58 -04:00
|
|
|
|
|
|
|
# Turn unwanted chars into the separator.
|
2015-10-07 08:16:38 -04:00
|
|
|
parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
|
2015-10-07 17:43:58 -04:00
|
|
|
|
2015-10-07 08:16:38 -04:00
|
|
|
unless separator.nil? || separator.empty?
|
|
|
|
if separator == "-".freeze
|
2015-09-18 05:41:26 -04:00
|
|
|
re_duplicate_separator = /-{2,}/
|
2015-07-26 14:59:12 -04:00
|
|
|
re_leading_trailing_separator = /^-|-$/i
|
|
|
|
else
|
2015-10-07 08:16:38 -04:00
|
|
|
re_sep = Regexp.escape(separator)
|
2015-09-18 05:41:26 -04:00
|
|
|
re_duplicate_separator = /#{re_sep}{2,}/
|
2015-07-26 14:59:12 -04:00
|
|
|
re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
|
|
|
|
end
|
2009-11-07 14:23:21 -05:00
|
|
|
# No more than one of the separator in a row.
|
2015-10-07 08:16:38 -04:00
|
|
|
parameterized_string.gsub!(re_duplicate_separator, separator)
|
2009-11-07 14:23:21 -05:00
|
|
|
# Remove leading/trailing separator.
|
2016-08-06 11:58:50 -04:00
|
|
|
parameterized_string.gsub!(re_leading_trailing_separator, "".freeze)
|
2009-11-07 14:23:21 -05:00
|
|
|
end
|
2016-08-06 13:55:02 -04:00
|
|
|
|
2015-10-07 08:16:38 -04:00
|
|
|
parameterized_string.downcase! unless preserve_case
|
2015-07-26 14:59:12 -04:00
|
|
|
parameterized_string
|
2010-04-12 11:44:25 -04:00
|
|
|
end
|
2009-11-07 14:23:21 -05:00
|
|
|
end
|
2010-04-04 02:03:41 -04:00
|
|
|
end
|