Module: Linguistics

Extended by:
Loggability
Includes:
ISO639
Defined in:
lib/linguistics.rb,
lib/linguistics/monkeypatches.rb

Overview

An interface for extending core Ruby classes with natural-language methods.

Defined Under Namespace

Modules: ArrayExtensions, EN, ISO639 Classes: Inflector

Constant Summary collapse

VERSION =

Release version

'2.0.2'
REVISION =

VCS version

%q$Revision: d2eeec0b7832 $
DEFAULT_EXT_CLASSES =

The list of Classes to add linguistic behaviours to.

[ String, Numeric, Array ]

Constants included from ISO639

ISO639::LANGUAGE_CODES

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.inflector_mixinsObject (readonly)

The Hash of anonymous inflector modules that act as the mixin interface to a language module’s inflector, keyed by the language module they belong to



46
47
48
# File 'lib/linguistics.rb', line 46

def inflector_mixins
  @inflector_mixins
end

.languagesObject (readonly)

The Hash of loaded languages keyed by 3-letter bibliographic ISO639-2 code



42
43
44
# File 'lib/linguistics.rb', line 42

def languages
  @languages
end

Class Method Details

.load_language(lang) ⇒ Object

Try to load the module that implements the given language, returning the Module object if successful.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/linguistics.rb', line 89

def self::load_language( lang )
	unless mod = self.languages[ lang.to_sym ]

		self.log.debug "Trying to load language %p" % [ lang ]
		language = LANGUAGE_CODES[ lang.to_sym ] or
			raise "Unknown ISO639-2 language code '#{lang}'"
		self.log.debug "  got language code %p" % [ language ]

		# Sort all the codes for the specified language, trying the 2-letter
		# versions first in alphabetical order, then the 3-letter ones
		msgs = []
		mod = nil

		language[:codes].sort.each do |code|
			next if code == ''

			begin
				require "linguistics/#{code}"
				self.log.debug "  loaded linguistics/#{code}!"
				mod = self.languages[ lang.to_sym ]
				self.log.debug "  set mod to %p" % [ mod ]
				break
			rescue LoadError => err
				self.log.error "  require of linguistics/#{code} failed: #{err.message}"
				msgs << "Tried 'linguistics/#{code}': #{err.message}\n"
			end
		end

		if mod.is_a?( Array )
			raise LoadError,
				"Failed to load language extension %s:\n%s" %
				[ lang, msgs.join ]
		end

	end

	return mod
end

.make_inflector_mixin(lang, mod) ⇒ Object

Create a mixin module/class pair that act as the per-object interface to the given language mod‘s inflector.



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/linguistics.rb', line 177

def self::make_inflector_mixin( lang, mod )
	language = LANGUAGE_CODES[ lang.to_sym ] or
		raise "Unknown ISO639-2 language code '#{lang}'"

	unless mixin = self.inflector_mixins[ mod ]
		self.log.debug "Making an inflector mixin for %p" % [ mod ]

		bibcode, alpha2code, termcode = *language[:codes]
		inflector = Class.new( Linguistics::Inflector ) { include(mod) }
		self.log.debug "  created inflector class %p for [%p, %p, %p]" %
			[ inflector, bibcode, termcode, alpha2code ]

		mixin = Module.new do
			define_method( bibcode ) do
				inflector.new( bibcode, self )
			end
			alias_method termcode, bibcode unless termcode.nil? || termcode.empty?
			alias_method alpha2code, bibcode unless alpha2code.nil? || alpha2code.empty?
		end
		self.inflector_mixins[ mod ] = mixin
	end

	return mixin
end

.register_language(language, mod) ⇒ Object

Register a module as providing linguistic functions for the specified language (a two- or three-letter ISO639-2 language codes as a Symbol)



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/linguistics.rb', line 60

def self::register_language( language, mod )
	language_entry = LANGUAGE_CODES[ language.to_sym ] or
		raise "Unknown ISO639-2 language code '#{language}'"
	self.log.info "Registering %s for language %p" % [ mod, language_entry ]

	language_entry[:codes].each do |lang|
		self.languages[ lang.to_sym ] = mod
	end

	# Load in plugins for the language
	Gem.find_files( "linguistics/#{language}/*.rb" ).each do |extension|
		next if extension.include?( '/spec/' ) # Skip specs
		extension.sub!( %r{.*/linguistics/}, 'linguistics/' )
		self.log.debug "  trying to load #{language_entry[:eng_name]} extension %p" % [ extension ]
		begin
			require extension
		rescue LoadError => err
			self.log.debug "    failed (%s): %s %s" %
				[ err.class.name, err.message, err.backtrace.first ]
		else
			self.log.debug "    success."
		end
	end

end

.use(*languages) ⇒ Object

Add linguistics functions for the specified languages to Ruby’s core classes. The interface to all linguistic functions for a given language is through a method which is the same the language’s international 2- or 3-letter code (ISO 639). You can also specify a Hash of configuration options which control which classes are extended:

:classes

Specify the classes which are to be extended. If this is not specified, the Class objects in Linguistics::DEFAULT_EXT_CLASSES (an Array) are extended.

:monkeypatch

Monkeypatch directly (albeit responsibly, via a mixin) the specified classes instead of adding a single language-code method.



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/linguistics.rb', line 142

def self::use( *languages )
	config = languages.pop if languages.last.is_a?( Hash )
	config ||= {}

	classes = Array(config[:classes]) if config[:classes] 
	classes ||= DEFAULT_EXT_CLASSES

	self.log.debug "Extending %d classes with %d language modules." %
		[ classes.length, languages.length ]

	# Mix the language module for each requested language into each
	# specified class
	classes.each do |klass|
		self.log.debug "  extending %p" % [ klass ]
		languages.each do |lang|
			mod = load_language( lang ) or
				raise LoadError, "failed to load a language extension for %p" % [ lang ]
			self.log.debug "    using %s language module: %p" % [ lang, mod ]

			if config[:monkeypatch]
				klass.send( :include, mod )
			else
				inflector = make_inflector_mixin( lang, mod )
				self.log.debug "    made an inflector mixin: %p" % [ inflector ]
				klass.send( :include, inflector )
			end
		end
	end

	return classes
end

.version_string(include_buildnum = false) ⇒ Object

Return the library’s version string



51
52
53
54
55
# File 'lib/linguistics.rb', line 51

def self::version_string( include_buildnum=false )
	vstring = "%s %s" % [ self.name, VERSION ]
	vstring << " (build %s)" % [ REVISION[/: ([[:xdigit:]]+)/, 1] || '0' ] if include_buildnum
	return vstring
end