Module: Pressroom::Transliteration

Defined in:
lib/pressroom/transliteration.rb

Overview

Transliteration rules the gem carries itself.

These cannot live in locale files alone. I18n leaves a locale out of available_locales when its data holds nothing but an :i18n key, which is exactly the shape of a transliteration-rules file, and I18n.transliterate then rejects that locale. Padding the files with a filler key would fix the lookup but would also push :ru and :uk into the host application's available_locales, which is not this gem's business.

So: when the locale really is one of the host's, its own rules win -- including the YAML this gem ships, which the host picks up automatically in that case. Otherwise these tables are used directly.

Constant Summary collapse

RULES =
{
  ru: {
    "а" => "a",
    "б" => "b",
    "в" => "v",
    "г" => "g",
    "д" => "d",
    "е" => "e",
    "ё" => "e",
    "ж" => "zh",
    "з" => "z",
    "и" => "i",
    "й" => "i",
    "к" => "k",
    "л" => "l",
    "м" => "m",
    "н" => "n",
    "о" => "o",
    "п" => "p",
    "р" => "r",
    "с" => "s",
    "т" => "t",
    "у" => "u",
    "ф" => "f",
    "х" => "h",
    "ц" => "ts",
    "ч" => "ch",
    "ш" => "sh",
    "щ" => "sch",
    "ъ" => "",
    "ы" => "y",
    "ь" => "",
    "э" => "e",
    "ю" => "yu",
    "я" => "ya",
    "А" => "A",
    "Б" => "B",
    "В" => "V",
    "Г" => "G",
    "Д" => "D",
    "Е" => "E",
    "Ё" => "E",
    "Ж" => "Zh",
    "З" => "Z",
    "И" => "I",
    "Й" => "I",
    "К" => "K",
    "Л" => "L",
    "М" => "M",
    "Н" => "N",
    "О" => "O",
    "П" => "P",
    "Р" => "R",
    "С" => "S",
    "Т" => "T",
    "У" => "U",
    "Ф" => "F",
    "Х" => "H",
    "Ц" => "Ts",
    "Ч" => "Ch",
    "Ш" => "Sh",
    "Щ" => "Sch",
    "Ъ" => "",
    "Ы" => "Y",
    "Ь" => "",
    "Э" => "E",
    "Ю" => "Yu",
    "Я" => "Ya",
  }.freeze,
  uk: {
    "а" => "a",
    "б" => "b",
    "в" => "v",
    "г" => "h",
    "ґ" => "g",
    "д" => "d",
    "е" => "e",
    "є" => "ie",
    "ж" => "zh",
    "з" => "z",
    "и" => "y",
    "і" => "i",
    "ї" => "i",
    "й" => "i",
    "к" => "k",
    "л" => "l",
    "м" => "m",
    "н" => "n",
    "о" => "o",
    "п" => "p",
    "р" => "r",
    "с" => "s",
    "т" => "t",
    "у" => "u",
    "ф" => "f",
    "х" => "kh",
    "ц" => "ts",
    "ч" => "ch",
    "ш" => "sh",
    "щ" => "shch",
    "ь" => "",
    "ю" => "iu",
    "я" => "ia",
    "А" => "A",
    "Б" => "B",
    "В" => "V",
    "Г" => "H",
    "Ґ" => "G",
    "Д" => "D",
    "Е" => "E",
    "Є" => "Ie",
    "Ж" => "Zh",
    "З" => "Z",
    "И" => "Y",
    "І" => "I",
    "Ї" => "I",
    "Й" => "I",
    "К" => "K",
    "Л" => "L",
    "М" => "M",
    "Н" => "N",
    "О" => "O",
    "П" => "P",
    "Р" => "R",
    "С" => "S",
    "Т" => "T",
    "У" => "U",
    "Ф" => "F",
    "Х" => "Kh",
    "Ц" => "Ts",
    "Ч" => "Ch",
    "Ш" => "Sh",
    "Щ" => "Shch",
    "Ь" => "",
    "Ю" => "Iu",
    "Я" => "Ia",
  }.freeze
}.freeze
CYRILLIC =
/\p{Cyrillic}/
UKRAINIAN_ONLY =
/[іїєґІЇЄҐ]/

Class Method Summary collapse

Class Method Details

.call(string, locale) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/pressroom/transliteration.rb', line 160

def call(string, locale)
  string = string.to_s
  key = locale.to_s.to_sym
  result = transliterate(string, key)

  cyrillic = string.scan(CYRILLIC).join
  return result if cyrillic.empty?

  # Judge the Cyrillic characters on their own. A title like
  # "Как устроен Rails" keeps its Latin word under any locale, so
  # looking at the whole result would wrongly suggest the locale
  # coped.
  return result if usable?(transliterate(cyrillic, key))

  # The configured locale has no rules for this script -- an
  # English-locale application with a Russian article, which is the
  # common case rather than the exotic one. Falling back to the
  # script's own rules beats an empty slug that numbers every article
  # post-2, post-3, post-4.
  transliterate(string, detect_script(string))
end