Difference between revisions of "Module:Card/models/Locale"
(some fixes to `getHtmlLang`, add `getRomanizedHtmlLang`) |
(It should still be okay to make this local.) |
||
(20 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
+ | local Ruby = require('Module:Ruby') | ||
+ | |||
+ | -- Generic functions | ||
+ | |||
+ | -- Check if a value is filled (i.e. not `nil` or an empty string) | ||
+ | -- @param value mixed | ||
+ | -- @return boolean | ||
+ | local function isFilled(value) | ||
+ | return (value ~= nil and value ~= '') | ||
+ | end | ||
+ | |||
+ | |||
-- Base object for the Locale | -- Base object for the Locale | ||
-- Represents a card's details in a particular language | -- Represents a card's details in a particular language | ||
Line 9: | Line 21: | ||
-- @field pendulumEffect string The card's Penudlum Effect | -- @field pendulumEffect string The card's Penudlum Effect | ||
-- @field material string The material portion of the card's lore | -- @field material string The material portion of the card's lore | ||
+ | -- @field summoningCondition string The Summoning condition portion of the card's lore | ||
+ | -- @field requirement string The requirement portion of the card's lore (Should not include the '[REQUIREMENT]' prefix) | ||
-- @field lore string The card description/effect portion of the lore (Should not include italic markup) | -- @field lore string The card description/effect portion of the lore (Should not include italic markup) | ||
− | -- @field | + | -- @field condition string The condition portion of the lore (Should not include parentheses) |
local Locale = { | local Locale = { | ||
lang = nil, | lang = nil, | ||
name = nil, | name = nil, | ||
romanizedName = nil, | romanizedName = nil, | ||
+ | baseRomanizedName = nil, | ||
translatedName = nil, | translatedName = nil, | ||
+ | baseTranslatedName = nil, | ||
pendulumEffect = nil, | pendulumEffect = nil, | ||
material = nil, | material = nil, | ||
+ | requirement = nil, | ||
lore = nil, | lore = nil, | ||
− | + | condition = nil, | |
} | } | ||
Line 29: | Line 46: | ||
romanizedNames = false, | romanizedNames = false, | ||
italicLores = true, | italicLores = true, | ||
+ | text = { | ||
+ | ['Requirement'] = '[REQUIREMENT]', | ||
+ | ['Effect'] = '[EFFECT]', | ||
+ | ['Continuous Effect'] = '[CONTINUOUS EFFECT]', | ||
+ | ['Multi-Choice Effect'] = '[MULTI-CHOICE EFFECT]' | ||
+ | } | ||
}, | }, | ||
fr = { | fr = { | ||
Line 36: | Line 59: | ||
romanizedNames = false, | romanizedNames = false, | ||
italicLores = true, | italicLores = true, | ||
+ | text = {} | ||
}, | }, | ||
de = { | de = { | ||
Line 43: | Line 67: | ||
romanizedNames = false, | romanizedNames = false, | ||
italicLores = true, | italicLores = true, | ||
+ | text = {} | ||
}, | }, | ||
it = { | it = { | ||
Line 50: | Line 75: | ||
romanizedNames = false, | romanizedNames = false, | ||
italicLores = true, | italicLores = true, | ||
+ | text = {} | ||
}, | }, | ||
pt = { | pt = { | ||
Line 57: | Line 83: | ||
romanizedNames = false, | romanizedNames = false, | ||
italicLores = true, | italicLores = true, | ||
+ | text = {} | ||
}, | }, | ||
es = { | es = { | ||
Line 64: | Line 91: | ||
romanizedNames = false, | romanizedNames = false, | ||
italicLores = true, | italicLores = true, | ||
+ | text = {} | ||
}, | }, | ||
ja = { | ja = { | ||
Line 71: | Line 99: | ||
romanizedNames = true, | romanizedNames = true, | ||
italicLores = false, | italicLores = false, | ||
+ | text = { | ||
+ | ['Requirement'] = '【<ruby><rb>条</rb><rt>じょう</rt><rb>件</rb><rt>けん</rt>】', | ||
+ | ['Effect'] = '【<ruby><rb>効</rb><rt>こう</rt><rb>果</rb><rt>か</rt>】', | ||
+ | ['Continuous Effect'] = '【<ruby><rb>永</rb><rt>えい</rt><rb>続</rb><rt>ぞく</rt><rb>効</rb><rt>こう</rt><rb>果</rb><rt>か</rt></ruby>】', | ||
+ | ['Multi-Choice Effect'] = '【<ruby><rb>選</rb><rt>せん</rt><rb>択</rb><rt>たく</rt><rb>効</rb><rt>こう</rt><rb>果</rb><rt>か</rt></ruby>】' | ||
+ | } | ||
}, | }, | ||
zh = { | zh = { | ||
Line 78: | Line 112: | ||
romanizedNames = true, | romanizedNames = true, | ||
italicLores = false, | italicLores = false, | ||
+ | text = {} | ||
}, | }, | ||
tc = { | tc = { | ||
Line 83: | Line 118: | ||
langCode = 'zh', | langCode = 'zh', | ||
scriptCode = 'Hant', | scriptCode = 'Hant', | ||
− | romanizedNames = | + | romanizedNames = true, |
− | italicLores = | + | italicLores = false, |
+ | text = {} | ||
}, | }, | ||
sc = { | sc = { | ||
Line 92: | Line 128: | ||
romanizedNames = true, | romanizedNames = true, | ||
italicLores = false, | italicLores = false, | ||
+ | text = {} | ||
}, | }, | ||
ko = { | ko = { | ||
Line 99: | Line 136: | ||
romanizedNames = true, | romanizedNames = true, | ||
italicLores = false, | italicLores = false, | ||
+ | text = { | ||
+ | ['Requirement'] = '【조건】', | ||
+ | ['Effect'] = '【효과】', | ||
+ | ['Continuous Effect'] = '【지속 효과】', | ||
+ | ['Multi-Choice Effect'] = '【선택 효과】' | ||
+ | } | ||
}, | }, | ||
+ | ru = { | ||
+ | name = 'Russian', | ||
+ | langCode = 'ru', | ||
+ | scriptCode = nil, | ||
+ | romanizedNames = true, | ||
+ | italicLores = false, | ||
+ | text = {} | ||
+ | } | ||
} | } | ||
Line 108: | Line 159: | ||
function Locale:new(lang, params) | function Locale:new(lang, params) | ||
-- Create a new instance of the Locale class with all the default values | -- Create a new instance of the Locale class with all the default values | ||
− | local l = | + | local l = mw.clone(Locale) |
− | |||
− | |||
-- English parameters don't have a prefix e.g. `name`, `lore` | -- English parameters don't have a prefix e.g. `name`, `lore` | ||
Line 118: | Line 167: | ||
l.lang = lang | l.lang = lang | ||
l.language = languages[lang] | l.language = languages[lang] | ||
− | l.name = params[prefix .. 'name'] | + | l.name = params[prefix .. 'name'] or nil |
− | l.romanizedName = params[prefix .. 'romanized_name'] | + | l.romanizedName = params[prefix .. 'romanized_name'] or nil |
− | l.translatedName = params[prefix .. 'translated_name'] | + | l.baseRomanizedName = params[prefix .. 'base_romanized_name'] or nil |
− | l.pendulumEffect = params[prefix .. 'pendulum_effect'] | + | l.translatedName = params[prefix .. 'translated_name'] or nil |
− | l.material = params[prefix .. 'material'] | + | l.baseTranslatedName = params[prefix .. 'base_translated_name'] or nil |
− | l.lore = params[prefix .. 'lore'] | + | l.pendulumEffect = params[prefix .. 'pendulum_effect'] or nil |
− | l. | + | l.material = params[prefix .. 'material'] or nil |
+ | l.summoningCondition = params[prefix .. 'summoning_condition'] or nil | ||
+ | l.requirement = params[prefix .. 'requirement'] or nil | ||
+ | l.lore = params[prefix .. 'lore'] or nil | ||
+ | l.condition = params[prefix .. 'condition'] or nil | ||
return l | return l | ||
Line 156: | Line 209: | ||
-- table mapping labels to standardized ones | -- table mapping labels to standardized ones | ||
local mappings = { | local mappings = { | ||
− | romaji_name = 'ja_romanized_name', | + | romaji_name = 'ja_romanized_name', |
− | trans_name = ' | + | base_romaji_name = 'ja_base_romanized_name', |
− | ko_rr_name | + | trans_name = 'ja_translated_name', |
+ | base_trans_name = 'ja_base_translated_name', | ||
+ | zh_pinyin_name = 'zh_romanized_name', | ||
+ | tc_pinyin_name = 'tc_romanized_name', | ||
+ | sc_pinyin_name = 'sc_romanized_name', | ||
+ | ko_rr_name = 'ko_romanized_name' | ||
} | } | ||
Line 182: | Line 240: | ||
-- Check if at least one param is supplied for the language | -- Check if at least one param is supplied for the language | ||
return ( | return ( | ||
− | params[lang .. '_name'] or | + | isFilled(params[lang .. '_name']) or |
− | params[lang .. '_lore'] or | + | isFilled(params[lang .. '_lore']) or |
− | params[lang .. '_pendulum_effect'] or | + | isFilled(params[lang .. '_pendulum_effect']) or |
− | params[lang .. '_material'] or | + | isFilled(params[lang .. '_material']) or |
− | params[lang .. '_archetype_condition'] or | + | isFilled(params[lang .. '_archetype_condition']) or |
− | params[lang .. '_romanized_name'] or | + | isFilled(params[lang .. '_summoning_condition']) or |
− | params[lang .. '_translated_name'] | + | isFilled(params[lang .. '_romanized_name']) or |
− | ) | + | isFilled(params[lang .. '_translated_name']) |
+ | ) | ||
+ | end | ||
+ | |||
+ | -- Get the name without any ruby annotations | ||
+ | -- e.g. デーモンの{{Ruby|召|しょう}}{{Ruby|喚|かん}} → デーモンの召喚 | ||
+ | -- @return string | ||
+ | function Locale:getBaseName() | ||
+ | return Ruby.split(self.name) | ||
end | end | ||
− | -- Get the name | + | -- Get the name favoring "top" text over base text for ruby annotations |
+ | -- e.g. デーモンの{{Ruby|召|しょう}}{{Ruby|喚|かん}} → デーモンのしょうかん | ||
-- @return string | -- @return string | ||
− | function Locale: | + | function Locale:getTopName() |
− | return self | + | return Ruby.split(self.name, 'top') |
end | end | ||
Line 215: | Line 282: | ||
function Locale:getRomanizedHtmlLang() | function Locale:getRomanizedHtmlLang() | ||
return self.language.langCode .. '-Latn' | return self.language.langCode .. '-Latn' | ||
+ | end | ||
+ | |||
+ | -- Get a piece of text in the current language | ||
+ | -- @param message string | ||
+ | -- @return string | ||
+ | function Locale:getText(message) | ||
+ | -- If the language has a translation for the message use that | ||
+ | return self.language.text[message] | ||
+ | -- Otherwise use the English one if it exists | ||
+ | or languages.en[message] | ||
+ | -- Otherwise just return the supplied text | ||
+ | or message | ||
end | end | ||
-- Put the material, lore and archetype condition together to form the full lore | -- Put the material, lore and archetype condition together to form the full lore | ||
− | -- @param | + | -- @param card Card The full card object |
-- @return string | -- @return string | ||
− | function Locale:getFullLore( | + | function Locale:getFullLore(card) |
local output = '' | local output = '' | ||
− | local | + | local condition = nil |
− | if (self. | + | if (self.condition) then |
− | + | condition = '(' .. self.condition .. ')' | |
end | end | ||
-- Handle Normal Monsters | -- Handle Normal Monsters | ||
-- Lore (with italics depending on language, followed by archetype condition) | -- Lore (with italics depending on language, followed by archetype condition) | ||
− | if (isNormalMonster) then | + | if (card.isNormalMonster) then |
− | local output = self.lore | + | local output = isFilled(self.lore) and self.lore or '' |
− | + | ||
− | if (self.language.italicLores) then | + | if (self.language.italicLores and isFilled(self.lore)) then |
− | output = | + | output = '<i>' .. self.lore .. '</i>' |
end | end | ||
− | if ( | + | if (condition) then |
− | output = output .. '<br /><br />' .. | + | output = output .. '<br /><br />' .. condition |
end | end | ||
Line 245: | Line 324: | ||
-- Handle everything else | -- Handle everything else | ||
− | -- Array of different lore | + | lore = self.lore |
+ | requirement = self.requirement | ||
+ | |||
+ | -- If there is a requirement, prefix the lore and requirement with their labels | ||
+ | if (isFilled(self.requirement)) then | ||
+ | requirement = '<b>' .. self:getText('Requirement') .. '</b> ' .. requirement | ||
+ | lore = '<b>' .. self:getText(card.mainEffectType or 'Effect') .. '</b> ' .. lore | ||
+ | end | ||
+ | |||
+ | -- Array of different lore components | ||
local loreParts = { | local loreParts = { | ||
self.material or nil, | self.material or nil, | ||
− | + | condition or nil, | |
− | self.lore or nil | + | self.summoningCondition or nil, |
+ | requirement, | ||
+ | lore or nil, | ||
} | } | ||
− | + | ||
-- Remove empty values | -- Remove empty values | ||
loreParts = TableTools.compressSparseArray(loreParts) | loreParts = TableTools.compressSparseArray(loreParts) |
Latest revision as of 02:48, 27 December 2023
local Ruby = require('Module:Ruby')
-- Generic functions
-- Check if a value is filled (i.e. not `nil` or an empty string)
-- @param value mixed
-- @return boolean
local function isFilled(value)
return (value ~= nil and value ~= '')
end
-- Base object for the Locale
-- Represents a card's details in a particular language
--
-- Unless otherwise stated, string params are in the language in question
-- @field lang string Two-letter code for the language
-- @field name string The card's name
-- @field romanizedName string The card's name, romanized
-- @field translatedName string The card's name, translated into English
-- @field pendulumEffect string The card's Penudlum Effect
-- @field material string The material portion of the card's lore
-- @field summoningCondition string The Summoning condition portion of the card's lore
-- @field requirement string The requirement portion of the card's lore (Should not include the '[REQUIREMENT]' prefix)
-- @field lore string The card description/effect portion of the lore (Should not include italic markup)
-- @field condition string The condition portion of the lore (Should not include parentheses)
local Locale = {
lang = nil,
name = nil,
romanizedName = nil,
baseRomanizedName = nil,
translatedName = nil,
baseTranslatedName = nil,
pendulumEffect = nil,
material = nil,
requirement = nil,
lore = nil,
condition = nil,
}
local languages = {
en = {
name = 'English',
LangCode = 'en',
scriptCode = nil,
romanizedNames = false,
italicLores = true,
text = {
['Requirement'] = '[REQUIREMENT]',
['Effect'] = '[EFFECT]',
['Continuous Effect'] = '[CONTINUOUS EFFECT]',
['Multi-Choice Effect'] = '[MULTI-CHOICE EFFECT]'
}
},
fr = {
name = 'French',
langCode = 'fr',
scriptCode = nil,
romanizedNames = false,
italicLores = true,
text = {}
},
de = {
name = 'German',
langCode = 'de',
scriptCode = nil,
romanizedNames = false,
italicLores = true,
text = {}
},
it = {
name = 'Italian',
langCode = 'it',
scriptCode = nil,
romanizedNames = false,
italicLores = true,
text = {}
},
pt = {
name = 'Portuguese',
langCode = 'pt',
scriptCode = nil,
romanizedNames = false,
italicLores = true,
text = {}
},
es = {
name = 'Spanish',
langCode = 'es',
scriptCode = nil,
romanizedNames = false,
italicLores = true,
text = {}
},
ja = {
name = 'Japanese',
langCode = 'ja',
scriptCode = 'Japn',
romanizedNames = true,
italicLores = false,
text = {
['Requirement'] = '【<ruby><rb>条</rb><rt>じょう</rt><rb>件</rb><rt>けん</rt>】',
['Effect'] = '【<ruby><rb>効</rb><rt>こう</rt><rb>果</rb><rt>か</rt>】',
['Continuous Effect'] = '【<ruby><rb>永</rb><rt>えい</rt><rb>続</rb><rt>ぞく</rt><rb>効</rb><rt>こう</rt><rb>果</rb><rt>か</rt></ruby>】',
['Multi-Choice Effect'] = '【<ruby><rb>選</rb><rt>せん</rt><rb>択</rb><rt>たく</rt><rb>効</rb><rt>こう</rt><rb>果</rb><rt>か</rt></ruby>】'
}
},
zh = {
name = 'Chinese',
langCode = 'zh',
scriptCode = nil,
romanizedNames = true,
italicLores = false,
text = {}
},
tc = {
name = 'Traditional Chinese',
langCode = 'zh',
scriptCode = 'Hant',
romanizedNames = true,
italicLores = false,
text = {}
},
sc = {
name = 'Simplified Chinese',
langCode = 'zh',
scriptCode = 'Hans',
romanizedNames = true,
italicLores = false,
text = {}
},
ko = {
name = 'Korean',
langCode = 'ko',
scriptCode = nil,
romanizedNames = true,
italicLores = false,
text = {
['Requirement'] = '【조건】',
['Effect'] = '【효과】',
['Continuous Effect'] = '【지속 효과】',
['Multi-Choice Effect'] = '【선택 효과】'
}
},
ru = {
name = 'Russian',
langCode = 'ru',
scriptCode = nil,
romanizedNames = true,
italicLores = false,
text = {}
}
}
-- Create a new instance of the Locale object
-- @param lang string The language code
-- @param params table
-- @return Locale
function Locale:new(lang, params)
-- Create a new instance of the Locale class with all the default values
local l = mw.clone(Locale)
-- English parameters don't have a prefix e.g. `name`, `lore`
-- Other languages use their code as their prefix e.g. `ja_name`, `ja_lore`
local prefix = lang == 'en' and '' or lang .. '_'
l.lang = lang
l.language = languages[lang]
l.name = params[prefix .. 'name'] or nil
l.romanizedName = params[prefix .. 'romanized_name'] or nil
l.baseRomanizedName = params[prefix .. 'base_romanized_name'] or nil
l.translatedName = params[prefix .. 'translated_name'] or nil
l.baseTranslatedName = params[prefix .. 'base_translated_name'] or nil
l.pendulumEffect = params[prefix .. 'pendulum_effect'] or nil
l.material = params[prefix .. 'material'] or nil
l.summoningCondition = params[prefix .. 'summoning_condition'] or nil
l.requirement = params[prefix .. 'requirement'] or nil
l.lore = params[prefix .. 'lore'] or nil
l.condition = params[prefix .. 'condition'] or nil
return l
end
-- Create many instances of the Locale object
-- @param langs array List of language codes
-- @param params table
-- @return table Mapping of language codes to Locale objects
function Locale:createMany(langs, params)
params = Locale.normalizeParams(params)
-- List of all Locale objects for the card
local locales = {}
for _, lang in pairs(langs) do
-- Only add to the list if there is data for this language
if (Locale.hasParams(lang, params)) then
locales[lang] = self:new(lang, params)
end
end
return locales
end
-- Normalize the input params
-- Relable params to use a consistent format across all languages.
-- e.g. "romaji_name", "ko_rr_name" → "ja_romanized_name", "ko_romanized_name"
-- @param params table
function Locale.normalizeParams(params)
-- table mapping labels to standardized ones
local mappings = {
romaji_name = 'ja_romanized_name',
base_romaji_name = 'ja_base_romanized_name',
trans_name = 'ja_translated_name',
base_trans_name = 'ja_base_translated_name',
zh_pinyin_name = 'zh_romanized_name',
tc_pinyin_name = 'tc_romanized_name',
sc_pinyin_name = 'sc_romanized_name',
ko_rr_name = 'ko_romanized_name'
}
-- Loop through the mappings
-- If the old label is used in params, also its value under the new label
for inputParam, normalizedParam in pairs(mappings) do
if params[inputParam] then
params[normalizedParam] = params[inputParam]
end
end
return params
end
-- Check if a supplied input has params in a specified language
-- @param lang string
-- @param params table - Input params (after normalization)
-- @return boolean
function Locale.hasParams(lang, params)
-- There should always be an English
if lang == 'en' then return true end
-- Check if at least one param is supplied for the language
return (
isFilled(params[lang .. '_name']) or
isFilled(params[lang .. '_lore']) or
isFilled(params[lang .. '_pendulum_effect']) or
isFilled(params[lang .. '_material']) or
isFilled(params[lang .. '_archetype_condition']) or
isFilled(params[lang .. '_summoning_condition']) or
isFilled(params[lang .. '_romanized_name']) or
isFilled(params[lang .. '_translated_name'])
)
end
-- Get the name without any ruby annotations
-- e.g. デーモンの{{Ruby|召|しょう}}{{Ruby|喚|かん}} → デーモンの召喚
-- @return string
function Locale:getBaseName()
return Ruby.split(self.name)
end
-- Get the name favoring "top" text over base text for ruby annotations
-- e.g. デーモンの{{Ruby|召|しょう}}{{Ruby|喚|かん}} → デーモンのしょうかん
-- @return string
function Locale:getTopName()
return Ruby.split(self.name, 'top')
end
-- Get the code for the HTML lang attribute
-- i.e. text that appears inside `lang="..."` in HTML
-- @return string
function Locale:getHtmlLang()
local output = self.language.langCode
if (self.language.scriptCode ~= nil) then
output = output .. '-' .. self.language.scriptCode
end
return output
end
-- Get the code for the HTML lang attribute for romanized text
-- @return string
function Locale:getRomanizedHtmlLang()
return self.language.langCode .. '-Latn'
end
-- Get a piece of text in the current language
-- @param message string
-- @return string
function Locale:getText(message)
-- If the language has a translation for the message use that
return self.language.text[message]
-- Otherwise use the English one if it exists
or languages.en[message]
-- Otherwise just return the supplied text
or message
end
-- Put the material, lore and archetype condition together to form the full lore
-- @param card Card The full card object
-- @return string
function Locale:getFullLore(card)
local output = ''
local condition = nil
if (self.condition) then
condition = '(' .. self.condition .. ')'
end
-- Handle Normal Monsters
-- Lore (with italics depending on language, followed by archetype condition)
if (card.isNormalMonster) then
local output = isFilled(self.lore) and self.lore or ''
if (self.language.italicLores and isFilled(self.lore)) then
output = '<i>' .. self.lore .. '</i>'
end
if (condition) then
output = output .. '<br /><br />' .. condition
end
return output
end
-- Handle everything else
lore = self.lore
requirement = self.requirement
-- If there is a requirement, prefix the lore and requirement with their labels
if (isFilled(self.requirement)) then
requirement = '<b>' .. self:getText('Requirement') .. '</b> ' .. requirement
lore = '<b>' .. self:getText(card.mainEffectType or 'Effect') .. '</b> ' .. lore
end
-- Array of different lore components
local loreParts = {
self.material or nil,
condition or nil,
self.summoningCondition or nil,
requirement,
lore or nil,
}
-- Remove empty values
loreParts = TableTools.compressSparseArray(loreParts)
-- Join the components, separating each with a line break
return table.concat(loreParts, '<br />')
end
return Locale