Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions linter/testcases/language-code/expected-output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

/testcases/language-code/openapi.json
92:52 error nlgov:specify-format-for-language-code Any field that represents a language must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json.schema.properties.language
95:65 error nlgov:specify-format-for-language-code Any field that represents a language must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json.schema.properties.thoroughfare_language
98:70 error nlgov:specify-format-for-language-code Any field that represents a language must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json.schema.properties.railName_localNameLanguage
101:48 error nlgov:specify-format-for-language-code Any field that represents a language must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json.schema.properties.taal
104:59 error nlgov:specify-format-for-language-code Any field that represents a language must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json.schema.properties.organisatieTaal
107:60 error nlgov:specify-format-for-language-code Any field that represents a language must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json.schema.properties.organisatie_taal
127:55 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json+verkeerd-format.schema.properties.language.format
131:55 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json+verkeerd-format.schema.properties.thoroughfare_language.format
135:55 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json+verkeerd-format.schema.properties.railName_localNameLanguage.format
139:55 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json+verkeerd-format.schema.properties.taal.format
143:55 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json+verkeerd-format.schema.properties.organisatieTaal.format
147:55 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' paths./resources-with-language-incorrect.get.responses[200].content.application/json+verkeerd-format.schema.properties.organisatie_taal.format
236:27 error nlgov:use-language-code Field represents a language and therefore must set 'format' to 'language' components.schemas.LanguageIncorrect.format

✖ 13 problems (13 errors, 0 warnings, 0 infos, 0 hints)
256 changes: 256 additions & 0 deletions linter/testcases/language-code/openapi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
{
"openapi": "3.0.3",
"info": {
"title": "Baseline",
"description": "Deze OpenAPI specification bevat het minimale om aan alle regels te voldoen.",
"contact": {
"name": "Beheerder",
"url": "https://www.example.com",
"email": "mail@example.com"
},
"version": "1.0.0"
},
"servers": [
{
"url": "https://example.com/api/v1"
}
],
"security": [
{
"default": []
}
],
"tags": [
{
"name": "openapi"
},
{
"name": "language"
}
],
"paths": {
"/openapi.json": {
"get": {
"tags": [
"openapi"
],
"description": "OpenAPI document",
"operationId": "getOpenapiJSON",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"headers": {
"API-Version": {
"description": "De huidige versie van de applicatie",
"style": "simple",
"schema": {
"type": "string"
}
},
"access-control-allow-origin": {
"description": "Alle origins mogen bij deze resource",
"schema": {
"type": "string"
}
}
}
}
},
"security": [
{
"default": []
}
]
}
},
"/resources-with-language-incorrect": {
"get": {
"tags": [
"language"
],
"description": "Resources with language incorrect",
"operationId": "getLanguageIncorrect",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"headers": {
"API-Version": {
"description": "De huidige versie van de applicatie",
"style": "simple",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"language": {
"type": "string"
},
"thoroughfare_language": {
"type": "string"
},
"railName_localNameLanguage": {
"type": "string"
},
"taal": {
"type": "string"
},
"organisatieTaal": {
"type": "string"
},
"organisatie_taal": {
"type": "string"
},
"meerdereTaal": {
"type": "string",
"allOf": [
{
"$ref": "#/components/schemas/LanguageIncorrect"
}
]
}
}
}
},
"application/json+verkeerd-format": {
"schema": {
"type": "object",
"properties": {
"language": {
"type": "string",
"format": "byte"
},
"thoroughfare_language": {
"type": "string",
"format": "byte"
},
"railName_localNameLanguage": {
"type": "string",
"format": "byte"
},
"taal": {
"type": "string",
"format": "byte"
},
"organisatieTaal": {
"type": "string",
"format": "byte"
},
"organisatie_taal": {
"type": "string",
"format": "byte"
}
}
}
}
}
}
},
"security": [
{
"default": []
}
]
}
},
"/resources-with-language-correct": {
"get": {
"tags": [
"language"
],
"description": "Resources with language correct",
"operationId": "getLanguagesCorrect",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"headers": {
"API-Version": {
"description": "De huidige versie van de applicatie",
"style": "simple",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"language": {
"type": "string",
"format": "language"
},
"thoroughfare_language": {
"type": "string",
"format": "language"
},
"railName_localNameLanguage": {
"type": "string",
"format": "language"
},
"taal": {
"type": "string",
"format": "language"
},
"organisatieTaal": {
"type": "string",
"format": "language"
},
"organisatie_taal": {
"type": "string",
"format": "language"
},
"meerdereTaal": {
"type": "string",
"allOf": [
{
"$ref": "#/components/schemas/LanguageCorrect"
}
]
}
}
}
}
}
}
},
"security": [
{
"default": []
}
]
}
}
},
"components": {
"schemas": {
"LanguageIncorrect": {
"format": "byte",
"type": "string"
},
"LanguageCorrect": {
"format": "language",
"type": "string"
}
},
"securitySchemes": {
"default": {
"type": "oauth2",
"flows": {
"implicit": {
"authorizationUrl": "https://test.com",
"scopes": {}
}
}
}
}
}
}
33 changes: 33 additions & 0 deletions media/linter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,39 @@ rules:
functionOptions:
notMatch: "/^date-time$/"

