<table' then
		-- Assume list text is for a subgroup navbox so no automatic striping for this row.
		oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part
	end

	local liststyle_and_num = format
	local listclass_and_num = format
	listCell
				(index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em'
			)

	if index == 1 and args[cfg.arg.image] then
		row
	end
end

local function has_list_class(htmlclass)
	local patterns = {
		'^' .. htmlclass .. '$',
		'%s' .. htmlclass .. '$',
		'^' .. htmlclass .. '%s',
		'%s' .. htmlclass .. '%s'
	
	for arg, _ in pairs(args) do
		if type(arg) == 'string' and mw.ustring.find then
			for _, pattern in ipairs(patterns) do
				if mw.ustring.find then
					return true
				end
			end
		end
	end
	return false
end

-- there are a lot of list classes in the wild, so we add their TemplateStyles
local function add_list_styles
	local frame = mw.getCurrentFrame
	local function add_list_templatestyles
		if has_list_class(htmlclass) then
			return frame:extensionTag{
				name = 'templatestyles', args = { src = templatestyles }
		else
			return ''
		end
	end
	
	local hlist_styles = add_list_templatestyles
	local plainlist_styles = add_list_templatestyles
	
	-- a second workaround for phab:T303378
	-- when that issue is fixed, we can actually use has_navbar not to emit the
	-- tag here if we want
	if has_navbar and hlist_styles == '' then
		hlist_styles = frame:extensionTag{
			name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
	end
	
	-- hlist -> plainlist is best-effort to preserve old Common.css ordering.
	-- this ordering is not a guarantee because most navboxes will emit only
	-- one of these classes [hlist_note]
	return hlist_styles .. plainlist_styles
end

local function needsHorizontalLists(border)
	if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then
		return false
	end
	return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist)
end

local function hasBackgroundColors
	for _, key in ipairs do
		if tostring(args[key]):find then
			return true
		end
	end
	return false
end

local function hasBorders
	for _, key in ipairs do
		if tostring(args[key]):find then
			return true
		end
	end
	return false
end

local function isIllegible
	local styleratio = require('Module:Color contrast')._styleratio
	for key, style in pairs(args) do
		if tostring(key):match(cfg.pattern.style) then
			if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
				return true
			end
		end
	end
	return false
end

local function getTrackingCategories(border)
	local cats = {}
	if needsHorizontalLists(border) then table.insert end
	if hasBackgroundColors then table.insert end
	if isIllegible then table.insert end
	if hasBorders then table.insert end
	return cats
end

local function renderTrackingCategories
	local title = mw.title.getCurrentTitle
	if title.namespace ~= 10 then return end -- not in template space
	local subpage = title.subpageText
	if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox
		or subpage == cfg.keyword.subpage_testcases then return end

	for _, cat in ipairs(getTrackingCategories(border)) do
		builder:wikitext('분류:' .. cat .. '')
	end
end

local function renderMainTable
	local tbl = mw.html.create('table')

	local state = args[cfg.arg.state]
	if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then
		if state == cfg.keyword.state_collapsed then
			state = cfg.class.collapsed
		end
		tbl
	end

	tbl:css
	if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then
		tbl
	else -- regular navbox - bodystyle and style will be applied to the wrapper table
		tbl
	end
	tbl:cssText(args[cfg.arg.innerstyle])

	renderTitleRow(tbl)
	renderAboveRow(tbl)
	local listnums_size = #listnums
	for i, listnum in ipairs(listnums) do
		renderListRow
	end
	renderBelowRow(tbl)

	return tbl
end

local function add_navbox_styles(hiding_templatestyles)
	local frame = mw.getCurrentFrame
	-- This is a lambda so that it doesn't need the frame as a parameter
	local function add_user_styles(templatestyles)
		if templatestyles and templatestyles ~= '' then
			return frame:extensionTag{
				name = 'templatestyles', args = { src = templatestyles }
		end
		return ''
	end

	-- get templatestyles. load base from config so that Lua only needs to do
	-- the work once of parser tag expansion
	local base_templatestyles = cfg.templatestyles
	local templatestyles = add_user_styles(args[cfg.arg.templatestyles])
	local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles])

	-- The 'navbox-styles' div exists to wrap the styles to work around T200206
	-- more elegantly. Instead of combinatorial rules, this ends up being linear
	-- number of CSS rules.
	return mw.html.create('div')
			add_list_styles .. -- see [hlist_note] applied to 'before base_templatestyles'
			base_templatestyles ..
			templatestyles ..
			child_templatestyles ..
			table.concat(hiding_templatestyles)
		)
end

-- work around phab:T303378
-- for each arg: find all the templatestyles strip markers, insert them into a
-- table. then remove all templatestyles markers from the arg
local function move_hiding_templatestyles(args)
	local gfind = string.gfind
	local gsub = string.gsub
	local templatestyles_markers = {}
	local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
	for k, arg in pairs(args) do
		for marker in gfind do
			table.insert
		end
		args[k] = gsub
	end
	return templatestyles_markers
