Wiktionary
omwiktionary
https://om.wiktionary.org/wiki/Fuula_Dura
MediaWiki 1.47.0-wmf.9
case-sensitive
Media
Special
Talk
User
User talk
Wiktionary
Wiktionary talk
File
File talk
MediaWiki
MediaWiki talk
Template
Template talk
Help
Help talk
Category
Category talk
TimedText
TimedText talk
Module
Module talk
Event
Event talk
Module:syllables
828
26651
81997
81993
2026-07-04T17:50:45Z
EyobAbebe7
3540
81997
Scribunto
text/plain
local p = {}
local vowels = {a=true,e=true,i=true,o=true,u=true}
local digraphs = {
dh="D", ch="C", ny="N",
ph="P", sh="S", ts="T", zy="Z"
}
-- Gabatee qubee dachaa gara iddoo duraatti deebisuuf gargaaru
local reverse_digraphs = {
D="dh", C="ch", N="ny",
P="ph", S="sh", T="ts", Z="zy"
}
-- =====================
-- TOKENIZE (keeps real chars too)
-- =====================
local function tokenize(word)
local tokens = {}
local i = 1
while i <= mw.ustring.len(word) do
local two = mw.ustring.sub(word, i, i+1)
if digraphs[two] then
table.insert(tokens, digraphs[two])
i = i + 2
else
table.insert(tokens, mw.ustring.sub(word, i, i))
i = i + 1
end
end
return tokens
end
-- =====================
-- DETOKENIZE (restores digraphs)
-- =====================
local function detokenize(str)
for k, v in pairs(reverse_digraphs) do
str = string.gsub(str, k, v)
end
return str
end
-- =====================
-- CHECK TYPE
-- =====================
local function isV(c)
return vowels[c] == true
end
local function isC(c)
return not isV(c)
end
-- =====================
-- SYLLABLE BUILDER (IMPORTANT FIX)
-- =====================
local function syllabify(word)
local t = tokenize(word)
local syllables = {}
local i = 1
while i <= #t do
local syll = {}
-- STEP 1: onset (C cluster)
while i <= #t and isC(t[i]) do
table.insert(syll, t[i])
i = i + 1
end
-- STEP 2: nucleus (V)
while i <= #t and isV(t[i]) do
table.insert(syll, t[i])
i = i + 1
end
-- STEP 3: coda (optional C, but stop before next vowel)
while i <= #t and isC(t[i]) do
-- lookahead: if next is vowel → break (onset rule)
if t[i+1] and isV(t[i+1]) then
break
end
table.insert(syll, t[i])
i = i + 1
end
table.insert(syllables, table.concat(syll))
end
return syllables
end
-- =====================
-- MAIN
-- =====================
function p.split(frame)
local word = frame.args[1] or ""
-- RAKKOO HUDHAA SIRREESSUU: ' gara ' deebisa
word = mw.text.decode(word)
word = mw.ustring.lower(mw.text.trim(word))
local s = syllabify(word)
-- Firiin erga walitti qabamee booda gara qubee dachaatti deebisuu
local result = table.concat(s, "-")
return detokenize(result)
end
function p.count(frame)
local word = frame.args[1] or ""
-- RAKKOO HUDHAA SIRREESSUU
word = mw.text.decode(word)
word = mw.text.trim(word)
if word == "" then return "0" end
local syll = p.split(frame)
local _, n = mw.ustring.gsub(syll, "-", "-")
return tostring(n + 1)
end
return p
qr6jmtob839k1cw4kdq09vc5ez1l9jr
Module:adjective
828
62062
81998
81926
2026-07-05T05:28:50Z
EyobAbebe7
3540
81998
Scribunto
text/plain
local export = {}
-- =====================================
-- 1. HELPER: Check for long vowels (aa, ee, ii, uu)
-- (JS: /(aa|ee|ii|uu)$/.test)
-- =====================================
local function ends_with_long_vowel(str)
return mw.ustring.match(str, "aa$") or
mw.ustring.match(str, "ee$") or
mw.ustring.match(str, "ii$") or
mw.ustring.match(str, "uu$")
end
-- =====================================
-- 2. TOKENIZER (ch, dh, ny, ph, sh, ts, zy)
-- =====================================
local function tokenize_oromo(text)
local digraphs = {
["ch"] = true, ["dh"] = true, ["ny"] = true,
["ph"] = true, ["sh"] = true, ["ts"] = true, ["zy"] = true
}
local tokens = {}
local i = 1
local len = mw.ustring.len(text)
while i <= len do
local two = mw.ustring.sub(text, i, i + 1)
if mw.ustring.len(two) == 2 and digraphs[two] then
table.insert(tokens, two)
i = i + 2
else
table.insert(tokens, mw.ustring.sub(text, i, i))
i = i + 1
end
end
return tokens
end
-- =====================================
-- 3. VCC DETECTOR
-- =====================================
local function is_vccuu(word)
local stem = mw.ustring.sub(word, 1, -3) -- removes 'uu'
local tokens = tokenize_oromo(stem)
local vowels = { a=true, e=true, i=true, o=true, u=true }
local consonants_at_end = 0
for i = #tokens, 1, -1 do
if vowels[tokens[i]] then
break
end
consonants_at_end = consonants_at_end + 1
end
return consonants_at_end >= 2
end
-- =====================================
-- 4. LONG VOWEL + CONSONANT CHECK
-- =====================================
local function ends_with_long_vowel_plus_consonant(stem)
local tokens = tokenize_oromo(stem)
local len = #tokens
if len < 2 then return false end
local last = tokens[len]
local prev = tokens[len - 1]
local vowels = { a=true, e=true, i=true, o=true, u=true }
local is_consonant = not vowels[last]
local is_long_vowel = (prev == "aa" or prev == "ee" or prev == "ii" or prev == "oo" or prev == "uu")
-- Fallback yoo tokenizer qubee wal-fakkaataa addaan baase
if not is_long_vowel and len >= 3 then
local prev2 = tokens[len - 2]
if vowels[prev] and prev == prev2 then
is_long_vowel = true
end
end
return is_long_vowel and is_consonant
end
-- =====================================
-- 5. MAIN FUNCTION: Generate Forms
-- =====================================
function export.get_adjective_forms(word)
if not word or word == "" then
return { error = "Verb galchi." }
end
word = mw.ustring.lower(mw.text.trim(word))
if not mw.ustring.match(word, "uu$") then
return { error = "Verb Afaan Oromoo 'uu'n xumuramuu qaba." }
end
local male = ""
local female = ""
local plural = ""
local stem2 = mw.ustring.sub(word, 1, -3) -- Default stem (removes 'uu')
-- =====================================
-- EXACT oochuu, eechuu, ichuu, uchuu
-- =====================================
if mw.ustring.match(word, "eechuu$") or mw.ustring.match(word, "ichuu$") or
mw.ustring.match(word, "uchuu$") or mw.ustring.match(word, "oochuu$") then
local stem_chuu = mw.ustring.sub(word, 1, -5)
male = stem_chuu .. "chaa"
female = stem_chuu .. "chituu"
plural = stem_chuu .. "chitoota"
-- =====================================
-- jjechuu, jechuu, ochuu
-- =====================================
elseif mw.ustring.match(word, "jjechuu$") then
local root = mw.ustring.sub(word, 1, -7)
male = root .. "etaa"
female = root .. "ettuu"
plural = root .. "ettoota"
elseif mw.ustring.match(word, "jechuu$") then
local root = mw.ustring.sub(word, 1, -6)
male = root .. "edhaa"
female = root .. "ettuu"
plural = root .. "ettoota"
elseif mw.ustring.match(word, "ochuu$") then
local root = mw.ustring.sub(word, 1, -6)
male = root .. "odhaa"
female = root .. "ootuu"
plural = root .. "ootota"
-- =====================================
-- ', w, y, h endings ['wyh]uu
-- =====================================
elseif mw.ustring.match(word, "oo['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "ssuu"
plural = root .. "ssota"
elseif mw.ustring.match(word, "o['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "otuu"
plural = root .. "otota"
elseif mw.ustring.match(word, "aa['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -4)
male = stem2 .. "aa"
female = root .. "ooftuu"
plural = root .. "ooftota"
elseif mw.ustring.match(word, "[aeio]ta['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "oftuu"
plural = root .. "oftoota"
elseif mw.ustring.match(word, "[aeiou]ga['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "eessuu"
plural = root .. "a'oota"
elseif mw.ustring.match(word, "ga['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "eessuu"
plural = root .. "eessota"
elseif mw.ustring.match(word, "a['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "atuu"
plural = root .. "atota"
elseif mw.ustring.match(word, "ii['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "i['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "toota"
elseif mw.ustring.match(word, "e['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "etuu"
plural = root .. "etota"
elseif mw.ustring.match(word, "u['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "utuu"
plural = root .. "utota"
-- =====================================
-- dhuu endings
-- =====================================
elseif mw.ustring.match(word, "[ae]dhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "iidhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "idhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "ituu"
plural = root .. "itota"
elseif mw.ustring.match(word, "uudhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "udhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "utuu"
plural = root .. "utota"
elseif mw.ustring.match(word, "dhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "otuu"
plural = root .. "otota"
-- =====================================
-- nyuu, shuu
-- =====================================
elseif mw.ustring.match(word, "nyuu$") then
male = stem2 .. "aa"
female = stem2 .. "ituu"
plural = stem2 .. "itoota"
elseif mw.ustring.match(word, "shuu$") then
male = stem2 .. "aa"
female = stem2 .. "tuu"
plural = stem2 .. "toota"
-- =====================================
-- Consonant + chuu
-- =====================================
elseif mw.ustring.match(word, "[bcdfghjklmnpqrstvwxyz]chuu$") then
local base = mw.ustring.sub(word, 1, -5)
local is_long = ends_with_long_vowel(base)
male = base .. "chaa"
female = base .. "chituu"
plural = base .. (is_long and "chitota" or "chitoota")
-- =====================================
-- General chuu
-- =====================================
elseif mw.ustring.match(word, "chuu$") then
local base = mw.ustring.sub(word, 1, -5)
local is_long = ends_with_long_vowel(base)
male = base .. "taa"
female = base .. "ttuu"
plural = base .. (is_long and "ttota" or "ttoota")
-- =====================================
-- V + CC + uu
-- =====================================
elseif is_vccuu(word) then
male = stem2 .. "aa"
female = stem2 .. "ituu"
plural = stem2 .. "itoota"
-- =====================================
-- cuu
-- =====================================
elseif mw.ustring.match(word, "cuu$") then
local base = mw.ustring.sub(word, 1, -4)
male = base .. "caa"
female = base .. "ccuu"
plural = base .. "ccitoota"
-- =====================================
-- [d j x t]uu
-- =====================================
elseif mw.ustring.match(word, "[djxt]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local c = mw.ustring.sub(word, -3, -3)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. c .. "uu"
plural = base .. c .. (is_long and "ota" or "oota")
-- =====================================
-- [bg]uu
-- =====================================
elseif mw.ustring.match(word, "[bg]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "duu"
plural = base .. (is_long and "dota" or "doota")
-- =====================================
-- [fklmnprsvz]uu
-- =====================================
elseif mw.ustring.match(word, "[fklmnprsvz]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "tuu"
plural = base .. (is_long and "tota" or "toota")
-- =====================================
-- quu / phuu / zyuu
-- =====================================
elseif mw.ustring.match(word, "quu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "xuu"
plural = base .. (is_long and "xota" or "xoota")
elseif mw.ustring.match(word, "phuu$") or mw.ustring.match(word, "zyuu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -3)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "xuu"
plural = base .. (is_long and "xota" or "xoota")
-- =====================================
-- RULE NOT FOUND (Fallback)
-- =====================================
else
return { error = "Rule kanaaf hin jiru." }
end
return { male = male, female = female, plural = plural, word = word }
end
-- =====================================
-- 6. TEMPLATE ENTRY POINT (LIST OUTPUT)
-- =====================================
function export.generate(frame)
local args = frame.args
if not args[1] and not args.word and not args.verb then
args = frame:getParent().args
end
local word = args[1] or args.word or args.verb
-- Yoo parameter hin kennamne maqaa fuulaa irraa fudhata
if not word or word == "" then
local pagename = mw.title.getCurrentTitle().text
if mw.ustring.match(pagename, "uu$") then
word = pagename
else
word = "gochuu"
end
end
local results = export.get_adjective_forms(word)
if results.error then
return "<strong class='error'>" .. results.error .. "</strong>"
end
local lines = {}
table.insert(lines, "====Derived terms====")
table.insert(lines, "* {{l|om|" .. results.male .. "}} (male adjective)")
table.insert(lines, "* {{l|om|" .. results.female .. "}} (female adjective)")
table.insert(lines, "* {{l|om|" .. results.plural .. "}} (plural adjective)")
return table.concat(lines, "\n")
end
return export
njybap4nbpj9lxuox46kg3ukso1lyzb
81999
81998
2026-07-05T05:44:36Z
EyobAbebe7
3540
81999
Scribunto
text/plain
local export = {}
-- =====================================
-- 1. HELPER: Check for long vowels (aa, ee, ii, uu)
-- (JS: /(aa|ee|ii|uu)$/.test)
-- =====================================
local function ends_with_long_vowel(str)
return mw.ustring.match(str, "aa$") or
mw.ustring.match(str, "ee$") or
mw.ustring.match(str, "ii$") or
mw.ustring.match(str, "uu$")
end
-- =====================================
-- 2. TOKENIZER (ch, dh, ny, ph, sh, ts, zy)
-- =====================================
local function tokenize_oromo(text)
local digraphs = {
["ch"] = true, ["dh"] = true, ["ny"] = true,
["ph"] = true, ["sh"] = true, ["ts"] = true, ["zy"] = true
}
local tokens = {}
local i = 1
local len = mw.ustring.len(text)
while i <= len do
local two = mw.ustring.sub(text, i, i + 1)
if mw.ustring.len(two) == 2 and digraphs[two] then
table.insert(tokens, two)
i = i + 2
else
table.insert(tokens, mw.ustring.sub(text, i, i))
i = i + 1
end
end
return tokens
end
-- =====================================
-- 3. VCC DETECTOR
-- =====================================
local function is_vccuu(word)
local stem = mw.ustring.sub(word, 1, -3) -- removes 'uu'
local tokens = tokenize_oromo(stem)
local vowels = { a=true, e=true, i=true, o=true, u=true }
local consonants_at_end = 0
for i = #tokens, 1, -1 do
if vowels[tokens[i]] then
break
end
consonants_at_end = consonants_at_end + 1
end
return consonants_at_end >= 2
end
-- =====================================
-- 4. LONG VOWEL + CONSONANT CHECK
-- =====================================
local function ends_with_long_vowel_plus_consonant(stem)
local tokens = tokenize_oromo(stem)
local len = #tokens
if len < 2 then return false end
local last = tokens[len]
local prev = tokens[len - 1]
local vowels = { a=true, e=true, i=true, o=true, u=true }
local is_consonant = not vowels[last]
local is_long_vowel = (prev == "aa" or prev == "ee" or prev == "ii" or prev == "oo" or prev == "uu")
-- Fallback yoo tokenizer qubee wal-fakkaataa addaan baase
if not is_long_vowel and len >= 3 then
local prev2 = tokens[len - 2]
if vowels[prev] and prev == prev2 then
is_long_vowel = true
end
end
return is_long_vowel and is_consonant
end
-- =====================================
-- 5. MAIN FUNCTION: Generate Forms
-- =====================================
function export.get_adjective_forms(word)
if not word or word == "" then
return { error = "Verb galchi." }
end
word = mw.ustring.lower(mw.text.trim(word))
if not mw.ustring.match(word, "uu$") then
return { error = "Verb Afaan Oromoo 'uu'n xumuramuu qaba." }
end
local male = ""
local female = ""
local plural = ""
local stem2 = mw.ustring.sub(word, 1, -3) -- Default stem (removes 'uu')
-- =====================================
-- EXACT oochuu, eechuu, ichuu, uchuu
-- =====================================
if mw.ustring.match(word, "eechuu$") or mw.ustring.match(word, "ichuu$") or
mw.ustring.match(word, "uchuu$") or mw.ustring.match(word, "oochuu$") then
local stem_chuu = mw.ustring.sub(word, 1, -5)
male = stem_chuu .. "chaa"
female = stem_chuu .. "chituu"
plural = stem_chuu .. "chitoota"
-- =====================================
-- jjechuu, jechuu, ochuu
-- =====================================
elseif mw.ustring.match(word, "jjechuu$") then
local root = mw.ustring.sub(word, 1, -7)
male = root .. "etaa"
female = root .. "ettuu"
plural = root .. "ettoota"
elseif mw.ustring.match(word, "jechuu$") then
local root = mw.ustring.sub(word, 1, -6)
male = root .. "edhaa"
female = root .. "ettuu"
plural = root .. "ettoota"
elseif mw.ustring.match(word, "ochuu$") then
local root = mw.ustring.sub(word, 1, -6)
male = root .. "odhaa"
female = root .. "ootuu"
plural = root .. "ootota"
-- =====================================
-- ', w, y, h endings ['wyh]uu
-- =====================================
elseif mw.ustring.match(word, "oo['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "ssuu"
plural = root .. "ssota"
elseif mw.ustring.match(word, "o['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "otuu"
plural = root .. "otota"
elseif mw.ustring.match(word, "aa['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -4)
male = stem2 .. "aa"
female = root .. "ooftuu"
plural = root .. "ooftota"
elseif mw.ustring.match(word, "[aeio]ta['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "oftuu"
plural = root .. "oftoota"
elseif mw.ustring.match(word, "[aeiou]ga['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "eessuu"
plural = root .. "a'oota"
elseif mw.ustring.match(word, "ga['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "eessuu"
plural = root .. "eessota"
elseif mw.ustring.match(word, "a['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "atuu"
plural = root .. "atota"
elseif mw.ustring.match(word, "ii['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "i['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "toota"
elseif mw.ustring.match(word, "e['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "etuu"
plural = root .. "etota"
elseif mw.ustring.match(word, "u['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "utuu"
plural = root .. "utota"
-- =====================================
-- dhuu endings
-- =====================================
elseif mw.ustring.match(word, "[ae]dhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "iidhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "idhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "ituu"
plural = root .. "itota"
elseif mw.ustring.match(word, "uudhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "udhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "utuu"
plural = root .. "utota"
elseif mw.ustring.match(word, "dhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "otuu"
plural = root .. "otota"
-- =====================================
-- nyuu, shuu
-- =====================================
elseif mw.ustring.match(word, "nyuu$") then
male = stem2 .. "aa"
female = stem2 .. "ituu"
plural = stem2 .. "itoota"
elseif mw.ustring.match(word, "shuu$") then
male = stem2 .. "aa"
female = stem2 .. "tuu"
plural = stem2 .. "toota"
-- =====================================
-- Consonant + chuu
-- =====================================
elseif mw.ustring.match(word, "[bcdfghjklmnpqrstvwxyz]chuu$") then
local base = mw.ustring.sub(word, 1, -5)
local is_long = ends_with_long_vowel(base)
male = base .. "chaa"
female = base .. "chituu"
plural = base .. (is_long and "chitota" or "chitoota")
-- =====================================
-- General chuu
-- =====================================
elseif mw.ustring.match(word, "chuu$") then
local base = mw.ustring.sub(word, 1, -5)
local is_long = ends_with_long_vowel(base)
male = base .. "taa"
female = base .. "ttuu"
plural = base .. (is_long and "ttota" or "ttoota")
-- =====================================
-- V + CC + uu
-- =====================================
elseif is_vccuu(word) then
male = stem2 .. "aa"
female = stem2 .. "ituu"
plural = stem2 .. "itoota"
-- =====================================
-- cuu
-- =====================================
elseif mw.ustring.match(word, "cuu$") then
local base = mw.ustring.sub(word, 1, -4)
male = base .. "caa"
female = base .. "ccuu"
plural = base .. "ccitoota"
-- =====================================
-- [d j x t]uu
-- =====================================
elseif mw.ustring.match(word, "[djxt]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local c = mw.ustring.sub(word, -3, -3)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. c .. "uu"
plural = base .. c .. (is_long and "ota" or "oota")
-- =====================================
-- [bg]uu
-- =====================================
elseif mw.ustring.match(word, "[bg]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "duu"
plural = base .. (is_long and "dota" or "doota")
-- =====================================
-- [fklmnprsvz]uu
-- =====================================
elseif mw.ustring.match(word, "[fklmnprsvz]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "tuu"
plural = base .. (is_long and "tota" or "toota")
-- =====================================
-- quu / phuu / zyuu
-- =====================================
elseif mw.ustring.match(word, "quu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "xuu"
plural = base .. (is_long and "xota" or "xoota")
elseif mw.ustring.match(word, "phuu$") or mw.ustring.match(word, "zyuu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -3)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "xuu"
plural = base .. (is_long and "xota" or "xoota")
-- =====================================
-- RULE NOT FOUND (Fallback)
-- =====================================
else
return { error = "Rule kanaaf hin jiru." }
end
return { male = male, female = female, plural = plural, word = word }
end
-- =====================================
-- 6. TEMPLATE ENTRY POINT (LIST OUTPUT)
-- =====================================
function export.generate(frame)
local args = frame.args
if not args[1] and not args.word and not args.verb then
args = frame:getParent().args
end
local word = args[1] or args.word or args.verb
-- Yoo parameter hin kennamne maqaa fuulaa irraa fudhata
if not word or word == "" then
local pagename = mw.title.getCurrentTitle().text
if mw.ustring.match(pagename, "uu$") then
word = pagename
else
word = "gochuu"
end
end
local results = export.get_adjective_forms(word)
if results.error then
return "<strong class='error'>" .. results.error .. "</strong>"
end
local lines = {}
table.insert(lines, "====Derived terms====")
table.insert(lines, "* [[" .. results.male .. "]] (male adjective)")
table.insert(lines, "* [[" .. results.female .. "]] (female adjective)")
table.insert(lines, "* [[" .. results.plural .. "]] (plural adjective)")
return table.concat(lines, "\n")
end
return export
679j8faf5cz89udyweiicw2p3odio29
82000
81999
2026-07-05T05:58:32Z
EyobAbebe7
3540
82000
Scribunto
text/plain
local export = {}
-- =====================================
-- 1. HELPER: Check for long vowels (aa, ee, ii, uu)
-- (JS: /(aa|ee|ii|uu)$/.test)
-- =====================================
local function ends_with_long_vowel(str)
return mw.ustring.match(str, "aa$") or
mw.ustring.match(str, "ee$") or
mw.ustring.match(str, "ii$") or
mw.ustring.match(str, "uu$")
end
-- =====================================
-- 2. TOKENIZER (ch, dh, ny, ph, sh, ts, zy)
-- =====================================
local function tokenize_oromo(text)
local digraphs = {
["ch"] = true, ["dh"] = true, ["ny"] = true,
["ph"] = true, ["sh"] = true, ["ts"] = true, ["zy"] = true
}
local tokens = {}
local i = 1
local len = mw.ustring.len(text)
while i <= len do
local two = mw.ustring.sub(text, i, i + 1)
if mw.ustring.len(two) == 2 and digraphs[two] then
table.insert(tokens, two)
i = i + 2
else
table.insert(tokens, mw.ustring.sub(text, i, i))
i = i + 1
end
end
return tokens
end
-- =====================================
-- 3. VCC DETECTOR
-- =====================================
local function is_vccuu(word)
local stem = mw.ustring.sub(word, 1, -3) -- removes 'uu'
local tokens = tokenize_oromo(stem)
local vowels = { a=true, e=true, i=true, o=true, u=true }
local consonants_at_end = 0
for i = #tokens, 1, -1 do
if vowels[tokens[i]] then
break
end
consonants_at_end = consonants_at_end + 1
end
return consonants_at_end >= 2
end
-- =====================================
-- 4. LONG VOWEL + CONSONANT CHECK
-- =====================================
local function ends_with_long_vowel_plus_consonant(stem)
local tokens = tokenize_oromo(stem)
local len = #tokens
if len < 2 then return false end
local last = tokens[len]
local prev = tokens[len - 1]
local vowels = { a=true, e=true, i=true, o=true, u=true }
local is_consonant = not vowels[last]
local is_long_vowel = (prev == "aa" or prev == "ee" or prev == "ii" or prev == "oo" or prev == "uu")
-- Fallback yoo tokenizer qubee wal-fakkaataa addaan baase
if not is_long_vowel and len >= 3 then
local prev2 = tokens[len - 2]
if vowels[prev] and prev == prev2 then
is_long_vowel = true
end
end
return is_long_vowel and is_consonant
end
-- =====================================
-- 5. MAIN FUNCTION: Generate Forms
-- =====================================
function export.get_adjective_forms(word)
if not word or word == "" then
return { error = "Verb galchi." }
end
word = mw.ustring.lower(mw.text.trim(word))
if not mw.ustring.match(word, "uu$") then
return { error = "Verb Afaan Oromoo 'uu'n xumuramuu qaba." }
end
local male = ""
local female = ""
local plural = ""
local stem2 = mw.ustring.sub(word, 1, -3) -- Default stem (removes 'uu')
-- =====================================
-- EXACT oochuu, eechuu, ichuu, uchuu
-- =====================================
if mw.ustring.match(word, "eechuu$") or mw.ustring.match(word, "ichuu$") or
mw.ustring.match(word, "uchuu$") or mw.ustring.match(word, "oochuu$") then
local stem_chuu = mw.ustring.sub(word, 1, -5)
male = stem_chuu .. "chaa"
female = stem_chuu .. "chituu"
plural = stem_chuu .. "chitoota"
-- =====================================
-- jjechuu, jechuu, ochuu
-- =====================================
elseif mw.ustring.match(word, "jjechuu$") then
local root = mw.ustring.sub(word, 1, -7)
male = root .. "etaa"
female = root .. "ettuu"
plural = root .. "ettoota"
elseif mw.ustring.match(word, "jechuu$") then
local root = mw.ustring.sub(word, 1, -6)
male = root .. "edhaa"
female = root .. "ettuu"
plural = root .. "ettoota"
elseif mw.ustring.match(word, "ochuu$") then
local root = mw.ustring.sub(word, 1, -6)
male = root .. "odhaa"
female = root .. "ootuu"
plural = root .. "ootota"
-- =====================================
-- ', w, y, h endings ['wyh]uu
-- =====================================
elseif mw.ustring.match(word, "oo['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "ssuu"
plural = root .. "ssota"
elseif mw.ustring.match(word, "o['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "otuu"
plural = root .. "otota"
elseif mw.ustring.match(word, "aa['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -4)
male = stem2 .. "aa"
female = root .. "ooftuu"
plural = root .. "ooftota"
elseif mw.ustring.match(word, "[aeio]ta['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "oftuu"
plural = root .. "oftoota"
elseif mw.ustring.match(word, "[aeiou]ga['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "eessuu"
plural = root .. "a'oota"
elseif mw.ustring.match(word, "ga['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "eessuu"
plural = root .. "eessota"
elseif mw.ustring.match(word, "a['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "atuu"
plural = root .. "atota"
elseif mw.ustring.match(word, "ii['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "i['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "toota"
elseif mw.ustring.match(word, "e['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "etuu"
plural = root .. "etota"
elseif mw.ustring.match(word, "u['wyh]uu$") then
local root = mw.ustring.sub(stem2, 1, -2)
male = stem2 .. "aa"
female = root .. "utuu"
plural = root .. "utota"
-- =====================================
-- dhuu endings
-- =====================================
elseif mw.ustring.match(word, "[ae]dhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "iidhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "idhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "ituu"
plural = root .. "itota"
elseif mw.ustring.match(word, "uudhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "tuu"
plural = root .. "tota"
elseif mw.ustring.match(word, "udhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "utuu"
plural = root .. "utota"
elseif mw.ustring.match(word, "dhuu$") then
local root = mw.ustring.sub(stem2, 1, -3)
male = stem2 .. "aa"
female = root .. "otuu"
plural = root .. "otota"
-- =====================================
-- nyuu, shuu
-- =====================================
elseif mw.ustring.match(word, "nyuu$") then
male = stem2 .. "aa"
female = stem2 .. "ituu"
plural = stem2 .. "itoota"
elseif mw.ustring.match(word, "shuu$") then
male = stem2 .. "aa"
female = stem2 .. "tuu"
plural = stem2 .. "toota"
-- =====================================
-- Consonant + chuu
-- =====================================
elseif mw.ustring.match(word, "[bcdfghjklmnpqrstvwxyz]chuu$") then
local base = mw.ustring.sub(word, 1, -5)
local is_long = ends_with_long_vowel(base)
male = base .. "chaa"
female = base .. "chituu"
plural = base .. (is_long and "chitota" or "chitoota")
-- =====================================
-- General chuu
-- =====================================
elseif mw.ustring.match(word, "chuu$") then
local base = mw.ustring.sub(word, 1, -5)
local is_long = ends_with_long_vowel(base)
male = base .. "taa"
female = base .. "ttuu"
plural = base .. (is_long and "ttota" or "ttoota")
-- =====================================
-- V + CC + uu
-- =====================================
elseif is_vccuu(word) then
male = stem2 .. "aa"
female = stem2 .. "ituu"
plural = stem2 .. "itoota"
-- =====================================
-- cuu
-- =====================================
elseif mw.ustring.match(word, "cuu$") then
local base = mw.ustring.sub(word, 1, -4)
male = base .. "caa"
female = base .. "ccuu"
plural = base .. "ccitoota"
-- =====================================
-- [d j x t]uu
-- =====================================
elseif mw.ustring.match(word, "[djxt]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local c = mw.ustring.sub(word, -3, -3)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. c .. "uu"
plural = base .. c .. (is_long and "ota" or "oota")
-- =====================================
-- [bg]uu
-- =====================================
elseif mw.ustring.match(word, "[bg]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "duu"
plural = base .. (is_long and "dota" or "doota")
-- =====================================
-- [fklmnprsvz]uu
-- =====================================
elseif mw.ustring.match(word, "[fklmnprsvz]uu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "tuu"
plural = base .. (is_long and "tota" or "toota")
-- =====================================
-- quu / phuu / zyuu
-- =====================================
elseif mw.ustring.match(word, "quu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -2)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "xuu"
plural = base .. (is_long and "xota" or "xoota")
elseif mw.ustring.match(word, "phuu$") or mw.ustring.match(word, "zyuu$") then
local base = mw.ustring.sub(word, 1, -3)
local root = mw.ustring.sub(base, 1, -3)
local is_long = ends_with_long_vowel(root)
male = base .. "aa"
female = base .. "xuu"
plural = base .. (is_long and "xota" or "xoota")
-- =====================================
-- RULE NOT FOUND (Fallback)
-- =====================================
else
return { error = "Rule kanaaf hin jiru." }
end
return { male = male, female = female, plural = plural, word = word }
end
-- =====================================
-- 6. TEMPLATE ENTRY POINT (LIST OUTPUT)
-- =====================================
function export.generate(frame)
local args = frame.args
if not args[1] and not args.word and not args.verb then
args = frame:getParent().args
end
local word = args[1] or args.word or args.verb
-- Yoo parameter hin kennamne maqaa fuulaa irraa fudhata
if not word or word == "" then
local pagename = mw.title.getCurrentTitle().text
if mw.ustring.match(pagename, "uu$") then
word = pagename
else
word = "gochuu"
end
end
local results = export.get_adjective_forms(word)
if results.error then
return "<strong class='error'>" .. results.error .. "</strong>"
end
local lines = {}
table.insert(lines, "* [[" .. results.male .. "]] (male adjective)")
table.insert(lines, "* [[" .. results.female .. "]] (female adjective)")
table.insert(lines, "* [[" .. results.plural .. "]] (plural adjective)")
table.insert(lines, "* [[" .. results.word .. "dhaan]] (adverb)")
return table.concat(lines, "\n")
end
return export
77bxrrzt301y368qgr11q26npwzwhcg