Class: Kotoshu::Language::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/language/registry.rb

Overview

Central registry for language registration and retrieval.

Uses Registry pattern for dynamic language discovery and management. Languages register themselves on load, making the system extensible.

Examples:

Register a language

Kotoshu::Language::Registry.register("en-US", English::American)

Retrieve a language

lang = Kotoshu::Language::Registry.get("en-US")

List supported languages

codes = Kotoshu::Language::Registry.supported_codes

Class Method Summary collapse

Class Method Details

.allHash

Get all registered language classes.

Returns:

  • (Hash)

    Hash mapping codes to classes



97
98
99
100
# File 'lib/kotoshu/language/registry.rb', line 97

def all
  ensure_languages_loaded
  @languages.dup
end

.clearvoid

This method returns an undefined value.

Clear all registrations (mainly for testing).

Marks the registry as loaded so ensure_languages_loaded does not re-populate from autoloaded language files. Tests rely on clear producing an actually-empty registry. Pair with restore_autoload! in an after(:all) hook so the registry is repopulated for specs that depend on it.



143
144
145
146
147
# File 'lib/kotoshu/language/registry.rb', line 143

def clear
  @languages.clear
  @detectors.clear
  @languages_loaded = true
end

.detect(text) ⇒ String?

Detect language from text.

Tries registered detectors in order.

Parameters:

  • text (String)

    Text to analyze

Returns:

  • (String, nil)

    Detected language code or nil



123
124
125
126
127
128
129
130
131
132
# File 'lib/kotoshu/language/registry.rb', line 123

def detect(text)
  return nil if text.nil? || text.empty?

  @detectors.each do |detector|
    result = detector.detect(text)
    return result if result
  end

  nil
end

.ensure_languages_loadedvoid

This method returns an undefined value.

Trigger load of every per-language implementation in Kotoshu::Languages. Each language file calls Registry.register at file-load time, so loading all constants fully populates the registry. Safe to call multiple times.



108
109
110
111
112
113
114
115
# File 'lib/kotoshu/language/registry.rb', line 108

def ensure_languages_loaded
  return if @languages_loaded

  # Reference Kotoshu::Languages to trigger autoload of the
  # namespace file, which sets up per-language autoloads.
  Kotoshu::Languages.constants.each { |c| Kotoshu::Languages.const_get(c) }
  @languages_loaded = true
end

.get(code) ⇒ Class?

Get language class by code.

Supports fallback to base language if variant not found. Also supports finding variants when asking for base language. For example:

  • "en-GB" falls back to "en" if "en-GB" not registered
  • "en" returns "en-US" if only "en-US" is registered

Parameters:

  • code (String)

    Language code

Returns:

  • (Class, nil)

    Language class or nil if not found



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/kotoshu/language/registry.rb', line 55

def get(code)
  return nil unless code

  ensure_languages_loaded

  # Try exact match first
  return @languages[code] if @languages.key?(code)

  base = code.split('-').first

  # If code has a hyphen (e.g., "en-GB"), try base language
  if code.include?('-')
    return @languages[base]
  end

  # If code is base language (e.g., "en"), find any variant
  @languages.each do |registered_code, klass|
    return klass if registered_code.split('-').first == base
  end

  nil
end

.info(code) ⇒ Hash?

Get language info by code.

Parameters:

  • code (String)

    Language code

Returns:

  • (Hash, nil)

    Language info or nil



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/kotoshu/language/registry.rb', line 181

def info(code)
  klass = get(code)
  return nil unless klass

  # Every registered language class inherits from Language::Base,
  # which provides the .instance singleton accessor. The type
  # bound is the contract; the respond_to? check it replaced
  # would have silently returned a fresh instance for any
  # stray non-Base class that happened to be registered.
  instance = if klass.is_a?(Class) && klass <= Kotoshu::Language::Base
               klass.instance
             else
               klass.new
             end

  {
    code: code,
    name: instance.name,
    variant: instance.variant,
    region: instance.region,
    encoding: instance.encoding,
    rtl?: instance.rtl?,
    script_type: instance.script_type
  }
end

.register(code, language_class) ⇒ void

This method returns an undefined value.

Register a language class with its code.

Examples:

Registry.register("en-US", English::American)

Parameters:

  • code (String)

    Language code (e.g., "en-US", "de-DE")

  • language_class (Class)

    Class implementing Kotoshu::Language::Base



31
32
33
# File 'lib/kotoshu/language/registry.rb', line 31

def register(code, language_class)
  @languages[code] = language_class
end

.register_detector(detector) ⇒ void

This method returns an undefined value.

Register a detector for auto-detection.

Detectors are tried in order of registration.

Parameters:

  • detector (#detect)

    Object with detect method



41
42
43
# File 'lib/kotoshu/language/registry.rb', line 41

def register_detector(detector)
  @detectors << detector
end

.registered?(code) ⇒ Boolean

Check if a language is registered.

Parameters:

  • code (String)

    Language code

Returns:

  • (Boolean)

    True if registered



82
83
84
# File 'lib/kotoshu/language/registry.rb', line 82

def registered?(code)
  !get(code).nil?
end

.restore_autoload!void

This method returns an undefined value.

Re-enable lazy autoload of per-language implementations after a clear, then replay the registration of every loaded per-language class. File-level register calls only fire once (Ruby autoload runs each file exactly once), so the replay walks the already-loaded constants and re-issues register from each class's registered_codes list.

Intended for test-suite cleanup so one spec's clear does not leak an empty registry into unrelated specs.



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/kotoshu/language/registry.rb', line 160

def restore_autoload!
  @languages_loaded = false
  return if @replaying

  @replaying = true
  begin
    Kotoshu::Languages.constants.each do |c|
      klass = Kotoshu::Languages.const_get(c)
      next unless klass.is_a?(Class) && (klass < Kotoshu::Language::Base)

      klass.registered_codes.each { |code| register(code, klass) }
    end
  ensure
    @replaying = false
  end
end

.supported_codesArray<String>

Get all supported language codes.

Returns:

  • (Array<String>)

    Sorted list of language codes



89
90
91
92
# File 'lib/kotoshu/language/registry.rb', line 89

def supported_codes
  ensure_languages_loaded
  @languages.keys.sort
end