Localization
draftStatus of this Document
This report was published by the User Journey Graph Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .
1. Overview
This optional module defines a graph-native vocabulary for attaching localization metadata to UJG
nodes. It lets a producer bind any addressable node to a reusable MessageMeta resource through
l10n:copyRef, and model concrete locale-specific text as addressable Message nodes.
This module is optional. Its properties annotate Graph resources and do not themselves change topology, traversal rules, or import resolution. A producer may nevertheless model different Graph Journeys, States, or affordances when content structure genuinely differs by locale; Graph owns those topology differences.
2. Terminology
Locale: An addressable locale resource identified by a language tag.
MessageMeta: An addressable message identity and shared metadata resource.
Message: An addressable locale-specific value for one
MessageMetaand oneLocale.
3. Locale
A Locale identifies one locale used by localization metadata or locale-specific messages.
classDiagram
class Locale {
id
localeCode
} Example JSON node:
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
} {
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
} 4. MessageMeta
A MessageMeta identifies a reusable copy contract. The MessageMeta IRI is the stable message
identity. UJG nodes reference a message meta node with l10n:copyRef.
classDiagram
class Locale
class MessageMeta {
id
argumentNames
defaultLocaleRef
fallbackLocaleRefs
rtl
}
MessageMeta --> Locale : defaultLocaleRef
MessageMeta --> "0..*" Locale : fallbackLocaleRefs Example JSON node:
{
"@type": "l10n:MessageMeta",
"@id": "urn:l10n:message-meta:order-confirmation-title",
"l10n:argumentNames": ["orderNumber"],
"l10n:defaultLocaleRef": "urn:l10n:locale:en",
"l10n:fallbackLocaleRefs": ["urn:l10n:locale:en", "urn:l10n:locale:de"],
"l10n:rtl": false
} {
"@type": "l10n:MessageMeta",
"@id": "urn:l10n:message-meta:order-confirmation-title",
"l10n:argumentNames": ["orderNumber"],
"l10n:defaultLocaleRef": "urn:l10n:locale:en",
"l10n:fallbackLocaleRefs": ["urn:l10n:locale:en", "urn:l10n:locale:de"],
"l10n:rtl": false
} 5. Message
A Message carries one locale-specific string value for one MessageMeta and one Locale. The value is an opaque string from the perspective of Localization conformance.
classDiagram
class MessageMeta
class Locale
class Message {
id
messageMetaRef
localeRef
value
}
Message --> MessageMeta : messageMetaRef
Message --> Locale : localeRef Example JSON node:
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:en",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:en",
"l10n:value": "Order ${orderNumber} confirmed"
} {
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:en",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:en",
"l10n:value": "Order ${orderNumber} confirmed"
} 6. Attachment Model
The module introduces real JSON-LD terms and RDF edges for localization attachment:
l10n:copyReflinks any UJG node to aMessageMeta.l10n:messageMetaReflinks aMessageto theMessageMetait realizes.l10n:localeReflinks aMessageto itsLocale.l10n:defaultLocaleRefandl10n:fallbackLocaleRefslinkMessageMetato fallback locale resources.l10n:targetLocaleRefdeclares the requestedLocaleassociated with an OutgoingTransition.
classDiagram
class Node {
copyRef
}
class MessageMeta
class Locale
class OutgoingTransition {
targetLocaleRef
}
Node --> MessageMeta : copyRef
OutgoingTransition --> Locale : targetLocaleRef Example JSON nodes:
[
{
"@type": "Journey",
"@id": "urn:ujg:journey:order-confirmation",
"defaultEntryRef": "urn:ujg:entry:order-confirmation",
"entryRefs": ["urn:ujg:entry:order-confirmation"],
"stateRefs": ["urn:ujg:state:order-confirmation"]
},
{
"@type": "JourneyEntry",
"@id": "urn:ujg:entry:order-confirmation",
"stateRef": "urn:ujg:state:order-confirmation"
},
{
"@type": "State",
"@id": "urn:ujg:state:order-confirmation",
"label": "Order confirmation",
"outgoingTransitionRefs": ["urn:example:ot:language-english"],
"l10n:copyRef": "urn:l10n:message-meta:order-confirmation-title"
},
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
},
{
"@type": "l10n:MessageMeta",
"@id": "urn:l10n:message-meta:order-confirmation-title",
"l10n:argumentNames": ["orderNumber"],
"l10n:defaultLocaleRef": "urn:l10n:locale:en"
},
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:en",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:en",
"l10n:value": "Order ${orderNumber} confirmed"
},
{
"@type": "OutgoingTransition",
"@id": "urn:example:ot:language-english",
"label": "English",
"toEntryRef": "urn:ujg:entry:order-confirmation",
"l10n:targetLocaleRef": "urn:l10n:locale:en"
}
] [
{
"@type": "Journey",
"@id": "urn:ujg:journey:order-confirmation",
"defaultEntryRef": "urn:ujg:entry:order-confirmation",
"entryRefs": ["urn:ujg:entry:order-confirmation"],
"stateRefs": ["urn:ujg:state:order-confirmation"]
},
{
"@type": "JourneyEntry",
"@id": "urn:ujg:entry:order-confirmation",
"stateRef": "urn:ujg:state:order-confirmation"
},
{
"@type": "State",
"@id": "urn:ujg:state:order-confirmation",
"label": "Order confirmation",
"outgoingTransitionRefs": ["urn:example:ot:language-english"],
"l10n:copyRef": "urn:l10n:message-meta:order-confirmation-title"
},
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
},
{
"@type": "l10n:MessageMeta",
"@id": "urn:l10n:message-meta:order-confirmation-title",
"l10n:argumentNames": ["orderNumber"],
"l10n:defaultLocaleRef": "urn:l10n:locale:en"
},
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:en",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:en",
"l10n:value": "Order ${orderNumber} confirmed"
},
{
"@type": "OutgoingTransition",
"@id": "urn:example:ot:language-english",
"label": "English",
"toEntryRef": "urn:ujg:entry:order-confirmation",
"l10n:targetLocaleRef": "urn:l10n:locale:en"
}
] Here the locale switch explicitly re-enters the same Journey and State through its entry contract. Localization supplies the requested locale; Graph supplies the destination.
The module also defines non-reference properties l10n:localeCode, l10n:argumentNames,
l10n:rtl, and l10n:value.
7. Normative Artifacts
This module is published through the following artifacts:
l10n.ttl: ontology, published athttps://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10nl10n.context.jsonld: JSON-LD term mappings, published athttps://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.context.jsonldl10n.shape.ttl: SHACL validation rules, published athttps://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.shape
Examples in this page compose the shared baseline context https://ujg.specs.openuji.org/tr/1.0-rc3/ns/context.jsonld
with the Localization context.
Non-goals:
This module does not define locale negotiation, runtime translation loading, JavaScript evaluation, ICU formatting behavior, pluralization, or runtime interpolation APIs.
This module does not introduce new traversal semantics beyond [UJG Graph].
This module does not replace opaque vendor-private hints carried in [UJG Core]
extensions.
7.1. Ontology
The normative Localization ontology is defined below and is published at
https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n. It is the authoritative structural definition for
Locale, MessageMeta, Message, and the properties declared by this module.
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/graph#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .
<https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#> a owl:Ontology ;
rdfs:label "UJG Localization 1.0 Vocabulary"@en ;
dct:description "UJG Localization ontology declaration" .
### Classes
ujgl10n:Locale a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgl10n:MessageMeta a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgl10n:Message a owl:Class ;
rdfs:subClassOf ujg:Node .
### Properties
ujgl10n:copyRef a owl:ObjectProperty ;
rdfs:domain ujg:Node ;
rdfs:range ujgl10n:MessageMeta .
ujgl10n:localeCode a owl:DatatypeProperty ;
rdfs:domain ujgl10n:Locale ;
rdfs:range xsd:language .
ujgl10n:argumentNames a owl:DatatypeProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range xsd:string .
ujgl10n:defaultLocaleRef a owl:ObjectProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range ujgl10n:Locale .
ujgl10n:fallbackLocaleRefs a owl:ObjectProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range ujgl10n:Locale .
ujgl10n:rtl a owl:DatatypeProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range xsd:boolean .
ujgl10n:messageMetaRef a owl:ObjectProperty ;
rdfs:domain ujgl10n:Message ;
rdfs:range ujgl10n:MessageMeta .
ujgl10n:localeRef a owl:ObjectProperty ;
rdfs:domain ujgl10n:Message ;
rdfs:range ujgl10n:Locale .
ujgl10n:value a owl:DatatypeProperty ;
rdfs:domain ujgl10n:Message ;
rdfs:range xsd:string .
ujgl10n:targetLocaleRef a owl:ObjectProperty ;
rdfs:domain ujggraph:OutgoingTransition ;
rdfs:range ujgl10n:Locale . @prefix ujg: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/graph#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .
<https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#> a owl:Ontology ;
rdfs:label "UJG Localization 1.0 Vocabulary"@en ;
dct:description "UJG Localization ontology declaration" .
### Classes
ujgl10n:Locale a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgl10n:MessageMeta a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgl10n:Message a owl:Class ;
rdfs:subClassOf ujg:Node .
### Properties
ujgl10n:copyRef a owl:ObjectProperty ;
rdfs:domain ujg:Node ;
rdfs:range ujgl10n:MessageMeta .
ujgl10n:localeCode a owl:DatatypeProperty ;
rdfs:domain ujgl10n:Locale ;
rdfs:range xsd:language .
ujgl10n:argumentNames a owl:DatatypeProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range xsd:string .
ujgl10n:defaultLocaleRef a owl:ObjectProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range ujgl10n:Locale .
ujgl10n:fallbackLocaleRefs a owl:ObjectProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range ujgl10n:Locale .
ujgl10n:rtl a owl:DatatypeProperty ;
rdfs:domain ujgl10n:MessageMeta ;
rdfs:range xsd:boolean .
ujgl10n:messageMetaRef a owl:ObjectProperty ;
rdfs:domain ujgl10n:Message ;
rdfs:range ujgl10n:MessageMeta .
ujgl10n:localeRef a owl:ObjectProperty ;
rdfs:domain ujgl10n:Message ;
rdfs:range ujgl10n:Locale .
ujgl10n:value a owl:DatatypeProperty ;
rdfs:domain ujgl10n:Message ;
rdfs:range xsd:string .
ujgl10n:targetLocaleRef a owl:ObjectProperty ;
rdfs:domain ujggraph:OutgoingTransition ;
rdfs:range ujgl10n:Locale . 7.2. JSON-LD Context
The normative Localization JSON-LD context is defined below and is published at
https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.context.jsonld. It provides the compact JSON-LD term
mappings and coercions for Localization-specific properties and classes.
{
"@context": {
"@version": 1.1,
"ujgl10n": "https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#",
"l10n": "https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"Locale": "ujgl10n:Locale",
"MessageMeta": "ujgl10n:MessageMeta",
"Message": "ujgl10n:Message",
"copyRef": {
"@id": "ujgl10n:copyRef",
"@type": "@id"
},
"l10n:copyRef": {
"@id": "ujgl10n:copyRef",
"@type": "@id"
},
"localeCode": {
"@id": "ujgl10n:localeCode",
"@type": "xsd:language"
},
"l10n:localeCode": {
"@id": "ujgl10n:localeCode",
"@type": "xsd:language"
},
"argumentNames": {
"@id": "ujgl10n:argumentNames",
"@container": "@set"
},
"l10n:argumentNames": {
"@id": "ujgl10n:argumentNames",
"@container": "@set"
},
"defaultLocaleRef": {
"@id": "ujgl10n:defaultLocaleRef",
"@type": "@id"
},
"l10n:defaultLocaleRef": {
"@id": "ujgl10n:defaultLocaleRef",
"@type": "@id"
},
"fallbackLocaleRefs": {
"@id": "ujgl10n:fallbackLocaleRefs",
"@type": "@id",
"@container": "@set"
},
"l10n:fallbackLocaleRefs": {
"@id": "ujgl10n:fallbackLocaleRefs",
"@type": "@id",
"@container": "@set"
},
"rtl": "ujgl10n:rtl",
"l10n:rtl": "ujgl10n:rtl",
"messageMetaRef": {
"@id": "ujgl10n:messageMetaRef",
"@type": "@id"
},
"l10n:messageMetaRef": {
"@id": "ujgl10n:messageMetaRef",
"@type": "@id"
},
"localeRef": {
"@id": "ujgl10n:localeRef",
"@type": "@id"
},
"l10n:localeRef": {
"@id": "ujgl10n:localeRef",
"@type": "@id"
},
"value": "ujgl10n:value",
"l10n:value": "ujgl10n:value",
"targetLocaleRef": {
"@id": "ujgl10n:targetLocaleRef",
"@type": "@id"
},
"l10n:targetLocaleRef": {
"@id": "ujgl10n:targetLocaleRef",
"@type": "@id"
}
}
} {
"@context": {
"@version": 1.1,
"ujgl10n": "https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#",
"l10n": "https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"Locale": "ujgl10n:Locale",
"MessageMeta": "ujgl10n:MessageMeta",
"Message": "ujgl10n:Message",
"copyRef": {
"@id": "ujgl10n:copyRef",
"@type": "@id"
},
"l10n:copyRef": {
"@id": "ujgl10n:copyRef",
"@type": "@id"
},
"localeCode": {
"@id": "ujgl10n:localeCode",
"@type": "xsd:language"
},
"l10n:localeCode": {
"@id": "ujgl10n:localeCode",
"@type": "xsd:language"
},
"argumentNames": {
"@id": "ujgl10n:argumentNames",
"@container": "@set"
},
"l10n:argumentNames": {
"@id": "ujgl10n:argumentNames",
"@container": "@set"
},
"defaultLocaleRef": {
"@id": "ujgl10n:defaultLocaleRef",
"@type": "@id"
},
"l10n:defaultLocaleRef": {
"@id": "ujgl10n:defaultLocaleRef",
"@type": "@id"
},
"fallbackLocaleRefs": {
"@id": "ujgl10n:fallbackLocaleRefs",
"@type": "@id",
"@container": "@set"
},
"l10n:fallbackLocaleRefs": {
"@id": "ujgl10n:fallbackLocaleRefs",
"@type": "@id",
"@container": "@set"
},
"rtl": "ujgl10n:rtl",
"l10n:rtl": "ujgl10n:rtl",
"messageMetaRef": {
"@id": "ujgl10n:messageMetaRef",
"@type": "@id"
},
"l10n:messageMetaRef": {
"@id": "ujgl10n:messageMetaRef",
"@type": "@id"
},
"localeRef": {
"@id": "ujgl10n:localeRef",
"@type": "@id"
},
"l10n:localeRef": {
"@id": "ujgl10n:localeRef",
"@type": "@id"
},
"value": "ujgl10n:value",
"l10n:value": "ujgl10n:value",
"targetLocaleRef": {
"@id": "ujgl10n:targetLocaleRef",
"@type": "@id"
},
"l10n:targetLocaleRef": {
"@id": "ujgl10n:targetLocaleRef",
"@type": "@id"
}
}
} 7.3. Validation
The normative Localization SHACL shape is defined below and is published at
https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.shape. It is the authoritative validation artifact for
Localization structural constraints.
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/graph#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#> .
@prefix ujgl10nshape: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ujgl10nshape:NodeCopyShape a sh:NodeShape ;
sh:targetClass ujg:Node ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:copyRef ;
sh:class ujgl10n:MessageMeta ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
ujgl10nshape:LocaleShape a sh:NodeShape ;
sh:targetClass ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:localeCode ;
sh:datatype xsd:language ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgl10nshape:MessageMetaShape a sh:NodeShape ;
sh:targetClass ujgl10n:MessageMeta ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:argumentNames ;
sh:datatype xsd:string ;
] ;
sh:property [
sh:path ujgl10n:defaultLocaleRef ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgl10n:fallbackLocaleRefs ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
] ;
sh:property [
sh:path ujgl10n:rtl ;
sh:datatype xsd:boolean ;
sh:maxCount 1 ;
] .
ujgl10nshape:MessageShape a sh:NodeShape ;
sh:targetClass ujgl10n:Message ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:messageMetaRef ;
sh:class ujgl10n:MessageMeta ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgl10n:localeRef ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgl10n:value ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:sparql [
a sh:SPARQLConstraint ;
sh:message "No two Message nodes may share the same messageMetaRef and localeRef pair." ;
sh:select """
SELECT $this
WHERE {
$this ujgl10n:messageMetaRef ?meta ;
ujgl10n:localeRef ?locale .
?other a ujgl10n:Message ;
ujgl10n:messageMetaRef ?meta ;
ujgl10n:localeRef ?locale .
FILTER (?other != $this)
}
""" ;
] .
ujgl10nshape:OutgoingTransitionLocaleShape a sh:NodeShape ;
sh:targetClass ujggraph:OutgoingTransition ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:targetLocaleRef ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] . @prefix ujg: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/graph#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n#> .
@prefix ujgl10nshape: <https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ujgl10nshape:NodeCopyShape a sh:NodeShape ;
sh:targetClass ujg:Node ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:copyRef ;
sh:class ujgl10n:MessageMeta ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
ujgl10nshape:LocaleShape a sh:NodeShape ;
sh:targetClass ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:localeCode ;
sh:datatype xsd:language ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgl10nshape:MessageMetaShape a sh:NodeShape ;
sh:targetClass ujgl10n:MessageMeta ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:argumentNames ;
sh:datatype xsd:string ;
] ;
sh:property [
sh:path ujgl10n:defaultLocaleRef ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgl10n:fallbackLocaleRefs ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
] ;
sh:property [
sh:path ujgl10n:rtl ;
sh:datatype xsd:boolean ;
sh:maxCount 1 ;
] .
ujgl10nshape:MessageShape a sh:NodeShape ;
sh:targetClass ujgl10n:Message ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:messageMetaRef ;
sh:class ujgl10n:MessageMeta ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgl10n:localeRef ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgl10n:value ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:sparql [
a sh:SPARQLConstraint ;
sh:message "No two Message nodes may share the same messageMetaRef and localeRef pair." ;
sh:select """
SELECT $this
WHERE {
$this ujgl10n:messageMetaRef ?meta ;
ujgl10n:localeRef ?locale .
?other a ujgl10n:Message ;
ujgl10n:messageMetaRef ?meta ;
ujgl10n:localeRef ?locale .
FILTER (?other != $this)
}
""" ;
] .
ujgl10nshape:OutgoingTransitionLocaleShape a sh:NodeShape ;
sh:targetClass ujggraph:OutgoingTransition ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgl10n:targetLocaleRef ;
sh:class ujgl10n:Locale ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] . The rules below define the remaining module semantics beyond the structural constraints captured by the SHACL shape.
Attachment only: Localization properties MUST NOT change Graph validity, graph traversal behavior, import resolution, or core node identity. Locale-dependent topology MAY be modeled explicitly with distinct Graph Journeys, Entries, States, and Transitions.
Message identity: A
MessageMetaIRI identifies the reusable message contract. Producers MUST use that IRI as the shared message identity.Locale identity: Locale references use
LocaleIRIs. ALocale.localeCodevalue identifies the language tag represented by that locale resource.Message uniqueness: Producers MUST NOT create more than one
Messagefor the samemessageMetaRefandlocaleRefpair.Opaque value:
Message.valueis a string value. Consumers MUST NOT infer UJG graph edges, message dependencies, JavaScript execution, ICU behavior, or cycle constraints from the string.Locale target metadata:
l10n:targetLocaleRefdeclares the requested locale associated with an outgoing affordance. It does not itself define graph traversal behavior. The host OutgoingTransition'stoEntryRefselects the destination JourneyEntry.Shared-topology state preservation: When a locale switch must preserve whichever of several States is active, each source State MUST directly reference a state-specific OutgoingTransition. Each transition's
toEntryRefMUST target the JourneyEntry for the corresponding destination State.Fixed group destinations: An OutgoingTransitionGroup MAY contain a locale switch only when its one fixed destination entry is correct for every effective source. Consumers MUST NOT reinterpret a grouped transition's
toEntryRefas relative to the active State.Locale topology: When locales share topology, a state-scoped locale-switch OutgoingTransition may target an entry whose
stateRefis the same State where that affordance is available. When content structure differs by locale, it may target an entry owned by a locale-specific Journey with different local topology.No locale inference: Consumers MUST NOT infer a Journey, JourneyEntry, or State from
targetLocaleRef; the Graph reference remains explicit and authoritative.Graceful degradation: A consumer that does not implement this module MAY ignore Localization semantics, but it SHOULD preserve recognized JSON-LD data during read-transform-write when possible.
Private runtime hints: Platform-specific i18n loader configuration that is not intended for shared queryability or validation SHOULD remain in Core
extensions.
8. Examples
8.2. Locale Switch Affordance Example
{
"@context": [
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/core.context.jsonld",
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/graph.context.jsonld",
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.context.jsonld"
],
"@type": "UJGDocument",
"@id": "https://example.com/ujg/l10n/locale-switch.jsonld",
"nodes": [
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
},
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:de",
"l10n:localeCode": "de"
},
{
"@type": "Journey",
"@id": "urn:journey:confirmation-en",
"defaultEntryRef": "urn:entry:confirmation-en",
"entryRefs": ["urn:entry:confirmation-en"],
"stateRefs": ["urn:state:confirmation-en"]
},
{
"@type": "JourneyEntry",
"@id": "urn:entry:confirmation-en",
"stateRef": "urn:state:confirmation-en"
},
{
"@type": "State",
"@id": "urn:state:confirmation-en",
"label": "English confirmation",
"outgoingTransitionRefs": ["urn:example:ot:language-german"]
},
{
"@type": "Journey",
"@id": "urn:journey:confirmation-de",
"defaultEntryRef": "urn:entry:confirmation-de",
"entryRefs": ["urn:entry:confirmation-de"],
"stateRefs": ["urn:state:summary-de", "urn:state:legal-notice-de"],
"transitionRefs": ["urn:transition:summary-to-legal-notice-de"]
},
{
"@type": "JourneyEntry",
"@id": "urn:entry:confirmation-de",
"stateRef": "urn:state:summary-de"
},
{
"@type": "State",
"@id": "urn:state:summary-de",
"label": "German order summary"
},
{
"@type": "State",
"@id": "urn:state:legal-notice-de",
"label": "German legal notice"
},
{
"@type": "Transition",
"@id": "urn:transition:summary-to-legal-notice-de",
"from": "urn:state:summary-de",
"to": "urn:state:legal-notice-de"
},
{
"@type": "OutgoingTransition",
"@id": "urn:example:ot:language-german",
"label": "Deutsch",
"toEntryRef": "urn:entry:confirmation-de",
"l10n:targetLocaleRef": "urn:l10n:locale:de"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/core.context.jsonld",
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/graph.context.jsonld",
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.context.jsonld"
],
"@type": "UJGDocument",
"@id": "https://example.com/ujg/l10n/locale-switch.jsonld",
"nodes": [
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
},
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:de",
"l10n:localeCode": "de"
},
{
"@type": "Journey",
"@id": "urn:journey:confirmation-en",
"defaultEntryRef": "urn:entry:confirmation-en",
"entryRefs": ["urn:entry:confirmation-en"],
"stateRefs": ["urn:state:confirmation-en"]
},
{
"@type": "JourneyEntry",
"@id": "urn:entry:confirmation-en",
"stateRef": "urn:state:confirmation-en"
},
{
"@type": "State",
"@id": "urn:state:confirmation-en",
"label": "English confirmation",
"outgoingTransitionRefs": ["urn:example:ot:language-german"]
},
{
"@type": "Journey",
"@id": "urn:journey:confirmation-de",
"defaultEntryRef": "urn:entry:confirmation-de",
"entryRefs": ["urn:entry:confirmation-de"],
"stateRefs": ["urn:state:summary-de", "urn:state:legal-notice-de"],
"transitionRefs": ["urn:transition:summary-to-legal-notice-de"]
},
{
"@type": "JourneyEntry",
"@id": "urn:entry:confirmation-de",
"stateRef": "urn:state:summary-de"
},
{
"@type": "State",
"@id": "urn:state:summary-de",
"label": "German order summary"
},
{
"@type": "State",
"@id": "urn:state:legal-notice-de",
"label": "German legal notice"
},
{
"@type": "Transition",
"@id": "urn:transition:summary-to-legal-notice-de",
"from": "urn:state:summary-de",
"to": "urn:state:legal-notice-de"
},
{
"@type": "OutgoingTransition",
"@id": "urn:example:ot:language-german",
"label": "Deutsch",
"toEntryRef": "urn:entry:confirmation-de",
"l10n:targetLocaleRef": "urn:l10n:locale:de"
}
]
} The English Journey has one confirmation State. The German Journey has a summary followed by a separate legal-notice State. The locale switch therefore targets the German entry contract rather than assuming that both locales share a State or topology.
8.3. Combined JSON Example
{
"@context": [
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/context.jsonld",
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.context.jsonld"
],
"@id": "https://example.com/ujg/l10n/checkout.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
},
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:de",
"l10n:localeCode": "de"
},
{
"@type": "State",
"@id": "urn:ujg:state:order-confirmation",
"label": "Order confirmation",
"l10n:copyRef": "urn:l10n:message-meta:order-confirmation-title"
},
{
"@type": "l10n:MessageMeta",
"@id": "urn:l10n:message-meta:order-confirmation-title",
"l10n:argumentNames": ["orderNumber"],
"l10n:defaultLocaleRef": "urn:l10n:locale:en",
"l10n:fallbackLocaleRefs": ["urn:l10n:locale:en", "urn:l10n:locale:de"],
"l10n:rtl": false
},
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:en",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:en",
"l10n:value": "Order ${orderNumber} confirmed"
},
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:de",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:de",
"l10n:value": "Bestellung ${orderNumber} bestaetigt"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/context.jsonld",
"https://ujg.specs.openuji.org/tr/1.0-rc3/ns/l10n.context.jsonld"
],
"@id": "https://example.com/ujg/l10n/checkout.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:en",
"l10n:localeCode": "en"
},
{
"@type": "l10n:Locale",
"@id": "urn:l10n:locale:de",
"l10n:localeCode": "de"
},
{
"@type": "State",
"@id": "urn:ujg:state:order-confirmation",
"label": "Order confirmation",
"l10n:copyRef": "urn:l10n:message-meta:order-confirmation-title"
},
{
"@type": "l10n:MessageMeta",
"@id": "urn:l10n:message-meta:order-confirmation-title",
"l10n:argumentNames": ["orderNumber"],
"l10n:defaultLocaleRef": "urn:l10n:locale:en",
"l10n:fallbackLocaleRefs": ["urn:l10n:locale:en", "urn:l10n:locale:de"],
"l10n:rtl": false
},
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:en",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:en",
"l10n:value": "Order ${orderNumber} confirmed"
},
{
"@type": "l10n:Message",
"@id": "urn:l10n:message:order-confirmation-title:de",
"l10n:messageMetaRef": "urn:l10n:message-meta:order-confirmation-title",
"l10n:localeRef": "urn:l10n:locale:de",
"l10n:value": "Bestellung ${orderNumber} bestaetigt"
}
]
} 8.4. Opaque Runtime Hints
{
"@id": "urn:l10n:message-meta:order-confirmation-title",
"@type": "l10n:MessageMeta",
"extensions": {
"com.acme.i18n-runtime": {
"resourceFile": "checkout/confirmation.json",
"bundleFormat": "icu"
}
}
} {
"@id": "urn:l10n:message-meta:order-confirmation-title",
"@type": "l10n:MessageMeta",
"extensions": {
"com.acme.i18n-runtime": {
"resourceFile": "checkout/confirmation.json",
"bundleFormat": "icu"
}
}
}