#/core/lang-code
nlgov:specify-format-for-language-code:
severity: error
given:
- $..properties[taal,lang,language]
- $..properties[?(@property && @property.match(/((\w+T)|(_[tT]))aal/))]
- $..properties[?(@property && @property.match(/((\w+L)|(_[lL]))ang(uage)?/))]
message: "Any field that represents a language must set 'format' to 'language'"
then:
function: schema
functionOptions:
schema:
anyOf:
- required: ["format"]
- properties:
allOf:
type: array
items:
required: ["format"]
required: ["allOf"]

nlgov:use-language-code:
severity: error
given:
- $..properties[taal,lang,language]..format
- $..properties[?(@property && @property.match(/((\w+T)|(_[tT]))aal/))]..format
- $..properties[?(@property && @property.match(/((\w+L)|(_[lL]))ang(uage)?/))]..format
message: "Field represents a language and therefore must set 'format' to 'language'"
then:
function: pattern
functionOptions:
match: "/^language$/"

nlgov:semver:
severity: error
message: "Version {{value}} is not in semver format."
Expand Down
28 changes: 28 additions & 0 deletions sections/designRules.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,34 @@ https://api.example.org/v1/vergunningen/d285e05c-6b01-45c3-92d8-5e19a946b66f</pr
</dl>
</div>

<div class="rule" id="/core/lang-code" data-type="technical">
<p class="rulelab">Use standard language codes and field names for language content</p>
<dl>
<dt>Statement</dt>
<dd>
<p>A resource containing language content MUST follow <a href="https://www.rfc-editor.org/info/bcp47">BCP 47</a> [[RFC4647]] [[RFC5646]].
The <a href="https://www.rfc-editor.org/info/rfc5646/#section-2.2.1">Primary Language Subtag</a> MUST be lowercase.
Languages MUST have a <a href="https://www.rfc-editor.org/info/rfc5646/#section-2.2.4">Region</a> subtag in uppercase.
<p class="warning">[[?ISO3166-1]] concerns identifiers of countries and MUST NOT be used to denote languages, since countries and languages are not equivalent.
<p class="note">Following [[RFC4647]] a language code in [[?ISO-639-1]] format matches a language tag in [[RFC5646]] format regardless of language subtag.
<aside class="example">
<p>The Dutch language in The Netherlands is <code>nl-NL</code> where <code>nl</code> is the Primary Language Subtag and <code>NL</code> is the Region subtag.
</aside>
<aside class="example">
<p>The English language in The United Kingdom is <code>en-GB</code> where <code>en</code> is the Primary Language Subtag and <code>GB</code> is the Region subtag.
</aside>
</dd>
<dt>Rationale</dt>
<dd>
Standardised language codes removes ambiguity in language handling between systems, potentially present in separate regions with different (spoken) languages.
</dd>
<dt>How to test</dt>
<dd>
Confirm each field that represents a language has a value in [[RFC5646]] format.
</dd>
</dl>
</div>

## Date and time

Handling date and time is tricky and can lead to confusion among clients. The date-time rules remove ambiguity and provide clarity in the API contract between servers and clients.
Expand Down
3 changes: 2 additions & 1 deletion standaard.dic
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
32
33
Aanbeveling
backend
camelCase
Expand All @@ -25,6 +25,7 @@ SameSite
Specref
Strategie
subresource
subtag
URIs
voor
WebDAV
Expand Down
Loading