feat(quick-261016-0fm): admin language follows the stored preference

- principalFrom sets PreferredLocale from metadata admin_locale; personal
  API token principals clear it, so token clients keep the request locale
- the guarded admin group runs locale.from-principal after the backend
  guard, overriding the LocaleResolver or Accept-Language locale
- GET /lang honours a supported ?locale= and reports meta.locales
  (cabana.LangEnvelope, cabana.LangMeta)
- Docker test for the override, refusals and /lang; docs and OpenAPI
This commit is contained in:
Jakub Zych
2026-10-16 10:58:29 +02:00
parent 3d2f9d0cf6
commit f67e8915b8
15 changed files with 216 additions and 39 deletions

View File

@@ -1055,21 +1055,6 @@
],
"type": "object"
},
"cabana.Envelope-cabana_LangBundle": {
"properties": {
"data": {
"$ref": "#/components/schemas/cabana.LangBundle"
},
"meta": {
"$ref": "#/components/schemas/cabana.SuccessMeta"
}
},
"required": [
"data",
"meta"
],
"type": "object"
},
"cabana.Envelope-cabana_ListSchema": {
"properties": {
"data": {
@@ -1783,6 +1768,41 @@
},
"type": "object"
},
"cabana.LangEnvelope": {
"properties": {
"data": {
"$ref": "#/components/schemas/cabana.LangBundle"
},
"meta": {
"$ref": "#/components/schemas/cabana.LangMeta"
}
},
"required": [
"data",
"meta"
],
"type": "object"
},
"cabana.LangMeta": {
"properties": {
"locale": {
"description": "Locale is the locale the bundle resolved to.",
"type": "string"
},
"locales": {
"description": "Locales are the supported admin locales, sorted.",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"locale",
"locales"
],
"type": "object"
},
"cabana.ListColumn": {
"properties": {
"currency": {
@@ -3642,13 +3662,23 @@
},
"/lang": {
"get": {
"description": "Every backend::lang key as CLDR plural forms for the Accept-Language locale, over the fallback locale's keys. Public: the login screen loads it before signing in. meta.locale is the locale the bundle resolved to.",
"description": "Every backend::lang key as CLDR plural forms for the request locale, over the fallback locale's keys. The locale query parameter selects one of the supported admin locales instead (the SPA sends the admin's chosen language); a value that is not one of them is ignored. Public: the login screen loads it before signing in. meta.locale is the locale the bundle resolved to and meta.locales lists the supported admin locales.",
"parameters": [
{
"description": "A supported admin locale (one of meta.locales); other values are ignored",
"in": "query",
"name": "locale",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/cabana.Envelope-cabana_LangBundle"
"$ref": "#/components/schemas/cabana.LangEnvelope"
}
}
},