status: proposed date: 2026-03-15
ADR-0038: Alternate Names and Localization Support
Context and Problem Statement
The Game entity currently has a single name field and a sort_name field. Board games are published internationally under different names – Brass: Birmingham has alternate names in Russian (Brass. Бирмингем), Ukrainian (Brass. Бірмінгем), Japanese (ブラス:バーミンガム), Chinese (工业革命:伯明翰), and Korean (브라스: 버밍엄). Without alternate name storage, these names are invisible to search, making the API unusable for non-English discovery. BGG tracks alternate names per game; OpenTabletop must do the same to support international adoption and BGG migration (ADR-0032).
Decision Drivers
- International editions have localized names that users search by – a Japanese user searches “ブラス:バーミンガム”, not “Brass: Birmingham”
- Full-text search (ADR-0027) currently indexes only
nameandsort_name, missing all localized names - BGG migration requires importing alternate names to maintain search parity
- Game editions (ADR-0035) relate to localized names but serve a different purpose – edition names identify products, alternate names identify the game itself
- The change is small (one new schema, one new array field) with outsized impact on global usability
Considered Options
- Array of strings on Game – Simple
alternate_names: string[]with no metadata - Structured AlternateName schema with language and source – Each alternate name carries a BCP 47 language tag, primary flag, and source attribution
- Derive alternate names from editions – Use
GameEdition.nameas the source of localized names, no separate storage
Decision Outcome
Chosen option: “Structured AlternateName schema,” because language tags enable language-specific search indexing (e.g., Japanese tokenizer for Japanese names) and source attribution supports data provenance tracking. A flat string array loses the language signal that search depends on. Deriving from editions was rejected because alternate names and edition names serve different purposes – an edition name like “Brass: Birmingham – Czech edition 2025” is a product identifier, while the alternate name “Brass. Бірмінгем” is what users search for.
Consequences
- Good, because non-English users can discover games by their localized names
- Good, because full-text search can use language-appropriate tokenizers per alternate name
- Good, because BGG alternate names import directly into this schema
- Good, because source attribution tracks whether a name came from BGG, a publisher, or the community
- Bad, because alternate names may duplicate information already present in edition names – the boundary between the two should be documented clearly
- Bad, because deduplication across sources (same name from BGG and from a publisher submission) requires implementation-level logic
Implementation
New Schema
spec/schemas/AlternateName.yaml – A structured alternate name entry with language metadata.
Fields:
name(string, required) – The alternate namelanguage(string, nullable) – BCP 47 language tag (e.g., “ja”, “zh-Hans”, “ko”)is_primary(boolean, default false) – Whether this is the primary name in its languagesource(string, nullable) – Data source (“bgg”, “publisher”, “community”)
Game Schema Changes
Add alternate_names array to Game.yaml, included via ?include=alternate_names.
Include Parameter
Add alternate_names to the list of available include values in spec/parameters/include.yaml.
Search Integration
Alternate names should be indexed for full-text search (ADR-0027) with language-appropriate analyzers where available.
BGG Migration Mapping
BGG <name type="alternate"> elements map directly to AlternateName entries. The BGG type="primary" name maps to Game.name; all type="alternate" names become AlternateName entries with source: "bgg". Language tags must be inferred from the edition language or detected algorithmically – BGG does not store language metadata on alternate names.