end

function p._navbox(navboxArgs)
	args = navboxArgs
	local hiding_templatestyles = move_hiding_templatestyles(args)
	local listnums = {}

	for k, _ in pairs(args) do
		if type(k) == 'string' then
			local listnum = k:match(cfg.pattern.listnum)
			if listnum then table.insert(listnums, tonumber(listnum)) end
		end
	end
	table.sort(listnums)

	local border = mw.text.trim(args[cfg.arg.border] or args[1] or '')
	if border == '자식' then
		border = 'child'
	end

	if border == '중첩' then
		border = 'subgroup'
	end

	if border == cfg.keyword.border_child then
		border = cfg.keyword.border_subgroup
	end

	-- render the main body of the navbox
	local tbl = renderMainTable

	local res = mw.html.create
	-- render the appropriate wrapper for the navbox, based on the border param

	if border == cfg.keyword.border_none then
		res:node(add_navbox_styles(hiding_templatestyles))
		local nav = res:tag('div')
		-- aria-labelledby title, otherwise above, otherwise lone group
		if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1]
			and not args[cfg.arg.group2]) then
			nav:attr(
				'aria-labelledby',
				mw.uri.anchorEncode(
					args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
				)
			)
		else
			nav:attr
		end
	elseif border == cfg.keyword.border_subgroup then
		-- We assume that this navbox is being rendered in a list cell of a
		-- parent navbox, and is therefore inside a div with padding:0em 0.25em.
		-- We start with a  to avoid the padding being applied, and at the
		-- end add a 
		res
	else
		res:node(add_navbox_styles(hiding_templatestyles))
		local nav = res:tag('div')
		-- aria-labelledby title, otherwise above, otherwise lone group
		if args[cfg.arg.title] or args[cfg.arg.above]
			or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then
			nav:attr(
				'aria-labelledby',
				mw.uri.anchorEncode(args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1])
			)
		else
			nav:attr
		end
	end

	if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower == cfg.keyword.nocat_false then
		renderTrackingCategories
	end
	return striped(tostring(res), border)
end

local param_ko = {
 ['이름'] = 'name',
 ['제목'] = 'title',
 ['상태'] = 'state',
 ['그림'] = 'image',
 ['왼쪽그림'] = 'imageleft',
 ['윗글'] = 'above',
 ['아랫글'] = 'below',
 ['안내바'] = 'navbar',
 ['테두리'] = 'border',
 
 ['모양'] = 'style',
 ['기본모양'] = 'basestyle',
 ['전체모양'] = 'bodystyle',
 ['제목모양'] = 'titlestyle',
 ['내용모양'] = 'liststyle',
 ['묶음모양'] = 'groupstyle',
 ['묶음너비'] = 'groupwidth',
 ['내용여백'] = 'listpadding',
 ['홀수모양'] = 'oddstyle',
 ['짝수모양'] = 'evenstyle',
 ['홀짝'] = 'evenodd',
 ['윗글모양'] = 'abovestyle',
 ['아랫글모양'] = 'belowstyle',
 ['그림모양'] = 'imagestyle',
 ['왼쪽그림모양'] = 'imageleftstyle',
 
 ['전체속성'] = 'bodyclass',
 ['제목속성'] = 'titleclass',
 ['윗글속성'] = 'aboveclass',
 ['묶음속성'] = 'groupclass',
 ['내용속성'] = 'listclass',
 ['아랫글속성'] = 'belowclass',

 ['제목묶음'] = 'titlegroup',
 ['제목묶음속성'] = 'titlegroupclass',
 ['제목묶음모양'] = 'titlegroupstyle',
 
 ['내부모양'] = 'innerstyle',

for i = 1, 60 do
 param_ko['묶음' .. i] = 'group' .. i
 param_ko['묶음' .. i .. '모양'] = 'group' .. i .. 'style'
 param_ko['내용' .. i] = 'list' .. i
 param_ko['내용' .. i .. '모양'] = 'list' .. i .. 'style'
end

local function localname(parameter)
 return param_ko[parameter] or parameter
end

function p.navbox(frame)
	if not getArgs then
		getArgs = require('Module:Arguments').getArgs
	end
	local args = {}
	local parent_args = getArgs

	-- Read the arguments in the order they'll be output in, to make references
	-- number in the right order.
	local _
	_ = parent_args[cfg.arg.title] or parent_args['제목']
	_ = parent_args[cfg.arg.above] or parent_args['윗글']
	for i = 1, 60 do
		_ = parent_args[format] or parent_args["묶음" .. tostring(i)]
		_ = parent_args[format] or parent_args["내용" .. tostring(i)]
	end
	_ = parent_args[cfg.arg.below] or parent_args["아랫글"]

 for k, v in pairs(parent_args) do
 if v ~= '' then
 args[localname(k)] = v
 end
 end

	return p._navbox(args)
end