Cruddl provides a sophisticated way to provide human readable field and type names and storing them along where they belong: together with the model. A client consuming a cruddl graphql api can not only query data and meta schema, but also fetch labels and hints.
A cruddl project contains GraphQL schema files and metadata (json/yaml) files. Localizations are
defined in metadata files within the i18n
object as follows:
i18n:
en:
types:
Hero:
label: Hero
labelPlural: Heroes
hint: A brave person with cool features
fields:
name:
label: Name
hint: The name of the hero
age: age # shortcut for age: { label: age, hint: undefined }
Color:
values:
RED: red
BLUE: blue
fields:
createdAt:
label: Created at
hint: When this hero's record was created
de:
types:
Hero: ...
fields:
createdAt:
label: Erfasst am
hint: Wann der Held in diesem System angelegt wurde
updatedAt: Geändert am
id: ID
Localizable parts are types, fields and enum values. I18n for fields can also be defined
independently from the declaring type to provide translation for fields which appear in several
types, e. g. createdAt
.
Types have the localization fields label
, labelPlural
, and hint
; fields and enum values
label
and hint
. You can specify a string directly (e.g. age: age
) if you just want to specify
a label (this is a shortcut for age: { label: "age" }
).
The GraphQL meta schema provides localizations via the localization(resolutionOrder)
fields on
Type
, Field
, and EnumValue
. The resolutionOrder
argument expects a list of languages (code
from the yaml/json files) and can contain other strings for special resolution features.
_LOCALE
uses the language code provided in thelocale
property on the GraphQL context This way, the language can be automatically selected from a user session an http header etc._GENERIC
is auto-generated localization from field and type names (e. G.orderDate
=>Order date
) The defaultresolutionOrder
is["_LOCALE", "_GENERIC"]
(if not specified).
localization(...)
tries always to get a complete set ofFieldLocalization
orFieldLocalization
from all namespaces applying to the type/field and given languages.- Namespaces can provide localizations for sub-namespaces (but not vice versa)
- There will never be a localization in another than the first language, if in the first language there is a namespace which has a matching localization (namespace over language).
- Field i18n specified in a type wins over a namespace field i18n.
- Defining a localization twice within the same namespace is a validation error.
- Localization resolution can return undefined values. There will be not errors on missing translations.
interface Metadata {
i18n?: { [language: string]: Localization };
}
interface Localization {
types?: { [name: string]: TypeLocalization };
fields?: { [name: string]: FieldLocalization | string };
}
interface TypeLocalization {
label?: string;
labelPlural?: string;
hint?: string;
fields?: { [name: string]: FieldLocalization | string };
values?: { [name: string]: EnumValueLocalization | string };
}
interface FieldLocalization {
label?: string;
hint?: string;
}
interface EnumValueLocalization {
label?: string;
hint?: string;
}