Multilingual Decks+solution+implementation
Data Representation
We will need to make, at a minimum, this alteration to the cards table:
cards
+ lang
+ translatee_id
The basic idea is that if a card is a translation of another card, it will have that card's id as its translatee id. If not, it will have its own id as a translatee_id.
To spell it out a bit, here's how the data would look in the four patterns:
-
Universal: lang is null
-
Monolingual/Mapped: lang is non-null. there is only one card per translatee_id. The complexity of translation type of names composed of different types deserves its out subsection: (in the case of mapped plus cards, cards in all the others languages are virtual)
-
Strict/Free: language is non-null. First card is its own translatee every additional translation has but same translatee_id.
Note that we may need an additional field to flag out-of-date translations.
Representation Details
Here are some representational invariants and constraits to help define the data structures:
- translatee_id is not null
- if lang is null, there are no other translators (besides itself)
- translatee_id is used whenever we need the card with all its translations (Maybe the idea of the languag type General when the language is not specified (yet), which could be used in memory Card objects, but not in cards)
- language is unique within the scope of a translatee_id
- no chains, the translatee card is always its own translatee
- type_id, left_id, right_id are be considered General it that it will always be the translatee_id of the type card.
Name related constraints:
- We have A+B exists => A exists and B exists. This has implications for languages where the card with name and left, right, type references doesn't exist for a particular language and we do have tranlations for all parts of the name (and therefore the whole name).
- Such are card will exist?, but there might not be content for the requested language. UI has to deal with this, representationally this is a card that exists and has content, but no translated content. Developer interface for UI code will signal this state and the UI handles per mode.
Question: is a lang going to be a card or a new model?
How are these translation classes represented? Is it connected to the lang model and by extension a property of tha name and content? Maybe it just isn't represented at this level except by lang = NULL
Database references
- never use the id of a translator card in a type_id, left_id, or right_id reference. Always use the original/translatee
- however, do use the specific translatee id in card_references
name, lang, id, translatee_idCompany, en, 1, 1Firma, de, 2, 1
name, lang, id, translatee_id, type_id
Aldi, de, 3, 3, 1
select * from cards where translatee_id = 1
English in the Codebase
This proposal does not give much attention to handling multiple languages in hard-coded content, like text on buttons, error messages, etc. That’s largely because it’s a very common problem with lots of helpful libraries / methodologies.
My expectation is that we’ll roughly follow the pattern of localization files, and that we’ll do this via “coded card content”, in which code is connected to a card via a codename. This approach is nice because it avoids having to do code migrations with each update, but allows room for wagneers to break away from the codebase if they so desire by removing the card’s codename.
Singularization
Currently Wagn handles singularizing card names with an english-specific algorithm, but this algorithm applies to all cardnames regardless of their language. In the new system, we can introduce Language Specific Key Generation.
Implementation
The proposal as it stands would involve a lot of work, including reworking:
-
the database
-
name processing
-
routing
-
WQL
-
caching
-
inclusion processing
-
links
-
a little bit of everything else
Existing Wagns
We would probably need to make a configuration option to allow existing (and future) wagns to remain monolingual, but we also need an upgrade path for those wishing to to make use of the functionality. The good news is the data migration can be kept very simple.