Skip to content

Commit

Permalink
Merge pull request #151 from eemeli/data-model
Browse files Browse the repository at this point in the history
Update data_model/ts_eemeli in experiments
  • Loading branch information
mihnita authored Feb 15, 2021
2 parents 7aaf1da + 0e8396f commit c328609
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 65 deletions.
147 changes: 94 additions & 53 deletions experiments/data_model/ts_eemeli/data-model-examples.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MF1: { gender, select, male{he} female{she} other{they} }
const genderSelect: Select = {
select: [['gender']],
select: [{ var_path: ['gender'] }],
cases: [
{ key: ['male'], value: ['he'] },
{ key: ['female'], value: ['she'] },
Expand All @@ -10,83 +10,124 @@ const genderSelect: Select = {

// MF1: { count, plural, one{a message} other{# messages} }
const countPlural: Select = {
select: [{ func: 'plural', args: [['count']] }],
select: [{ func: 'plural', args: [{ var_path: ['count'] }] }],
cases: [
{ key: ['one'], value: ['a message'] },
{
key: ['other'],
value: [{ func: 'number', args: [['count']] }, ' messages']
value: [{ func: 'number', args: [{ var_path: ['count'] }] }, ' messages']
}
]
}

const gameMessages: Resource = {
id: 'game-messages',
locale: 'en',
messages: {
monsters: {
dinosaur: { indefinite: ['a Dinosaur'], plural: ['Dinosaurs'] },
elephant: { indefinite: ['an Elephant'], plural: ['Elephants'] },
ogre: { indefinite: ['an Ogre'], plural: ['Ogres'] },
other: { indefinite: ['a Monster'], plural: ['Monsters'] }
},
'killed-by': [
'You have been killed by ',
{ msg: ['monsters', ['monster'], 'indefinite'] }
],
'kill-count': {
select: [
{ func: 'plural', args: [['monster-count']] },
{ func: 'plural', args: [['dungeon-count']] }
],
cases: [
entries: [
{
id: 'monsters',
entries: [
{
id: 'dinosaur',
entries: [
{ id: 'indefinite', value: ['a Dinosaur'] },
{ id: 'plural', value: ['Dinosaurs'] }
]
},
{
key: ['one'],
value: [
'You have killed ',
{ msg: ['monsters', ['monster'], 'indefinite'] },
'.'
id: 'elephant',
entries: [
{ id: 'indefinite', value: ['an Elephant'] },
{ id: 'plural', value: ['Elephants'] }
]
},
{
key: ['other', 'one'],
value: [
'You have killed ',
{ func: 'number', args: [['monster-count']] },
' ',
{ msg: ['monsters', ['monster'], 'plural'] },
' in one dungeon.'
id: 'ogre',
entries: [
{ id: 'indefinite', value: ['an Ogre'] },
{ id: 'plural', value: ['Ogres'] }
]
},
{
key: ['other', 'other'],
value: [
'You have killed ',
{ func: 'number', args: [['monster-count']] },
' ',
{ msg: ['monsters', ['monster'], 'plural'] },
' in ',
{ func: 'number', args: [['dungeon-count']] },
' dungeons.'
id: 'other',
entries: [
{ id: 'indefinite', value: ['a Monster'] },
{ id: 'plural', value: ['Monsters'] }
]
}
]
},
{
id: 'killed-by',
value: [
'You have been killed by ',
{ msg_path: ['monsters', { var_path: ['monster'] }, 'indefinite'] }
]
},
{
id: 'kill-count',
value: {
select: [
{ func: 'plural', args: [{ var_path: ['monster-count'] }] },
{ func: 'plural', args: [{ var_path: ['dungeon-count'] }] }
],
cases: [
{
key: ['one'],
value: [
'You have killed ',
{
msg_path: ['monsters', { var_path: ['monster'] }, 'indefinite']
},
'.'
]
},
{
key: ['other', 'one'],
value: [
'You have killed ',
{ func: 'number', args: [{ var_path: ['monster-count'] }] },
' ',
{ msg_path: ['monsters', { var_path: ['monster'] }, 'plural'] },
' in one dungeon.'
]
},
{
key: ['other', 'other'],
value: [
'You have killed ',
{ func: 'number', args: [{ var_path: ['monster-count'] }] },
' ',
{ msg_path: ['monsters', { var_path: ['monster'] }, 'plural'] },
' in ',
{ func: 'number', args: [{ var_path: ['dungeon-count'] }] },
' dungeons.'
]
}
]
}
}
}
]
}

const extMessages: Resource = {
id: 'remote-ref',
locale: 'en',
messages: {
friend: [
'Your friend has become ',
{
func: 'sparkle',
args: [
{ id: 'game-messages', msg: ['monsters', ['monster'], 'indefinite'] }
]
}
]
}
entries: [
{
id: 'friend',
value: [
'Your friend has become ',
{
func: 'sparkle',
args: [
{
res_id: 'game-messages',
msg_path: ['monsters', { var_path: ['monster'] }, 'indefinite']
}
]
}
]
}
]
}
52 changes: 40 additions & 12 deletions experiments/data_model/ts_eemeli/data-model.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,36 @@
interface Resource {
id: string
locale: string
messages: MessageSet
entries: Entry[]
meta?: Meta
}

type Entry = Message | MessageSet

interface MessageSet {
id: string
entries: Entry[]
meta?: Meta
}

/**
* Really this ought to be a Record, but TS only allows circular references for
* a limited set of types.
* Additional meta information amy be attached to most nodes. In common use,
* this information is not required when formatting a message.
*/
type MessageSet = { [key in string]: Message | Select | MessageSet }
interface Meta {
comment?: string
[key: string]: unknown
}

/**
* The string parts of a message represent fixed values, while placeholder
* values are variable.
*/
type Message = Value[]
interface Message {
id: string
value: Value[] | Select
meta?: Meta
}

/**
* Select generalises the plural, selectordinal and select argument types of
Expand All @@ -32,7 +48,7 @@ type Message = Value[]
*/
interface Select {
select: Value[]
cases: Array<{ key: string[]; value: Message }>
cases: Array<{ key: Literal[]; value: Value[]; meta?: Meta }>
}

/**
Expand Down Expand Up @@ -61,7 +77,10 @@ type Literal = string | number
* object value, so e.g. `['user', 'name']` would require something like
* `{ name: 'Kat' }` as the value of the `'user'` scope variable.
*/
type VariableReference = string[]
interface VariableReference {
var_path: Path
meta?: Meta
}

/**
* To resolve a FunctionReference, an externally defined function is called.
Expand All @@ -79,13 +98,14 @@ type VariableReference = string[]
interface FunctionReference {
func: string
args: Value[]
options?: Record<string, string | number | boolean>
options?: Array<{ key: string; value: string | number | boolean }>
meta?: Meta
}

/**
* A MessageReference is a pointer to a Message or a Select.
*
* If `id` is undefined, the message is sought in the current Resource.
* If `resource` is undefined, the message is sought in the current Resource.
* If it is set, it identifies the resource for the sought message.
*
* While `msg` has superficially the same type as a Message, all but the last
Expand All @@ -96,7 +116,15 @@ interface FunctionReference {
* `scope` overrides values in the current scope when resolving the message.
*/
interface MessageReference {
id?: string
msg: Value[]
scope?: Record<string, Value>
res_id?: string
msg_path: Path
scope?: Scope[]
meta?: Meta
}

interface Scope {
name: string
value: Value | boolean | Scope
}

type Path = Value[]

0 comments on commit c328609

Please sign in to comment.