Skip to main content
Version: Next

Variants

Variants fix one edition at export time; generated code and public names stay the same. Luban supports two layers:

LayerProblemAfter export
Field variantsOne field, multiple region/version valuesStill one field name (e.g. item_id)
Table variants (since v5.1.0)Same table name, multiple definitions (different input / even different value type)Still one table (e.g. TbItem)

Both share the --variant CLI option and --variant default=....


Field variants

One logical field, multiple value sets: on export, only the currently selected set remains, instead of keeping item_id_zh / item_id_en columns side by side.

Why not split into multiple columns?​

Naive approach:

##variditem_iditem_id_zhitem_id_en
##typeintintintint
1100120013001

Problems: every end carries unused columns; code must pick which column to read. After variant export, only one item_id remains.

Declaring in Schema​

XML:

<bean name="TestVariant">
<var name="id" type="int"/>
<var name="value" type="int" variants="zh,en,fr"/>
</bean>

__beans__.xlsx: fill the variants column on the field row (e.g. zh,en,fr), following your template.

How to write Excel headers​

Add a column per variant: {fieldName}@{variantName}.

Rules:

  1. Variant columns must come after the original field column (value@en to the right of value).
  2. Variant columns do not need their own ##type / ##group; they inherit from the original field.
##varidvaluevalue@zhvalue@en
##typeintint
##groupc,s
1100120013001
210023002

Reading: the original value column is the default/fallback; value@zh and value@en override per variant.

Other data sources​

FormatExample
json"value@en": 1001
yamlvalue@en: 1001
lua["value@en"] = 1001
xml<value variant="en">1001</value>

Field variants: choosing on export​

# Per field: variantKey = {Bean full name}.{field name}
--variant test.TestVariant.value=en

# Global default variant (used by fields not specified individually)
--variant default=zh
SituationBehavior
en is selected and value@en existsUse the variant column
en is selected but value@en is missingFall back to the original field value
variants are defined but CLI has no --variantUse the original field and emit a warning log
Both variant and original field are missingError

You may pass multiple --variant options for different fields.


Table variants

Version requirement

Table variants are supported since v5.1.0. Earlier releases only have field variants.

You may declare multiple definitions for the same table name; each belongs to one (or several) variants. One generation keeps only one definition. FullName, generated type names, ref=TbItem, and output file names never carry suffixes like @zh.

Table variants are whole-definition replacement (swap input; you may also swap value / mode, etc.). They are not field-style “extra columns with fallback”, and they do not merge records.

Declaring in Schema​

Use the singular attribute variant (which variants this table belongs to), distinct from field variants (allowed list).

XML:

<!-- No variant: fallback / default table -->
<table name="TbItem" value="Item" input="item.xlsx"/>

<!-- Per-variant input; value type may differ -->
<table name="TbItem" variant="zh" value="Item" input="item_zh.xlsx"/>
<table name="TbItem" variant="en" value="ItemEn" input="item_en.xlsx"/>

<!-- One definition shared by multiple variants -->
<table name="TbGlobal" variant="zh,en" value="Global" input="global.xlsx"/>

__tables__.xlsx: add a variant column; empty cell means fallback. Older sheets without that column still load (treated as no variants).

full_namevariantvalue_typeinput
TbItemItemitem.xlsx
TbItemzhItemitem_zh.xlsx
TbItemenItemEnitem_en.xlsx
TbGlobalzh,enGlobalglobal.xlsx

Table variants: choosing on export​

Same --variant map as field variants; default is shared:

# By full name (preferred) or short name
--variant cfg.TbItem=zh
--variant TbItem=zh

# Global default: applies to both fields and tables
--variant default=zh

# Global en, one table overridden to zh
--variant default=en --variant TbItem=zh

Lookup order per logical table:

  1. --variant {FullName}=x
  2. --variant {Name}=x
  3. --variant default=x
  4. none → unset

Ordinary tables (no tagged variant definitions under that full name) skip variant logic and ignore default.

SituationBehavior
zh is selected and a definition with variant=zh (or zh,en) existsUse that definition
Selected variant misses, but a fallback (no variant) existsUse fallback and emit a warning
No --variant, but fallback existsUse fallback and emit a warning
Selected variant misses and no fallbackError
No --variant and no fallback (all tagged)Error
Duplicate variant or two fallbacks under the same full nameError

Structure constraints​

  • Must match: table name and namespace (grouping key)
  • May differ: input, value, mode, index, group, tags, comment, output, readSchemaFromFile

When packaging per variant, generated code may follow the selected table definition (e.g. en uses another Bean).


Field vs table variants

DimensionField variantsTable variants
DeclarationOne field: variants="zh,en"Multiple same-name tables, each with variant="zh"
Data shapeExtra columns / keys; miss → original fieldEach table has its own input (and value); whole replace
CLI key{Bean full name}.{field}{Table full name}, then short name
UnsetOriginal column + warningFallback table + warning; error if none

Choosing vs L10N text tables

ApproachBest for
Field variantsSame field with multi-region numbers/short copy, fixed at export
Table variantsWhole table swaps data source or schema by region/channel
text + text tablekey → multi-language long copy, replaced at runtime or generation; see Localization

Prefer one primary approach per project to avoid maintaining multiple hard-to-sync systems.