模組:Gender and number
- 下列說明文檔位於Module:Gender and number/doc。[編輯] 分類由 Module:documentation 自動生成。 [編輯]
- 相關連結:子頁面列表 • 链入 • 嵌入包含 • 測試用例 • 沙盒
此模組顯示性/數標記,例如 陽(陽性)、中 複(中性複數)或 陰 有生 雙(陰性有生雙數)。「性」(Gender)在這裡有點名不副實,因為可用的標記類別還包括其他類似的詞彙特徵,如有生性和動詞體(儘管前者有時也被視為詞性的組成部分)。根據特定語言,這些標記會附於名詞、代名詞及其他具有此類詞彙類別的詞類。標記以參數形式出現,例如用於詞頭模板 {{head}}、{{es-noun}}(西班牙語名詞)、{{fr-proper noun}}(法語專有名詞)和 {{ru-verb}}(俄語動詞);翻譯模板如 {{t}}、{{t+}} 和 {{t-check}};定義模板如 {{demonym-noun}};以及專門的性/數模板如 {{g}}。
性/數規範
指定的標記使用「性/數規範」來描述。每個規範都是一個以連字號分隔的「性/數代碼」列表,其中每個代碼描述特定類別的單一值(例如:m 代表「陽性」,an 代表「有生」,p 代表「複數」)。由於某些術語屬於多個可能的性/數類別,模板通常接受一組性/數規範列表,而不僅僅是單個規範。根據所使用的模板,這些規範將透過不同的參數或單個以逗號分隔的參數提供。
顯示規範時,規範中的每個代碼都會轉換為相應的顯示形式。隨後將規範內的各個代碼相連,並以空格分隔。
範例:
| 列表 | 結果 |
|---|---|
| {"m"} | 陽 |
| {"m-p"} | 陽 複 |
| {"m-an-p"} | 陽 有生 複 |
| {"mfbysense-p"} | 陽 複 或 陰 複 遵詞義 |
| {"?-p"} | ? 複 |
| {"?!-an-s"} | 性別無記錄 有生 單 |
| {"f-d", "m-p"} | 陰 雙 或 陽 複 |
| {"m-p", "f-p"} | 陽 複 或 陰 複 |
| {"m", "f", "p"} | 陽 或 陰 或 複 |
目前所辨識之代碼的資料來源為 Module:gender and number/data。
下表列出了:
- 目前可辨識的代碼;
- 它們所屬的類型類別(在給定的規範中,每個類型類別只能出現一個代碼);
- 代碼的顯示方式(將滑鼠懸停在顯示形式上可查看該代碼含義的說明);
- 如果術語的詞頭性/數規範中包含該代碼,該術語將被分配到的分類(如果有),其中
POS會替換為術語複數形式的詞性。
| 代碼 | 類型 | 顯示文字 | 分類 |
|---|---|---|---|
g? |
gender | 性別未指定 | — |
n |
gender | 中 | 中性POS
|
m |
gender | 陽 | 陽性POS
|
gneut |
gender | 中立 | 性別中立POS
|
f |
gender | 陰 | 陰性POS
|
c |
gender | 通 | 通性POS
|
g! |
gender | 性別無記錄 | — |
d |
number | 雙 | 唯雙POS
|
s |
number | 單 | — |
num! |
number | 數無記載 | — |
p |
number | 複 | 唯複POS
|
an |
animacy | 有生 | 有生POS
|
in |
animacy | 無生 | 無生POS
|
an! |
animacy | 有生性無記錄 | — |
pr |
animacy | 個人 | 個人POS
|
an? |
animacy | 有生性未指定 | — |
np |
animacy | 非個人 | 非個人POS
|
anml |
animacy | 動物 | 動物POS
|
vr |
virility | 男 | 男性POS
|
nv |
virility | 非男 | 非男性POS
|
asp! |
aspect | 體貌無記錄 | — |
pf |
aspect | 完 | 完整體POS
|
asp? |
aspect | 體貌未指定 | — |
impf |
aspect | 非完 | 非完整體POS
|
? |
other | ? | — |
?! |
other | 性別無記錄 | — |
某些性/數代碼是「組合代碼」,這與在不同的性/數規範中分別指定兩個或多個同一類型的代碼大致等效。某些組合代碼會有額外的分類和顯示方式。下表列出了這些組合代碼:
| 組合 | 獨立代碼 | 額外顯示的文字 | 分類 |
|---|---|---|---|
biasp |
impf, pf |
— | — |
mf |
m, f |
— | — |
mfbysense |
m, f |
遵詞義 | 性別遵照被指代者的POS
|
mfequiv |
m, f |
同義 | — |
在某些類型類別中,如果給出了多個該類別的代碼(必須在不同的性/數規範中),則該術語會被加入到一個特殊的分類。下表列出了這些多代碼分類:
| 類型 | 存在多個相同類型代碼時的分類 |
|---|---|
gender |
有多種性別的POS
|
animacy |
有多種有生性的POS
|
aspect |
雙體POS
|
名詞類別
以「c」開頭(但「c」本身除外)的規範會被特殊處理。它們被視為名詞類別(noun classes),「c」後面的部分被簡單地視為名詞類別的某種名稱;通常是一個數字。名詞類別沒有子部分,因此不包含連字號。當提供多個規範時,它們必須全部都是名詞類別,並改用斜線(/)分隔顯示,且前面冠以「類別」。
範例:
| 列表 | 結果 |
|---|---|
| {"c1"} | 類別1 |
| {"c1", "c2"} | 類別1/2 |
| {"c1a", "c2a"} | 類別1a/2a |
用法
本模組可供其他模組調用,方法是導入模組並調用其導出的 format_list 函式。它需要一個參數,該參數必須是由零個或多個字串組成的表(table)。它隨後將返回包含結果的字串。例如:
local gen = require("Module:gender and number")
local example1 = gen.format_list({"m"})
local example2 = gen.format_list({"m", "f"})
local example3 = gen.format_list({"m-p"})
警告:傳入的列表(table)內容將被覆蓋。
它也可以從模板中調用,此時應使用 show_list 函式。其工作方式與 format_list 函式相同,但規範是作為模組調用的參數傳遞的,如下所示:
*{{#invoke:gender and number|show_list|m}}
*{{#invoke:gender and number|show_list|m|f}}
*{{#invoke:gender and number|show_list|m-p}}
- 陽
- 陽 或 陰
- 陽 複
以這種方式提供的參數數量沒有限制。模組將處理其所有參數,直到遇到空參數為止。這意味著以下範例僅會顯示「陽」而不會顯示「陽 或 中」:
{{#invoke:gender and number|show_list|m||n}}
導出函式
Module:Module_categorization第227行Lua错误:Did not recognize inferred module-type keyword 'and number' from root pagename 'Gender and number'
local export = {}
local debug_track_module = "Module:debug/track"
local load_module = "Module:load"
local pron_qualifier_module = "Module:pron qualifier"
local parameters_module = "Module:parameters"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local concat = table.concat
local insert = table.insert
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_pron_qualifiers(...)
format_pron_qualifiers = require(pron_qualifier_module).format_qualifiers
return format_pron_qualifiers(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local gender_and_number_data
local function get_gender_and_number_data()
gender_and_number_data, get_gender_and_number_data = load_data("Module:gender and number/data"), nil
return gender_and_number_data
end
--[==[ intro:
This module creates standardised displays for gender and number. It converts a gender specification into Wiki/HTML format.
A gender/number specification consists of one or more gender/number elements, separated by hyphens. Examples are:
{"n"} (neuter gender), {"f-p"} (feminine plural), {"m-an-p"} (masculine animate plural),
{"pf"} (perfective aspect). Each gender/number element has the following properties:
# A code, as used in the spec, e.g. {"f"} for feminine, {"p"} for plural.
# A type, e.g. `gender`, `number` or `animacy`. Each element in a given spec must be of a different type.
# A display form, which in turn consists of a display code and a tooltip gloss. The display code
may not be the same as the spec code, e.g. the spec code {"an"} has display code {"anim"} and tooltip
gloss ''animate''.
# A category into which lemmas of the right part of speech are placed if they have a gender/number
spec containing the given element. For example, a noun with gender/number spec {"m-an-p"} is placed
into the categories `<var>lang</var> masculine nouns`, `<var>lang</var> animate nouns` and `<var>lang</var> pluralia tantum`.
]==]
--[==[
Version of format_list that can be invoked from a template.
]==]
function export.show_list(frame)
local params = {
[1] = {list = true},
["lang"] = {type = "language"},
}
local iargs = process_params(frame.args, params)
return export.format_list(iargs[1], iargs.lang)
end
--[==[
Older entry point; equivalent to format_genders() except that it formats the
categories and returns them appended to the formatted gender text rather than
returning the formatted text and categories separately.
]==]
function export.format_list(specs, lang, pos_for_cat, sort_key)
debug_track("gender and number/old-format-list")
local text, cats = export.format_genders(specs, lang, pos_for_cat)
if not cats then
return text
end
return text .. format_categories(cats, lang, sort_key)
end
local function autoadd_abbr(display)
if not display then
error("Internal error: '.display' for gender/number code is missing")
end
if display:find("<abbr", nil, true) then
return display
end
return ('%s'):format(display, display)
end
-- Add qualifiers, labels and references to a formatted gender/number spec. `spec` is the object describing the
-- gender/number spec, which should optionally contain:
-- * left qualifiers in `q` or (for compatibility) `qualifiers`, an array of strings;
-- * right qualifiers in `qq`, an array of strings;
-- * left labels in `l`, an array of strings;
-- * right labels in `ll`, an array of strings;
-- * references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
-- (formatted reference text) and optionally `name` and/or `group`;
-- `formatted` is the formatted version of the term itself, and `lang` is the optional language object passed into
-- format_genders().
local function add_qualifiers_and_refs(formatted, spec, lang)
local function field_non_empty(field)
local list = spec[field]
if not list then
return nil
end
if type(list) ~= "table" then
error(("Internal error: Wrong type for `spec.%s`=%s, should be \"table\""):format(
field, mw.dumpObject(list)))
end
return list[1]
end
if field_non_empty("q") or field_non_empty("qq") or field_non_empty("l") or field_non_empty("ll") or
field_non_empty("qualifiers") or field_non_empty("refs") then
formatted = format_pron_qualifiers{
lang = lang,
text = formatted,
q = spec.q,
qq = spec.qq,
qualifiers = spec.qualifiers,
l = spec.l,
ll = spec.ll,
refs = spec.refs,
}
end
return formatted
end
--[==[
Format one or more gender/number specifications. Each spec is either a string, e.g. {"f-p"}, or a table of the form
{ {spec = "SPEC", qualifiers = {"QUALIFIER", "QUALIFIER", ...}}} where `.spec` is a gender/number spec such as {"f-p"}
and `.qualifiers` is a list of qualifiers to display before the formatted gender/number spec. `.spec` must be present
but `.qualifiers` may be omitted.
The function returns two values:
# the formatted text;
# a list of the categories to add.
If `lang` (which should be a language object) and `pos_for_cat` (which should be a plural part of speech) are given,
gender categories such as `German masculine nouns` or `Russian imperfective verbs` are added to the categories, and
request categories such as `Requests for gender in <var>lang</var> entries` or
`Requests for animacy in <var>lang</var> entries` may also be added. Otherwise, if only `lang` is given, only request
categories may be returned. If both are omitted, the returned list is empty.
]==]
function export.format_genders(specs, lang, pos_for_cat)
local formatted_specs, categories, seen_types = {}
local all_is_nounclass = nil
local full_langname = lang and lang:getFullName() or nil
local function do_gender_spec(spec, parts)
local types = {}
local codes = (gender_and_number_data or get_gender_and_number_data()).codes
for key, code in ipairs(parts) do
-- Is this code valid?
if not codes[code] then
error('The tag "' .. code .. '" in the gender specification "' .. spec.spec .. '" is not valid. See [[Module:gender and number]] for a list of valid tags.')
end
-- Check for multiple genders/numbers/animacies in a single spec.
local typ = codes[code].type
if typ ~= "other" and types[typ] then
error('The gender specification "' .. spec.spec .. '" contains multiple tags of type "' .. typ .. '".')
end
types[typ] = true
parts[key] = autoadd_abbr(codes[code].display)
-- Generate categories if called for.
if lang and pos_for_cat then
local cat = codes[code].cat
if cat then
if not categories then
categories = {}
end
insert(categories, mw.ustring.find(cat, "的") and mw.ustring.gsub(cat, "的", "的" .. full_langname) or full_langname .. cat)
end
if not seen_types then
seen_types = {}
elseif seen_types[typ] and seen_types[typ] ~= code then
cat = (gender_and_number_data or get_gender_and_number_data()).multicode_cats[typ]
if cat then
if not categories then
categories = {}
end
insert(categories, mw.ustring.find(cat, "的") and mw.ustring.gsub(cat, "的", "的" .. full_langname) or full_langname .. cat)
end
end
seen_types[typ] = code
end
if lang and codes[code].req then
local type_for_req = typ
if code == "?" then
-- Keep in mind `pos_for_cat` may be nil here.
type_for_req = pos_for_cat == "動詞" and "體" or "性別"
end
if not categories then
categories = {}
end
insert(categories, full_langname .. "詞條" .. type_for_req .. "請求")
end
end
-- Add the processed codes together with non-breaking spaces
if not parts[2] and parts[1] then
return parts[1]
else
return concat(parts, " ")
end
end
for _, spec in ipairs(specs) do
if type(spec) ~= "table" then
spec = {spec = spec}
end
local spec_spec, is_nounclass = spec.spec
-- If the specification starts with cX, then it is a noun class specification.
if spec_spec:match("^%d") or spec_spec:match("^c[^-]") then
is_nounclass = true
local code = spec_spec:gsub("^c", "")
local text
if code == "?" then
text = '<abbr class="noun-class" title="名詞類別缺失">?</abbr>'
if lang then
if not categories then
categories = {}
end
insert(categories, "Requests for noun class in " .. full_langname .. " entries")
end
else
text = '<abbr class="noun-class" title="名詞類別' .. code .. '">' .. code .. "</abbr>"
if lang and pos_for_cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. "第" .. code .. "類POS")
end
end
local text_with_qual = add_qualifiers_and_refs(text, spec, lang)
insert(formatted_specs, text_with_qual)
else
-- Split the parts and iterate over each part, converting it into its display form
local parts = split(spec.spec, "-", true, true)
local combined_codes = (gender_and_number_data or get_gender_and_number_data()).combinations
if lang then
-- Check if the specification is valid
--elseif langinfo.genders then
-- local valid_genders = {}
-- for _, g in ipairs(langinfo.genders) do valid_genders[g] = true end
--
-- if not valid_genders[spec.spec] then
-- local valid_string = {}
-- for i, g in ipairs(langinfo.genders) do valid_string[i] = g end
-- error('The gender specification "' .. spec.spec .. '" is not valid for ' .. langinfo.names[1] .. ". Valid are: " .. concat(valid_string, ", "))
-- end
--end
end
local has_combined = false
for _, code in ipairs(parts) do
if combined_codes[code] then
has_combined = true
break
end
end
if not has_combined then
if formatted_specs[1] then
insert(formatted_specs, " <small>或</small> ")
end
insert(formatted_specs, add_qualifiers_and_refs(do_gender_spec(spec, parts), spec, lang))
else
-- This logic is to handle combined gender specs like 'mf' and 'mfbysense'.
local all_parts = {{}}
local extra_displays
local this_formatted_specs = {}
for _, code in ipairs(parts) do
if combined_codes[code] then
local new_all_parts = {}
for _, one_parts in ipairs(all_parts) do
for _, one_code in ipairs(combined_codes[code].codes) do
local new_combined_parts = deep_copy(one_parts)
insert(new_combined_parts, one_code)
insert(new_all_parts, new_combined_parts)
end
end
all_parts = new_all_parts
if lang and pos_for_cat then
local extra_cat = combined_codes[code].cat
if extra_cat then
if not categories then
categories = {}
end
rindex_de = mw.ustring.find(extra_cat, '的[^的]*$') -- L10N
if rindex_de then
extra_cat = mw.ustring.sub(extra_cat, 1, rindex_de) .. lang:getCanonicalName() .. mw.ustring.sub(extra_cat, rindex_de + 1)
else
extra_cat = lang:getCanonicalName() .. extra_cat
end
table.insert(categories, extra_cat)
end
end
local extra_display = combined_codes[code].display
if extra_display then
if not extra_displays then
extra_displays = {}
end
insert(extra_displays, autoadd_abbr(extra_display))
end
else
for _, one_parts in ipairs(all_parts) do
insert(one_parts, code)
end
end
end
for _, parts in ipairs(all_parts) do
if this_formatted_specs[1] then
insert(this_formatted_specs, " <small>或</small> ")
end
insert(this_formatted_specs, do_gender_spec(spec, parts))
end
if extra_displays then
for _, display in ipairs(extra_displays) do
insert(this_formatted_specs, display)
end
end
insert(formatted_specs, add_qualifiers_and_refs(
concat(this_formatted_specs, " "), spec, lang))
end
is_nounclass = false
end
-- Ensure that the specifications are either all noun classes, or none are.
if all_is_nounclass == nil then
all_is_nounclass = is_nounclass
elseif all_is_nounclass ~= is_nounclass then
error("Noun classes and genders cannot be mixed. Please use either one or the other.")
end
end
if categories and lang and pos_for_cat then
for i, cat in ipairs(categories) do
categories[i] = cat:gsub("POS", pos_for_cat)
end
end
if all_is_nounclass then
-- Add the processed codes together with slashes
return '<span class="gender">類別' .. concat(formatted_specs, "/") .. "</span>", categories
else
-- Add the processed codes together with spaces
return '<span class="gender">' .. concat(formatted_specs, " ") .. "</span>", categories
end
end
return export