Class: Kotoshu::Language::Normalizer::Arabic

Inherits:
Base
  • Object
show all
Defined in:
lib/kotoshu/language/normalizer/arabic.rb

Overview

Normalizer for Arabic script.

Arabic has many presentation forms (the U+FE70..U+FEFF Arabic Presentation Forms-A block plus the FB50..FDFF / FE70..FEFF blocks for Presentation Forms-B) that look the same to a reader but are distinct codepoints. Input text often arrives in any of these forms depending on the source editor — same word can be encoded three different ways and not match a dictionary lookup. This normalizer canonicalizes them all to the base U+0621..U+064A range.

Also handles:

  • NFC composition (combines base + combining marks).
  • Optional diacritic (tashkeel) stripping for spell checking — Modern Standard Arabic is typically written without diacritics; the dictionary stores bare forms.
  • Tatweel (U+0640) removal — a decorative elongation mark that creates variants of the same word.

Examples:

Default (strip diacritics)

norm = Arabic.new
norm.normalize_word("كِتَابٌ")  # => "كتاب"

Direct Known Subclasses

Persian

Constant Summary collapse

PRESENTATION_FORM_MAP =

Arabic Presentation Forms-A and Forms-B codepoints that have a base-form equivalent in the U+0621..U+064A range. Ruby's String#unicode_normalize(:nfc) handles the composition for most pairs; the legacy Presentation Forms-B range (FE70..FEFF) needs an explicit table because NFC doesn't cover it.

{
  "" => "ا", "" => "ا",
  "" => "ب", "" => "ب", "" => "ب", "" => "ة",
  "" => "ت", "" => "ت", "" => "ت", "" => "ث",
  "" => "ث", "" => "ث", "" => "ج", "" => "ج",
  "" => "ج", "" => "ح", "" => "ح", "" => "ح",
  "" => "خ", "" => "خ", "" => "خ", "" => "د",
  "" => "د", "" => "ذ", "" => "ذ", "" => "ر",
  "" => "ر", "" => "ز", "" => "ز", "" => "س",
  "" => "س", "" => "س", "" => "ش", "" => "ش",
  "" => "ش", "" => "ص", "" => "ص", "" => "ص",
  "" => "ض", "ﺿ" => "ض", "" => "ض", "" => "ط",
  "" => "ط", "" => "ط", "" => "ظ", "" => "ظ",
  "" => "ظ", "" => "ع", "" => "ع", "" => "ع",
  "" => "غ", "" => "غ", "" => "غ", "" => "ف",
  "" => "ف", "" => "ف", "" => "ق", "" => "ق",
  "" => "ق", "" => "ك", "" => "ك", "" => "ك",
  "" => "ل", "" => "ل", "" => "ل", "" => "م",
  "" => "م", "" => "م", "" => "ن", "" => "ن",
  "" => "ن", "" => "ه", "" => "ه", "" => "ه",
  "" => "و", "" => "و", "" => "ي", "" => "ي",
  "" => "ي", "" => "آ", "" => "آ", "" => "أ",
  "" => "أ", "" => "إ", "" => "إ", "" => "لا",
  "" => "لا"
}.freeze
DIACRITICS =

Arabic diacritics (tashkeel) — harakat, tanwin, shaddah, sukun, dagger alef. Stripped for spell-checking since the dictionary stores bare forms.

/[ؐ-ًؚ-ٰٟۖ-ۜ۟-ۤۧ-۪ۨ-ۭ]/
TATWEEL =

Tatweel (kashida) — decorative horizontal elongation.

"ـ"

Instance Method Summary collapse

Methods inherited from Base

#normalized_eql?

Constructor Details

#initialize(strip_diacritics: true, strip_tatweel: true) ⇒ Arabic

Returns a new instance of Arabic.

Parameters:

  • strip_diacritics (Boolean) (defaults to: true)

    default true. When true, tashkeel (vowel points) are removed before lookup.

  • strip_tatweel (Boolean) (defaults to: true)

    default true. When true, tatweel elongation marks are removed.



73
74
75
76
# File 'lib/kotoshu/language/normalizer/arabic.rb', line 73

def initialize(strip_diacritics: true, strip_tatweel: true)
  @strip_diacritics = strip_diacritics
  @strip_tatweel = strip_tatweel
end

Instance Method Details

#normalize(text, _options = {}) ⇒ String

Normalize text: NFC + presentation-form canonicalization + optional diacritic/tatweel stripping. Skips the Base class's downcase step because Arabic has no case.

Parameters:

  • text (String)
  • _options (Hash) (defaults to: {})

    ignored (Arabic has no case to fold)

Returns:

  • (String)


85
86
87
88
89
90
91
92
93
# File 'lib/kotoshu/language/normalizer/arabic.rb', line 85

def normalize(text, _options = {})
  return "" if text.nil? || text.empty?

  result = text.unicode_normalize(:nfc)
  result = canonicalize_presentation_forms(result)
  result = result.gsub(DIACRITICS, "") if @strip_diacritics
  result = result.delete(TATWEEL) if @strip_tatweel
  result.strip
end

#normalize_word(word) ⇒ Object

Normalize a word: same as normalize but operates on a single token. Arabic words don't need different treatment.



97
98
99
# File 'lib/kotoshu/language/normalizer/arabic.rb', line 97

def normalize_word(word)
  normalize(word)
end