web: Replace lingui.js with lit-localize (#5761)

* \#\# Details

web: replace lingui with lit/localize

\#\# Changes

This rather massive shift replaces the lingui and `t()` syntax with lit-localize, XLIFF, and the `msg()`
syntax used by lit-localize.  90% of this work was mechanized; simple perl scripts found and replaced
all uses of `t()` with the appropriate corresponding syntax for `msg()` and `msg(str())`.

The XLIFF files were auto-generated from the PO files.  They have not been audited, and they should be
checked over by professional translators.  The actual _strings_ have not been changed, but as this was
a mechanized change there is always the possibility of mis-translation-- not by the translator, but by
the script.

* web: revise lit/localize: fix two installation issues.

* web: revise localization

TL;DR:

- Replaced all of Lingui's `t()` syntax with `msg()` syntax.
- Mechanically (i.e with a script) converted all of the PO files to XLIFF files
- Refactored the localization code to be a bit smarter:
  - the function `getBestMatchLocale` takes the locale lists and a requested locale, and returns the
    first match of:
    - The locale's code exactly matches the requested locale
    - The locale code exactly matches the prefix of the requested locale (i.e the "en" part of "en-US")
    - the locale code's prefix exactly matches the prefix of the requested locale
    This function is passed to lit-locate's `loadLocale()`.
  - `activateLocale()` just calls `loadLocale()` now.
  - `autodetectLanguage` searches the following, and picks the first that returns a valid locale
    object, before passing it to `loadLocale()`:
    - The User's settings
    - A `?locale=` component found in `window.location.search`
    - The `window.navigator.language` field
    - English

The `msg()` only runs when it's run.  This seems obvious, but it means that you cannot cache
strings at load time; they must be kept inside functions that are re-run so that the `msg()` engine
can look up the strings in the preferred language of the user at that moment.

You can use thunks-of-strings if you really need them that way.

* Including the 'xliff-converter' in case anyone wants to review it.

* The xliff-converter is tagged as 'xliff-converter', but has been
deleted.

\#\# Details

-   Resolves #5171

\#\# Changes

\#\#\# New Features

-   Adds a "Add an Application" to the LibraryView if there are no applications and the user is an administrator.

\#\#\# Breaking Changes

-   Adds breaking change which causes \<issue\>.

\#\# Checklist

-   [ ] Local tests pass (`ak test authentik/`)
-   [ ] The code has been formatted (`make lint-fix`)

If an API change has been made

-   [ ] The API schema has been updated (`make gen-build`)

If changes to the frontend have been made

-   [ ] The code has been formatted (`make web`)
-   [ ] The translation files have been updated (`make i18n-extract`)

If applicable

-   [ ] The documentation has been updated
-   [ ] The documentation has been formatted (`make website`)

* web: fix redundant locales for zh suite.

* web: prettier pass for locale update

* web: localization moderization

Changed the names of the lit-localize commands to make it clear they're
part of the localization effort, and not just "build" and "extract".

* update transifex config

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix package lock?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use build not compile

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: conversion to lit-localize

The CI produced a list of problems that I hadn't caught earlier,
due to a typo ("localize build" is correct, "localize compile" is
not) I had left in package.json.  They were minor and linty, but
it was still wise to fix them.

* web: replace lingui with lit/locale

This commit fixes some minor linting issues that were hidden by a typo in package.json.  The
issues were not apparently problematic from a Javascript point of view, but they pointed
to sloppy thinking in the progression of types through the system, so I cleaned them
up and formalized the types from LocaleModule to AkLocale.

* web: replace lingui with lit/localize

One problem that has repeatedly come up is that localize's templates do not produce
JavaScript that conforms with our shop style.  I've replaced `build-locale` with
a two-step that builds the locale *and* ensures that it conforms to the shop style
via `prettier` every time.

* web: replace lingui with lit-locale

This commit applies the most recent bundle of translations to the
new lit-locale aspect component.  It also revises the algorithm
for *finding* the correct locale, replacing the complex fall-back
with some rather straightforward regular expressions.

In the case of Chinese, the fallback comes at the end of the
selection list, which may not be, er, politically valuable
(since Taiwan and Hong Kong come before, being exceptions that
need to be tested).  If we need a different order for presentation,
that'll be a future feature.

* web: replace lingui with lit/locale

Well, that was embarassing.

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Ken Sternberg 2023-06-02 08:08:36 -07:00 committed by GitHub
parent afa8a505ee
commit 44a057ed9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
273 changed files with 64104 additions and 117217 deletions

View File

@ -2,11 +2,11 @@ git:
filters: filters:
- filter_type: file - filter_type: file
# all supported i18n types: https://docs.transifex.com/formats # all supported i18n types: https://docs.transifex.com/formats
file_format: PO file_format: XLIFF
source_language: en source_language: en
source_file: web/src/locales/en.po source_file: web/xliff/en.xlf
# path expression to translation files, must contain <lang> placeholder # path expression to translation files, must contain <lang> placeholder
translation_files_expression: "web/src/locales/<lang>.po" translation_files_expression: "web/xliff/<lang>.xlf"
- filter_type: file - filter_type: file
# all supported i18n types: https://docs.transifex.com/formats # all supported i18n types: https://docs.transifex.com/formats
file_format: PO file_format: PO

0
web/dist/.gitkeep vendored
View File

26
web/lit-localize.json Normal file
View File

@ -0,0 +1,26 @@
{
"$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
"sourceLocale": "en",
"targetLocales": [
"en",
"pseudo-LOCALE",
"fr_FR",
"tr",
"es",
"pl",
"zh_TW",
"zh-Hans",
"zh-Hant",
"de"
],
"tsConfig": "./tsconfig.json",
"output": {
"mode": "runtime",
"outputDir": "./src/locales",
"localeCodesModule": "./src/locale-codes.ts"
},
"interchange": {
"format": "xliff",
"xliffDir": "./xliff/"
}
}

5081
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,15 +4,18 @@
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"extract": "lingui extract", "extract-locales": "lit-localize extract",
"build": "lingui compile && node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.config.js", "build-locales": "run-s build-locales:build build-locales:repair",
"build-proxy": "lingui compile && node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.proxy.js", "build-locales:build": "lit-localize build",
"watch": "lingui compile && node --max-old-space-size=8192 node_modules/.bin/rollup -c -w", "build-locales:repair": "prettier --write ./src/locale-codes.ts",
"build": "lit-localize build && node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.config.js",
"build-proxy": "lit-localize build && node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.proxy.js",
"watch": "lit-localize build && node --max-old-space-size=8192 node_modules/.bin/rollup -c -w",
"lint": "eslint . --max-warnings 0 --fix", "lint": "eslint . --max-warnings 0 --fix",
"lit-analyse": "lit-analyzer src", "lit-analyse": "lit-analyzer src",
"prettier-check": "prettier --check .", "prettier-check": "prettier --check .",
"prettier": "prettier --write .", "prettier": "prettier --write .",
"tsc": "lingui compile && tsc --noEmit -p .", "tsc": "lit-localize build && tsc --noEmit -p .",
"background-image": "npx @squoosh/cli -d src/assets/images --resize '{\"enabled\":true,\"width\":2560,\"method\":\"lanczos3\",\"fitMethod\":\"contain\",\"premultiply\":true,\"linearRGB\":true}' --mozjpeg '{\"quality\":75,\"baseline\":false,\"arithmetic\":false,\"progressive\":true,\"optimize_coding\":true,\"smoothing\":0,\"color_space\":3,\"quant_table\":3,\"trellis_multipass\":false,\"trellis_opt_zero\":false,\"trellis_opt_table\":false,\"trellis_loops\":1,\"auto_subsample\":true,\"chroma_subsample\":2,\"separate_chroma_quality\":false,\"chroma_quality\":75}' src/assets/images/flow_background.jpg" "background-image": "npx @squoosh/cli -d src/assets/images --resize '{\"enabled\":true,\"width\":2560,\"method\":\"lanczos3\",\"fitMethod\":\"contain\",\"premultiply\":true,\"linearRGB\":true}' --mozjpeg '{\"quality\":75,\"baseline\":false,\"arithmetic\":false,\"progressive\":true,\"optimize_coding\":true,\"smoothing\":0,\"color_space\":3,\"quant_table\":3,\"trellis_multipass\":false,\"trellis_opt_zero\":false,\"trellis_opt_table\":false,\"trellis_loops\":1,\"auto_subsample\":true,\"chroma_subsample\":2,\"separate_chroma_quality\":false,\"chroma_quality\":75}' src/assets/images/flow_background.jpg"
}, },
"dependencies": { "dependencies": {
@ -25,11 +28,7 @@
"@formatjs/intl-listformat": "^7.2.2", "@formatjs/intl-listformat": "^7.2.2",
"@fortawesome/fontawesome-free": "^6.4.0", "@fortawesome/fontawesome-free": "^6.4.0",
"@goauthentik/api": "^2023.5.3-1685646044", "@goauthentik/api": "^2023.5.3-1685646044",
"@lingui/cli": "^4.2.0", "@lit/localize": "^0.11.4",
"@lingui/core": "^4.2.0",
"@lingui/detect-locale": "^4.2.0",
"@lingui/format-po-gettext": "^4.2.0",
"@lingui/macro": "^4.2.0",
"@patternfly/patternfly": "^4.224.2", "@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.53.1", "@sentry/browser": "^7.53.1",
"@sentry/tracing": "^7.53.1", "@sentry/tracing": "^7.53.1",
@ -58,6 +57,7 @@
"@babel/preset-typescript": "^7.21.5", "@babel/preset-typescript": "^7.21.5",
"@hcaptcha/types": "^1.0.3", "@hcaptcha/types": "^1.0.3",
"@jackfranklin/rollup-plugin-markdown": "^0.4.0", "@jackfranklin/rollup-plugin-markdown": "^0.4.0",
"@lit/localize-tools": "^0.6.9",
"@rollup/plugin-babel": "^6.0.3", "@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^25.0.0", "@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-node-resolve": "^15.1.0", "@rollup/plugin-node-resolve": "^15.1.0",
@ -76,6 +76,7 @@
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.8", "eslint-plugin-custom-elements": "0.0.8",
"eslint-plugin-lit": "^1.8.3", "eslint-plugin-lit": "^1.8.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"pyright": "^1.1.311", "pyright": "^1.1.311",
"rollup": "^2.79.1", "rollup": "^2.79.1",

View File

@ -21,8 +21,7 @@ import "@goauthentik/elements/router/RouterOutlet";
import "@goauthentik/elements/sidebar/Sidebar"; import "@goauthentik/elements/sidebar/Sidebar";
import "@goauthentik/elements/sidebar/SidebarItem"; import "@goauthentik/elements/sidebar/SidebarItem";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
@ -167,7 +166,7 @@ export class AdminInterface extends Interface {
? html` ? html`
<ak-sidebar-item ?highlight=${true}> <ak-sidebar-item ?highlight=${true}>
<span slot="label" <span slot="label"
>${t`A newer version of the frontend is available.`}</span >${msg("A newer version of the frontend is available.")}</span
> >
</ak-sidebar-item> </ak-sidebar-item>
` `
@ -181,125 +180,127 @@ export class AdminInterface extends Interface {
)}`} )}`}
> >
<span slot="label" <span slot="label"
>${t`You're currently impersonating ${this.user.user.username}. Click to stop.`}</span >${msg(
str`You're currently impersonating ${this.user.user.username}. Click to stop.`,
)}</span
> >
</ak-sidebar-item>` </ak-sidebar-item>`
: html``} : html``}
<ak-sidebar-item path="/if/user/" ?isAbsoluteLink=${true} ?highlight=${true}> <ak-sidebar-item path="/if/user/" ?isAbsoluteLink=${true} ?highlight=${true}>
<span slot="label">${t`User interface`}</span> <span slot="label">${msg("User interface")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item .expanded=${true}> <ak-sidebar-item .expanded=${true}>
<span slot="label">${t`Dashboards`}</span> <span slot="label">${msg("Dashboards")}</span>
<ak-sidebar-item path="/administration/overview"> <ak-sidebar-item path="/administration/overview">
<span slot="label">${t`Overview`}</span> <span slot="label">${msg("Overview")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/administration/dashboard/users"> <ak-sidebar-item path="/administration/dashboard/users">
<span slot="label">${t`Users`}</span> <span slot="label">${msg("Users")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/administration/system-tasks"> <ak-sidebar-item path="/administration/system-tasks">
<span slot="label">${t`System Tasks`}</span> <span slot="label">${msg("System Tasks")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item> <ak-sidebar-item>
<span slot="label">${t`Applications`}</span> <span slot="label">${msg("Applications")}</span>
<ak-sidebar-item <ak-sidebar-item
path="/core/applications" path="/core/applications"
.activeWhen=${[`^/core/applications/(?<slug>${SLUG_REGEX})$`]} .activeWhen=${[`^/core/applications/(?<slug>${SLUG_REGEX})$`]}
> >
<span slot="label">${t`Applications`}</span> <span slot="label">${msg("Applications")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item <ak-sidebar-item
path="/core/providers" path="/core/providers"
.activeWhen=${[`^/core/providers/(?<id>${ID_REGEX})$`]} .activeWhen=${[`^/core/providers/(?<id>${ID_REGEX})$`]}
> >
<span slot="label">${t`Providers`}</span> <span slot="label">${msg("Providers")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/outpost/outposts"> <ak-sidebar-item path="/outpost/outposts">
<span slot="label">${t`Outposts`}</span> <span slot="label">${msg("Outposts")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item> <ak-sidebar-item>
<span slot="label">${t`Events`}</span> <span slot="label">${msg("Events")}</span>
<ak-sidebar-item <ak-sidebar-item
path="/events/log" path="/events/log"
.activeWhen=${[`^/events/log/(?<id>${UUID_REGEX})$`]} .activeWhen=${[`^/events/log/(?<id>${UUID_REGEX})$`]}
> >
<span slot="label">${t`Logs`}</span> <span slot="label">${msg("Logs")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/events/rules"> <ak-sidebar-item path="/events/rules">
<span slot="label">${t`Notification Rules`}</span> <span slot="label">${msg("Notification Rules")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/events/transports"> <ak-sidebar-item path="/events/transports">
<span slot="label">${t`Notification Transports`}</span> <span slot="label">${msg("Notification Transports")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item> <ak-sidebar-item>
<span slot="label">${t`Customisation`}</span> <span slot="label">${msg("Customisation")}</span>
<ak-sidebar-item path="/policy/policies"> <ak-sidebar-item path="/policy/policies">
<span slot="label">${t`Policies`}</span> <span slot="label">${msg("Policies")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/core/property-mappings"> <ak-sidebar-item path="/core/property-mappings">
<span slot="label">${t`Property Mappings`}</span> <span slot="label">${msg("Property Mappings")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/blueprints/instances"> <ak-sidebar-item path="/blueprints/instances">
<span slot="label">${t`Blueprints`}</span> <span slot="label">${msg("Blueprints")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/policy/reputation"> <ak-sidebar-item path="/policy/reputation">
<span slot="label">${t`Reputation scores`}</span> <span slot="label">${msg("Reputation scores")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item> <ak-sidebar-item>
<span slot="label">${t`Flows & Stages`}</span> <span slot="label">${msg("Flows & Stages")}</span>
<ak-sidebar-item <ak-sidebar-item
path="/flow/flows" path="/flow/flows"
.activeWhen=${[`^/flow/flows/(?<slug>${SLUG_REGEX})$`]} .activeWhen=${[`^/flow/flows/(?<slug>${SLUG_REGEX})$`]}
> >
<span slot="label">${t`Flows`}</span> <span slot="label">${msg("Flows")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/flow/stages"> <ak-sidebar-item path="/flow/stages">
<span slot="label">${t`Stages`}</span> <span slot="label">${msg("Stages")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/flow/stages/prompts"> <ak-sidebar-item path="/flow/stages/prompts">
<span slot="label">${t`Prompts`}</span> <span slot="label">${msg("Prompts")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item> <ak-sidebar-item>
<span slot="label">${t`Directory`}</span> <span slot="label">${msg("Directory")}</span>
<ak-sidebar-item <ak-sidebar-item
path="/identity/users" path="/identity/users"
.activeWhen=${[`^/identity/users/(?<id>${ID_REGEX})$`]} .activeWhen=${[`^/identity/users/(?<id>${ID_REGEX})$`]}
> >
<span slot="label">${t`Users`}</span> <span slot="label">${msg("Users")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item <ak-sidebar-item
path="/identity/groups" path="/identity/groups"
.activeWhen=${[`^/identity/groups/(?<id>${UUID_REGEX})$`]} .activeWhen=${[`^/identity/groups/(?<id>${UUID_REGEX})$`]}
> >
<span slot="label">${t`Groups`}</span> <span slot="label">${msg("Groups")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item <ak-sidebar-item
path="/core/sources" path="/core/sources"
.activeWhen=${[`^/core/sources/(?<slug>${SLUG_REGEX})$`]} .activeWhen=${[`^/core/sources/(?<slug>${SLUG_REGEX})$`]}
> >
<span slot="label">${t`Federation & Social login`}</span> <span slot="label">${msg("Federation & Social login")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/core/tokens"> <ak-sidebar-item path="/core/tokens">
<span slot="label">${t`Tokens & App passwords`}</span> <span slot="label">${msg("Tokens & App passwords")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/flow/stages/invitations"> <ak-sidebar-item path="/flow/stages/invitations">
<span slot="label">${t`Invitations`}</span> <span slot="label">${msg("Invitations")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item> <ak-sidebar-item>
<span slot="label">${t`System`}</span> <span slot="label">${msg("System")}</span>
<ak-sidebar-item path="/core/tenants"> <ak-sidebar-item path="/core/tenants">
<span slot="label">${t`Tenants`}</span> <span slot="label">${msg("Tenants")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/crypto/certificates"> <ak-sidebar-item path="/crypto/certificates">
<span slot="label">${t`Certificates`}</span> <span slot="label">${msg("Certificates")}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/outpost/integrations"> <ak-sidebar-item path="/outpost/integrations">
<span slot="label">${t`Outpost Integrations`}</span> <span slot="label">${msg("Outpost Integrations")}</span>
</ak-sidebar-item> </ak-sidebar-item>
</ak-sidebar-item> </ak-sidebar-item>
`; `;

View File

@ -14,8 +14,7 @@ import "@goauthentik/elements/PageHeader";
import "@goauthentik/elements/cards/AggregatePromiseCard"; import "@goauthentik/elements/cards/AggregatePromiseCard";
import { paramURL } from "@goauthentik/elements/router/RouterOutlet"; import { paramURL } from "@goauthentik/elements/router/RouterOutlet";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
@ -70,8 +69,8 @@ export class AdminOverviewPage extends AKElement {
if (this.user?.user.name) { if (this.user?.user.name) {
name = this.user.user.name; name = this.user.user.name;
} }
return html`<ak-page-header icon="" header="" description=${t`General system status`}> return html`<ak-page-header icon="" header="" description=${msg("General system status")}>
<span slot="header"> ${t`Welcome, ${name}.`} </span> <span slot="header"> ${msg(str`Welcome, ${name}.`)} </span>
</ak-page-header> </ak-page-header>
<section class="pf-c-page__main-section"> <section class="pf-c-page__main-section">
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">
@ -82,7 +81,7 @@ export class AdminOverviewPage extends AKElement {
> >
<ak-aggregate-card <ak-aggregate-card
icon="fa fa-share" icon="fa fa-share"
header=${t`Quick actions`} header=${msg("Quick actions")}
.isCenter=${false} .isCenter=${false}
> >
<ul class="pf-c-list"> <ul class="pf-c-list">
@ -92,12 +91,12 @@ export class AdminOverviewPage extends AKElement {
href=${paramURL("/core/applications", { href=${paramURL("/core/applications", {
createForm: true, createForm: true,
})} })}
>${t`Create a new application`}</a >${msg("Create a new application")}</a
> >
</li> </li>
<li> <li>
<a class="pf-u-mb-xl" href=${paramURL("/events/log")} <a class="pf-u-mb-xl" href=${paramURL("/events/log")}
>${t`Check the logs`}</a >${msg("Check the logs")}</a
> >
</li> </li>
<li> <li>
@ -105,12 +104,12 @@ export class AdminOverviewPage extends AKElement {
class="pf-u-mb-xl" class="pf-u-mb-xl"
target="_blank" target="_blank"
href="https://goauthentik.io/integrations/" href="https://goauthentik.io/integrations/"
>${t`Explore integrations`}</a >${msg("Explore integrations")}</a
> >
</li> </li>
<li> <li>
<a class="pf-u-mb-xl" href=${paramURL("/identity/users")} <a class="pf-u-mb-xl" href=${paramURL("/identity/users")}
>${t`Manage users`}</a >${msg("Manage users")}</a
> >
</li> </li>
<li> <li>
@ -121,7 +120,7 @@ export class AdminOverviewPage extends AKElement {
".", ".",
"", "",
)}" )}"
>${t`Check release notes`}</a >${msg("Check release notes")}</a
> >
</li> </li>
</ul> </ul>
@ -132,7 +131,7 @@ export class AdminOverviewPage extends AKElement {
> >
<ak-aggregate-card <ak-aggregate-card
icon="pf-icon pf-icon-zone" icon="pf-icon pf-icon-zone"
header=${t`Outpost status`} header=${msg("Outpost status")}
headerLink="#/outpost/outposts" headerLink="#/outpost/outposts"
> >
<ak-admin-status-chart-outpost></ak-admin-status-chart-outpost> <ak-admin-status-chart-outpost></ak-admin-status-chart-outpost>
@ -141,7 +140,7 @@ export class AdminOverviewPage extends AKElement {
<div <div
class="pf-l-grid__item pf-m-12-col pf-m-8-col-on-xl pf-m-4-col-on-2xl graph-container" class="pf-l-grid__item pf-m-12-col pf-m-8-col-on-xl pf-m-4-col-on-2xl graph-container"
> >
<ak-aggregate-card icon="fa fa-sync-alt" header=${t`Sync status`}> <ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
<ak-admin-status-chart-sync></ak-admin-status-chart-sync> <ak-admin-status-chart-sync></ak-admin-status-chart-sync>
</ak-aggregate-card> </ak-aggregate-card>
</div> </div>
@ -176,7 +175,9 @@ export class AdminOverviewPage extends AKElement {
> >
<ak-aggregate-card <ak-aggregate-card
icon="pf-icon pf-icon-server" icon="pf-icon pf-icon-server"
header=${t`Logins and authorizations over the last week (per 8 hours)`} header=${msg(
"Logins and authorizations over the last week (per 8 hours)",
)}
> >
<ak-charts-admin-login-authorization></ak-charts-admin-login-authorization> <ak-charts-admin-login-authorization></ak-charts-admin-login-authorization>
</ak-aggregate-card> </ak-aggregate-card>
@ -186,7 +187,7 @@ export class AdminOverviewPage extends AKElement {
> >
<ak-aggregate-card <ak-aggregate-card
icon="pf-icon pf-icon-server" icon="pf-icon pf-icon-server"
header=${t`Apps with most usage`} header=${msg("Apps with most usage")}
> >
<ak-top-applications-table></ak-top-applications-table> <ak-top-applications-table></ak-top-applications-table>
</ak-aggregate-card> </ak-aggregate-card>

View File

@ -3,8 +3,7 @@ import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/PageHeader"; import "@goauthentik/elements/PageHeader";
import "@goauthentik/elements/cards/AggregatePromiseCard"; import "@goauthentik/elements/cards/AggregatePromiseCard";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
@ -42,14 +41,14 @@ export class DashboardUserPage extends AKElement {
} }
render(): TemplateResult { render(): TemplateResult {
return html`<ak-page-header icon="pf-icon pf-icon-user" header=${t`User statistics`}> return html`<ak-page-header icon="pf-icon pf-icon-user" header=${msg("User statistics")}>
</ak-page-header> </ak-page-header>
<section class="pf-c-page__main-section"> <section class="pf-c-page__main-section">
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">
<div <div
class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-12-col-on-2xl big-graph-container" class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-12-col-on-2xl big-graph-container"
> >
<ak-aggregate-card header=${t`Users created per day in the last month`}> <ak-aggregate-card header=${msg("Users created per day in the last month")}>
<ak-charts-admin-model-per-day <ak-charts-admin-model-per-day
.query=${{ .query=${{
context__model__app: "authentik_core", context__model__app: "authentik_core",
@ -66,7 +65,7 @@ export class DashboardUserPage extends AKElement {
<div <div
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl big-graph-container" class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl big-graph-container"
> >
<ak-aggregate-card header=${t`Logins per day in the last month`}> <ak-aggregate-card header=${msg("Logins per day in the last month")}>
<ak-charts-admin-model-per-day action=${EventActions.Login}> <ak-charts-admin-model-per-day action=${EventActions.Login}>
</ak-charts-admin-model-per-day> </ak-charts-admin-model-per-day>
</ak-aggregate-card> </ak-aggregate-card>
@ -74,7 +73,7 @@ export class DashboardUserPage extends AKElement {
<div <div
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl big-graph-container" class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl big-graph-container"
> >
<ak-aggregate-card header=${t`Failed Logins per day in the last month`}> <ak-aggregate-card header=${msg("Failed Logins per day in the last month")}>
<ak-charts-admin-model-per-day action=${EventActions.LoginFailed}> <ak-charts-admin-model-per-day action=${EventActions.LoginFailed}>
</ak-charts-admin-model-per-day> </ak-charts-admin-model-per-day>
</ak-aggregate-card> </ak-aggregate-card>

View File

@ -2,8 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/Spinner";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -48,8 +47,8 @@ export class TopApplicationsTable extends AKElement {
return html`<table class="pf-c-table pf-m-compact" role="grid"> return html`<table class="pf-c-table pf-m-compact" role="grid">
<thead> <thead>
<tr role="row"> <tr role="row">
<th role="columnheader" scope="col">${t`Application`}</th> <th role="columnheader" scope="col">${msg("Application")}</th>
<th role="columnheader" scope="col">${t`Logins`}</th> <th role="columnheader" scope="col">${msg("Logins")}</th>
<th role="columnheader" scope="col"></th> <th role="columnheader" scope="col"></th>
</tr> </tr>
</thead> </thead>

View File

@ -10,8 +10,7 @@ import "@goauthentik/elements/buttons/SpinnerButton";
import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -53,17 +52,17 @@ export class RecentEventsCard extends Table<Event> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Action`, "action"), new TableColumn(msg("Action"), "action"),
new TableColumn(t`User`, "user"), new TableColumn(msg("User"), "user"),
new TableColumn(t`Creation Date`, "created"), new TableColumn(msg("Creation Date"), "created"),
new TableColumn(t`Client IP`, "client_ip"), new TableColumn(msg("Client IP"), "client_ip"),
new TableColumn(t`Tenant`, "tenant_name"), new TableColumn(msg("Tenant"), "tenant_name"),
]; ];
} }
renderToolbar(): TemplateResult { renderToolbar(): TemplateResult {
return html`<div class="pf-c-card__title"> return html`<div class="pf-c-card__title">
<i class="pf-icon pf-icon-catalog"></i>&nbsp;${t`Recent events`} <i class="pf-icon pf-icon-catalog"></i>&nbsp;${msg("Recent events")}
</div>`; </div>`;
} }
@ -80,21 +79,21 @@ export class RecentEventsCard extends Table<Event> {
${item.user.on_behalf_of ${item.user.on_behalf_of
? html`<small> ? html`<small>
<a href="#/identity/users/${item.user.on_behalf_of.pk}" <a href="#/identity/users/${item.user.on_behalf_of.pk}"
>${t`On behalf of ${item.user.on_behalf_of.username}`}</a >${msg(str`On behalf of ${item.user.on_behalf_of.username}`)}</a
> >
</small>` </small>`
: html``}` : html``}`
: html`-`, : html`-`,
html`<span>${item.created?.toLocaleString()}</span>`, html`<span>${item.created?.toLocaleString()}</span>`,
html` <div>${item.clientIp || t`-`}</div> html` <div>${item.clientIp || msg("-")}</div>
<small>${EventGeo(item)}</small>`, <small>${EventGeo(item)}</small>`,
html`<span>${item.tenant?.name || t`-`}</span>`, html`<span>${item.tenant?.name || msg("-")}</span>`,
]; ];
} }
renderEmpty(): TemplateResult { renderEmpty(): TemplateResult {
return super.renderEmpty(html`<ak-empty-state header=${t`No Events found.`}> return super.renderEmpty(html`<ak-empty-state header=${msg("No Events found.")}>
<div slot="body">${t`No matching events could be found.`}</div> <div slot="body">${msg("No matching events could be found.")}</div>
</ak-empty-state>`); </ak-empty-state>`);
} }
} }

View File

@ -4,8 +4,7 @@ import {
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard"; } from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
@ -52,37 +51,37 @@ export class SystemStatusCard extends AdminStatusCard<System> {
getStatus(value: System): Promise<AdminStatus> { getStatus(value: System): Promise<AdminStatus> {
if (value.embeddedOutpostHost === "") { if (value.embeddedOutpostHost === "") {
this.statusSummary = t`Warning`; this.statusSummary = msg("Warning");
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: html`${t`Embedded outpost is not configured correctly.`} message: html`${msg("Embedded outpost is not configured correctly.")}
<a href="#/outpost/outposts">${t`Check outposts.`}</a>`, <a href="#/outpost/outposts">${msg("Check outposts.")}</a>`,
}); });
} }
if (!value.httpIsSecure && document.location.protocol === "https:") { if (!value.httpIsSecure && document.location.protocol === "https:") {
this.statusSummary = t`Warning`; this.statusSummary = msg("Warning");
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: html`${t`HTTPS is not detected correctly`}`, message: html`${msg("HTTPS is not detected correctly")}`,
}); });
} }
const timeDiff = value.serverTime.getTime() - (this.now || new Date()).getTime(); const timeDiff = value.serverTime.getTime() - (this.now || new Date()).getTime();
if (timeDiff > 5000 || timeDiff < -5000) { if (timeDiff > 5000 || timeDiff < -5000) {
this.statusSummary = t`Warning`; this.statusSummary = msg("Warning");
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: html`${t`Server and client are further than 5 seconds apart.`}`, message: html`${msg("Server and client are further than 5 seconds apart.")}`,
}); });
} }
this.statusSummary = t`OK`; this.statusSummary = msg("OK");
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-check-circle pf-m-success", icon: "fa fa-check-circle pf-m-success",
message: html`${t`Everything is ok.`}`, message: html`${msg("Everything is ok.")}`,
}); });
} }
renderHeader(): TemplateResult { renderHeader(): TemplateResult {
return html`${t`System status`}`; return html`${msg("System status")}`;
} }
renderValue(): TemplateResult { renderValue(): TemplateResult {

View File

@ -4,8 +4,7 @@ import {
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard"; } from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
@ -24,23 +23,23 @@ export class VersionStatusCard extends AdminStatusCard<Version> {
if (value.buildHash) { if (value.buildHash) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-check-circle pf-m-success", icon: "fa fa-check-circle pf-m-success",
message: html`${t`Based on ${value.versionCurrent}`}`, message: html`${msg(str`Based on ${value.versionCurrent}`)}`,
}); });
} }
if (value.outdated) { if (value.outdated) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: html`${t`${value.versionLatest} is available!`}`, message: html`${msg(str`${value.versionLatest} is available!`)}`,
}); });
} }
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-check-circle pf-m-success", icon: "fa fa-check-circle pf-m-success",
message: html`${t`Up-to-date!`}`, message: html`${msg("Up-to-date!")}`,
}); });
} }
renderHeader(): TemplateResult { renderHeader(): TemplateResult {
return html`${t`Version`}`; return html`${msg("Version")}`;
} }
renderValue(): TemplateResult { renderValue(): TemplateResult {

View File

@ -4,8 +4,7 @@ import {
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard"; } from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
@ -22,14 +21,14 @@ export class WorkersStatusCard extends AdminStatusCard<number> {
} }
renderHeader(): TemplateResult { renderHeader(): TemplateResult {
return html`${t`Workers`}`; return html`${msg("Workers")}`;
} }
getStatus(value: number): Promise<AdminStatus> { getStatus(value: number): Promise<AdminStatus> {
if (value < 1) { if (value < 1) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-times-circle pf-m-danger", icon: "fa fa-times-circle pf-m-danger",
message: html`${t`No workers connected. Background tasks will not run.`}`, message: html`${msg("No workers connected. Background tasks will not run.")}`,
}); });
} else { } else {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({

View File

@ -2,8 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKChart, RGBAColor } from "@goauthentik/elements/charts/Chart"; import { AKChart, RGBAColor } from "@goauthentik/elements/charts/Chart";
import { ChartData, Tick } from "chart.js"; import { ChartData, Tick } from "chart.js";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { AdminApi, LoginMetrics } from "@goauthentik/api"; import { AdminApi, LoginMetrics } from "@goauthentik/api";
@ -18,14 +17,14 @@ export class AdminLoginAuthorizeChart extends AKChart<LoginMetrics> {
const valueStamp = ticks[index]; const valueStamp = ticks[index];
const delta = Date.now() - valueStamp.value; const delta = Date.now() - valueStamp.value;
const ago = Math.round(delta / 1000 / 3600 / 24); const ago = Math.round(delta / 1000 / 3600 / 24);
return t`${ago} day(s) ago`; return msg(str`${ago} day(s) ago`);
} }
getChartData(data: LoginMetrics): ChartData { getChartData(data: LoginMetrics): ChartData {
return { return {
datasets: [ datasets: [
{ {
label: t`Authorizations`, label: msg("Authorizations"),
backgroundColor: new RGBAColor(43, 154, 243, 0.5).toString(), backgroundColor: new RGBAColor(43, 154, 243, 0.5).toString(),
borderColor: new RGBAColor(43, 154, 243, 1).toString(), borderColor: new RGBAColor(43, 154, 243, 1).toString(),
spanGaps: true, spanGaps: true,
@ -40,7 +39,7 @@ export class AdminLoginAuthorizeChart extends AKChart<LoginMetrics> {
}), }),
}, },
{ {
label: t`Failed Logins`, label: msg("Failed Logins"),
backgroundColor: new RGBAColor(201, 24, 11, 0.5).toString(), backgroundColor: new RGBAColor(201, 24, 11, 0.5).toString(),
borderColor: new RGBAColor(201, 24, 11, 1).toString(), borderColor: new RGBAColor(201, 24, 11, 1).toString(),
spanGaps: true, spanGaps: true,
@ -55,7 +54,7 @@ export class AdminLoginAuthorizeChart extends AKChart<LoginMetrics> {
}), }),
}, },
{ {
label: t`Successful Logins`, label: msg("Successful Logins"),
backgroundColor: new RGBAColor(62, 134, 53, 0.5).toString(), backgroundColor: new RGBAColor(62, 134, 53, 0.5).toString(),
borderColor: new RGBAColor(62, 134, 53, 1).toString(), borderColor: new RGBAColor(62, 134, 53, 1).toString(),
spanGaps: true, spanGaps: true,

View File

@ -2,8 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKChart } from "@goauthentik/elements/charts/Chart"; import { AKChart } from "@goauthentik/elements/charts/Chart";
import { ChartData, Tick } from "chart.js"; import { ChartData, Tick } from "chart.js";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { Coordinate, EventActions, EventsApi } from "@goauthentik/api"; import { Coordinate, EventActions, EventsApi } from "@goauthentik/api";
@ -27,14 +26,14 @@ export class AdminModelPerDay extends AKChart<Coordinate[]> {
const valueStamp = ticks[index]; const valueStamp = ticks[index];
const delta = Date.now() - valueStamp.value; const delta = Date.now() - valueStamp.value;
const ago = Math.round(delta / 1000 / 3600 / 24); const ago = Math.round(delta / 1000 / 3600 / 24);
return t`${ago} days ago`; return msg(str`${ago} days ago`);
} }
getChartData(data: Coordinate[]): ChartData { getChartData(data: Coordinate[]): ChartData {
return { return {
datasets: [ datasets: [
{ {
label: t`Objects created`, label: msg("Objects created"),
backgroundColor: "rgba(189, 229, 184, .5)", backgroundColor: "rgba(189, 229, 184, .5)",
spanGaps: true, spanGaps: true,
data: data:

View File

@ -4,8 +4,7 @@ import { AKChart } from "@goauthentik/elements/charts/Chart";
import "@goauthentik/elements/forms/ConfirmationForm"; import "@goauthentik/elements/forms/ConfirmationForm";
import { ChartData, ChartOptions } from "chart.js"; import { ChartData, ChartOptions } from "chart.js";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { OutpostsApi } from "@goauthentik/api"; import { OutpostsApi } from "@goauthentik/api";
@ -62,7 +61,7 @@ export class OutpostStatusChart extends AKChart<SyncStatus[]> {
getChartData(data: SyncStatus[]): ChartData { getChartData(data: SyncStatus[]): ChartData {
return { return {
labels: [t`Healthy outposts`, t`Outdated outposts`, t`Unhealthy outposts`], labels: [msg("Healthy outposts"), msg("Outdated outposts"), msg("Unhealthy outposts")],
datasets: data.map((d) => { datasets: data.map((d) => {
return { return {
backgroundColor: ["#3e8635", "#C9190B", "#2b9af3"], backgroundColor: ["#3e8635", "#C9190B", "#2b9af3"],

View File

@ -3,8 +3,7 @@ import { AKChart } from "@goauthentik/elements/charts/Chart";
import "@goauthentik/elements/forms/ConfirmationForm"; import "@goauthentik/elements/forms/ConfirmationForm";
import { ChartData, ChartOptions } from "chart.js"; import { ChartData, ChartOptions } from "chart.js";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ProvidersApi, SourcesApi, TaskStatusEnum } from "@goauthentik/api"; import { ProvidersApi, SourcesApi, TaskStatusEnum } from "@goauthentik/api";
@ -74,7 +73,7 @@ export class LDAPSyncStatusChart extends AKChart<SyncStatus[]> {
failed: metrics.failed, failed: metrics.failed,
unsynced: sources.pagination.count === 0 ? 1 : metrics.unsynced, unsynced: sources.pagination.count === 0 ? 1 : metrics.unsynced,
total: sources.pagination.count, total: sources.pagination.count,
label: t`LDAP Source`, label: msg("LDAP Source"),
}; };
} }
@ -114,7 +113,7 @@ export class LDAPSyncStatusChart extends AKChart<SyncStatus[]> {
failed: metrics.failed, failed: metrics.failed,
unsynced: providers.pagination.count === 0 ? 1 : metrics.unsynced, unsynced: providers.pagination.count === 0 ? 1 : metrics.unsynced,
total: providers.pagination.count, total: providers.pagination.count,
label: t`SCIM Provider`, label: msg("SCIM Provider"),
}; };
} }
@ -127,7 +126,7 @@ export class LDAPSyncStatusChart extends AKChart<SyncStatus[]> {
getChartData(data: SyncStatus[]): ChartData { getChartData(data: SyncStatus[]): ChartData {
return { return {
labels: [t`Healthy`, t`Failed`, t`Unsynced / N/A`], labels: [msg("Healthy"), msg("Failed"), msg("Unsynced / N/A")],
datasets: data.map((d) => { datasets: data.map((d) => {
return { return {
backgroundColor: ["#3e8635", "#C9190B", "#2b9af3"], backgroundColor: ["#3e8635", "#C9190B", "#2b9af3"],

View File

@ -2,8 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKChart } from "@goauthentik/elements/charts/Chart"; import { AKChart } from "@goauthentik/elements/charts/Chart";
import { ChartData, Tick } from "chart.js"; import { ChartData, Tick } from "chart.js";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { Coordinate, CoreApi } from "@goauthentik/api"; import { Coordinate, CoreApi } from "@goauthentik/api";
@ -23,14 +22,14 @@ export class ApplicationAuthorizeChart extends AKChart<Coordinate[]> {
const valueStamp = ticks[index]; const valueStamp = ticks[index];
const delta = Date.now() - valueStamp.value; const delta = Date.now() - valueStamp.value;
const ago = Math.round(delta / 1000 / 3600 / 24); const ago = Math.round(delta / 1000 / 3600 / 24);
return t`${ago} days ago`; return msg(str`${ago} days ago`);
} }
getChartData(data: Coordinate[]): ChartData { getChartData(data: Coordinate[]): ChartData {
return { return {
datasets: [ datasets: [
{ {
label: t`Authorizations`, label: msg("Authorizations"),
backgroundColor: "rgba(189, 229, 184, .5)", backgroundColor: "rgba(189, 229, 184, .5)",
spanGaps: true, spanGaps: true,
data: data:

View File

@ -4,8 +4,7 @@ import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -31,7 +30,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
request?: number; request?: number;
getSuccessMessage(): string { getSuccessMessage(): string {
return t`Successfully sent test-request.`; return msg("Successfully sent test-request.");
} }
async send(data: { forUser: number }): Promise<PolicyTestResult> { async send(data: { forUser: number }): Promise<PolicyTestResult> {
@ -54,18 +53,18 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html` return html`
<ak-form-element-horizontal label=${t`Passing`}> <ak-form-element-horizontal label=${msg("Passing")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<span class="pf-c-form__label-text"> <span class="pf-c-form__label-text">
<ak-label color=${this.result?.passing ? PFColor.Green : PFColor.Red}> <ak-label color=${this.result?.passing ? PFColor.Green : PFColor.Red}>
${this.result?.passing ? t`Yes` : t`No`} ${this.result?.passing ? msg("Yes") : msg("No")}
</ak-label> </ak-label>
</span> </span>
</div> </div>
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Messages`}> <ak-form-element-horizontal label=${msg("Messages")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<ul> <ul>
@ -82,7 +81,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
</div> </div>
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Log messages`}> <ak-form-element-horizontal label=${msg("Log messages")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
@ -104,7 +103,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
: html`<div class="pf-c-description-list__group"> : html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`No log messages.`}</span >${msg("No log messages.")}</span
> >
</dt> </dt>
</div>`} </div>`}
@ -117,7 +116,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="forUser"> <ak-form-element-horizontal label=${msg("User")} ?required=${true} name="forUser">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<User[]> => { .fetchObjects=${async (query?: string): Promise<User[]> => {
const args: CoreUsersListRequest = { const args: CoreUsersListRequest = {

View File

@ -1,4 +1,5 @@
import "@goauthentik/admin/applications/ProviderSelectModal"; import "@goauthentik/admin/applications/ProviderSelectModal";
import { iconHelperText } from "@goauthentik/admin/helperText";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import { first, groupBy } from "@goauthentik/common/utils"; import { first, groupBy } from "@goauthentik/common/utils";
import { rootInterface } from "@goauthentik/elements/Base"; import { rootInterface } from "@goauthentik/elements/Base";
@ -10,8 +11,7 @@ import "@goauthentik/elements/forms/ProxyForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -48,9 +48,9 @@ export class ApplicationForm extends ModelForm<Application, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated application.`; return msg("Successfully updated application.");
} else { } else {
return t`Successfully created application.`; return msg("Successfully created application.");
} }
} }
@ -90,35 +90,39 @@ export class ApplicationForm extends ModelForm<Application, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
<p class="pf-c-form__helper-text">${t`Application's display Name.`}</p> <p class="pf-c-form__helper-text">${msg("Application's display Name.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Slug`} ?required=${true} name="slug"> <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.slug)}" value="${ifDefined(this.instance?.slug)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
<p class="pf-c-form__helper-text">${t`Internal application name, used in URLs.`}</p> <p class="pf-c-form__helper-text">
${msg("Internal application name, used in URLs.")}
</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Group`} name="group"> <ak-form-element-horizontal label=${msg("Group")} name="group">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.group)}" value="${ifDefined(this.instance?.group)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Optionally enter a group name. Applications with identical groups are shown grouped together.`} ${msg(
"Optionally enter a group name. Applications with identical groups are shown grouped together.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Provider`} name="provider"> <ak-form-element-horizontal label=${msg("Provider")} name="provider">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Provider[]> => { .fetchObjects=${async (query?: string): Promise<Provider[]> => {
const args: ProvidersAllListRequest = { const args: ProvidersAllListRequest = {
@ -146,12 +150,12 @@ export class ApplicationForm extends ModelForm<Application, string> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Select a provider that this application should use.`} ${msg("Select a provider that this application should use.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Backchannel providers`} label=${msg("Backchannel providers")}
name="backchannelProviders" name="backchannelProviders"
> >
<div class="pf-c-input-group"> <div class="pf-c-input-group">
@ -186,12 +190,14 @@ export class ApplicationForm extends ModelForm<Application, string> {
</div> </div>
</div> </div>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Select backchannel providers which augment the functionality of the main provider.`} ${msg(
"Select backchannel providers which augment the functionality of the main provider.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Policy engine mode`} label=${msg("Policy engine mode")}
?required=${true} ?required=${true}
name="policyEngineMode" name="policyEngineMode"
> >
@ -201,12 +207,12 @@ export class ApplicationForm extends ModelForm<Application, string> {
label: "any", label: "any",
value: PolicyEngineMode.Any, value: PolicyEngineMode.Any,
default: true, default: true,
description: html`${t`Any policy must match to grant access`}`, description: html`${msg("Any policy must match to grant access")}`,
}, },
{ {
label: "all", label: "all",
value: PolicyEngineMode.All, value: PolicyEngineMode.All,
description: html`${t`All policies must match to grant access`}`, description: html`${msg("All policies must match to grant access")}`,
}, },
]} ]}
.value=${this.instance?.policyEngineMode} .value=${this.instance?.policyEngineMode}
@ -214,16 +220,18 @@ export class ApplicationForm extends ModelForm<Application, string> {
</ak-radio> </ak-radio>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group> <ak-form-group>
<span slot="header"> ${t`UI settings`} </span> <span slot="header"> ${msg("UI settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Launch URL`} name="metaLaunchUrl"> <ak-form-element-horizontal label=${msg("Launch URL")} name="metaLaunchUrl">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.metaLaunchUrl)}" value="${ifDefined(this.instance?.metaLaunchUrl)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If left empty, authentik will try to extract the launch URL based on the selected provider.`} ${msg(
"If left empty, authentik will try to extract the launch URL based on the selected provider.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="openInNewTab"> <ak-form-element-horizontal name="openInNewTab">
@ -238,19 +246,22 @@ export class ApplicationForm extends ModelForm<Application, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Open in new tab`}</span> <span class="pf-c-switch__label">${msg("Open in new tab")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If checked, the launch URL will open in a new browser tab or window from the user's application library.`} ${msg(
"If checked, the launch URL will open in a new browser tab or window from the user's application library.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanSaveMedia) ${rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanSaveMedia)
? html`<ak-form-element-horizontal label=${t`Icon`} name="metaIcon"> ? html`<ak-form-element-horizontal label="${msg("Icon")}" name="metaIcon">
<input type="file" value="" class="pf-c-form-control" /> <input type="file" value="" class="pf-c-form-control" />
${this.instance?.metaIcon ${this.instance?.metaIcon
? html` ? html`
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Currently set to:`} ${this.instance?.metaIcon} ${msg("Currently set to:")}
${this.instance?.metaIcon}
</p> </p>
` `
: html``} : html``}
@ -277,33 +288,31 @@ export class ApplicationForm extends ModelForm<Application, string> {
</span> </span>
</span> </span>
<span class="pf-c-switch__label"> <span class="pf-c-switch__label">
${t`Clear icon`} ${msg("Clear icon")}
</span> </span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Delete currently set icon.`} ${msg("Delete currently set icon.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
` `
: html``}` : html``}`
: html`<ak-form-element-horizontal label=${t`Icon`} name="metaIcon"> : html`<ak-form-element-horizontal label=${msg("Icon")} name="metaIcon">
<input <input
type="text" type="text"
value="${first(this.instance?.metaIcon, "")}" value="${first(this.instance?.metaIcon, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">${iconHelperText}</p>
${t`Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".`}
</p>
</ak-form-element-horizontal>`} </ak-form-element-horizontal>`}
<ak-form-element-horizontal label=${t`Publisher`} name="metaPublisher"> <ak-form-element-horizontal label=${msg("Publisher")} name="metaPublisher">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.metaPublisher)}" value="${ifDefined(this.instance?.metaPublisher)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Description`} name="metaDescription"> <ak-form-element-horizontal label=${msg("Description")} name="metaDescription">
<textarea class="pf-c-form-control"> <textarea class="pf-c-form-control">
${ifDefined(this.instance?.metaDescription)}</textarea ${ifDefined(this.instance?.metaDescription)}</textarea
> >

View File

@ -12,8 +12,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -29,10 +28,12 @@ export class ApplicationListPage extends TablePage<Application> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Applications`; return msg("Applications");
} }
pageDescription(): string { pageDescription(): string {
return t`External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.`; return msg(
"External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.",
);
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-applications"; return "pf-icon pf-icon-applications";
@ -78,11 +79,11 @@ export class ApplicationListPage extends TablePage<Application> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(""), new TableColumn(""),
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Group`, "group"), new TableColumn(msg("Group"), "group"),
new TableColumn(t`Provider`), new TableColumn(msg("Provider")),
new TableColumn(t`Provider Type`), new TableColumn(msg("Provider Type")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
@ -105,7 +106,7 @@ export class ApplicationListPage extends TablePage<Application> {
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Application(s)`} objectLabel=${msg("Application(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Application) => { .usedBy=${(item: Application) => {
return new CoreApi(DEFAULT_CONFIG).coreApplicationsUsedByList({ return new CoreApi(DEFAULT_CONFIG).coreApplicationsUsedByList({
@ -119,7 +120,7 @@ export class ApplicationListPage extends TablePage<Application> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -133,7 +134,7 @@ export class ApplicationListPage extends TablePage<Application> {
return html`<img return html`<img
class="app-icon pf-c-avatar" class="app-icon pf-c-avatar"
src="${ifDefined(item.metaIcon)}" src="${ifDefined(item.metaIcon)}"
alt="${t`Application Icon`}" alt="${msg("Application Icon")}"
/>`; />`;
} }
return html`<i class="fas fa-share-square"></i>`; return html`<i class="fas fa-share-square"></i>`;
@ -146,16 +147,16 @@ export class ApplicationListPage extends TablePage<Application> {
<div>${item.name}</div> <div>${item.name}</div>
${item.metaPublisher ? html`<small>${item.metaPublisher}</small>` : html``} ${item.metaPublisher ? html`<small>${item.metaPublisher}</small>` : html``}
</a>`, </a>`,
html`${item.group || t`-`}`, html`${item.group || msg("-")}`,
item.provider item.provider
? html`<a href="#/core/providers/${item.providerObj?.pk}"> ? html`<a href="#/core/providers/${item.providerObj?.pk}">
${item.providerObj?.name} ${item.providerObj?.name}
</a>` </a>`
: html`-`, : html`-`,
html`${item.providerObj?.verboseName || t`-`}`, html`${item.providerObj?.verboseName || msg("-")}`,
html`<ak-forms-modal> html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Application`} </span> <span slot="header"> ${msg("Update Application")} </span>
<ak-application-form slot="form" .instancePk=${item.slug}> <ak-application-form slot="form" .instancePk=${item.slug}>
</ak-application-form> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
@ -172,10 +173,10 @@ export class ApplicationListPage extends TablePage<Application> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html`<ak-forms-modal .open=${getURLParam("createForm", false)}> return html`<ak-forms-modal .open=${getURLParam("createForm", false)}>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Application`} </span> <span slot="header"> ${msg("Create Application")} </span>
<ak-application-form slot="form"> </ak-application-form> <ak-application-form slot="form"> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal>`; </ak-forms-modal>`;
} }
} }

View File

@ -10,8 +10,7 @@ import "@goauthentik/elements/Tabs";
import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/ObjectChangelog"; import "@goauthentik/elements/events/ObjectChangelog";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -82,7 +81,7 @@ export class ApplicationViewPage extends AKElement {
render(): TemplateResult { render(): TemplateResult {
return html`<ak-page-header return html`<ak-page-header
icon=${this.application?.metaIcon || ""} icon=${this.application?.metaIcon || ""}
header=${this.application?.name || t`Loading`} header=${this.application?.name || msg("Loading")}
description=${ifDefined(this.application?.metaPublisher)} description=${ifDefined(this.application?.metaPublisher)}
.iconImage=${true} .iconImage=${true}
> >
@ -92,31 +91,32 @@ export class ApplicationViewPage extends AKElement {
renderApp(): TemplateResult { renderApp(): TemplateResult {
if (!this.application) { if (!this.application) {
return html`<ak-empty-state ?loading="${true}" header=${t`Loading`}> </ak-empty-state>`; return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
} }
return html`<ak-tabs> return html`<ak-tabs>
${this.missingOutpost ${this.missingOutpost
? html`<div slot="header" class="pf-c-banner pf-m-warning"> ? html`<div slot="header" class="pf-c-banner pf-m-warning">
${t`Warning: Application is not used by any Outpost.`} ${msg("Warning: Application is not used by any Outpost.")}
</div>` </div>`
: html``} : html``}
<section <section
slot="page-overview" slot="page-overview"
data-tab-title="${t`Overview`}" data-tab-title="${msg("Overview")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Related`}</div> <div class="pf-c-card__title">${msg("Related")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<dl class="pf-c-description-list"> <dl class="pf-c-description-list">
${this.application.providerObj ${this.application.providerObj
? html`<div class="pf-c-description-list__group"> ? html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Provider`}</span >${msg("Provider")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -136,7 +136,7 @@ export class ApplicationViewPage extends AKElement {
? html`<div class="pf-c-description-list__group"> ? html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Backchannel Providers`}</span >${msg("Backchannel Providers")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -164,7 +164,7 @@ export class ApplicationViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Policy engine mode`}</span >${msg("Policy engine mode")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -175,14 +175,16 @@ export class ApplicationViewPage extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Edit`}</span> <span class="pf-c-description-list__text"
>${msg("Edit")}</span
>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> <span slot="header">
${t`Update Application`} ${msg("Update Application")}
</span> </span>
<ak-application-form <ak-application-form
slot="form" slot="form"
@ -193,7 +195,7 @@ export class ApplicationViewPage extends AKElement {
slot="trigger" slot="trigger"
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-secondary"
> >
${t`Edit`} ${msg("Edit")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -202,15 +204,15 @@ export class ApplicationViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Check access`}</span >${msg("Check access")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
<ak-forms-modal .closeAfterSuccessfulSubmit=${false}> <ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
<span slot="submit"> ${t`Check`} </span> <span slot="submit"> ${msg("Check")} </span>
<span slot="header"> <span slot="header">
${t`Check Application access`} ${msg("Check Application access")}
</span> </span>
<ak-application-check-access-form <ak-application-check-access-form
slot="form" slot="form"
@ -221,7 +223,7 @@ export class ApplicationViewPage extends AKElement {
slot="trigger" slot="trigger"
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-secondary"
> >
${t`Test`} ${msg("Test")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -231,7 +233,7 @@ export class ApplicationViewPage extends AKElement {
? html`<div class="pf-c-description-list__group"> ? html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Launch`}</span >${msg("Launch")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -242,7 +244,7 @@ export class ApplicationViewPage extends AKElement {
slot="trigger" slot="trigger"
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-secondary"
> >
${t`Launch`} ${msg("Launch")}
</a> </a>
</div> </div>
</dd> </dd>
@ -255,7 +257,7 @@ export class ApplicationViewPage extends AKElement {
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl"
> >
<div class="pf-c-card__title"> <div class="pf-c-card__title">
${t`Logins over the last week (per 8 hours)`} ${msg("Logins over the last week (per 8 hours)")}
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.application && ${this.application &&
@ -266,7 +268,7 @@ export class ApplicationViewPage extends AKElement {
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col"> <div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__title">${t`Changelog`}</div> <div class="pf-c-card__title">${msg("Changelog")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-object-changelog <ak-object-changelog
targetModelPk=${this.application.pk || ""} targetModelPk=${this.application.pk || ""}
@ -280,12 +282,12 @@ export class ApplicationViewPage extends AKElement {
</section> </section>
<section <section
slot="page-policy-bindings" slot="page-policy-bindings"
data-tab-title="${t`Policy / Group / User Bindings`}" data-tab-title="${msg("Policy / Group / User Bindings")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__title"> <div class="pf-c-card__title">
${t`These policies control which users can access this application.`} ${msg("These policies control which users can access this application.")}
</div> </div>
<ak-bound-policies-list .target=${this.application.pk}> <ak-bound-policies-list .target=${this.application.pk}>
</ak-bound-policies-list> </ak-bound-policies-list>

View File

@ -5,8 +5,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TableModal } from "@goauthentik/elements/table/TableModal"; import { TableModal } from "@goauthentik/elements/table/TableModal";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -40,7 +39,7 @@ export class ProviderSelectModal extends TableModal<Provider> {
} }
columns(): TableColumn[] { columns(): TableColumn[] {
return [new TableColumn(t`Name`, "username"), new TableColumn(t`Type`)]; return [new TableColumn(msg("Name"), "username"), new TableColumn(msg("Type"))];
} }
row(item: Provider): TemplateResult[] { row(item: Provider): TemplateResult[] {
@ -60,7 +59,7 @@ export class ProviderSelectModal extends TableModal<Provider> {
return html`<section class="pf-c-modal-box__header pf-c-page__main-section pf-m-light"> return html`<section class="pf-c-modal-box__header pf-c-page__main-section pf-m-light">
<div class="pf-c-content"> <div class="pf-c-content">
<h1 class="pf-c-title pf-m-2xl"> <h1 class="pf-c-title pf-m-2xl">
${t`Select providers to add to application`} ${msg("Select providers to add to application")}
</h1> </h1>
</div> </div>
</section> </section>
@ -73,7 +72,7 @@ export class ProviderSelectModal extends TableModal<Provider> {
}} }}
class="pf-m-primary" class="pf-m-primary"
> >
${t`Add`} </ak-spinner-button ${msg("Add")} </ak-spinner-button
>&nbsp; >&nbsp;
<ak-spinner-button <ak-spinner-button
.callAction=${async () => { .callAction=${async () => {
@ -81,7 +80,7 @@ export class ProviderSelectModal extends TableModal<Provider> {
}} }}
class="pf-m-secondary" class="pf-m-secondary"
> >
${t`Cancel`} ${msg("Cancel")}
</ak-spinner-button> </ak-spinner-button>
</footer>`; </footer>`;
} }

View File

@ -13,8 +13,7 @@ import "@goauthentik/admin/applications/wizard/saml/TypeSAMLImportApplicationWiz
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/wizard/Wizard"; import "@goauthentik/elements/wizard/Wizard";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { property } from "lit/decorators.js"; import { property } from "lit/decorators.js";
@ -33,7 +32,7 @@ export class ApplicationWizard extends AKElement {
open = false; open = false;
@property() @property()
createText = t`Create`; createText = msg("Create");
@property({ type: Boolean }) @property({ type: Boolean })
showButton = true; showButton = true;
@ -48,8 +47,8 @@ export class ApplicationWizard extends AKElement {
<ak-wizard <ak-wizard
.open=${this.open} .open=${this.open}
.steps=${["ak-application-wizard-initial", "ak-application-wizard-type"]} .steps=${["ak-application-wizard-initial", "ak-application-wizard-type"]}
header=${t`New application`} header=${msg("New application")}
description=${t`Create a new application.`} description=${msg("Create a new application.")}
.finalHandler=${() => { .finalHandler=${() => {
return this.finalHandler(); return this.finalHandler();
}} }}

View File

@ -5,8 +5,7 @@ import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@ -14,7 +13,7 @@ import { ApplicationRequest, CoreApi, Provider } from "@goauthentik/api";
@customElement("ak-application-wizard-initial") @customElement("ak-application-wizard-initial")
export class InitialApplicationWizardPage extends WizardFormPage { export class InitialApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`Application details`; sidebarLabel = () => msg("Application details");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
const name = data.name as string; const name = data.name as string;
@ -28,7 +27,7 @@ export class InitialApplicationWizardPage extends WizardFormPage {
} }
this.host.state["slug"] = slug; this.host.state["slug"] = slug;
this.host.state["name"] = name; this.host.state["name"] = name;
this.host.addActionBefore(t`Create application`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create application"), async (): Promise<boolean> => {
const req: ApplicationRequest = { const req: ApplicationRequest = {
name: name || "", name: name || "",
slug: slug, slug: slug,
@ -52,17 +51,20 @@ export class InitialApplicationWizardPage extends WizardFormPage {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html` return html`
<form class="pf-c-form pf-m-horizontal"> <form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input type="text" value="" class="pf-c-form-control" required /> <input type="text" value="" class="pf-c-form-control" required />
<p class="pf-c-form__helper-text">${t`Application's display Name.`}</p> <p class="pf-c-form__helper-text">${msg("Application's display Name.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group ?expanded=${true}> <ak-form-group ?expanded=${true}>
<span slot="header"> ${t`Additional UI settings`} </span> <span slot="header"> ${msg("Additional UI settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Description`} name="metaDescription"> <ak-form-element-horizontal
label=${msg("Description")}
name="metaDescription"
>
<textarea class="pf-c-form-control"></textarea> <textarea class="pf-c-form-control"></textarea>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Publisher`} name="metaPublisher"> <ak-form-element-horizontal label=${msg("Publisher")} name="metaPublisher">
<input type="text" value="" class="pf-c-form-control" /> <input type="text" value="" class="pf-c-form-control" />
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -1,7 +1,6 @@
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
@ -17,37 +16,43 @@ export class TypeApplicationWizardPage extends WizardPage {
applicationTypes: TypeCreate[] = [ applicationTypes: TypeCreate[] = [
{ {
component: "ak-application-wizard-type-oauth", component: "ak-application-wizard-type-oauth",
name: t`OAuth2/OIDC`, name: msg("OAuth2/OIDC"),
description: t`Modern applications, APIs and Single-page applications.`, description: msg("Modern applications, APIs and Single-page applications."),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-saml", component: "ak-application-wizard-type-saml",
name: t`SAML`, name: msg("SAML"),
description: t`XML-based SSO standard. Use this if your application only supports SAML.`, description: msg(
"XML-based SSO standard. Use this if your application only supports SAML.",
),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-proxy", component: "ak-application-wizard-type-proxy",
name: t`Proxy`, name: msg("Proxy"),
description: t`Legacy applications which don't natively support SSO.`, description: msg("Legacy applications which don't natively support SSO."),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-ldap", component: "ak-application-wizard-type-ldap",
name: t`LDAP`, name: msg("LDAP"),
description: t`Provide an LDAP interface for applications and users to authenticate against.`, description: msg(
"Provide an LDAP interface for applications and users to authenticate against.",
),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-link", component: "ak-application-wizard-type-link",
name: t`Link`, name: msg("Link"),
description: t`Provide an LDAP interface for applications and users to authenticate against.`, description: msg(
"Provide an LDAP interface for applications and users to authenticate against.",
),
modelName: "", modelName: "",
}, },
]; ];
sidebarLabel = () => t`Authentication method`; sidebarLabel = () => msg("Authentication method");
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFButton, PFForm, PFRadio]; return [PFBase, PFButton, PFForm, PFRadio];

View File

@ -3,8 +3,7 @@ import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@ -19,7 +18,7 @@ import {
@customElement("ak-application-wizard-type-ldap") @customElement("ak-application-wizard-type-ldap")
export class TypeLDAPApplicationWizardPage extends WizardFormPage { export class TypeLDAPApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`LDAP details`; sidebarLabel = () => msg("LDAP details");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
let name = this.host.state["name"] as string; let name = this.host.state["name"] as string;
@ -30,7 +29,7 @@ export class TypeLDAPApplicationWizardPage extends WizardFormPage {
if (providers.results.filter((provider) => provider.name == name)) { if (providers.results.filter((provider) => provider.name == name)) {
name += "-1"; name += "-1";
} }
this.host.addActionBefore(t`Create service account`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create service account"), async (): Promise<boolean> => {
const serviceAccount = await new CoreApi(DEFAULT_CONFIG).coreUsersServiceAccountCreate({ const serviceAccount = await new CoreApi(DEFAULT_CONFIG).coreUsersServiceAccountCreate({
userServiceAccountRequest: { userServiceAccountRequest: {
name: name, name: name,
@ -40,7 +39,7 @@ export class TypeLDAPApplicationWizardPage extends WizardFormPage {
this.host.state["serviceAccount"] = serviceAccount; this.host.state["serviceAccount"] = serviceAccount;
return true; return true;
}); });
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create provider"), async (): Promise<boolean> => {
// Get all flows and default to the implicit authorization // Get all flows and default to the implicit authorization
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
@ -66,7 +65,7 @@ export class TypeLDAPApplicationWizardPage extends WizardFormPage {
const domainParts = window.location.hostname.split("."); const domainParts = window.location.hostname.split(".");
const defaultBaseDN = domainParts.map((part) => `dc=${part}`).join(","); const defaultBaseDN = domainParts.map((part) => `dc=${part}`).join(",");
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Base DN`} name="baseDN" ?required=${true}> <ak-form-element-horizontal label=${msg("Base DN")} name="baseDN" ?required=${true}>
<input type="text" value="${defaultBaseDN}" class="pf-c-form-control" required /> <input type="text" value="${defaultBaseDN}" class="pf-c-form-control" required />
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form> `; </form> `;

View File

@ -2,14 +2,13 @@ import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@customElement("ak-application-wizard-type-link") @customElement("ak-application-wizard-type-link")
export class TypeLinkApplicationWizardPage extends WizardFormPage { export class TypeLinkApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`Application Link`; sidebarLabel = () => msg("Application Link");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
this.host.state["link"] = data.link; this.host.state["link"] = data.link;
@ -19,10 +18,10 @@ export class TypeLinkApplicationWizardPage extends WizardFormPage {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html` return html`
<form class="pf-c-form pf-m-horizontal"> <form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Link`} ?required=${true} name="link"> <ak-form-element-horizontal label=${msg("Link")} ?required=${true} name="link">
<input type="text" value="" class="pf-c-form-control" required /> <input type="text" value="" class="pf-c-form-control" required />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`URL which will be opened when a user clicks on the application.`} ${msg("URL which will be opened when a user clicks on the application.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form> </form>

View File

@ -1,8 +1,7 @@
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
@ -17,15 +16,19 @@ export class TypeOAuthAPIApplicationWizardPage extends WizardPage {
return [PFBase, PFButton, PFForm, PFRadio]; return [PFBase, PFButton, PFForm, PFRadio];
} }
sidebarLabel = () => t`Method details`; sidebarLabel = () => msg("Method details");
render(): TemplateResult { render(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<p> <p>
${t`This configuration can be used to authenticate to authentik with other APIs other otherwise programmatically.`} ${msg(
"This configuration can be used to authenticate to authentik with other APIs other otherwise programmatically.",
)}
</p> </p>
<p> <p>
${t`By default, all service accounts can authenticate as this application, as long as they have a valid token of the type app-password.`} ${msg(
"By default, all service accounts can authenticate as this application, as long as they have a valid token of the type app-password.",
)}
</p> </p>
</form> `; </form> `;
} }

View File

@ -1,8 +1,7 @@
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
@ -18,26 +17,34 @@ export class TypeOAuthApplicationWizardPage extends WizardPage {
applicationTypes: TypeCreate[] = [ applicationTypes: TypeCreate[] = [
{ {
component: "ak-application-wizard-type-oauth-code", component: "ak-application-wizard-type-oauth-code",
name: t`Web application`, name: msg("Web application"),
description: t`Applications which handle the authentication server-side (for example, Python, Go, Rust, Java, PHP)`, description: msg(
"Applications which handle the authentication server-side (for example, Python, Go, Rust, Java, PHP)",
),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-oauth-implicit", component: "ak-application-wizard-type-oauth-implicit",
name: t`Single-page applications`, name: msg("Single-page applications"),
description: t`Single-page applications which handle authentication in the browser (for example, Javascript, Angular, React, Vue)`, description: msg(
"Single-page applications which handle authentication in the browser (for example, Javascript, Angular, React, Vue)",
),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-oauth-implicit", component: "ak-application-wizard-type-oauth-implicit",
name: t`Native application`, name: msg("Native application"),
description: t`Applications which redirect users to a non-web callback (for example, Android, iOS)`, description: msg(
"Applications which redirect users to a non-web callback (for example, Android, iOS)",
),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-oauth-api", component: "ak-application-wizard-type-oauth-api",
name: t`API`, name: msg("API"),
description: t`Authentication without user interaction, or machine-to-machine authentication.`, description: msg(
"Authentication without user interaction, or machine-to-machine authentication.",
),
modelName: "", modelName: "",
}, },
]; ];
@ -46,7 +53,7 @@ export class TypeOAuthApplicationWizardPage extends WizardPage {
return [PFBase, PFButton, PFForm, PFRadio]; return [PFBase, PFButton, PFForm, PFRadio];
} }
sidebarLabel = () => t`Application type`; sidebarLabel = () => msg("Application type");
render(): TemplateResult { render(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">

View File

@ -6,8 +6,7 @@ import "@goauthentik/elements/forms/SearchSelect";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import "@goauthentik/elements/wizard/WizardFormPage"; import "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@ -23,10 +22,10 @@ import {
@customElement("ak-application-wizard-type-oauth-code") @customElement("ak-application-wizard-type-oauth-code")
export class TypeOAuthCodeApplicationWizardPage extends WizardFormPage { export class TypeOAuthCodeApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`Method details`; sidebarLabel = () => msg("Method details");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create provider"), async (): Promise<boolean> => {
const req: OAuth2ProviderRequest = { const req: OAuth2ProviderRequest = {
name: this.host.state["name"] as string, name: this.host.state["name"] as string,
clientType: ClientTypeEnum.Confidential, clientType: ClientTypeEnum.Confidential,
@ -44,7 +43,7 @@ export class TypeOAuthCodeApplicationWizardPage extends WizardFormPage {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authorization flow`} label=${msg("Authorization flow")}
?required=${true} ?required=${true}
name="authorizationFlow" name="authorizationFlow"
> >
@ -72,7 +71,7 @@ export class TypeOAuthCodeApplicationWizardPage extends WizardFormPage {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Flow used when users access this application.`} ${msg("Flow used when users access this application.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -1,14 +1,13 @@
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@customElement("ak-application-wizard-type-oauth-implicit") @customElement("ak-application-wizard-type-oauth-implicit")
export class TypeOAuthImplicitApplicationWizardPage extends WizardFormPage { export class TypeOAuthImplicitApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`Method details`; sidebarLabel = () => msg("Method details");
render(): TemplateResult { render(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal">some stuff idk</form> `; return html`<form class="pf-c-form pf-m-horizontal">some stuff idk</form> `;

View File

@ -3,8 +3,7 @@ import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@ -17,7 +16,7 @@ import {
@customElement("ak-application-wizard-type-proxy") @customElement("ak-application-wizard-type-proxy")
export class TypeProxyApplicationWizardPage extends WizardFormPage { export class TypeProxyApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`Proxy details`; sidebarLabel = () => msg("Proxy details");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
let name = this.host.state["name"] as string; let name = this.host.state["name"] as string;
@ -28,7 +27,7 @@ export class TypeProxyApplicationWizardPage extends WizardFormPage {
if (providers.results.filter((provider) => provider.name == name)) { if (providers.results.filter((provider) => provider.name == name)) {
name += "-1"; name += "-1";
} }
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create provider"), async (): Promise<boolean> => {
// Get all flows and default to the implicit authorization // Get all flows and default to the implicit authorization
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
@ -51,13 +50,13 @@ export class TypeProxyApplicationWizardPage extends WizardFormPage {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`External domain`} label=${msg("External domain")}
name="externalHost" name="externalHost"
?required=${true} ?required=${true}
> >
<input type="text" value="" class="pf-c-form-control" required /> <input type="text" value="" class="pf-c-form-control" required />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`External domain you will be accessing the domain from.`} ${msg("External domain you will be accessing the domain from.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form> `; </form> `;

View File

@ -1,8 +1,7 @@
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
@ -18,14 +17,16 @@ export class TypeOAuthApplicationWizardPage extends WizardPage {
applicationTypes: TypeCreate[] = [ applicationTypes: TypeCreate[] = [
{ {
component: "ak-application-wizard-type-saml-import", component: "ak-application-wizard-type-saml-import",
name: t`Import SAML Metadata`, name: msg("Import SAML Metadata"),
description: t`Import the metadata document of the applicaation you want to configure.`, description: msg(
"Import the metadata document of the applicaation you want to configure.",
),
modelName: "", modelName: "",
}, },
{ {
component: "ak-application-wizard-type-saml-config", component: "ak-application-wizard-type-saml-config",
name: t`Manual configuration`, name: msg("Manual configuration"),
description: t`Manually configure SAML`, description: msg("Manually configure SAML"),
modelName: "", modelName: "",
}, },
]; ];
@ -34,7 +35,7 @@ export class TypeOAuthApplicationWizardPage extends WizardPage {
return [PFBase, PFButton, PFForm, PFRadio]; return [PFBase, PFButton, PFForm, PFRadio];
} }
sidebarLabel = () => t`Application type`; sidebarLabel = () => msg("Application type");
render(): TemplateResult { render(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">

View File

@ -3,8 +3,7 @@ import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@ -12,7 +11,7 @@ import { FlowDesignationEnum, FlowsApi, ProvidersApi, SAMLProviderRequest } from
@customElement("ak-application-wizard-type-saml-config") @customElement("ak-application-wizard-type-saml-config")
export class TypeSAMLApplicationWizardPage extends WizardFormPage { export class TypeSAMLApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`SAML details`; sidebarLabel = () => msg("SAML details");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
let name = this.host.state["name"] as string; let name = this.host.state["name"] as string;
@ -23,7 +22,7 @@ export class TypeSAMLApplicationWizardPage extends WizardFormPage {
if (providers.results.filter((provider) => provider.name == name)) { if (providers.results.filter((provider) => provider.name == name)) {
name += "-1"; name += "-1";
} }
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create provider"), async (): Promise<boolean> => {
// Get all flows and default to the implicit authorization // Get all flows and default to the implicit authorization
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
@ -45,10 +44,12 @@ export class TypeSAMLApplicationWizardPage extends WizardFormPage {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`ACS URL`} name="acsUrl" ?required=${true}> <ak-form-element-horizontal label=${msg("ACS URL")} name="acsUrl" ?required=${true}>
<input type="text" value="" class="pf-c-form-control" required /> <input type="text" value="" class="pf-c-form-control" required />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`URL that authentik will redirect back to after successful authentication.`} ${msg(
"URL that authentik will redirect back to after successful authentication.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form> `; </form> `;

View File

@ -3,8 +3,7 @@ import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage"; import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
@ -17,7 +16,7 @@ import {
@customElement("ak-application-wizard-type-saml-import") @customElement("ak-application-wizard-type-saml-import")
export class TypeSAMLImportApplicationWizardPage extends WizardFormPage { export class TypeSAMLImportApplicationWizardPage extends WizardFormPage {
sidebarLabel = () => t`Import SAML metadata`; sidebarLabel = () => msg("Import SAML metadata");
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => { nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
let name = this.host.state["name"] as string; let name = this.host.state["name"] as string;
@ -28,7 +27,7 @@ export class TypeSAMLImportApplicationWizardPage extends WizardFormPage {
if (providers.results.filter((provider) => provider.name == name)) { if (providers.results.filter((provider) => provider.name == name)) {
name += "-1"; name += "-1";
} }
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => { this.host.addActionBefore(msg("Create provider"), async (): Promise<boolean> => {
// Get all flows and default to the implicit authorization // Get all flows and default to the implicit authorization
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
@ -50,7 +49,7 @@ export class TypeSAMLImportApplicationWizardPage extends WizardFormPage {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Metadata`} name="metadata"> <ak-form-element-horizontal label=${msg("Metadata")} name="metadata">
<input type="file" value="" class="pf-c-form-control" /> <input type="file" value="" class="pf-c-form-control" />
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form> `; </form> `;

View File

@ -8,8 +8,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import YAML from "yaml"; import YAML from "yaml";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -45,9 +44,9 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated instance.`; return msg("Successfully updated instance.");
} else { } else {
return t`Successfully created instance.`; return msg("Successfully created instance.");
} }
} }
@ -78,7 +77,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -98,9 +97,11 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Enabled`}</span> <span class="pf-c-switch__label">${msg("Enabled")}</span>
</label> </label>
<p class="pf-c-form__helper-text">${t`Disabled blueprints are never applied.`}</p> <p class="pf-c-form__helper-text">
${msg("Disabled blueprints are never applied.")}
</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<div class="pf-c-card pf-m-selectable pf-m-selected"> <div class="pf-c-card pf-m-selectable pf-m-selected">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
@ -116,7 +117,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
this.source = blueprintSource.file; this.source = blueprintSource.file;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`Local path`}</span> <span class="pf-c-toggle-group__text">${msg("Local path")}</span>
</button> </button>
</div> </div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div> <div class="pf-c-divider pf-m-vertical" role="separator"></div>
@ -131,7 +132,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
this.source = blueprintSource.oci; this.source = blueprintSource.oci;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`OCI Registry`}</span> <span class="pf-c-toggle-group__text">${msg("OCI Registry")}</span>
</button> </button>
</div> </div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div> <div class="pf-c-divider pf-m-vertical" role="separator"></div>
@ -146,14 +147,14 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
this.source = blueprintSource.internal; this.source = blueprintSource.internal;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`Internal`}</span> <span class="pf-c-toggle-group__text">${msg("Internal")}</span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<div class="pf-c-card__footer"> <div class="pf-c-card__footer">
${this.source === blueprintSource.file ${this.source === blueprintSource.file
? html`<ak-form-element-horizontal label=${t`Path`} name="path"> ? html`<ak-form-element-horizontal label=${msg("Path")} name="path">
<ak-search-select <ak-search-select
.fetchObjects=${async ( .fetchObjects=${async (
query?: string, query?: string,
@ -186,7 +187,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
</ak-form-element-horizontal>` </ak-form-element-horizontal>`
: html``} : html``}
${this.source === blueprintSource.oci ${this.source === blueprintSource.oci
? html`<ak-form-element-horizontal label=${t`URL`} name="path"> ? html`<ak-form-element-horizontal label=${msg("URL")} name="path">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.path)}" value="${ifDefined(this.instance?.path)}"
@ -194,22 +195,24 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`OCI URL, in the format of oci://registry.domain.tld/path/to/manifest.`} ${msg(
"OCI URL, in the format of oci://registry.domain.tld/path/to/manifest.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`See more about OCI support here:`}&nbsp; ${msg("See more about OCI support here:")}&nbsp;
<a <a
target="_blank" target="_blank"
href="${docLink( href="${docLink(
"/developer-docs/blueprints/?utm_source=authentik#storage---oci", "/developer-docs/blueprints/?utm_source=authentik#storage---oci",
)}" )}"
>${t`Documentation`}</a >${msg("Documentation")}</a
> >
</p> </p>
</ak-form-element-horizontal>` </ak-form-element-horizontal>`
: html``} : html``}
${this.source === blueprintSource.internal ${this.source === blueprintSource.internal
? html`<ak-form-element-horizontal label=${t`Blueprint`} name="content"> ? html`<ak-form-element-horizontal label=${msg("Blueprint")} name="content">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
.parseValue=${false} .parseValue=${false}
@ -221,16 +224,16 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
</div> </div>
<ak-form-group> <ak-form-group>
<span slot="header">${t`Additional settings`}</span> <span slot="header">${msg("Additional settings")}</span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Context`} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(first(this.instance?.context, {}))}" value="${YAML.stringify(first(this.instance?.context, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure the blueprint context, used for templating.`} ${msg("Configure the blueprint context, used for templating.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -11,8 +11,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -24,15 +23,15 @@ export function BlueprintStatus(blueprint?: BlueprintInstance): string {
if (!blueprint) return ""; if (!blueprint) return "";
switch (blueprint.status) { switch (blueprint.status) {
case BlueprintInstanceStatusEnum.Successful: case BlueprintInstanceStatusEnum.Successful:
return t`Successful`; return msg("Successful");
case BlueprintInstanceStatusEnum.Orphaned: case BlueprintInstanceStatusEnum.Orphaned:
return t`Orphaned`; return msg("Orphaned");
case BlueprintInstanceStatusEnum.Warning: case BlueprintInstanceStatusEnum.Warning:
return t`Warning`; return msg("Warning");
case BlueprintInstanceStatusEnum.Error: case BlueprintInstanceStatusEnum.Error:
return t`Error`; return msg("Error");
} }
return t`Unknown`; return msg("Unknown");
} }
@customElement("ak-blueprint-list") @customElement("ak-blueprint-list")
@ -41,10 +40,10 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Blueprints`; return msg("Blueprints");
} }
pageDescription(): string { pageDescription(): string {
return t`Automate and template configuration within authentik.`; return msg("Automate and template configuration within authentik.");
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-blueprint"; return "pf-icon pf-icon-blueprint";
@ -71,21 +70,21 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Status`, "status"), new TableColumn(msg("Status"), "status"),
new TableColumn(t`Last applied`, "last_applied"), new TableColumn(msg("Last applied"), "last_applied"),
new TableColumn(t`Enabled`, "enabled"), new TableColumn(msg("Enabled"), "enabled"),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Blueprint(s)`} objectLabel=${msg("Blueprint(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.metadata=${(item: BlueprintInstance) => { .metadata=${(item: BlueprintInstance) => {
return [{ key: t`Name`, value: item.name }]; return [{ key: msg("Name"), value: item.name }];
}} }}
.usedBy=${(item: BlueprintInstance) => { .usedBy=${(item: BlueprintInstance) => {
return new ManagedApi(DEFAULT_CONFIG).managedBlueprintsUsedByList({ return new ManagedApi(DEFAULT_CONFIG).managedBlueprintsUsedByList({
@ -99,7 +98,7 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -110,7 +109,7 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Path`}</span> <span class="pf-c-description-list__text">${msg("Path")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -139,11 +138,11 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
html`${BlueprintStatus(item)}`, html`${BlueprintStatus(item)}`,
html`${item.lastApplied.toLocaleString()}`, html`${item.lastApplied.toLocaleString()}`,
html`<ak-label color=${item.enabled ? PFColor.Green : PFColor.Red}> html`<ak-label color=${item.enabled ? PFColor.Green : PFColor.Red}>
${item.enabled ? t`Yes` : t`No`} ${item.enabled ? msg("Yes") : msg("No")}
</ak-label>`, </ak-label>`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Blueprint`} </span> <span slot="header"> ${msg("Update Blueprint")} </span>
<ak-blueprint-form slot="form" .instancePk=${item.pk}> </ak-blueprint-form> <ak-blueprint-form slot="form" .instancePk=${item.pk}> </ak-blueprint-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i> <i class="fas fa-edit"></i>
@ -173,10 +172,10 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Blueprint Instance`} </span> <span slot="header"> ${msg("Create Blueprint Instance")} </span>
<ak-blueprint-form slot="form"> </ak-blueprint-form> <ak-blueprint-form slot="form"> </ak-blueprint-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }

View File

@ -2,8 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { Form } from "@goauthentik/elements/forms/Form"; import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
@ -12,7 +11,7 @@ import { CertificateGenerationRequest, CertificateKeyPair, CryptoApi } from "@go
@customElement("ak-crypto-certificate-generate-form") @customElement("ak-crypto-certificate-generate-form")
export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> { export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> {
getSuccessMessage(): string { getSuccessMessage(): string {
return t`Successfully generated certificate-key pair.`; return msg("Successfully generated certificate-key pair.");
} }
async send(data: CertificateGenerationRequest): Promise<CertificateKeyPair> { async send(data: CertificateGenerationRequest): Promise<CertificateKeyPair> {
@ -23,17 +22,21 @@ export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Common Name`} name="commonName" ?required=${true}> <ak-form-element-horizontal
label=${msg("Common Name")}
name="commonName"
?required=${true}
>
<input type="text" class="pf-c-form-control" required /> <input type="text" class="pf-c-form-control" required />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Subject-alt name`} name="subjectAltName"> <ak-form-element-horizontal label=${msg("Subject-alt name")} name="subjectAltName">
<input class="pf-c-form-control" type="text" /> <input class="pf-c-form-control" type="text" />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Optional, comma-separated SubjectAlt Names.`} ${msg("Optional, comma-separated SubjectAlt Names.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Validity days`} label=${msg("Validity days")}
name="validityDays" name="validityDays"
?required=${true} ?required=${true}
> >

View File

@ -3,8 +3,7 @@ import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -21,9 +20,9 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated certificate-key pair.`; return msg("Successfully updated certificate-key pair.");
} else { } else {
return t`Successfully created certificate-key pair.`; return msg("Successfully created certificate-key pair.");
} }
} }
@ -42,7 +41,7 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} name="name" ?required=${true}> <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -51,22 +50,24 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Certificate`} label=${msg("Certificate")}
name="certificateData" name="certificateData"
?writeOnly=${this.instance !== undefined} ?writeOnly=${this.instance !== undefined}
?required=${true} ?required=${true}
> >
<textarea class="pf-c-form-control" required></textarea> <textarea class="pf-c-form-control" required></textarea>
<p class="pf-c-form__helper-text">${t`PEM-encoded Certificate data.`}</p> <p class="pf-c-form__helper-text">${msg("PEM-encoded Certificate data.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
name="keyData" name="keyData"
?writeOnly=${this.instance !== undefined} ?writeOnly=${this.instance !== undefined}
label=${t`Private Key`} label=${msg("Private Key")}
> >
<textarea class="pf-c-form-control"></textarea> <textarea class="pf-c-form-control"></textarea>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Optional Private Key. If this is set, you can use this keypair for encryption.`} ${msg(
"Optional Private Key. If this is set, you can use this keypair for encryption.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -10,8 +10,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -28,10 +27,12 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Certificate-Key Pairs`; return msg("Certificate-Key Pairs");
} }
pageDescription(): string { pageDescription(): string {
return t`Import certificates of external providers or create certificates to sign requests with.`; return msg(
"Import certificates of external providers or create certificates to sign requests with.",
);
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-key"; return "pf-icon pf-icon-key";
@ -55,22 +56,22 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Private key available?`), new TableColumn(msg("Private key available?")),
new TableColumn(t`Expiry date`), new TableColumn(msg("Expiry date")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Certificate-Key Pair(s)`} objectLabel=${msg("Certificate-Key Pair(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.metadata=${(item: CertificateKeyPair) => { .metadata=${(item: CertificateKeyPair) => {
return [ return [
{ key: t`Name`, value: item.name }, { key: msg("Name"), value: item.name },
{ key: t`Expiry`, value: item.certExpiry?.toLocaleString() }, { key: msg("Expiry"), value: item.certExpiry?.toLocaleString() },
]; ];
}} }}
.usedBy=${(item: CertificateKeyPair) => { .usedBy=${(item: CertificateKeyPair) => {
@ -85,15 +86,15 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
row(item: CertificateKeyPair): TemplateResult[] { row(item: CertificateKeyPair): TemplateResult[] {
let managedSubText = t`Managed by authentik`; let managedSubText = msg("Managed by authentik");
if (item.managed && item.managed.startsWith("goauthentik.io/crypto/discovered")) { if (item.managed && item.managed.startsWith("goauthentik.io/crypto/discovered")) {
managedSubText = t`Managed by authentik (Discovered)`; managedSubText = msg("Managed by authentik (Discovered)");
} }
let color = PFColor.Green; let color = PFColor.Green;
if (item.certExpiry) { if (item.certExpiry) {
@ -111,12 +112,14 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
html`<div>${item.name}</div> html`<div>${item.name}</div>
${item.managed ? html`<small>${managedSubText}</small>` : html``}`, ${item.managed ? html`<small>${managedSubText}</small>` : html``}`,
html`<ak-label color=${item.privateKeyAvailable ? PFColor.Green : PFColor.Grey}> html`<ak-label color=${item.privateKeyAvailable ? PFColor.Green : PFColor.Grey}>
${item.privateKeyAvailable ? t`Yes (${item.privateKeyType?.toUpperCase()})` : t`No`} ${item.privateKeyAvailable
? msg(str`Yes (${item.privateKeyType?.toUpperCase()})`)
: msg("No")}
</ak-label>`, </ak-label>`,
html`<ak-label color=${color}> ${item.certExpiry?.toLocaleString()} </ak-label>`, html`<ak-label color=${color}> ${item.certExpiry?.toLocaleString()} </ak-label>`,
html`<ak-forms-modal> html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Certificate-Key Pair`} </span> <span slot="header"> ${msg("Update Certificate-Key Pair")} </span>
<ak-crypto-certificate-form slot="form" .instancePk=${item.pk}> <ak-crypto-certificate-form slot="form" .instancePk=${item.pk}>
</ak-crypto-certificate-form> </ak-crypto-certificate-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
@ -133,7 +136,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Certificate Fingerprint (SHA1)`}</span >${msg("Certificate Fingerprint (SHA1)")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -145,7 +148,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Certificate Fingerprint (SHA256)`}</span >${msg("Certificate Fingerprint (SHA256)")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -157,7 +160,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Certificate Subject`}</span >${msg("Certificate Subject")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -166,7 +169,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Download`}</span> <span class="pf-c-description-list__text">${msg("Download")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -175,7 +178,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
target="_blank" target="_blank"
href=${item.certificateDownloadUrl} href=${item.certificateDownloadUrl}
> >
${t`Download Certificate`} ${msg("Download Certificate")}
</a> </a>
${item.privateKeyAvailable ${item.privateKeyAvailable
? html`<a ? html`<a
@ -183,7 +186,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
target="_blank" target="_blank"
href=${item.privateKeyDownloadUrl} href=${item.privateKeyDownloadUrl}
> >
${t`Download Private key`} ${msg("Download Private key")}
</a>` </a>`
: html``} : html``}
</div> </div>
@ -199,17 +202,19 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Certificate-Key Pair`} </span> <span slot="header"> ${msg("Create Certificate-Key Pair")} </span>
<ak-crypto-certificate-form slot="form"> </ak-crypto-certificate-form> <ak-crypto-certificate-form slot="form"> </ak-crypto-certificate-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Generate`} </span> <span slot="submit"> ${msg("Generate")} </span>
<span slot="header"> ${t`Generate Certificate-Key Pair`} </span> <span slot="header"> ${msg("Generate Certificate-Key Pair")} </span>
<ak-crypto-certificate-generate-form slot="form"> <ak-crypto-certificate-generate-form slot="form">
</ak-crypto-certificate-generate-form> </ak-crypto-certificate-generate-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">${t`Generate`}</button> <button slot="trigger" class="pf-c-button pf-m-secondary">
${msg("Generate")}
</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }

View File

@ -6,8 +6,7 @@ import "@goauthentik/elements/Expand";
import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/Spinner";
import { PFSize } from "@goauthentik/elements/Spinner"; import { PFSize } from "@goauthentik/elements/Spinner";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { until } from "lit/directives/until.js"; import { until } from "lit/directives/until.js";
@ -62,7 +61,7 @@ export class EventInfo extends AKElement {
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`UID`}</span> <span class="pf-c-description-list__text">${msg("UID")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.pk}</div> <div class="pf-c-description-list__text">${context.pk}</div>
@ -70,7 +69,7 @@ export class EventInfo extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span> <span class="pf-c-description-list__text">${msg("Name")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.name}</div> <div class="pf-c-description-list__text">${context.name}</div>
@ -78,7 +77,7 @@ export class EventInfo extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`App`}</span> <span class="pf-c-description-list__text">${msg("App")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.app}</div> <div class="pf-c-description-list__text">${context.app}</div>
@ -86,7 +85,7 @@ export class EventInfo extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Model Name`}</span> <span class="pf-c-description-list__text">${msg("Model Name")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.model_name}</div> <div class="pf-c-description-list__text">${context.model_name}</div>
@ -103,7 +102,7 @@ export class EventInfo extends AKElement {
return html`<dl class="pf-c-description-list pf-m-horizontal"> return html`<dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Message`}</span> <span class="pf-c-description-list__text">${msg("Message")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.message}</div> <div class="pf-c-description-list__text">${context.message}</div>
@ -111,7 +110,7 @@ export class EventInfo extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Subject`}</span> <span class="pf-c-description-list__text">${msg("Subject")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.subject}</div> <div class="pf-c-description-list__text">${context.subject}</div>
@ -119,7 +118,7 @@ export class EventInfo extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`From`}</span> <span class="pf-c-description-list__text">${msg("From")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.from_email}</div> <div class="pf-c-description-list__text">${context.from_email}</div>
@ -127,7 +126,7 @@ export class EventInfo extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`To`}</span> <span class="pf-c-description-list__text">${msg("To")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -143,13 +142,13 @@ export class EventInfo extends AKElement {
defaultResponse(): TemplateResult { defaultResponse(): TemplateResult {
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Context`}</div> <div class="pf-c-card__title">${msg("Context")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<code>${JSON.stringify(this.event?.context, null, 4)}</code> <code>${JSON.stringify(this.event?.context, null, 4)}</code>
</div> </div>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`User`}</div> <div class="pf-c-card__title">${msg("User")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<code>${JSON.stringify(this.event?.user, null, 4)}</code> <code>${JSON.stringify(this.event?.user, null, 4)}</code>
</div> </div>
@ -212,7 +211,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
case EventActions.ModelUpdated: case EventActions.ModelUpdated:
case EventActions.ModelDeleted: case EventActions.ModelDeleted:
return html` return html`
<div class="pf-c-card__title">${t`Affected model:`}</div> <div class="pf-c-card__title">${msg("Affected model:")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.getModelInfo(this.event.context?.model as EventModel)} ${this.getModelInfo(this.event.context?.model as EventModel)}
</div> </div>
@ -220,7 +219,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
case EventActions.AuthorizeApplication: case EventActions.AuthorizeApplication:
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Authorized application:`}</div> <div class="pf-c-card__title">${msg("Authorized application:")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.getModelInfo( ${this.getModelInfo(
this.event.context.authorized_application as EventModel, this.event.context.authorized_application as EventModel,
@ -228,7 +227,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
</div> </div>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Using flow`}</div> <div class="pf-c-card__title">${msg("Using flow")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<span <span
>${until( >${until(
@ -250,13 +249,13 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
</div> </div>
<ak-expand>${this.defaultResponse()}</ak-expand>`; <ak-expand>${this.defaultResponse()}</ak-expand>`;
case EventActions.EmailSent: case EventActions.EmailSent:
return html`<div class="pf-c-card__title">${t`Email info:`}</div> return html`<div class="pf-c-card__title">${msg("Email info:")}</div>
<div class="pf-c-card__body">${this.getEmailInfo(this.event.context)}</div> <div class="pf-c-card__body">${this.getEmailInfo(this.event.context)}</div>
<ak-expand> <ak-expand>
<iframe srcdoc=${this.event.context.body}></iframe> <iframe srcdoc=${this.event.context.body}></iframe>
</ak-expand>`; </ak-expand>`;
case EventActions.SecretView: case EventActions.SecretView:
return html` <div class="pf-c-card__title">${t`Secret:`}</div> return html` <div class="pf-c-card__title">${msg("Secret:")}</div>
${this.getModelInfo(this.event.context.secret as EventModel)}`; ${this.getModelInfo(this.event.context.secret as EventModel)}`;
case EventActions.SystemException: case EventActions.SystemException:
return html` <a return html` <a
@ -264,11 +263,11 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
target="_blank" target="_blank"
href=${this.buildGitHubIssueUrl(this.event.context)} href=${this.buildGitHubIssueUrl(this.event.context)}
> >
${t`Open issue on GitHub...`} ${msg("Open issue on GitHub...")}
</a> </a>
<div class="pf-l-flex"> <div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Exception`}</div> <div class="pf-c-card__title">${msg("Exception")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<pre>${this.event.context.message}</pre> <pre>${this.event.context.message}</pre>
</div> </div>
@ -278,13 +277,13 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
case EventActions.PropertyMappingException: case EventActions.PropertyMappingException:
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Exception`}</div> <div class="pf-c-card__title">${msg("Exception")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<pre>${this.event.context.message || this.event.context.error}</pre> <pre>${this.event.context.message || this.event.context.error}</pre>
</div> </div>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Expression`}</div> <div class="pf-c-card__title">${msg("Expression")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<code>${this.event.context.expression}</code> <code>${this.event.context.expression}</code>
</div> </div>
@ -294,15 +293,15 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
case EventActions.PolicyException: case EventActions.PolicyException:
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Binding`}</div> <div class="pf-c-card__title">${msg("Binding")}</div>
${this.getModelInfo(this.event.context.binding as EventModel)} ${this.getModelInfo(this.event.context.binding as EventModel)}
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Request`}</div> <div class="pf-c-card__title">${msg("Request")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ul class="pf-c-list"> <ul class="pf-c-list">
<li> <li>
${t`Object`}: ${msg("Object")}:
${this.getModelInfo( ${this.getModelInfo(
(this.event.context.request as EventContext) (this.event.context.request as EventContext)
.obj as EventModel, .obj as EventModel,
@ -310,7 +309,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
</li> </li>
<li> <li>
<span <span
>${t`Context`}: >${msg("Context")}:
<code <code
>${JSON.stringify( >${JSON.stringify(
(this.event.context.request as EventContext) (this.event.context.request as EventContext)
@ -325,7 +324,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
</div> </div>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Exception`}</div> <div class="pf-c-card__title">${msg("Exception")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<code <code
>${this.event.context.message || this.event.context.error}</code >${this.event.context.message || this.event.context.error}</code
@ -337,15 +336,15 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
case EventActions.PolicyExecution: case EventActions.PolicyExecution:
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Binding`}</div> <div class="pf-c-card__title">${msg("Binding")}</div>
${this.getModelInfo(this.event.context.binding as EventModel)} ${this.getModelInfo(this.event.context.binding as EventModel)}
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Request`}</div> <div class="pf-c-card__title">${msg("Request")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ul class="pf-c-list"> <ul class="pf-c-list">
<li> <li>
${t`Object`}: ${msg("Object")}:
${this.getModelInfo( ${this.getModelInfo(
(this.event.context.request as EventContext) (this.event.context.request as EventContext)
.obj as EventModel, .obj as EventModel,
@ -353,7 +352,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
</li> </li>
<li> <li>
<span <span
>${t`Context`}: >${msg("Context")}:
<code <code
>${JSON.stringify( >${JSON.stringify(
(this.event.context.request as EventContext) (this.event.context.request as EventContext)
@ -368,15 +367,15 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
</div> </div>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Result`}</div> <div class="pf-c-card__title">${msg("Result")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ul class="pf-c-list"> <ul class="pf-c-list">
<li> <li>
${t`Passing`}: ${msg("Passing")}:
${(this.event.context.result as EventContext).passing} ${(this.event.context.result as EventContext).passing}
</li> </li>
<li> <li>
${t`Messages`}: ${msg("Messages")}:
<ul class="pf-c-list"> <ul class="pf-c-list">
${( ${(
(this.event.context.result as EventContext) (this.event.context.result as EventContext)
@ -395,7 +394,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
return html`<div class="pf-c-card__title">${this.event.context.message}</div> return html`<div class="pf-c-card__title">${this.event.context.message}</div>
<ak-expand>${this.defaultResponse()}</ak-expand>`; <ak-expand>${this.defaultResponse()}</ak-expand>`;
case EventActions.UpdateAvailable: case EventActions.UpdateAvailable:
return html`<div class="pf-c-card__title">${t`New version available!`}</div> return html`<div class="pf-c-card__title">${msg("New version available!")}</div>
<a <a
target="_blank" target="_blank"
href="https://github.com/goauthentik/authentik/releases/tag/version%2F${this href="https://github.com/goauthentik/authentik/releases/tag/version%2F${this
@ -409,7 +408,7 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
if ("using_source" in this.event.context) { if ("using_source" in this.event.context) {
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Using source`}</div> <div class="pf-c-card__title">${msg("Using source")}</div>
${this.getModelInfo(this.event.context.using_source as EventModel)} ${this.getModelInfo(this.event.context.using_source as EventModel)}
</div> </div>
</div>`; </div>`;
@ -417,18 +416,18 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
return this.defaultResponse(); return this.defaultResponse();
case EventActions.LoginFailed: case EventActions.LoginFailed:
return html` <div class="pf-c-card__title"> return html` <div class="pf-c-card__title">
${t`Attempted to log in as ${this.event.context.username}`} ${msg(str`Attempted to log in as ${this.event.context.username}`)}
</div> </div>
<ak-expand>${this.defaultResponse()}</ak-expand>`; <ak-expand>${this.defaultResponse()}</ak-expand>`;
case EventActions.Logout: case EventActions.Logout:
if (Object.keys(this.event.context).length === 0) { if (Object.keys(this.event.context).length === 0) {
return html`<span>${t`No additional data available.`}</span>`; return html`<span>${msg("No additional data available.")}</span>`;
} }
return this.defaultResponse(); return this.defaultResponse();
case EventActions.SystemTaskException: case EventActions.SystemTaskException:
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<div class="pf-c-card__title">${t`Exception`}</div> <div class="pf-c-card__title">${msg("Exception")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<pre>${this.event.context.message}</pre> <pre>${this.event.context.message}</pre>
</div> </div>

View File

@ -7,8 +7,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -19,7 +18,7 @@ export class EventListPage extends TablePage<Event> {
expandable = true; expandable = true;
pageTitle(): string { pageTitle(): string {
return t`Event Log`; return msg("Event Log");
} }
pageDescription(): string | undefined { pageDescription(): string | undefined {
return; return;
@ -45,12 +44,12 @@ export class EventListPage extends TablePage<Event> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Action`, "action"), new TableColumn(msg("Action"), "action"),
new TableColumn(t`User`, "user"), new TableColumn(msg("User"), "user"),
new TableColumn(t`Creation Date`, "created"), new TableColumn(msg("Creation Date"), "created"),
new TableColumn(t`Client IP`, "client_ip"), new TableColumn(msg("Client IP"), "client_ip"),
new TableColumn(t`Tenant`, "tenant_name"), new TableColumn(msg("Tenant"), "tenant_name"),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
@ -65,16 +64,16 @@ export class EventListPage extends TablePage<Event> {
${item.user.on_behalf_of ${item.user.on_behalf_of
? html`<small> ? html`<small>
<a href="#/identity/users/${item.user.on_behalf_of.pk}" <a href="#/identity/users/${item.user.on_behalf_of.pk}"
>${t`On behalf of ${item.user.on_behalf_of.username}`}</a >${msg(str`On behalf of ${item.user.on_behalf_of.username}`)}</a
> >
</small>` </small>`
: html``}` : html``}`
: html`-`, : html`-`,
html`<span>${item.created?.toLocaleString()}</span>`, html`<span>${item.created?.toLocaleString()}</span>`,
html`<div>${item.clientIp || t`-`}</div> html`<div>${item.clientIp || msg("-")}</div>
<small>${EventGeo(item)}</small>`, <small>${EventGeo(item)}</small>`,
html`<span>${item.tenant?.name || t`-`}</span>`, html`<span>${item.tenant?.name || msg("-")}</span>`,
html`<a href="#/events/log/${item.pk}"> html`<a href="#/events/log/${item.pk}">
<i class="fas fa-share-square"></i> <i class="fas fa-share-square"></i>
</a>`, </a>`,

View File

@ -5,8 +5,7 @@ import { EventWithContext } from "@goauthentik/common/events";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/PageHeader"; import "@goauthentik/elements/PageHeader";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -41,24 +40,24 @@ export class EventViewPage extends AKElement {
render(): TemplateResult { render(): TemplateResult {
if (!this.event) { if (!this.event) {
return html`<ak-page-header icon="pf-icon pf-icon-catalog" header=${t`Loading`}> return html`<ak-page-header icon="pf-icon pf-icon-catalog" header=${msg("Loading")}>
</ak-page-header> `; </ak-page-header> `;
} }
return html`<ak-page-header return html`<ak-page-header
icon="pf-icon pf-icon-catalog" icon="pf-icon pf-icon-catalog"
header=${t`Event ${this.event.pk}`} header=${msg(str`Event ${this.event.pk}`)}
> >
</ak-page-header> </ak-page-header>
<section class="pf-c-page__main-section pf-m-no-padding-mobile"> <section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">
<div class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-4-col-on-xl"> <div class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-4-col-on-xl">
<div class="pf-c-card__title">${t`Event info`}</div> <div class="pf-c-card__title">${msg("Event info")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Action`}</span >${msg("Action")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -69,7 +68,9 @@ export class EventViewPage extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`App`}</span> <span class="pf-c-description-list__text"
>${msg("App")}</span
>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -79,7 +80,9 @@ export class EventViewPage extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`User`}</span> <span class="pf-c-description-list__text"
>${msg("User")}</span
>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -97,7 +100,9 @@ export class EventViewPage extends AKElement {
href="#/identity/users/${this href="#/identity/users/${this
.event.user.on_behalf_of .event.user.on_behalf_of
.pk}" .pk}"
>${t`On behalf of ${this.event.user.on_behalf_of.username}`}</a >${msg(
str`On behalf of ${this.event.user.on_behalf_of.username}`,
)}</a
> >
</small>` </small>`
: html``}` : html``}`
@ -108,7 +113,7 @@ export class EventViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Created`}</span >${msg("Created")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -120,12 +125,12 @@ export class EventViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Client IP`}</span >${msg("Client IP")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
<div>${this.event.clientIp || t`-`}</div> <div>${this.event.clientIp || msg("-")}</div>
<small>${EventGeo(this.event)}</small> <small>${EventGeo(this.event)}</small>
</div> </div>
</dd> </dd>
@ -133,12 +138,12 @@ export class EventViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Tenant`}</span >${msg("Tenant")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
${this.event.tenant?.name || t`-`} ${this.event.tenant?.name || msg("-")}
</div> </div>
</dd> </dd>
</div> </div>

View File

@ -5,8 +5,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -39,9 +38,9 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated rule.`; return msg("Successfully updated rule.");
} else { } else {
return t`Successfully created rule.`; return msg("Successfully created rule.");
} }
} }
@ -60,7 +59,7 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -68,7 +67,7 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Group`} name="group"> <ak-form-element-horizontal label=${msg("Group")} name="group">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Group[]> => { .fetchObjects=${async (query?: string): Promise<Group[]> => {
const args: CoreGroupsListRequest = { const args: CoreGroupsListRequest = {
@ -93,10 +92,16 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Select the group of users which the alerts are sent to. If no group is selected the rule is disabled.`} ${msg(
"Select the group of users which the alerts are sent to. If no group is selected the rule is disabled.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Transports`} ?required=${true} name="transports"> <ak-form-element-horizontal
label=${msg("Transports")}
?required=${true}
name="transports"
>
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
${this.eventTransports?.results.map((transport) => { ${this.eventTransports?.results.map((transport) => {
const selected = Array.from(this.instance?.transports || []).some((su) => { const selected = Array.from(this.instance?.transports || []).some((su) => {
@ -108,13 +113,15 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.`} ${msg(
"Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`} ${msg("Hold control/command to select multiple items.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Severity`} ?required=${true} name="severity"> <ak-form-element-horizontal label=${msg("Severity")} ?required=${true} name="severity">
<ak-radio <ak-radio
.options=${[ .options=${[
{ {

View File

@ -10,8 +10,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -26,10 +25,12 @@ export class RuleListPage extends TablePage<NotificationRule> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Notification Rules`; return msg("Notification Rules");
} }
pageDescription(): string { pageDescription(): string {
return t`Send notifications whenever a specific Event is created and matched by policies.`; return msg(
"Send notifications whenever a specific Event is created and matched by policies.",
);
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-attention-bell"; return "pf-icon pf-icon-attention-bell";
@ -49,17 +50,17 @@ export class RuleListPage extends TablePage<NotificationRule> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Severity`, "severity"), new TableColumn(msg("Severity"), "severity"),
new TableColumn(t`Sent to group`, "group"), new TableColumn(msg("Sent to group"), "group"),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Notification rule(s)`} objectLabel=${msg("Notification rule(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: NotificationRule) => { .usedBy=${(item: NotificationRule) => {
return new EventsApi(DEFAULT_CONFIG).eventsRulesUsedByList({ return new EventsApi(DEFAULT_CONFIG).eventsRulesUsedByList({
@ -73,7 +74,7 @@ export class RuleListPage extends TablePage<NotificationRule> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -84,10 +85,10 @@ export class RuleListPage extends TablePage<NotificationRule> {
html`${SeverityToLabel(item.severity)}`, html`${SeverityToLabel(item.severity)}`,
html`${item.groupObj html`${item.groupObj
? html`<a href="#/identity/groups/${item.groupObj.pk}">${item.groupObj.name}</a>` ? html`<a href="#/identity/groups/${item.groupObj.pk}">${item.groupObj.name}</a>`
: t`None (rule disabled)`}`, : msg("None (rule disabled)")}`,
html`<ak-forms-modal> html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Notification Rule`} </span> <span slot="header"> ${msg("Update Notification Rule")} </span>
<ak-event-rule-form slot="form" .instancePk=${item.pk}> </ak-event-rule-form> <ak-event-rule-form slot="form" .instancePk=${item.pk}> </ak-event-rule-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i> <i class="fas fa-edit"></i>
@ -99,10 +100,10 @@ export class RuleListPage extends TablePage<NotificationRule> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Notification Rule`} </span> <span slot="header"> ${msg("Create Notification Rule")} </span>
<ak-event-rule-form slot="form"> </ak-event-rule-form> <ak-event-rule-form slot="form"> </ak-event-rule-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }
@ -111,8 +112,10 @@ export class RuleListPage extends TablePage<NotificationRule> {
return html` <td role="cell" colspan="4"> return html` <td role="cell" colspan="4">
<div class="pf-c-table__expandable-row-content"> <div class="pf-c-table__expandable-row-content">
<p> <p>
${t`These bindings control upon which events this rule triggers. Bindings to ${msg(
groups/users are checked against the user of the event.`} `These bindings control upon which events this rule triggers.
Bindings to groups/users are checked against the user of the event.`,
)}
</p> </p>
<ak-bound-policies-list .target=${item.pk}> </ak-bound-policies-list> <ak-bound-policies-list .target=${item.pk}> </ak-bound-policies-list>
</div> </div>

View File

@ -5,8 +5,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -38,9 +37,9 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated transport.`; return msg("Successfully updated transport.");
} else { } else {
return t`Successfully created transport.`; return msg("Successfully created transport.");
} }
} }
@ -70,7 +69,7 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -78,27 +77,27 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Mode`} ?required=${true} name="mode"> <ak-form-element-horizontal label=${msg("Mode")} ?required=${true} name="mode">
<ak-radio <ak-radio
@change=${(ev: CustomEvent<NotificationTransportModeEnum>) => { @change=${(ev: CustomEvent<NotificationTransportModeEnum>) => {
this.onModeChange(ev.detail); this.onModeChange(ev.detail);
}} }}
.options=${[ .options=${[
{ {
label: t`Local (notifications will be created within authentik)`, label: msg("Local (notifications will be created within authentik)"),
value: NotificationTransportModeEnum.Local, value: NotificationTransportModeEnum.Local,
default: true, default: true,
}, },
{ {
label: t`Email`, label: msg("Email"),
value: NotificationTransportModeEnum.Email, value: NotificationTransportModeEnum.Email,
}, },
{ {
label: t`Webhook (generic)`, label: msg("Webhook (generic)"),
value: NotificationTransportModeEnum.Webhook, value: NotificationTransportModeEnum.Webhook,
}, },
{ {
label: t`Webhook (Slack/Discord)`, label: msg("Webhook (Slack/Discord)"),
value: NotificationTransportModeEnum.WebhookSlack, value: NotificationTransportModeEnum.WebhookSlack,
}, },
]} ]}
@ -108,7 +107,7 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
?hidden=${!this.showWebhook} ?hidden=${!this.showWebhook}
label=${t`Webhook URL`} label=${msg("Webhook URL")}
name="webhookUrl" name="webhookUrl"
?required=${true} ?required=${true}
> >
@ -120,7 +119,7 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
?hidden=${!this.showWebhook} ?hidden=${!this.showWebhook}
label=${t`Webhook Mapping`} label=${msg("Webhook Mapping")}
name="webhookMapping" name="webhookMapping"
> >
<ak-search-select <ak-search-select
@ -163,10 +162,12 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Send once`}</span> <span class="pf-c-switch__label">${msg("Send once")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Only send notification once, for example when sending a webhook into a chat channel.`} ${msg(
"Only send notification once, for example when sending a webhook into a chat channel.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -9,8 +9,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -22,10 +21,10 @@ export class TransportListPage extends TablePage<NotificationTransport> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Notification Transports`; return msg("Notification Transports");
} }
pageDescription(): string { pageDescription(): string {
return t`Define how notifications are sent to users, like Email or Webhook.`; return msg("Define how notifications are sent to users, like Email or Webhook.");
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-export"; return "pf-icon pf-icon-export";
@ -47,16 +46,16 @@ export class TransportListPage extends TablePage<NotificationTransport> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Mode`, "mode"), new TableColumn(msg("Mode"), "mode"),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Notification transport(s)`} objectLabel=${msg("Notification transport(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: NotificationTransport) => { .usedBy=${(item: NotificationTransport) => {
return new EventsApi(DEFAULT_CONFIG).eventsTransportsUsedByList({ return new EventsApi(DEFAULT_CONFIG).eventsTransportsUsedByList({
@ -70,7 +69,7 @@ export class TransportListPage extends TablePage<NotificationTransport> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -80,8 +79,8 @@ export class TransportListPage extends TablePage<NotificationTransport> {
html`${item.name}`, html`${item.name}`,
html`${item.modeVerbose}`, html`${item.modeVerbose}`,
html`<ak-forms-modal> html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Notification Transport`} </span> <span slot="header"> ${msg("Update Notification Transport")} </span>
<ak-event-transport-form slot="form" .instancePk=${item.pk}> <ak-event-transport-form slot="form" .instancePk=${item.pk}>
</ak-event-transport-form> </ak-event-transport-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
@ -104,10 +103,10 @@ export class TransportListPage extends TablePage<NotificationTransport> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Notification Transport`} </span> <span slot="header"> ${msg("Create Notification Transport")} </span>
<ak-event-transport-form slot="form"> </ak-event-transport-form> <ak-event-transport-form slot="form"> </ak-event-transport-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }

View File

@ -1,8 +1,7 @@
import { EventWithContext } from "@goauthentik/common/events"; import { EventWithContext } from "@goauthentik/common/events";
import { KeyUnknown } from "@goauthentik/elements/forms/Form"; import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { EventActions, SeverityEnum } from "@goauthentik/api"; import { EventActions, SeverityEnum } from "@goauthentik/api";
@ -23,71 +22,71 @@ export function ActionToLabel(action?: EventActions): string {
if (!action) return ""; if (!action) return "";
switch (action) { switch (action) {
case EventActions.Login: case EventActions.Login:
return t`Login`; return msg("Login");
case EventActions.LoginFailed: case EventActions.LoginFailed:
return t`Failed login`; return msg("Failed login");
case EventActions.Logout: case EventActions.Logout:
return t`Logout`; return msg("Logout");
case EventActions.UserWrite: case EventActions.UserWrite:
return t`User was written to`; return msg("User was written to");
case EventActions.SuspiciousRequest: case EventActions.SuspiciousRequest:
return t`Suspicious request`; return msg("Suspicious request");
case EventActions.PasswordSet: case EventActions.PasswordSet:
return t`Password set`; return msg("Password set");
case EventActions.SecretView: case EventActions.SecretView:
return t`Secret was viewed`; return msg("Secret was viewed");
case EventActions.SecretRotate: case EventActions.SecretRotate:
return t`Secret was rotated`; return msg("Secret was rotated");
case EventActions.InvitationUsed: case EventActions.InvitationUsed:
return t`Invitation used`; return msg("Invitation used");
case EventActions.AuthorizeApplication: case EventActions.AuthorizeApplication:
return t`Application authorized`; return msg("Application authorized");
case EventActions.SourceLinked: case EventActions.SourceLinked:
return t`Source linked`; return msg("Source linked");
case EventActions.ImpersonationStarted: case EventActions.ImpersonationStarted:
return t`Impersonation started`; return msg("Impersonation started");
case EventActions.ImpersonationEnded: case EventActions.ImpersonationEnded:
return t`Impersonation ended`; return msg("Impersonation ended");
case EventActions.FlowExecution: case EventActions.FlowExecution:
return t`Flow execution`; return msg("Flow execution");
case EventActions.PolicyExecution: case EventActions.PolicyExecution:
return t`Policy execution`; return msg("Policy execution");
case EventActions.PolicyException: case EventActions.PolicyException:
return t`Policy exception`; return msg("Policy exception");
case EventActions.PropertyMappingException: case EventActions.PropertyMappingException:
return t`Property Mapping exception`; return msg("Property Mapping exception");
case EventActions.SystemTaskExecution: case EventActions.SystemTaskExecution:
return t`System task execution`; return msg("System task execution");
case EventActions.SystemTaskException: case EventActions.SystemTaskException:
return t`System task exception`; return msg("System task exception");
case EventActions.SystemException: case EventActions.SystemException:
return t`General system exception`; return msg("General system exception");
case EventActions.ConfigurationError: case EventActions.ConfigurationError:
return t`Configuration error`; return msg("Configuration error");
case EventActions.ModelCreated: case EventActions.ModelCreated:
return t`Model created`; return msg("Model created");
case EventActions.ModelUpdated: case EventActions.ModelUpdated:
return t`Model updated`; return msg("Model updated");
case EventActions.ModelDeleted: case EventActions.ModelDeleted:
return t`Model deleted`; return msg("Model deleted");
case EventActions.EmailSent: case EventActions.EmailSent:
return t`Email sent`; return msg("Email sent");
case EventActions.UpdateAvailable: case EventActions.UpdateAvailable:
return t`Update available`; return msg("Update available");
default: default:
return action; return action;
} }
} }
export function SeverityToLabel(severity: SeverityEnum | null | undefined): string { export function SeverityToLabel(severity: SeverityEnum | null | undefined): string {
if (!severity) return t`Unknown severity`; if (!severity) return msg("Unknown severity");
switch (severity) { switch (severity) {
case SeverityEnum.Alert: case SeverityEnum.Alert:
return t`Alert`; return msg("Alert");
case SeverityEnum.Notice: case SeverityEnum.Notice:
return t`Notice`; return msg("Notice");
case SeverityEnum.Warning: case SeverityEnum.Warning:
return t`Warning`; return msg("Warning");
} }
return t`Unknown severity`; return msg("Unknown severity");
} }

View File

@ -10,8 +10,7 @@ import "@goauthentik/elements/forms/ProxyForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -37,22 +36,22 @@ export class BoundStagesList extends Table<FlowStageBinding> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Order`), new TableColumn(msg("Order")),
new TableColumn(t`Name`), new TableColumn(msg("Name")),
new TableColumn(t`Type`), new TableColumn(msg("Type")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Stage binding(s)`} objectLabel=${msg("Stage binding(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.metadata=${(item: FlowStageBinding) => { .metadata=${(item: FlowStageBinding) => {
return [ return [
{ key: t`Stage`, value: item.stageObj?.name || "" }, { key: msg("Stage"), value: item.stageObj?.name || "" },
{ key: t`Stage type`, value: item.stageObj?.verboseName || "" }, { key: msg("Stage type"), value: item.stageObj?.verboseName || "" },
]; ];
}} }}
.usedBy=${(item: FlowStageBinding) => { .usedBy=${(item: FlowStageBinding) => {
@ -67,7 +66,7 @@ export class BoundStagesList extends Table<FlowStageBinding> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -78,8 +77,8 @@ export class BoundStagesList extends Table<FlowStageBinding> {
html`${item.stageObj?.name}`, html`${item.stageObj?.name}`,
html`${item.stageObj?.verboseName}`, html`${item.stageObj?.verboseName}`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update ${item.stageObj?.verboseName}`} </span> <span slot="header"> ${msg(str`Update ${item.stageObj?.verboseName}`)} </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
@ -89,16 +88,16 @@ export class BoundStagesList extends Table<FlowStageBinding> {
> >
</ak-proxy-form> </ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit Stage`} ${msg("Edit Stage")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Stage binding`} </span> <span slot="header"> ${msg("Update Stage binding")} </span>
<ak-stage-binding-form slot="form" .instancePk=${item.pk}> <ak-stage-binding-form slot="form" .instancePk=${item.pk}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit Binding`} ${msg("Edit Binding")}
</button> </button>
</ak-forms-modal>`, </ak-forms-modal>`,
]; ];
@ -110,7 +109,9 @@ export class BoundStagesList extends Table<FlowStageBinding> {
<div class="pf-c-table__expandable-row-content"> <div class="pf-c-table__expandable-row-content">
<div class="pf-c-content"> <div class="pf-c-content">
<p> <p>
${t`These bindings control if this stage will be applied to the flow.`} ${msg(
"These bindings control if this stage will be applied to the flow.",
)}
</p> </p>
<ak-bound-policies-list .target=${item.policybindingmodelPtrId}> <ak-bound-policies-list .target=${item.policybindingmodelPtrId}>
</ak-bound-policies-list> </ak-bound-policies-list>
@ -121,18 +122,18 @@ export class BoundStagesList extends Table<FlowStageBinding> {
renderEmpty(): TemplateResult { renderEmpty(): TemplateResult {
return super.renderEmpty(html`<ak-empty-state return super.renderEmpty(html`<ak-empty-state
header=${t`No Stages bound`} header=${msg("No Stages bound")}
icon="pf-icon-module" icon="pf-icon-module"
> >
<div slot="body">${t`No stages are currently bound to this flow.`}</div> <div slot="body">${msg("No stages are currently bound to this flow.")}</div>
<div slot="primary"> <div slot="primary">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Stage binding`} </span> <span slot="header"> ${msg("Create Stage binding")} </span>
<ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}> <ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Bind stage`} ${msg("Bind stage")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -142,17 +143,17 @@ export class BoundStagesList extends Table<FlowStageBinding> {
renderToolbar(): TemplateResult { renderToolbar(): TemplateResult {
return html` return html`
<ak-stage-wizard <ak-stage-wizard
createText=${t`Create & bind Stage`} createText=${msg("Create & bind Stage")}
?showBindingPage=${true} ?showBindingPage=${true}
bindingTarget=${ifDefined(this.target)} bindingTarget=${ifDefined(this.target)}
></ak-stage-wizard> ></ak-stage-wizard>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Stage binding`} </span> <span slot="header"> ${msg("Create Stage binding")} </span>
<ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}> <ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Bind existing stage`} ${msg("Bind existing stage")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -8,8 +8,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -36,9 +35,9 @@ export class FlowForm extends ModelForm<Flow, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated flow.`; return msg("Successfully updated flow.");
} else { } else {
return t`Successfully created flow.`; return msg("Successfully created flow.");
} }
} }
@ -80,7 +79,7 @@ export class FlowForm extends ModelForm<Flow, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -88,26 +87,26 @@ export class FlowForm extends ModelForm<Flow, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Title`} ?required=${true} name="title"> <ak-form-element-horizontal label=${msg("Title")} ?required=${true} name="title">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.title)}" value="${ifDefined(this.instance?.title)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
<p class="pf-c-form__helper-text">${t`Shown as the Title in Flow pages.`}</p> <p class="pf-c-form__helper-text">${msg("Shown as the Title in Flow pages.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Slug`} ?required=${true} name="slug"> <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.slug)}" value="${ifDefined(this.instance?.slug)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
<p class="pf-c-form__helper-text">${t`Visible in the URL.`}</p> <p class="pf-c-form__helper-text">${msg("Visible in the URL.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Designation`} label=${msg("Designation")}
?required=${true} ?required=${true}
name="designation" name="designation"
> >
@ -162,11 +161,13 @@ export class FlowForm extends ModelForm<Flow, string> {
</option> </option>
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.`} ${msg(
"Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authentication`} label=${msg("Authentication")}
?required=${true} ?required=${true}
name="authentication" name="authentication"
> >
@ -175,36 +176,36 @@ export class FlowForm extends ModelForm<Flow, string> {
value=${AuthenticationEnum.None} value=${AuthenticationEnum.None}
?selected=${this.instance?.authentication === AuthenticationEnum.None} ?selected=${this.instance?.authentication === AuthenticationEnum.None}
> >
${t`No requirement`} ${msg("No requirement")}
</option> </option>
<option <option
value=${AuthenticationEnum.RequireAuthenticated} value=${AuthenticationEnum.RequireAuthenticated}
?selected=${this.instance?.authentication === ?selected=${this.instance?.authentication ===
AuthenticationEnum.RequireAuthenticated} AuthenticationEnum.RequireAuthenticated}
> >
${t`Require authentication`} ${msg("Require authentication")}
</option> </option>
<option <option
value=${AuthenticationEnum.RequireUnauthenticated} value=${AuthenticationEnum.RequireUnauthenticated}
?selected=${this.instance?.authentication === ?selected=${this.instance?.authentication ===
AuthenticationEnum.RequireUnauthenticated} AuthenticationEnum.RequireUnauthenticated}
> >
${t`Require no authentication.`} ${msg("Require no authentication.")}
</option> </option>
<option <option
value=${AuthenticationEnum.RequireSuperuser} value=${AuthenticationEnum.RequireSuperuser}
?selected=${this.instance?.authentication === ?selected=${this.instance?.authentication ===
AuthenticationEnum.RequireSuperuser} AuthenticationEnum.RequireSuperuser}
> >
${t`Require superuser.`} ${msg("Require superuser.")}
</option> </option>
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Required authentication level for this flow.`} ${msg("Required authentication level for this flow.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group> <ak-form-group>
<span slot="header"> ${t`Behavior settings`} </span> <span slot="header"> ${msg("Behavior settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="compatibilityMode"> <ak-form-element-horizontal name="compatibilityMode">
<label class="pf-c-switch"> <label class="pf-c-switch">
@ -218,14 +219,16 @@ export class FlowForm extends ModelForm<Flow, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Compatibility mode`}</span> <span class="pf-c-switch__label">${msg("Compatibility mode")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Increases compatibility with password managers and mobile devices.`} ${msg(
"Increases compatibility with password managers and mobile devices.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Denied action`} label=${msg("Denied action")}
?required=${true} ?required=${true}
name="deniedAction" name="deniedAction"
> >
@ -235,28 +238,36 @@ export class FlowForm extends ModelForm<Flow, string> {
label: "MESSAGE_CONTINUE", label: "MESSAGE_CONTINUE",
value: DeniedActionEnum.MessageContinue, value: DeniedActionEnum.MessageContinue,
default: true, default: true,
description: html`${t`Will follow the ?next parameter if set, otherwise show a message`}`, description: html`${msg(
"Will follow the ?next parameter if set, otherwise show a message",
)}`,
}, },
{ {
label: "CONTINUE", label: "CONTINUE",
value: DeniedActionEnum.Continue, value: DeniedActionEnum.Continue,
description: html`${t`Will either follow the ?next parameter or redirect to the default interface`}`, description: html`${msg(
"Will either follow the ?next parameter or redirect to the default interface",
)}`,
}, },
{ {
label: "MESSAGE", label: "MESSAGE",
value: DeniedActionEnum.Message, value: DeniedActionEnum.Message,
description: html`${t`Will notify the user the flow isn't applicable`}`, description: html`${msg(
"Will notify the user the flow isn't applicable",
)}`,
}, },
]} ]}
.value=${this.instance?.deniedAction} .value=${this.instance?.deniedAction}
> >
</ak-radio> </ak-radio>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Decides the response when a policy denies access to this flow for a user.`} ${msg(
"Decides the response when a policy denies access to this flow for a user.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Policy engine mode`} label=${msg("Policy engine mode")}
?required=${true} ?required=${true}
name="policyEngineMode" name="policyEngineMode"
> >
@ -266,12 +277,16 @@ export class FlowForm extends ModelForm<Flow, string> {
label: "any", label: "any",
value: PolicyEngineMode.Any, value: PolicyEngineMode.Any,
default: true, default: true,
description: html`${t`Any policy must match to grant access`}`, description: html`${msg(
"Any policy must match to grant access",
)}`,
}, },
{ {
label: "all", label: "all",
value: PolicyEngineMode.All, value: PolicyEngineMode.All,
description: html`${t`All policies must match to grant access`}`, description: html`${msg(
"All policies must match to grant access",
)}`,
}, },
]} ]}
.value=${this.instance?.policyEngineMode} .value=${this.instance?.policyEngineMode}
@ -281,9 +296,13 @@ export class FlowForm extends ModelForm<Flow, string> {
</div> </div>
</ak-form-group> </ak-form-group>
<ak-form-group> <ak-form-group>
<span slot="header"> ${t`Appearance settings`} </span> <span slot="header"> ${msg("Appearance settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Layout`} ?required=${true} name="layout"> <ak-form-element-horizontal
label=${msg("Layout")}
?required=${true}
name="layout"
>
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option <option
value=${LayoutEnum.Stacked} value=${LayoutEnum.Stacked}
@ -318,18 +337,22 @@ export class FlowForm extends ModelForm<Flow, string> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanSaveMedia) ${rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanSaveMedia)
? html`<ak-form-element-horizontal label=${t`Background`} name="background"> ? html`<ak-form-element-horizontal
label=${msg("Background")}
name="background"
>
<input type="file" value="" class="pf-c-form-control" /> <input type="file" value="" class="pf-c-form-control" />
${this.instance?.background ${this.instance?.background
? html` ? html`
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Currently set to:`} ${this.instance?.background} ${msg("Currently set to:")}
${this.instance?.background}
</p> </p>
` `
: html``} : html``}
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Background shown during execution.`} ${msg("Background shown during execution.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.instance?.background ${this.instance?.background
@ -354,23 +377,26 @@ export class FlowForm extends ModelForm<Flow, string> {
</span> </span>
</span> </span>
<span class="pf-c-switch__label"> <span class="pf-c-switch__label">
${t`Clear background`} ${msg("Clear background")}
</span> </span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Delete currently set background image.`} ${msg("Delete currently set background image.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
` `
: html``}` : html``}`
: html`<ak-form-element-horizontal label=${t`Background`} name="background"> : html`<ak-form-element-horizontal
label=${msg("Background")}
name="background"
>
<input <input
type="text" type="text"
value="${first(this.instance?.background, "")}" value="${first(this.instance?.background, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Background shown during execution.`} ${msg("Background shown during execution.")}
</p> </p>
</ak-form-element-horizontal>`} </ak-form-element-horizontal>`}
</div> </div>

View File

@ -4,8 +4,7 @@ import { PFColor } from "@goauthentik/elements/Label";
import { Form } from "@goauthentik/elements/forms/Form"; import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
@ -19,7 +18,7 @@ export class FlowImportForm extends Form<Flow> {
result?: FlowImportResult; result?: FlowImportResult;
getSuccessMessage(): string { getSuccessMessage(): string {
return t`Successfully imported flow.`; return msg("Successfully imported flow.");
} }
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
@ -43,18 +42,18 @@ export class FlowImportForm extends Form<Flow> {
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html` return html`
<ak-form-element-horizontal label=${t`Successful`}> <ak-form-element-horizontal label=${msg("Successful")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<span class="pf-c-form__label-text"> <span class="pf-c-form__label-text">
<ak-label color=${this.result?.success ? PFColor.Green : PFColor.Red}> <ak-label color=${this.result?.success ? PFColor.Green : PFColor.Red}>
${this.result?.success ? t`Yes` : t`No`} ${this.result?.success ? msg("Yes") : msg("No")}
</ak-label> </ak-label>
</span> </span>
</div> </div>
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Log messages`}> <ak-form-element-horizontal label=${msg("Log messages")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
@ -76,7 +75,7 @@ export class FlowImportForm extends Form<Flow> {
: html`<div class="pf-c-description-list__group"> : html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`No log messages.`}</span >${msg("No log messages.")}</span
> >
</dt> </dt>
</div>`} </div>`}
@ -89,10 +88,12 @@ export class FlowImportForm extends Form<Flow> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Flow`} name="flow"> <ak-form-element-horizontal label=${msg("Flow")} name="flow">
<input type="file" value="" class="pf-c-form-control" /> <input type="file" value="" class="pf-c-form-control" />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`.yaml files, which can be found on goauthentik.io and can be exported by authentik.`} ${msg(
".yaml files, which can be found on goauthentik.io and can be exported by authentik.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.result ? this.renderResult() : html``} ${this.result ? this.renderResult() : html``}

View File

@ -12,8 +12,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -25,10 +24,12 @@ export class FlowListPage extends TablePage<Flow> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Flows`; return msg("Flows");
} }
pageDescription(): string { pageDescription(): string {
return t`Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them.`; return msg(
"Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them.",
);
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-process-automation"; return "pf-icon pf-icon-process-automation";
@ -56,18 +57,18 @@ export class FlowListPage extends TablePage<Flow> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Identifier`, "slug"), new TableColumn(msg("Identifier"), "slug"),
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Stages`), new TableColumn(msg("Stages")),
new TableColumn(t`Policies`), new TableColumn(msg("Policies")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Flow(s)`} objectLabel=${msg("Flow(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Flow) => { .usedBy=${(item: Flow) => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesUsedByList({ return new FlowsApi(DEFAULT_CONFIG).flowsInstancesUsedByList({
@ -81,7 +82,7 @@ export class FlowListPage extends TablePage<Flow> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -98,8 +99,8 @@ export class FlowListPage extends TablePage<Flow> {
html`${Array.from(item.stages || []).length}`, html`${Array.from(item.stages || []).length}`,
html`${Array.from(item.policies || []).length}`, html`${Array.from(item.policies || []).length}`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Flow`} </span> <span slot="header"> ${msg("Update Flow")} </span>
<ak-flow-form slot="form" .instancePk=${item.slug}> </ak-flow-form> <ak-flow-form slot="form" .instancePk=${item.slug}> </ak-flow-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i> <i class="fas fa-edit"></i>
@ -125,16 +126,16 @@ export class FlowListPage extends TablePage<Flow> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Flow`} </span> <span slot="header"> ${msg("Create Flow")} </span>
<ak-flow-form slot="form"> </ak-flow-form> <ak-flow-form slot="form"> </ak-flow-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Import`} </span> <span slot="submit"> ${msg("Import")} </span>
<span slot="header"> ${t`Import Flow`} </span> <span slot="header"> ${msg("Import Flow")} </span>
<ak-flow-import-form slot="form"> </ak-flow-import-form> <ak-flow-import-form slot="form"> </ak-flow-import-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Import`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Import")}</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }
@ -143,20 +144,22 @@ export class FlowListPage extends TablePage<Flow> {
return html` return html`
${super.renderToolbar()} ${super.renderToolbar()}
<ak-forms-confirm <ak-forms-confirm
successMessage=${t`Successfully cleared flow cache`} successMessage=${msg("Successfully cleared flow cache")}
errorMessage=${t`Failed to delete flow cache`} errorMessage=${msg("Failed to delete flow cache")}
action=${t`Clear cache`} action=${msg("Clear cache")}
.onConfirm=${() => { .onConfirm=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheClearCreate(); return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheClearCreate();
}} }}
> >
<span slot="header"> ${t`Clear Flow cache`} </span> <span slot="header"> ${msg("Clear Flow cache")} </span>
<p slot="body"> <p slot="body">
${t`Are you sure you want to clear the flow cache? ${msg(
This will cause all flows to be re-evaluated on their next usage.`} `Are you sure you want to clear the flow cache?
This will cause all flows to be re-evaluated on their next usage.`,
)}
</p> </p>
<button slot="trigger" class="pf-c-button pf-m-secondary" type="button"> <button slot="trigger" class="pf-c-button pf-m-secondary" type="button">
${t`Clear cache`} ${msg("Clear cache")}
</button> </button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-forms-confirm> </ak-forms-confirm>

View File

@ -9,8 +9,7 @@ import "@goauthentik/elements/Tabs";
import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/ObjectChangelog"; import "@goauthentik/elements/events/ObjectChangelog";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -66,27 +65,29 @@ export class FlowViewPage extends AKElement {
<ak-tabs> <ak-tabs>
<div <div
slot="page-overview" slot="page-overview"
data-tab-title="${t`Flow Overview`}" data-tab-title="${msg("Flow Overview")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Related actions`}</div> <div class="pf-c-card__title">${msg("Related actions")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<dl class="pf-c-description-list"> <dl class="pf-c-description-list">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Edit`}</span >${msg("Edit")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Flow`} </span> <span slot="header">
${msg("Update Flow")}
</span>
<ak-flow-form <ak-flow-form
slot="form" slot="form"
.instancePk=${this.flow.slug} .instancePk=${this.flow.slug}
@ -96,14 +97,14 @@ export class FlowViewPage extends AKElement {
slot="trigger" slot="trigger"
class="pf-c-button pf-m-block pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
> >
${t`Edit`} ${msg("Edit")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
</dd> </dd>
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Execute flow`}</span >${msg("Execute flow")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -119,7 +120,7 @@ export class FlowViewPage extends AKElement {
window.open(finalURL, "_blank"); window.open(finalURL, "_blank");
}} }}
> >
${t`Normal`} ${msg("Normal")}
</button> </button>
<button <button
class="pf-c-button pf-m-block pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
@ -138,7 +139,7 @@ export class FlowViewPage extends AKElement {
}); });
}} }}
> >
${t`with current user`} ${msg("with current user")}
</button> </button>
<button <button
class="pf-c-button pf-m-block pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
@ -165,13 +166,13 @@ export class FlowViewPage extends AKElement {
}); });
}} }}
> >
${t`with inspector`} ${msg("with inspector")}
</button> </button>
</div> </div>
</dd> </dd>
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Export flow`}</span >${msg("Export flow")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -180,7 +181,7 @@ export class FlowViewPage extends AKElement {
class="pf-c-button pf-m-block pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
href=${this.flow.exportUrl} href=${this.flow.exportUrl}
> >
${t`Export`} ${msg("Export")}
</a> </a>
</div> </div>
</dd> </dd>
@ -191,7 +192,7 @@ export class FlowViewPage extends AKElement {
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Diagram`}</div> <div class="pf-c-card__title">${msg("Diagram")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-flow-diagram flowSlug=${this.flow.slug}> </ak-flow-diagram> <ak-flow-diagram flowSlug=${this.flow.slug}> </ak-flow-diagram>
</div> </div>
@ -199,7 +200,7 @@ export class FlowViewPage extends AKElement {
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-12-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-12-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Changelog`}</div> <div class="pf-c-card__title">${msg("Changelog")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-object-changelog <ak-object-changelog
targetModelPk=${this.flow.pk || ""} targetModelPk=${this.flow.pk || ""}
@ -213,7 +214,7 @@ export class FlowViewPage extends AKElement {
</div> </div>
<div <div
slot="page-stage-bindings" slot="page-stage-bindings"
data-tab-title="${t`Stage Bindings`}" data-tab-title="${msg("Stage Bindings")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">
@ -224,12 +225,12 @@ export class FlowViewPage extends AKElement {
</div> </div>
<div <div
slot="page-policy-bindings" slot="page-policy-bindings"
data-tab-title="${t`Policy / Group / User Bindings`}" data-tab-title="${msg("Policy / Group / User Bindings")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__title"> <div class="pf-c-card__title">
${t`These bindings control which users can access this flow.`} ${msg("These bindings control which users can access this flow.")}
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-bound-policies-list .target=${this.flow.policybindingmodelPtrId}> <ak-bound-policies-list .target=${this.flow.policybindingmodelPtrId}>

View File

@ -6,8 +6,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
@ -42,9 +41,9 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance?.pk) { if (this.instance?.pk) {
return t`Successfully updated binding.`; return msg("Successfully updated binding.");
} else { } else {
return t`Successfully created binding.`; return msg("Successfully created binding.");
} }
} }
@ -82,7 +81,11 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
if (this.instance?.target || this.targetPk) { if (this.instance?.target || this.targetPk) {
return html``; return html``;
} }
return html`<ak-form-element-horizontal label=${t`Target`} ?required=${true} name="target"> return html`<ak-form-element-horizontal
label=${msg("Target")}
?required=${true}
name="target"
>
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Flow[]> => { .fetchObjects=${async (query?: string): Promise<Flow[]> => {
const args: FlowsInstancesListRequest = { const args: FlowsInstancesListRequest = {
@ -115,7 +118,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
${this.renderTarget()} ${this.renderTarget()}
<ak-form-element-horizontal label=${t`Stage`} ?required=${true} name="stage"> <ak-form-element-horizontal label=${msg("Stage")} ?required=${true} name="stage">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Stage[]> => { .fetchObjects=${async (query?: string): Promise<Stage[]> => {
const args: StagesAllListRequest = { const args: StagesAllListRequest = {
@ -142,7 +145,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
> >
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Order`} ?required=${true} name="order"> <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
<input <input
type="number" type="number"
value="${first(this.instance?.order, this.defaultOrder)}" value="${first(this.instance?.order, this.defaultOrder)}"
@ -162,10 +165,10 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Evaluate when flow is planned`}</span> <span class="pf-c-switch__label">${msg("Evaluate when flow is planned")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Evaluate policies during the Flow planning process.`} ${msg("Evaluate policies during the Flow planning process.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="reEvaluatePolicies"> <ak-form-element-horizontal name="reEvaluatePolicies">
@ -180,14 +183,14 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Evaluate when stage is run`}</span> <span class="pf-c-switch__label">${msg("Evaluate when stage is run")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Evaluate policies before the Stage is present to the user.`} ${msg("Evaluate policies before the Stage is present to the user.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Invalid response behavior`} label=${msg("Invalid response behavior")}
?required=${true} ?required=${true}
name="invalidResponseAction" name="invalidResponseAction"
> >
@ -197,28 +200,34 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
label: "RETRY", label: "RETRY",
value: InvalidResponseActionEnum.Retry, value: InvalidResponseActionEnum.Retry,
default: true, default: true,
description: html`${t`Returns the error message and a similar challenge to the executor`}`, description: html`${msg(
"Returns the error message and a similar challenge to the executor",
)}`,
}, },
{ {
label: "RESTART", label: "RESTART",
value: InvalidResponseActionEnum.Restart, value: InvalidResponseActionEnum.Restart,
description: html`${t`Restarts the flow from the beginning`}`, description: html`${msg("Restarts the flow from the beginning")}`,
}, },
{ {
label: "RESTART_WITH_CONTEXT", label: "RESTART_WITH_CONTEXT",
value: InvalidResponseActionEnum.RestartWithContext, value: InvalidResponseActionEnum.RestartWithContext,
description: html`${t`Restarts the flow from the beginning, while keeping the flow context`}`, description: html`${msg(
"Restarts the flow from the beginning, while keeping the flow context",
)}`,
}, },
]} ]}
.value=${this.instance?.invalidResponseAction} .value=${this.instance?.invalidResponseAction}
> >
</ak-radio> </ak-radio>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how the flow executor should handle an invalid response to a challenge given by this bound stage.`} ${msg(
"Configure how the flow executor should handle an invalid response to a challenge given by this bound stage.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Policy engine mode`} label=${msg("Policy engine mode")}
?required=${true} ?required=${true}
name="policyEngineMode" name="policyEngineMode"
> >
@ -228,12 +237,12 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
label: "any", label: "any",
value: PolicyEngineMode.Any, value: PolicyEngineMode.Any,
default: true, default: true,
description: html`${t`Any policy must match to grant access`}`, description: html`${msg("Any policy must match to grant access")}`,
}, },
{ {
label: "all", label: "all",
value: PolicyEngineMode.All, value: PolicyEngineMode.All,
description: html`${t`All policies must match to grant access`}`, description: html`${msg("All policies must match to grant access")}`,
}, },
]} ]}
.value=${this.instance?.policyEngineMode} .value=${this.instance?.policyEngineMode}

View File

@ -1,4 +1,4 @@
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { Flow, FlowDesignationEnum, LayoutEnum } from "@goauthentik/api"; import { Flow, FlowDesignationEnum, LayoutEnum } from "@goauthentik/api";
@ -9,37 +9,37 @@ export function RenderFlowOption(flow: Flow): string {
export function DesignationToLabel(designation: FlowDesignationEnum): string { export function DesignationToLabel(designation: FlowDesignationEnum): string {
switch (designation) { switch (designation) {
case FlowDesignationEnum.Authentication: case FlowDesignationEnum.Authentication:
return t`Authentication`; return msg("Authentication");
case FlowDesignationEnum.Authorization: case FlowDesignationEnum.Authorization:
return t`Authorization`; return msg("Authorization");
case FlowDesignationEnum.Enrollment: case FlowDesignationEnum.Enrollment:
return t`Enrollment`; return msg("Enrollment");
case FlowDesignationEnum.Invalidation: case FlowDesignationEnum.Invalidation:
return t`Invalidation`; return msg("Invalidation");
case FlowDesignationEnum.Recovery: case FlowDesignationEnum.Recovery:
return t`Recovery`; return msg("Recovery");
case FlowDesignationEnum.StageConfiguration: case FlowDesignationEnum.StageConfiguration:
return t`Stage Configuration`; return msg("Stage Configuration");
case FlowDesignationEnum.Unenrollment: case FlowDesignationEnum.Unenrollment:
return t`Unenrollment`; return msg("Unenrollment");
case FlowDesignationEnum.UnknownDefaultOpenApi: case FlowDesignationEnum.UnknownDefaultOpenApi:
return t`Unknown designation`; return msg("Unknown designation");
} }
} }
export function LayoutToLabel(layout: LayoutEnum): string { export function LayoutToLabel(layout: LayoutEnum): string {
switch (layout) { switch (layout) {
case LayoutEnum.Stacked: case LayoutEnum.Stacked:
return t`Stacked`; return msg("Stacked");
case LayoutEnum.ContentLeft: case LayoutEnum.ContentLeft:
return t`Content left`; return msg("Content left");
case LayoutEnum.ContentRight: case LayoutEnum.ContentRight:
return t`Content right`; return msg("Content right");
case LayoutEnum.SidebarLeft: case LayoutEnum.SidebarLeft:
return t`Sidebar left`; return msg("Sidebar left");
case LayoutEnum.SidebarRight: case LayoutEnum.SidebarRight:
return t`Sidebar right`; return msg("Sidebar right");
case LayoutEnum.UnknownDefaultOpenApi: case LayoutEnum.UnknownDefaultOpenApi:
return t`Unknown layout`; return msg("Unknown layout");
} }
} }

View File

@ -9,8 +9,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import YAML from "yaml"; import YAML from "yaml";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -38,9 +37,9 @@ export class GroupForm extends ModelForm<Group, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated group.`; return msg("Successfully updated group.");
} else { } else {
return t`Successfully created group.`; return msg("Successfully created group.");
} }
} }
@ -60,7 +59,7 @@ export class GroupForm extends ModelForm<Group, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -80,13 +79,13 @@ export class GroupForm extends ModelForm<Group, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Is superuser`}</span> <span class="pf-c-switch__label">${msg("Is superuser")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Users added to this group will be superusers.`} ${msg("Users added to this group will be superusers.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Parent`} name="parent"> <ak-form-element-horizontal label=${msg("Parent")} name="parent">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Group[]> => { .fetchObjects=${async (query?: string): Promise<Group[]> => {
const args: CoreGroupsListRequest = { const args: CoreGroupsListRequest = {
@ -111,14 +110,18 @@ export class GroupForm extends ModelForm<Group, string> {
> >
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Attributes`} ?required=${true} name="attributes"> <ak-form-element-horizontal
label=${msg("Attributes")}
?required=${true}
name="attributes"
>
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(first(this.instance?.attributes, {}))}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Set custom attributes using YAML or JSON.`} ${msg("Set custom attributes using YAML or JSON.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -9,8 +9,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -23,10 +22,10 @@ export class GroupListPage extends TablePage<Group> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Groups`; return msg("Groups");
} }
pageDescription(): string { pageDescription(): string {
return t`Group users together and give them permissions based on the membership.`; return msg("Group users together and give them permissions based on the membership.");
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-users"; return "pf-icon pf-icon-users";
@ -46,18 +45,18 @@ export class GroupListPage extends TablePage<Group> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Parent`, "parent"), new TableColumn(msg("Parent"), "parent"),
new TableColumn(t`Members`), new TableColumn(msg("Members")),
new TableColumn(t`Superuser privileges?`), new TableColumn(msg("Superuser privileges?")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Group(s)`} objectLabel=${msg("Group(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Group) => { .usedBy=${(item: Group) => {
return new CoreApi(DEFAULT_CONFIG).coreGroupsUsedByList({ return new CoreApi(DEFAULT_CONFIG).coreGroupsUsedByList({
@ -71,7 +70,7 @@ export class GroupListPage extends TablePage<Group> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -79,14 +78,14 @@ export class GroupListPage extends TablePage<Group> {
row(item: Group): TemplateResult[] { row(item: Group): TemplateResult[] {
return [ return [
html`<a href="#/identity/groups/${item.pk}">${item.name}</a>`, html`<a href="#/identity/groups/${item.pk}">${item.name}</a>`,
html`${item.parentName || t`-`}`, html`${item.parentName || msg("-")}`,
html`${Array.from(item.users || []).length}`, html`${Array.from(item.users || []).length}`,
html`<ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}> html`<ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}>
${item.isSuperuser ? t`Yes` : t`No`} ${item.isSuperuser ? msg("Yes") : msg("No")}
</ak-label>`, </ak-label>`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Group`} </span> <span slot="header"> ${msg("Update Group")} </span>
<ak-group-form slot="form" .instancePk=${item.pk}> </ak-group-form> <ak-group-form slot="form" .instancePk=${item.pk}> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i> <i class="fas fa-edit"></i>
@ -98,10 +97,10 @@ export class GroupListPage extends TablePage<Group> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Group`} </span> <span slot="header"> ${msg("Create Group")} </span>
<ak-group-form slot="form"> </ak-group-form> <ak-group-form slot="form"> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }

View File

@ -12,8 +12,7 @@ import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/ObjectChangelog"; import "@goauthentik/elements/events/ObjectChangelog";
import "@goauthentik/elements/forms/ModalForm"; import "@goauthentik/elements/forms/ModalForm";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -70,7 +69,7 @@ export class GroupViewPage extends AKElement {
render(): TemplateResult { render(): TemplateResult {
return html`<ak-page-header return html`<ak-page-header
icon="pf-icon pf-icon-users" icon="pf-icon pf-icon-users"
header=${t`Group ${this.group?.name || ""}`} header=${msg(str`Group ${this.group?.name || ""}`)}
description=${this.group?.name || ""} description=${this.group?.name || ""}
> >
</ak-page-header> </ak-page-header>
@ -84,19 +83,21 @@ export class GroupViewPage extends AKElement {
return html`<ak-tabs> return html`<ak-tabs>
<section <section
slot="page-overview" slot="page-overview"
data-tab-title="${t`Overview`}" data-tab-title="${msg("Overview")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-3-col-on-xl pf-m-3-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-3-col-on-xl pf-m-3-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Group Info`}</div> <div class="pf-c-card__title">${msg("Group Info")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-2-col"> <dl class="pf-c-description-list pf-m-2-col">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span> <span class="pf-c-description-list__text"
>${msg("Name")}</span
>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -107,7 +108,7 @@ export class GroupViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Superuser`}</span >${msg("Superuser")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -124,12 +125,12 @@ export class GroupViewPage extends AKElement {
</div> </div>
<div class="pf-c-card__footer"> <div class="pf-c-card__footer">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Group`} </span> <span slot="header"> ${msg("Update Group")} </span>
<ak-group-form slot="form" .instancePk=${this.group.pk}> <ak-group-form slot="form" .instancePk=${this.group.pk}>
</ak-group-form> </ak-group-form>
<button slot="trigger" class="pf-m-primary pf-c-button"> <button slot="trigger" class="pf-m-primary pf-c-button">
${t`Edit`} ${msg("Edit")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -137,13 +138,15 @@ export class GroupViewPage extends AKElement {
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-9-col-on-xl pf-m-9-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-9-col-on-xl pf-m-9-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Notes`}</div> <div class="pf-c-card__title">${msg("Notes")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${Object.hasOwn(this.group?.attributes || {}, "notes") ${Object.hasOwn(this.group?.attributes || {}, "notes")
? html`${this.group.attributes?.notes}` ? html`${this.group.attributes?.notes}`
: html` : html`
<p> <p>
${t`Edit the notes attribute of this group to add notes here.`} ${msg(
"Edit the notes attribute of this group to add notes here.",
)}
</p> </p>
`} `}
</div> </div>
@ -151,7 +154,7 @@ export class GroupViewPage extends AKElement {
<div <div
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-12-col-on-2xl" class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-12-col-on-2xl"
> >
<div class="pf-c-card__title">${t`Changelog`}</div> <div class="pf-c-card__title">${msg("Changelog")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-object-changelog <ak-object-changelog
targetModelPk=${this.group.pk} targetModelPk=${this.group.pk}
@ -165,7 +168,7 @@ export class GroupViewPage extends AKElement {
</section> </section>
<section <section
slot="page-users" slot="page-users"
data-tab-title="${t`Users`}" data-tab-title="${msg("Users")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">

View File

@ -7,8 +7,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TableModal } from "@goauthentik/elements/table/TableModal"; import { TableModal } from "@goauthentik/elements/table/TableModal";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -39,9 +38,9 @@ export class MemberSelectTable extends TableModal<User> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "username"), new TableColumn(msg("Name"), "username"),
new TableColumn(t`Active`, "active"), new TableColumn(msg("Active"), "active"),
new TableColumn(t`Last login`, "last_login"), new TableColumn(msg("Last login"), "last_login"),
]; ];
} }
@ -50,9 +49,9 @@ export class MemberSelectTable extends TableModal<User> {
html`<div>${item.username}</div> html`<div>${item.username}</div>
<small>${item.name}</small>`, <small>${item.name}</small>`,
html` <ak-label color=${item.isActive ? PFColor.Green : PFColor.Orange}> html` <ak-label color=${item.isActive ? PFColor.Green : PFColor.Orange}>
${item.isActive ? t`Yes` : t`No`} ${item.isActive ? msg("Yes") : msg("No")}
</ak-label>`, </ak-label>`,
html`${first(item.lastLogin?.toLocaleString(), t`-`)}`, html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`,
]; ];
} }
@ -63,7 +62,7 @@ export class MemberSelectTable extends TableModal<User> {
renderModalInner(): TemplateResult { renderModalInner(): TemplateResult {
return html`<section class="pf-c-modal-box__header pf-c-page__main-section pf-m-light"> return html`<section class="pf-c-modal-box__header pf-c-page__main-section pf-m-light">
<div class="pf-c-content"> <div class="pf-c-content">
<h1 class="pf-c-title pf-m-2xl">${t`Select users to add`}</h1> <h1 class="pf-c-title pf-m-2xl">${msg("Select users to add")}</h1>
</div> </div>
</section> </section>
<section class="pf-c-modal-box__body pf-m-light">${this.renderTable()}</section> <section class="pf-c-modal-box__body pf-m-light">${this.renderTable()}</section>
@ -76,7 +75,7 @@ export class MemberSelectTable extends TableModal<User> {
}} }}
class="pf-m-primary" class="pf-m-primary"
> >
${t`Add`} </ak-spinner-button ${msg("Add")} </ak-spinner-button
>&nbsp; >&nbsp;
<ak-spinner-button <ak-spinner-button
.callAction=${async () => { .callAction=${async () => {
@ -84,7 +83,7 @@ export class MemberSelectTable extends TableModal<User> {
}} }}
class="pf-m-secondary" class="pf-m-secondary"
> >
${t`Cancel`} ${msg("Cancel")}
</ak-spinner-button> </ak-spinner-button>
</footer>`; </footer>`;
} }

View File

@ -12,8 +12,7 @@ import "@goauthentik/elements/forms/ModalForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -29,7 +28,7 @@ export class RelatedGroupAdd extends Form<{ groups: string[] }> {
groupsToAdd: Group[] = []; groupsToAdd: Group[] = [];
getSuccessMessage(): string { getSuccessMessage(): string {
return t`Successfully added user to group(s).`; return msg("Successfully added user to group(s).");
} }
async send(data: { groups: string[] }): Promise<unknown> { async send(data: { groups: string[] }): Promise<unknown> {
@ -48,7 +47,7 @@ export class RelatedGroupAdd extends Form<{ groups: string[] }> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Groups to add`} name="groups"> <ak-form-element-horizontal label=${msg("Groups to add")} name="groups">
<div class="pf-c-input-group"> <div class="pf-c-input-group">
<ak-user-group-select-table <ak-user-group-select-table
.confirm=${(items: Group[]) => { .confirm=${(items: Group[]) => {
@ -109,19 +108,21 @@ export class RelatedGroupList extends Table<Group> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Parent`, "parent"), new TableColumn(msg("Parent"), "parent"),
new TableColumn(t`Superuser privileges?`), new TableColumn(msg("Superuser privileges?")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Group(s)`} objectLabel=${msg("Group(s)")}
actionLabel=${t`Remove from Group(s)`} actionLabel=${msg("Remove from Group(s)")}
actionSubtext=${t`Are you sure you want to remove user ${this.targetUser?.username} from the following groups?`} actionSubtext=${msg(
str`Are you sure you want to remove user ${this.targetUser?.username} from the following groups?`,
)}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.delete=${(item: Group) => { .delete=${(item: Group) => {
if (!this.targetUser) return; if (!this.targetUser) return;
@ -134,7 +135,7 @@ export class RelatedGroupList extends Table<Group> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Remove`} ${msg("Remove")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -142,13 +143,13 @@ export class RelatedGroupList extends Table<Group> {
row(item: Group): TemplateResult[] { row(item: Group): TemplateResult[] {
return [ return [
html`<a href="#/identity/groups/${item.pk}">${item.name}</a>`, html`<a href="#/identity/groups/${item.pk}">${item.name}</a>`,
html`${item.parentName || t`-`}`, html`${item.parentName || msg("-")}`,
html`<ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}> html`<ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}>
${item.isSuperuser ? t`Yes` : t`No`} ${item.isSuperuser ? msg("Yes") : msg("No")}
</ak-label>`, </ak-label>`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Group`} </span> <span slot="header"> ${msg("Update Group")} </span>
<ak-group-form slot="form" .instancePk=${item.pk}> </ak-group-form> <ak-group-form slot="form" .instancePk=${item.pk}> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i> <i class="fas fa-edit"></i>
@ -161,21 +162,21 @@ export class RelatedGroupList extends Table<Group> {
return html` return html`
${this.targetUser ${this.targetUser
? html`<ak-forms-modal> ? html`<ak-forms-modal>
<span slot="submit"> ${t`Add`} </span> <span slot="submit"> ${msg("Add")} </span>
<span slot="header"> ${t`Add Group`} </span> <span slot="header"> ${msg("Add Group")} </span>
<ak-group-related-add .user=${this.targetUser} slot="form"> <ak-group-related-add .user=${this.targetUser} slot="form">
</ak-group-related-add> </ak-group-related-add>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Add to existing group`} ${msg("Add to existing group")}
</button> </button>
</ak-forms-modal>` </ak-forms-modal>`
: html``} : html``}
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Group`} </span> <span slot="header"> ${msg("Create Group")} </span>
<ak-group-form slot="form"> </ak-group-form> <ak-group-form slot="form"> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Add new group`} ${msg("Add new group")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -0,0 +1,12 @@
import { msg } from "@lit/localize";
// These two strings are (a) longer than 80 characters, and (b) contain interesting punctuation, and (c) are used in
// multiple locations. They've been extracted to ensure consistency.
export const iconHelperText = msg(
"Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon \"fa-test\".",
);
export const placeholderHelperText = msg(
"Path template for users created. Use placeholders like `%(slug)s` to insert the source slug.",
);

View File

@ -2,8 +2,7 @@ import { docLink } from "@goauthentik/common/global";
import { ModalButton } from "@goauthentik/elements/buttons/ModalButton"; import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/TokenCopyButton"; import "@goauthentik/elements/buttons/TokenCopyButton";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -17,14 +16,14 @@ export class OutpostDeploymentModal extends ModalButton {
renderModalInner(): TemplateResult { renderModalInner(): TemplateResult {
return html`<div class="pf-c-modal-box__header"> return html`<div class="pf-c-modal-box__header">
<h1 class="pf-c-title pf-m-2xl">${t`Outpost Deployment Info`}</h1> <h1 class="pf-c-title pf-m-2xl">${msg("Outpost Deployment Info")}</h1>
</div> </div>
<div class="pf-c-modal-box__body"> <div class="pf-c-modal-box__body">
<p> <p>
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/outposts?utm_source=authentik#deploy")}" href="${docLink("/docs/outposts?utm_source=authentik#deploy")}"
>${t`View deployment documentation`}</a >${msg("View deployment documentation")}</a
> >
</p> </p>
<form class="pf-c-form"> <form class="pf-c-form">
@ -48,12 +47,14 @@ export class OutpostDeploymentModal extends ModalButton {
class="pf-m-primary" class="pf-m-primary"
identifier="${ifDefined(this.outpost?.tokenIdentifier)}" identifier="${ifDefined(this.outpost?.tokenIdentifier)}"
> >
${t`Click to copy token`} ${msg("Click to copy token")}
</ak-token-copy-button> </ak-token-copy-button>
</div> </div>
</div> </div>
<h3> <h3>
${t`If your authentik Instance is using a self-signed certificate, set this value.`} ${msg(
"If your authentik Instance is using a self-signed certificate, set this value.",
)}
</h3> </h3>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
@ -64,7 +65,9 @@ export class OutpostDeploymentModal extends ModalButton {
${this.outpost?.type == OutpostTypeEnum.Proxy ${this.outpost?.type == OutpostTypeEnum.Proxy
? html` ? html`
<h3> <h3>
${t`If your authentik_host setting does not match the URL you want to login with, add this setting.`} ${msg(
"If your authentik_host setting does not match the URL you want to login with, add this setting.",
)}
</h3> </h3>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
@ -90,7 +93,7 @@ export class OutpostDeploymentModal extends ModalButton {
this.open = false; this.open = false;
}} }}
> >
${t`Close`} ${msg("Close")}
</button> </button>
</footer>`; </footer>`;
} }

View File

@ -7,8 +7,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import YAML from "yaml"; import YAML from "yaml";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -80,9 +79,9 @@ export class OutpostForm extends ModelForm<Outpost, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated outpost.`; return msg("Successfully updated outpost.");
} else { } else {
return t`Successfully created outpost.`; return msg("Successfully created outpost.");
} }
} }
@ -101,7 +100,7 @@ export class OutpostForm extends ModelForm<Outpost, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -109,7 +108,7 @@ export class OutpostForm extends ModelForm<Outpost, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Type`} ?required=${true} name="type"> <ak-form-element-horizontal label=${msg("Type")} ?required=${true} name="type">
<select <select
class="pf-c-form-control" class="pf-c-form-control"
@change=${(ev: Event) => { @change=${(ev: Event) => {
@ -122,23 +121,23 @@ export class OutpostForm extends ModelForm<Outpost, string> {
value=${OutpostTypeEnum.Proxy} value=${OutpostTypeEnum.Proxy}
?selected=${this.instance?.type === OutpostTypeEnum.Proxy} ?selected=${this.instance?.type === OutpostTypeEnum.Proxy}
> >
${t`Proxy`} ${msg("Proxy")}
</option> </option>
<option <option
value=${OutpostTypeEnum.Ldap} value=${OutpostTypeEnum.Ldap}
?selected=${this.instance?.type === OutpostTypeEnum.Ldap} ?selected=${this.instance?.type === OutpostTypeEnum.Ldap}
> >
${t`LDAP`} ${msg("LDAP")}
</option> </option>
<option <option
value=${OutpostTypeEnum.Radius} value=${OutpostTypeEnum.Radius}
?selected=${this.instance?.type === OutpostTypeEnum.Radius} ?selected=${this.instance?.type === OutpostTypeEnum.Radius}
> >
${t`Radius`} ${msg("Radius")}
</option> </option>
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Integration`} name="serviceConnection"> <ak-form-element-horizontal label=${msg("Integration")} name="serviceConnection">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<ServiceConnection[]> => { .fetchObjects=${async (query?: string): Promise<ServiceConnection[]> => {
const args: OutpostsServiceConnectionsAllListRequest = { const args: OutpostsServiceConnectionsAllListRequest = {
@ -172,7 +171,9 @@ export class OutpostForm extends ModelForm<Outpost, string> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Selecting an integration enables the management of the outpost by authentik.`} ${msg(
"Selecting an integration enables the management of the outpost by authentik.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
See See
@ -182,7 +183,7 @@ export class OutpostForm extends ModelForm<Outpost, string> {
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Applications`} label=${msg("Applications")}
?required=${!this.embedded} ?required=${!this.embedded}
name="providers" name="providers"
> >
@ -201,13 +202,13 @@ export class OutpostForm extends ModelForm<Outpost, string> {
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`You can only select providers that match the type of the outpost.`} ${msg("You can only select providers that match the type of the outpost.")}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`} ${msg("Hold control/command to select multiple items.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Configuration`} name="config"> <ak-form-element-horizontal label=${msg("Configuration")} name="config">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify( value="${YAML.stringify(
@ -215,14 +216,14 @@ export class OutpostForm extends ModelForm<Outpost, string> {
)}" )}"
></ak-codemirror> ></ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Set custom attributes using YAML or JSON.`} ${msg("Set custom attributes using YAML or JSON.")}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`See more here:`}&nbsp; ${msg("See more here:")}&nbsp;
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/outposts?utm_source=authentik#configuration")}" href="${docLink("/docs/outposts?utm_source=authentik#configuration")}"
>${t`Documentation`}</a >${msg("Documentation")}</a
> >
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -2,8 +2,7 @@ import { AKElement } from "@goauthentik/elements/Base";
import { PFColor } from "@goauthentik/elements/Label"; import { PFColor } from "@goauthentik/elements/Label";
import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/Spinner";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -43,7 +42,7 @@ export class OutpostHealthElement extends AKElement {
return html`<dl class="pf-c-description-list pf-m-compact"> return html`<dl class="pf-c-description-list pf-m-compact">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Last seen`}</span> <span class="pf-c-description-list__text">${msg("Last seen")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -55,13 +54,15 @@ export class OutpostHealthElement extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Version`}</span> <span class="pf-c-description-list__text">${msg("Version")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
${this.outpostHealth.versionOutdated ${this.outpostHealth.versionOutdated
? html`<ak-label color=${PFColor.Red} ?compact=${true} ? html`<ak-label color=${PFColor.Red} ?compact=${true}
>${t`${this.outpostHealth.version}, should be ${this.outpostHealth.versionShould}`} >${msg(
str`${this.outpostHealth.version}, should be ${this.outpostHealth.versionShould}`,
)}
</ak-label>` </ak-label>`
: html`<ak-label color=${PFColor.Green} ?compact=${true} : html`<ak-label color=${PFColor.Green} ?compact=${true}
>${versionString} >${versionString}
@ -71,7 +72,7 @@ export class OutpostHealthElement extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Hostname`}</span> <span class="pf-c-description-list__text">${msg("Hostname")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.outpostHealth.hostname}</div> <div class="pf-c-description-list__text">${this.outpostHealth.hostname}</div>

View File

@ -4,8 +4,7 @@ import { AKElement } from "@goauthentik/elements/Base";
import { PFColor } from "@goauthentik/elements/Label"; import { PFColor } from "@goauthentik/elements/Label";
import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/Spinner";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -58,10 +57,10 @@ export class OutpostHealthSimpleElement extends AKElement {
return html`<ak-spinner></ak-spinner>`; return html`<ak-spinner></ak-spinner>`;
} }
if (!this.outpostHealth) { if (!this.outpostHealth) {
return html`<ak-label color=${PFColor.Grey}>${t`Not available`}</ak-label>`; return html`<ak-label color=${PFColor.Grey}>${msg("Not available")}</ak-label>`;
} }
return html`<ak-label color=${PFColor.Green}> return html`<ak-label color=${PFColor.Green}>
${t`Last seen: ${this.outpostHealth.lastSeen?.toLocaleTimeString()}`}</ak-label ${msg(str`Last seen: ${this.outpostHealth.lastSeen?.toLocaleTimeString()}`)}</ak-label
>`; >`;
} }
} }

View File

@ -14,8 +14,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { CSSResult } from "lit"; import { CSSResult } from "lit";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
@ -29,13 +28,13 @@ export function TypeToLabel(type?: OutpostTypeEnum): string {
if (!type) return ""; if (!type) return "";
switch (type) { switch (type) {
case OutpostTypeEnum.Proxy: case OutpostTypeEnum.Proxy:
return t`Proxy`; return msg("Proxy");
case OutpostTypeEnum.Ldap: case OutpostTypeEnum.Ldap:
return t`LDAP`; return msg("LDAP");
case OutpostTypeEnum.Radius: case OutpostTypeEnum.Radius:
return t`Radius`; return msg("Radius");
case OutpostTypeEnum.UnknownDefaultOpenApi: case OutpostTypeEnum.UnknownDefaultOpenApi:
return t`Unknown type`; return msg("Unknown type");
} }
} }
@ -44,10 +43,12 @@ export class OutpostListPage extends TablePage<Outpost> {
expandable = true; expandable = true;
pageTitle(): string { pageTitle(): string {
return t`Outposts`; return msg("Outposts");
} }
pageDescription(): string | undefined { pageDescription(): string | undefined {
return t`Outposts are deployments of authentik components to support different environments and protocols, like reverse proxies.`; return msg(
"Outposts are deployments of authentik components to support different environments and protocols, like reverse proxies.",
);
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-zone"; return "pf-icon pf-icon-zone";
@ -82,12 +83,12 @@ export class OutpostListPage extends TablePage<Outpost> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Type`, "type"), new TableColumn(msg("Type"), "type"),
new TableColumn(t`Providers`), new TableColumn(msg("Providers")),
new TableColumn(t`Integration`, "service_connection__name"), new TableColumn(msg("Integration"), "service_connection__name"),
new TableColumn(t`Health and Version`), new TableColumn(msg("Health and Version")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
@ -105,10 +106,12 @@ export class OutpostListPage extends TablePage<Outpost> {
html`<div>${item.name}</div> html`<div>${item.name}</div>
${item.config.authentik_host === "" ${item.config.authentik_host === ""
? html`<ak-label color=${PFColor.Orange} ?compact=${true}> ? html`<ak-label color=${PFColor.Orange} ?compact=${true}>
${t`Warning: authentik Domain is not configured, authentication will not work.`} ${msg(
"Warning: authentik Domain is not configured, authentication will not work.",
)}
</ak-label>` </ak-label>`
: html`<ak-label color=${PFColor.Green} ?compact=${true}> : html`<ak-label color=${PFColor.Green} ?compact=${true}>
${t`Logging in via ${item.config.authentik_host}.`} ${msg(str`Logging in via ${item.config.authentik_host}.`)}
</ak-label>`}`, </ak-label>`}`,
html`${TypeToLabel(item.type)}`, html`${TypeToLabel(item.type)}`,
html`<ul> html`<ul>
@ -118,13 +121,13 @@ export class OutpostListPage extends TablePage<Outpost> {
</li>`; </li>`;
})} })}
</ul>`, </ul>`,
html`${item.serviceConnectionObj?.name || t`No integration active`}`, html`${item.serviceConnectionObj?.name || msg("No integration active")}`,
html`<ak-outpost-health-simple html`<ak-outpost-health-simple
outpostId=${ifDefined(item.pk)} outpostId=${ifDefined(item.pk)}
></ak-outpost-health-simple>`, ></ak-outpost-health-simple>`,
html`<ak-forms-modal> html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Outpost`} </span> <span slot="header"> ${msg("Update Outpost")} </span>
<ak-outpost-form <ak-outpost-form
slot="form" slot="form"
.instancePk=${item.pk} .instancePk=${item.pk}
@ -138,7 +141,7 @@ export class OutpostListPage extends TablePage<Outpost> {
${item.managed !== "goauthentik.io/outposts/embedded" ${item.managed !== "goauthentik.io/outposts/embedded"
? html`<ak-outpost-deployment-modal .outpost=${item} size=${PFSize.Medium}> ? html`<ak-outpost-deployment-modal .outpost=${item} size=${PFSize.Medium}>
<button slot="trigger" class="pf-c-button pf-m-tertiary"> <button slot="trigger" class="pf-c-button pf-m-tertiary">
${t`View Deployment Info`} ${msg("View Deployment Info")}
</button> </button>
</ak-outpost-deployment-modal>` </ak-outpost-deployment-modal>`
: html``}`, : html``}`,
@ -149,7 +152,9 @@ export class OutpostListPage extends TablePage<Outpost> {
return html`<td role="cell" colspan="5"> return html`<td role="cell" colspan="5">
<div class="pf-c-table__expandable-row-content"> <div class="pf-c-table__expandable-row-content">
<h3> <h3>
${t`Detailed health (one instance per column, data is cached so may be out of date)`} ${msg(
"Detailed health (one instance per column, data is cached so may be out of date)",
)}
</h3> </h3>
<dl class="pf-c-description-list pf-m-3-col-on-lg"> <dl class="pf-c-description-list pf-m-3-col-on-lg">
${this.health[item.pk].map((h) => { ${this.health[item.pk].map((h) => {
@ -169,7 +174,7 @@ export class OutpostListPage extends TablePage<Outpost> {
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Outpost(s)`} objectLabel=${msg("Outpost(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Outpost) => { .usedBy=${(item: Outpost) => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesUsedByList({ return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesUsedByList({
@ -183,7 +188,7 @@ export class OutpostListPage extends TablePage<Outpost> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -191,10 +196,10 @@ export class OutpostListPage extends TablePage<Outpost> {
renderObjectCreate(): TemplateResult { renderObjectCreate(): TemplateResult {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Outpost`} </span> <span slot="header"> ${msg("Create Outpost")} </span>
<ak-outpost-form slot="form"> </ak-outpost-form> <ak-outpost-form slot="form"> </ak-outpost-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal> </ak-forms-modal>
`; `;
} }

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -28,9 +27,9 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated integration.`; return msg("Successfully updated integration.");
} else { } else {
return t`Successfully created integration.`; return msg("Successfully created integration.");
} }
} }
@ -49,7 +48,7 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -69,13 +68,15 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Local`}</span> <span class="pf-c-switch__label">${msg("Local")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If enabled, use the local connection. Required Docker socket/Kubernetes Integration.`} ${msg(
"If enabled, use the local connection. Required Docker socket/Kubernetes Integration.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Docker URL`} ?required=${true} name="url"> <ak-form-element-horizontal label=${msg("Docker URL")} ?required=${true} name="url">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.url)}" value="${ifDefined(this.instance?.url)}"
@ -83,11 +84,13 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Can be in the format of 'unix://' when connecting to a local docker daemon, using 'ssh://' to connect via SSH, or 'https://:2376' when connecting to a remote system.`} ${msg(
"Can be in the format of 'unix://' when connecting to a local docker daemon, using 'ssh://' to connect via SSH, or 'https://:2376' when connecting to a remote system.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`TLS Verification Certificate`} label=${msg("TLS Verification Certificate")}
name="tlsVerification" name="tlsVerification"
> >
<ak-search-select <ak-search-select
@ -118,11 +121,13 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`CA which the endpoint's Certificate is verified against. Can be left empty for no validation.`} ${msg(
"CA which the endpoint's Certificate is verified against. Can be left empty for no validation.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`TLS Authentication Certificate/SSH Keypair`} label=${msg("TLS Authentication Certificate/SSH Keypair")}
name="tlsAuthentication" name="tlsAuthentication"
> >
<ak-search-select <ak-search-select
@ -153,10 +158,12 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Certificate/Key used for authentication. Can be left empty for no authentication.`} ${msg(
"Certificate/Key used for authentication. Can be left empty for no authentication.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When connecting via SSH, this keypair is used for authentication.`} ${msg("When connecting via SSH, this keypair is used for authentication.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -5,8 +5,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import YAML from "yaml"; import YAML from "yaml";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -26,9 +25,9 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated integration.`; return msg("Successfully updated integration.");
} else { } else {
return t`Successfully created integration.`; return msg("Successfully created integration.");
} }
} }
@ -47,7 +46,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -67,20 +66,22 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Local`}</span> <span class="pf-c-switch__label">${msg("Local")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If enabled, use the local connection. Required Docker socket/Kubernetes Integration.`} ${msg(
"If enabled, use the local connection. Required Docker socket/Kubernetes Integration.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Kubeconfig`} name="kubeconfig"> <ak-form-element-horizontal label=${msg("Kubeconfig")} name="kubeconfig">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(first(this.instance?.kubeconfig, {}))}" value="${YAML.stringify(first(this.instance?.kubeconfig, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Set custom attributes using YAML or JSON.`} ${msg("Set custom attributes using YAML or JSON.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="verifySsl"> <ak-form-element-horizontal name="verifySsl">
@ -96,7 +97,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
</span> </span>
</span> </span>
<span class="pf-c-switch__label" <span class="pf-c-switch__label"
>${t`Verify Kubernetes API SSL Certificate`}</span >${msg("Verify Kubernetes API SSL Certificate")}</span
> >
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -13,8 +13,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -66,11 +65,11 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Type`), new TableColumn(msg("Type")),
new TableColumn(t`Local`, "local"), new TableColumn(msg("Local"), "local"),
new TableColumn(t`State`), new TableColumn(msg("State")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
@ -83,14 +82,14 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
html`${item.name}`, html`${item.name}`,
html`${item.verboseName}`, html`${item.verboseName}`,
html`<ak-label color=${item.local ? PFColor.Grey : PFColor.Green}> html`<ak-label color=${item.local ? PFColor.Grey : PFColor.Green}>
${item.local ? t`Yes` : t`No`} ${item.local ? msg("Yes") : msg("No")}
</ak-label>`, </ak-label>`,
html`${itemState?.healthy html`${itemState?.healthy
? html`<ak-label color=${PFColor.Green}>${ifDefined(itemState.version)}</ak-label>` ? html`<ak-label color=${PFColor.Green}>${ifDefined(itemState.version)}</ak-label>`
: html`<ak-label color=${PFColor.Red}>${t`Unhealthy`}</ak-label>`}`, : html`<ak-label color=${PFColor.Red}>${msg("Unhealthy")}</ak-label>`}`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span> <span slot="header"> ${msg(str`Update ${item.verboseName}`)} </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
@ -109,7 +108,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Outpost integration(s)`} objectLabel=${msg("Outpost integration(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: ServiceConnection) => { .usedBy=${(item: ServiceConnection) => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllUsedByList({ return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllUsedByList({
@ -123,7 +122,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }

View File

@ -7,8 +7,7 @@ import "@goauthentik/elements/wizard/FormWizardPage";
import "@goauthentik/elements/wizard/Wizard"; import "@goauthentik/elements/wizard/Wizard";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { property } from "lit/decorators.js"; import { property } from "lit/decorators.js";
@ -28,7 +27,7 @@ export class InitialServiceConnectionWizardPage extends WizardPage {
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFForm, PFButton, PFRadio]; return [PFBase, PFForm, PFButton, PFRadio];
} }
sidebarLabel = () => t`Select type`; sidebarLabel = () => msg("Select type");
activeCallback: () => Promise<void> = async () => { activeCallback: () => Promise<void> = async () => {
this.host.isValid = false; this.host.isValid = false;
@ -75,7 +74,7 @@ export class ServiceConnectionWizard extends AKElement {
} }
@property() @property()
createText = t`Create`; createText = msg("Create");
@property({ attribute: false }) @property({ attribute: false })
connectionTypes: TypeCreate[] = []; connectionTypes: TypeCreate[] = [];
@ -90,8 +89,8 @@ export class ServiceConnectionWizard extends AKElement {
return html` return html`
<ak-wizard <ak-wizard
.steps=${["initial"]} .steps=${["initial"]}
header=${t`New outpost integration`} header=${msg("New outpost integration")}
description=${t`Create a new outpost integration.`} description=${msg("Create a new outpost integration.")}
> >
<ak-service-connection-wizard-initial <ak-service-connection-wizard-initial
slot="initial" slot="initial"
@ -102,7 +101,7 @@ export class ServiceConnectionWizard extends AKElement {
return html` return html`
<ak-wizard-page-form <ak-wizard-page-form
slot=${`type-${type.component}-${type.modelName}`} slot=${`type-${type.component}-${type.modelName}`}
.sidebarLabel=${() => t`Create ${type.name}`} .sidebarLabel=${() => msg(str`Create ${type.name}`)}
> >
<ak-proxy-form type=${type.component}></ak-proxy-form> <ak-proxy-form type=${type.component}></ak-proxy-form>
</ak-wizard-page-form> </ak-wizard-page-form>

View File

@ -13,8 +13,7 @@ import "@goauthentik/elements/forms/ProxyForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -42,23 +41,23 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Order`, "order"), new TableColumn(msg("Order"), "order"),
new TableColumn(t`Policy / User / Group`), new TableColumn(msg("Policy / User / Group")),
new TableColumn(t`Enabled`, "enabled"), new TableColumn(msg("Enabled"), "enabled"),
new TableColumn(t`Timeout`, "timeout"), new TableColumn(msg("Timeout"), "timeout"),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
getPolicyUserGroupRowLabel(item: PolicyBinding): string { getPolicyUserGroupRowLabel(item: PolicyBinding): string {
if (item.policy) { if (item.policy) {
return t`Policy ${item.policyObj?.name}`; return msg(str`Policy ${item.policyObj?.name}`);
} else if (item.group) { } else if (item.group) {
return t`Group ${item.groupObj?.name}`; return msg(str`Group ${item.groupObj?.name}`);
} else if (item.user) { } else if (item.user) {
return t`User ${item.userObj?.name}`; return msg(str`User ${item.userObj?.name}`);
} else { } else {
return t`-`; return msg("-");
} }
} }
@ -76,8 +75,8 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
getObjectEditButton(item: PolicyBinding): TemplateResult { getObjectEditButton(item: PolicyBinding): TemplateResult {
if (item.policy) { if (item.policy) {
return html`<ak-forms-modal> return html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update ${item.policyObj?.name}`} </span> <span slot="header"> ${msg(str`Update ${item.policyObj?.name}`)} </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
@ -86,21 +85,27 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
type=${ifDefined(item.policyObj?.component)} type=${ifDefined(item.policyObj?.component)}
> >
</ak-proxy-form> </ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">${t`Edit Policy`}</button> <button slot="trigger" class="pf-c-button pf-m-secondary">
${msg("Edit Policy")}
</button>
</ak-forms-modal>`; </ak-forms-modal>`;
} else if (item.group) { } else if (item.group) {
return html`<ak-forms-modal> return html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Group`} </span> <span slot="header"> ${msg("Update Group")} </span>
<ak-group-form slot="form" .instancePk=${item.groupObj?.pk}> </ak-group-form> <ak-group-form slot="form" .instancePk=${item.groupObj?.pk}> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">${t`Edit Group`}</button> <button slot="trigger" class="pf-c-button pf-m-secondary">
${msg("Edit Group")}
</button>
</ak-forms-modal>`; </ak-forms-modal>`;
} else if (item.user) { } else if (item.user) {
return html`<ak-forms-modal> return html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update User`} </span> <span slot="header"> ${msg("Update User")} </span>
<ak-user-form slot="form" .instancePk=${item.userObj?.pk}> </ak-user-form> <ak-user-form slot="form" .instancePk=${item.userObj?.pk}> </ak-user-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">${t`Edit User`}</button> <button slot="trigger" class="pf-c-button pf-m-secondary">
${msg("Edit User")}
</button>
</ak-forms-modal>`; </ak-forms-modal>`;
} else { } else {
return html``; return html``;
@ -110,12 +115,15 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Policy binding(s)`} objectLabel=${msg("Policy binding(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.metadata=${(item: PolicyBinding) => { .metadata=${(item: PolicyBinding) => {
return [ return [
{ key: t`Order`, value: item.order.toString() }, { key: msg("Order"), value: item.order.toString() },
{ key: t`Policy / User / Group`, value: this.getPolicyUserGroupRowLabel(item) }, {
key: msg("Policy / User / Group"),
value: this.getPolicyUserGroupRowLabel(item),
},
]; ];
}} }}
.usedBy=${(item: PolicyBinding) => { .usedBy=${(item: PolicyBinding) => {
@ -130,7 +138,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -140,13 +148,13 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
html`${item.order}`, html`${item.order}`,
html`${this.getPolicyUserGroupRow(item)}`, html`${this.getPolicyUserGroupRow(item)}`,
html` <ak-label color=${item.enabled ? PFColor.Green : PFColor.Orange}> html` <ak-label color=${item.enabled ? PFColor.Green : PFColor.Orange}>
${item.enabled ? t`Yes` : t`No`} ${item.enabled ? msg("Yes") : msg("No")}
</ak-label>`, </ak-label>`,
html`${item.timeout}`, html`${item.timeout}`,
html` ${this.getObjectEditButton(item)} html` ${this.getObjectEditButton(item)}
<ak-forms-modal size=${PFSize.Medium}> <ak-forms-modal size=${PFSize.Medium}>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Binding`} </span> <span slot="header"> ${msg("Update Binding")} </span>
<ak-policy-binding-form <ak-policy-binding-form
slot="form" slot="form"
.instancePk=${item.pk} .instancePk=${item.pk}
@ -155,7 +163,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
> >
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit Binding`} ${msg("Edit Binding")}
</button> </button>
</ak-forms-modal>`, </ak-forms-modal>`,
]; ];
@ -163,14 +171,14 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
renderEmpty(): TemplateResult { renderEmpty(): TemplateResult {
return super.renderEmpty(html`<ak-empty-state return super.renderEmpty(html`<ak-empty-state
header=${t`No Policies bound.`} header=${msg("No Policies bound.")}
icon="pf-icon-module" icon="pf-icon-module"
> >
<div slot="body">${t`No policies are currently bound to this object.`}</div> <div slot="body">${msg("No policies are currently bound to this object.")}</div>
<div slot="primary"> <div slot="primary">
<ak-forms-modal size=${PFSize.Medium}> <ak-forms-modal size=${PFSize.Medium}>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Binding`} </span> <span slot="header"> ${msg("Create Binding")} </span>
<ak-policy-binding-form <ak-policy-binding-form
slot="form" slot="form"
targetPk=${ifDefined(this.target)} targetPk=${ifDefined(this.target)}
@ -178,7 +186,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
> >
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Create Binding`} ${msg("Create Binding")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -187,13 +195,13 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
renderToolbar(): TemplateResult { renderToolbar(): TemplateResult {
return html`<ak-policy-wizard return html`<ak-policy-wizard
createText=${t`Create & bind Policy`} createText=${msg("Create & bind Policy")}
?showBindingPage=${true} ?showBindingPage=${true}
bindingTarget=${ifDefined(this.target)} bindingTarget=${ifDefined(this.target)}
></ak-policy-wizard> ></ak-policy-wizard>
<ak-forms-modal size=${PFSize.Medium}> <ak-forms-modal size=${PFSize.Medium}>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Binding`} </span> <span slot="header"> ${msg("Create Binding")} </span>
<ak-policy-binding-form <ak-policy-binding-form
slot="form" slot="form"
targetPk=${ifDefined(this.target)} targetPk=${ifDefined(this.target)}
@ -201,7 +209,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
> >
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Bind existing policy`} ${msg("Bind existing policy")}
</button> </button>
</ak-forms-modal> `; </ak-forms-modal> `;
} }

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, css } from "lit"; import { CSSResult, css } from "lit";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
@ -64,9 +63,9 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance?.pk) { if (this.instance?.pk) {
return t`Successfully updated binding.`; return msg("Successfully updated binding.");
} else { } else {
return t`Successfully created binding.`; return msg("Successfully created binding.");
} }
} }
@ -123,7 +122,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
this.policyGroupUser = target.policy; this.policyGroupUser = target.policy;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`Policy`}</span> <span class="pf-c-toggle-group__text">${msg("Policy")}</span>
</button> </button>
</div> </div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div> <div class="pf-c-divider pf-m-vertical" role="separator"></div>
@ -137,7 +136,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
this.policyGroupUser = target.group; this.policyGroupUser = target.group;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`Group`}</span> <span class="pf-c-toggle-group__text">${msg("Group")}</span>
</button> </button>
</div> </div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div> <div class="pf-c-divider pf-m-vertical" role="separator"></div>
@ -151,7 +150,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
this.policyGroupUser = target.user; this.policyGroupUser = target.user;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`User`}</span> <span class="pf-c-toggle-group__text">${msg("User")}</span>
</button> </button>
</div>`; </div>`;
} }
@ -164,7 +163,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
</div> </div>
<div class="pf-c-card__footer"> <div class="pf-c-card__footer">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Policy`} label=${msg("Policy")}
name="policy" name="policy"
?hidden=${this.policyGroupUser !== target.policy} ?hidden=${this.policyGroupUser !== target.policy}
> >
@ -198,7 +197,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Group`} label=${msg("Group")}
name="group" name="group"
?hidden=${this.policyGroupUser !== target.group} ?hidden=${this.policyGroupUser !== target.group}
> >
@ -229,12 +228,14 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
</ak-search-select> </ak-search-select>
${this.policyOnly ${this.policyOnly
? html`<p class="pf-c-form__helper-text"> ? html`<p class="pf-c-form__helper-text">
${t`Group mappings can only be checked if a user is already logged in when trying to access this source.`} ${msg(
"Group mappings can only be checked if a user is already logged in when trying to access this source.",
)}
</p>` </p>`
: html``} : html``}
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`User`} label=${msg("User")}
name="user" name="user"
?hidden=${this.policyGroupUser !== target.user} ?hidden=${this.policyGroupUser !== target.user}
> >
@ -266,7 +267,9 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
</ak-search-select> </ak-search-select>
${this.policyOnly ${this.policyOnly
? html`<p class="pf-c-form__helper-text"> ? html`<p class="pf-c-form__helper-text">
${t`User mappings can only be checked if a user is already logged in when trying to access this source.`} ${msg(
"User mappings can only be checked if a user is already logged in when trying to access this source.",
)}
</p>` </p>`
: html``} : html``}
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -284,7 +287,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Enabled`}</span> <span class="pf-c-switch__label">${msg("Enabled")}</span>
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="negate"> <ak-form-element-horizontal name="negate">
@ -299,13 +302,13 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Negate result`}</span> <span class="pf-c-switch__label">${msg("Negate result")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Negates the outcome of the binding. Messages are unaffected.`} ${msg("Negates the outcome of the binding. Messages are unaffected.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Order`} ?required=${true} name="order"> <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
<input <input
type="number" type="number"
value="${first(this.instance?.order, this.defaultOrder)}" value="${first(this.instance?.order, this.defaultOrder)}"
@ -313,7 +316,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Timeout`} ?required=${true} name="timeout"> <ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout">
<input <input
type="number" type="number"
value="${first(this.instance?.timeout, 30)}" value="${first(this.instance?.timeout, 30)}"

View File

@ -17,8 +17,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -31,10 +30,12 @@ export class PolicyListPage extends TablePage<Policy> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Policies`; return msg("Policies");
} }
pageDescription(): string { pageDescription(): string {
return t`Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages.`; return msg(
"Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages.",
);
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-infrastructure"; return "pf-icon pf-icon-infrastructure";
@ -56,9 +57,9 @@ export class PolicyListPage extends TablePage<Policy> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Type`), new TableColumn(msg("Type")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
@ -67,15 +68,15 @@ export class PolicyListPage extends TablePage<Policy> {
html`<div>${item.name}</div> html`<div>${item.name}</div>
${(item.boundTo || 0) > 0 ${(item.boundTo || 0) > 0
? html`<ak-label color=${PFColor.Green} ?compact=${true}> ? html`<ak-label color=${PFColor.Green} ?compact=${true}>
${t`Assigned to ${item.boundTo} object(s).`} ${msg(str`Assigned to ${item.boundTo} object(s).`)}
</ak-label>` </ak-label>`
: html`<ak-label color=${PFColor.Orange} ?compact=${true}> : html`<ak-label color=${PFColor.Orange} ?compact=${true}>
${t`Warning: Policy is not assigned.`} ${msg("Warning: Policy is not assigned.")}
</ak-label>`}`, </ak-label>`}`,
html`${item.verboseName}`, html`${item.verboseName}`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span> <span slot="header"> ${msg(str`Update ${item.verboseName}`)} </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
@ -89,8 +90,8 @@ export class PolicyListPage extends TablePage<Policy> {
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal .closeAfterSuccessfulSubmit=${false}> <ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
<span slot="submit"> ${t`Test`} </span> <span slot="submit"> ${msg("Test")} </span>
<span slot="header"> ${t`Test Policy`} </span> <span slot="header"> ${msg("Test Policy")} </span>
<ak-policy-test-form slot="form" .policy=${item}> </ak-policy-test-form> <ak-policy-test-form slot="form" .policy=${item}> </ak-policy-test-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-vial" aria-hidden="true"></i> <i class="fas fa-vial" aria-hidden="true"></i>
@ -102,7 +103,7 @@ export class PolicyListPage extends TablePage<Policy> {
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Policy / Policies`} objectLabel=${msg("Policy / Policies")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Policy) => { .usedBy=${(item: Policy) => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllUsedByList({ return new PoliciesApi(DEFAULT_CONFIG).policiesAllUsedByList({
@ -116,7 +117,7 @@ export class PolicyListPage extends TablePage<Policy> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -128,20 +129,21 @@ export class PolicyListPage extends TablePage<Policy> {
renderToolbar(): TemplateResult { renderToolbar(): TemplateResult {
return html` ${super.renderToolbar()} return html` ${super.renderToolbar()}
<ak-forms-confirm <ak-forms-confirm
successMessage=${t`Successfully cleared policy cache`} successMessage=${msg("Successfully cleared policy cache")}
errorMessage=${t`Failed to delete policy cache`} errorMessage=${msg("Failed to delete policy cache")}
action=${t`Clear cache`} action=${msg("Clear cache")}
.onConfirm=${() => { .onConfirm=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheClearCreate(); return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheClearCreate();
}} }}
> >
<span slot="header"> ${t`Clear Policy cache`} </span> <span slot="header"> ${msg("Clear Policy cache")} </span>
<p slot="body"> <p slot="body">
${t`Are you sure you want to clear the policy cache? ${msg(
This will cause all policies to be re-evaluated on their next usage.`} "Are you sure you want to clear the policy cache? This will cause all policies to be re-evaluated on their next usage.",
)}
</p> </p>
<button slot="trigger" class="pf-c-button pf-m-secondary" type="button"> <button slot="trigger" class="pf-c-button pf-m-secondary" type="button">
${t`Clear cache`} ${msg("Clear cache")}
</button> </button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-forms-confirm>`; </ak-forms-confirm>`;

View File

@ -7,8 +7,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import YAML from "yaml"; import YAML from "yaml";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
@ -36,7 +35,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
request?: PolicyTestRequest; request?: PolicyTestRequest;
getSuccessMessage(): string { getSuccessMessage(): string {
return t`Successfully sent test-request.`; return msg("Successfully sent test-request.");
} }
async send(data: PolicyTestRequest): Promise<PolicyTestResult> { async send(data: PolicyTestRequest): Promise<PolicyTestResult> {
@ -54,18 +53,18 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html` return html`
<ak-form-element-horizontal label=${t`Passing`}> <ak-form-element-horizontal label=${msg("Passing")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<span class="pf-c-form__label-text"> <span class="pf-c-form__label-text">
<ak-label color=${this.result?.passing ? PFColor.Green : PFColor.Red}> <ak-label color=${this.result?.passing ? PFColor.Green : PFColor.Red}>
${this.result?.passing ? t`Yes` : t`No`} ${this.result?.passing ? msg("Yes") : msg("No")}
</ak-label> </ak-label>
</span> </span>
</div> </div>
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Messages`}> <ak-form-element-horizontal label=${msg("Messages")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<ul> <ul>
@ -83,7 +82,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Log messages`}> <ak-form-element-horizontal label=${msg("Log messages")}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
@ -105,7 +104,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
: html`<div class="pf-c-description-list__group"> : html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`No log messages.`}</span >${msg("No log messages.")}</span
> >
</dt> </dt>
</div>`} </div>`}
@ -118,7 +117,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="user"> <ak-form-element-horizontal label=${msg("User")} ?required=${true} name="user">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<User[]> => { .fetchObjects=${async (query?: string): Promise<User[]> => {
const args: CoreUsersListRequest = { const args: CoreUsersListRequest = {
@ -145,14 +144,14 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
> >
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Context`} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value=${YAML.stringify(first(this.request?.context, {}))} value=${YAML.stringify(first(this.request?.context, {}))}
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Set custom attributes using YAML or JSON.`} ${msg("Set custom attributes using YAML or JSON.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.result ? this.renderResult() : html``} ${this.result ? this.renderResult() : html``}

View File

@ -13,8 +13,7 @@ import { FormWizardPage } from "@goauthentik/elements/wizard/FormWizardPage";
import "@goauthentik/elements/wizard/Wizard"; import "@goauthentik/elements/wizard/Wizard";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { property } from "lit/decorators.js"; import { property } from "lit/decorators.js";
@ -34,7 +33,7 @@ export class InitialPolicyWizardPage extends WizardPage {
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFForm, PFButton, PFRadio]; return [PFBase, PFForm, PFButton, PFRadio];
} }
sidebarLabel = () => t`Select type`; sidebarLabel = () => msg("Select type");
activeCallback: () => Promise<void> = async () => { activeCallback: () => Promise<void> = async () => {
this.host.isValid = false; this.host.isValid = false;
@ -88,7 +87,7 @@ export class PolicyWizard extends AKElement {
} }
@property() @property()
createText = t`Create`; createText = msg("Create");
@property({ type: Boolean }) @property({ type: Boolean })
showBindingPage = false; showBindingPage = false;
@ -109,8 +108,8 @@ export class PolicyWizard extends AKElement {
return html` return html`
<ak-wizard <ak-wizard
.steps=${this.showBindingPage ? ["initial", "create-binding"] : ["initial"]} .steps=${this.showBindingPage ? ["initial", "create-binding"] : ["initial"]}
header=${t`New policy`} header=${msg("New policy")}
description=${t`Create a new policy.`} description=${msg("Create a new policy.")}
> >
<ak-policy-wizard-initial slot="initial" .policyTypes=${this.policyTypes}> <ak-policy-wizard-initial slot="initial" .policyTypes=${this.policyTypes}>
</ak-policy-wizard-initial> </ak-policy-wizard-initial>
@ -118,7 +117,7 @@ export class PolicyWizard extends AKElement {
return html` return html`
<ak-wizard-page-form <ak-wizard-page-form
slot=${`type-${type.component}-${type.modelName}`} slot=${`type-${type.component}-${type.modelName}`}
.sidebarLabel=${() => t`Create ${type.name}`} .sidebarLabel=${() => msg(str`Create ${type.name}`)}
> >
<ak-proxy-form type=${type.component}></ak-proxy-form> <ak-proxy-form type=${type.component}></ak-proxy-form>
</ak-wizard-page-form> </ak-wizard-page-form>
@ -127,7 +126,7 @@ export class PolicyWizard extends AKElement {
${this.showBindingPage ${this.showBindingPage
? html`<ak-wizard-page-form ? html`<ak-wizard-page-form
slot="create-binding" slot="create-binding"
.sidebarLabel=${() => t`Create Binding`} .sidebarLabel=${() => msg("Create Binding")}
.activePageCallback=${async (context: FormWizardPage) => { .activePageCallback=${async (context: FormWizardPage) => {
const createSlot = context.host.steps[1]; const createSlot = context.host.steps[1];
const bindingForm = const bindingForm =

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class DummyPolicyForm extends ModelForm<DummyPolicy, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated policy.`; return msg("Successfully updated policy.");
} else { } else {
return t`Successfully created policy.`; return msg("Successfully created policy.");
} }
} }
@ -44,9 +43,11 @@ export class DummyPolicyForm extends ModelForm<DummyPolicy, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<div class="form-help-text"> <div class="form-help-text">
${t`A policy used for testing. Always returns the same result as specified below after waiting a random duration.`} ${msg(
"A policy used for testing. Always returns the same result as specified below after waiting a random duration.",
)}
</div> </div>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name || "")}" value="${ifDefined(this.instance?.name || "")}"
@ -66,14 +67,16 @@ export class DummyPolicyForm extends ModelForm<DummyPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Execution logging`}</span> <span class="pf-c-switch__label">${msg("Execution logging")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`} ${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Policy-specific settings`} </span> <span slot="header"> ${msg("Policy-specific settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="result"> <ak-form-element-horizontal name="result">
<label class="pf-c-switch"> <label class="pf-c-switch">
@ -87,11 +90,11 @@ export class DummyPolicyForm extends ModelForm<DummyPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Pass policy?`}</span> <span class="pf-c-switch__label">${msg("Pass policy?")}</span>
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Wait (min)`} label=${msg("Wait (min)")}
?required=${true} ?required=${true}
name="waitMin" name="waitMin"
> >
@ -102,11 +105,13 @@ export class DummyPolicyForm extends ModelForm<DummyPolicy, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`The policy takes a random time to execute. This controls the minimum time it will take.`} ${msg(
"The policy takes a random time to execute. This controls the minimum time it will take.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Wait (max)`} label=${msg("Wait (max)")}
?required=${true} ?required=${true}
name="waitMax" name="waitMax"
> >

View File

@ -5,8 +5,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -36,9 +35,9 @@ export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated policy.`; return msg("Successfully updated policy.");
} else { } else {
return t`Successfully created policy.`; return msg("Successfully created policy.");
} }
} }
@ -58,9 +57,11 @@ export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<div class="form-help-text"> <div class="form-help-text">
${t`Matches an event against a set of criteria. If any of the configured values match, the policy passes.`} ${msg(
"Matches an event against a set of criteria. If any of the configured values match, the policy passes.",
)}
</div> </div>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name || "")}" value="${ifDefined(this.instance?.name || "")}"
@ -80,16 +81,18 @@ export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Execution logging`}</span> <span class="pf-c-switch__label">${msg("Execution logging")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`} ${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Policy-specific settings`} </span> <span slot="header"> ${msg("Policy-specific settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Action`} name="action"> <ak-form-element-horizontal label=${msg("Action")} name="action">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<TypeCreate[]> => { .fetchObjects=${async (query?: string): Promise<TypeCreate[]> => {
const items = await new EventsApi( const items = await new EventsApi(
@ -112,20 +115,24 @@ export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Match created events with this action type. When left empty, all action types will be matched.`} ${msg(
"Match created events with this action type. When left empty, all action types will be matched.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Client IP`} name="clientIp"> <ak-form-element-horizontal label=${msg("Client IP")} name="clientIp">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.clientIp || "")}" value="${ifDefined(this.instance?.clientIp || "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Matches Event's Client IP (strict matching, for network matching use an Expression Policy.`} ${msg(
"Matches Event's Client IP (strict matching, for network matching use an Expression Policy.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`App`} name="app"> <ak-form-element-horizontal label=${msg("App")} name="app">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.app === undefined}> <option value="" ?selected=${this.instance?.app === undefined}>
--------- ---------
@ -140,7 +147,9 @@ export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Match events created by selected application. When left empty, all applications are matched.`} ${msg(
"Match events created by selected application. When left empty, all applications are matched.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class PasswordExpiryPolicyForm extends ModelForm<PasswordExpiryPolicy, st
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated policy.`; return msg("Successfully updated policy.");
} else { } else {
return t`Successfully created policy.`; return msg("Successfully created policy.");
} }
} }
@ -44,9 +43,11 @@ export class PasswordExpiryPolicyForm extends ModelForm<PasswordExpiryPolicy, st
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<div class="form-help-text"> <div class="form-help-text">
${t`Checks if the request's user's password has been changed in the last x days, and denys based on settings.`} ${msg(
"Checks if the request's user's password has been changed in the last x days, and denys based on settings.",
)}
</div> </div>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name || "")}" value="${ifDefined(this.instance?.name || "")}"
@ -66,17 +67,19 @@ export class PasswordExpiryPolicyForm extends ModelForm<PasswordExpiryPolicy, st
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Execution logging`}</span> <span class="pf-c-switch__label">${msg("Execution logging")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`} ${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Policy-specific settings`} </span> <span slot="header"> ${msg("Policy-specific settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Maximum age (in days)`} label=${msg("Maximum age (in days)")}
?required=${true} ?required=${true}
name="days" name="days"
> >
@ -100,7 +103,9 @@ export class PasswordExpiryPolicyForm extends ModelForm<PasswordExpiryPolicy, st
</span> </span>
</span> </span>
<span class="pf-c-switch__label" <span class="pf-c-switch__label"
>${t`Only fail the policy, don't invalidate user's password`}</span >${msg(
"Only fail the policy, don't invalidate user's password",
)}</span
> >
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -6,8 +6,7 @@ import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -24,9 +23,9 @@ export class ExpressionPolicyForm extends ModelForm<ExpressionPolicy, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated policy.`; return msg("Successfully updated policy.");
} else { } else {
return t`Successfully created policy.`; return msg("Successfully created policy.");
} }
} }
@ -46,9 +45,11 @@ export class ExpressionPolicyForm extends ModelForm<ExpressionPolicy, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<div class="form-help-text"> <div class="form-help-text">
${t`Executes the python snippet to determine whether to allow or deny a request.`} ${msg(
"Executes the python snippet to determine whether to allow or deny a request.",
)}
</div> </div>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name || "")}" value="${ifDefined(this.instance?.name || "")}"
@ -68,17 +69,19 @@ export class ExpressionPolicyForm extends ModelForm<ExpressionPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Execution logging`}</span> <span class="pf-c-switch__label">${msg("Execution logging")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`} ${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Policy-specific settings`} </span> <span slot="header"> ${msg("Policy-specific settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Expression`} label=${msg("Expression")}
?required=${true} ?required=${true}
name="expression" name="expression"
> >
@ -88,12 +91,12 @@ export class ExpressionPolicyForm extends ModelForm<ExpressionPolicy, string> {
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${msg("Expression using Python.")}
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/policies/expression?utm_source=authentik")}" href="${docLink("/docs/policies/expression?utm_source=authentik")}"
> >
${t`See documentation for a list of all variables.`} ${msg("See documentation for a list of all variables.")}
</a> </a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -38,9 +37,9 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated policy.`; return msg("Successfully updated policy.");
} else { } else {
return t`Successfully created policy.`; return msg("Successfully created policy.");
} }
} }
@ -59,10 +58,10 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
renderStaticRules(): TemplateResult { renderStaticRules(): TemplateResult {
return html` <ak-form-group> return html` <ak-form-group>
<span slot="header"> ${t`Static rules`} </span> <span slot="header"> ${msg("Static rules")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum length`} label=${msg("Minimum length")}
?required=${true} ?required=${true}
name="lengthMin" name="lengthMin"
> >
@ -74,7 +73,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Uppercase Characters`} label=${msg("Minimum amount of Uppercase Characters")}
?required=${true} ?required=${true}
name="amountUppercase" name="amountUppercase"
> >
@ -86,7 +85,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Lowercase Characters`} label=${msg("Minimum amount of Lowercase Characters")}
?required=${true} ?required=${true}
name="amountLowercase" name="amountLowercase"
> >
@ -98,7 +97,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Digits`} label=${msg("Minimum amount of Digits")}
?required=${true} ?required=${true}
name="amountDigits" name="amountDigits"
> >
@ -110,7 +109,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Symbols Characters`} label=${msg("Minimum amount of Symbols Characters")}
?required=${true} ?required=${true}
name="amountSymbols" name="amountSymbols"
> >
@ -122,7 +121,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Error message`} label=${msg("Error message")}
?required=${true} ?required=${true}
name="errorMessage" name="errorMessage"
> >
@ -134,7 +133,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Symbol charset`} label=${msg("Symbol charset")}
?required=${true} ?required=${true}
name="symbolCharset" name="symbolCharset"
> >
@ -147,7 +146,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Characters which are considered as symbols.`} ${msg("Characters which are considered as symbols.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
@ -157,10 +156,10 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
renderHIBP(): TemplateResult { renderHIBP(): TemplateResult {
return html` return html`
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`HaveIBeenPwned settings`} </span> <span slot="header"> ${msg("HaveIBeenPwned settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Allowed count`} label=${msg("Allowed count")}
?required=${true} ?required=${true}
name="hibpAllowedCount" name="hibpAllowedCount"
> >
@ -171,7 +170,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Allow up to N occurrences in the HIBP database.`} ${msg("Allow up to N occurrences in the HIBP database.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
@ -182,10 +181,10 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
renderZxcvbn(): TemplateResult { renderZxcvbn(): TemplateResult {
return html` return html`
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`zxcvbn settings`} </span> <span slot="header"> ${msg("zxcvbn settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Score threshold`} label=${msg("Score threshold")}
?required=${true} ?required=${true}
name="zxcvbnScoreThreshold" name="zxcvbnScoreThreshold"
> >
@ -196,22 +195,32 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If the password's score is less than or equal this value, the policy will fail.`} ${msg(
"If the password's score is less than or equal this value, the policy will fail.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`0: Too guessable: risky password. (guesses < 10^3)`} ${msg("0: Too guessable: risky password. (guesses < 10^3)")}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`1: Very guessable: protection from throttled online attacks. (guesses < 10^6)`} ${msg(
"1: Very guessable: protection from throttled online attacks. (guesses < 10^6)",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`2: Somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)`} ${msg(
"2: Somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`3: Safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)`} ${msg(
"3: Safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`4: Very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)`} ${msg(
"4: Very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
@ -222,9 +231,11 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<div class="form-help-text"> <div class="form-help-text">
${t`Checks the value from the policy request against several rules, mostly used to ensure password strength.`} ${msg(
"Checks the value from the policy request against several rules, mostly used to ensure password strength.",
)}
</div> </div>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name || "")}" value="${ifDefined(this.instance?.name || "")}"
@ -244,14 +255,16 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Execution logging`}</span> <span class="pf-c-switch__label">${msg("Execution logging")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`} ${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Password field`} label=${msg("Password field")}
?required=${true} ?required=${true}
name="passwordField" name="passwordField"
> >
@ -262,7 +275,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Field key to check, field keys defined in Prompt stages are available.`} ${msg("Field key to check, field keys defined in Prompt stages are available.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -282,7 +295,7 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Check static rules`}</span> <span class="pf-c-switch__label">${msg("Check static rules")}</span>
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="checkHaveIBeenPwned"> <ak-form-element-horizontal name="checkHaveIBeenPwned">
@ -301,10 +314,10 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Check haveibeenpwned.com`}</span> <span class="pf-c-switch__label">${msg("Check haveibeenpwned.com")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`For more info see:`} ${msg("For more info see:")}
<a href="https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange" <a href="https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange"
>haveibeenpwned.com</a >haveibeenpwned.com</a
> >
@ -326,10 +339,10 @@ export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Check zxcvbn`}</span> <span class="pf-c-switch__label">${msg("Check zxcvbn")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Password strength estimator created by Dropbox, see:`} ${msg("Password strength estimator created by Dropbox, see:")}
<a href="https://github.com/dropbox/zxcvbn#readme">dropbox/zxcvbn</a> <a href="https://github.com/dropbox/zxcvbn#readme">dropbox/zxcvbn</a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -9,8 +9,7 @@ import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import getUnicodeFlagIcon from "country-flag-icons/unicode"; import getUnicodeFlagIcon from "country-flag-icons/unicode";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -22,10 +21,12 @@ export class ReputationListPage extends TablePage<Reputation> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Reputation scores`; return msg("Reputation scores");
} }
pageDescription(): string { pageDescription(): string {
return t`Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login.`; return msg(
"Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login.",
);
} }
pageIcon(): string { pageIcon(): string {
return "fa fa-ban"; return "fa fa-ban";
@ -47,17 +48,17 @@ export class ReputationListPage extends TablePage<Reputation> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Identifier`, "identifier"), new TableColumn(msg("Identifier"), "identifier"),
new TableColumn(t`IP`, "ip"), new TableColumn(msg("IP"), "ip"),
new TableColumn(t`Score`, "score"), new TableColumn(msg("Score"), "score"),
new TableColumn(t`Updated`, "updated"), new TableColumn(msg("Updated"), "updated"),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Reputation`} objectLabel=${msg("Reputation")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Reputation) => { .usedBy=${(item: Reputation) => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresUsedByList({ return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresUsedByList({
@ -71,7 +72,7 @@ export class ReputationListPage extends TablePage<Reputation> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class ReputationPolicyForm extends ModelForm<ReputationPolicy, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated policy.`; return msg("Successfully updated policy.");
} else { } else {
return t`Successfully created policy.`; return msg("Successfully created policy.");
} }
} }
@ -44,18 +43,21 @@ export class ReputationPolicyForm extends ModelForm<ReputationPolicy, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<div class="form-help-text"> <div class="form-help-text">
${t`Allows/denys requests based on the users and/or the IPs reputation.`} ${msg("Allows/denys requests based on the users and/or the IPs reputation.")}
</div> </div>
<div class="form-help-text"> <div class="form-help-text">
${t`Invalid login attempts will decrease the score for the client's IP, and the ${msg(
username they are attempting to login as, by one.`} `Invalid login attempts will decrease the score for the client's IP, and the
username they are attempting to login as, by one.`,
)}
</div> </div>
<div class="form-help-text"> <div class="form-help-text">
${t`The policy passes when the reputation score is below the threshold, and ${msg(
doesn't pass when either or both of the selected options are equal or above the `The policy passes when the reputation score is below the threshold, and
threshold.`} doesn't pass when either or both of the selected options are equal or above the threshold.`,
)}
</div> </div>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name || "")}" value="${ifDefined(this.instance?.name || "")}"
@ -75,14 +77,16 @@ export class ReputationPolicyForm extends ModelForm<ReputationPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Execution logging`}</span> <span class="pf-c-switch__label">${msg("Execution logging")}</span>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`} ${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Policy-specific settings`} </span> <span slot="header"> ${msg("Policy-specific settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="checkIp"> <ak-form-element-horizontal name="checkIp">
<label class="pf-c-switch"> <label class="pf-c-switch">
@ -96,7 +100,7 @@ export class ReputationPolicyForm extends ModelForm<ReputationPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Check IP`}</span> <span class="pf-c-switch__label">${msg("Check IP")}</span>
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="checkUsername"> <ak-form-element-horizontal name="checkUsername">
@ -111,11 +115,11 @@ export class ReputationPolicyForm extends ModelForm<ReputationPolicy, string> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Check Username`}</span> <span class="pf-c-switch__label">${msg("Check Username")}</span>
</label> </label>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Threshold`} label=${msg("Threshold")}
?required=${true} ?required=${true}
name="threshold" name="threshold"
> >

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class PropertyMappingLDAPForm extends ModelForm<LDAPPropertyMapping, stri
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated mapping.`; return msg("Successfully updated mapping.");
} else { } else {
return t`Successfully created mapping.`; return msg("Successfully created mapping.");
} }
} }
@ -43,7 +42,7 @@ export class PropertyMappingLDAPForm extends ModelForm<LDAPPropertyMapping, stri
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -52,7 +51,7 @@ export class PropertyMappingLDAPForm extends ModelForm<LDAPPropertyMapping, stri
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Object field`} label=${msg("Object field")}
?required=${true} ?required=${true}
name="objectField" name="objectField"
> >
@ -63,19 +62,23 @@ export class PropertyMappingLDAPForm extends ModelForm<LDAPPropertyMapping, stri
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Field of the user object this value is written to.`} ${msg("Field of the user object this value is written to.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Expression`} ?required=${true} name="expression"> <ak-form-element-horizontal
label=${msg("Expression")}
?required=${true}
name="expression"
>
<ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${msg("Expression using Python.")}
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}" href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}"
> >
${t`See documentation for a list of all variables.`} ${msg("See documentation for a list of all variables.")}
</a> </a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -15,8 +15,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -29,10 +28,10 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Property Mappings`; return msg("Property Mappings");
} }
pageDescription(): string { pageDescription(): string {
return t`Control how authentik exposes and interprets information.`; return msg("Control how authentik exposes and interprets information.");
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-blueprint"; return "pf-icon pf-icon-blueprint";
@ -58,16 +57,16 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Type`, "type"), new TableColumn(msg("Type"), "type"),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Property Mapping(s)`} objectLabel=${msg("Property Mapping(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: PropertyMapping) => { .usedBy=${(item: PropertyMapping) => {
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllUsedByList({ return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllUsedByList({
@ -81,7 +80,7 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -91,8 +90,8 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
html`${item.name}`, html`${item.name}`,
html`${item.verboseName}`, html`${item.verboseName}`,
html` <ak-forms-modal> html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span> <span slot="header"> ${msg(str`Update ${item.verboseName}`)} </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
@ -106,8 +105,8 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal .closeAfterSuccessfulSubmit=${false}> <ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
<span slot="submit"> ${t`Test`} </span> <span slot="submit"> ${msg("Test")} </span>
<span slot="header"> ${t`Test Property Mapping`} </span> <span slot="header"> ${msg("Test Property Mapping")} </span>
<ak-property-mapping-test-form slot="form" .mapping=${item}> <ak-property-mapping-test-form slot="form" .mapping=${item}>
</ak-property-mapping-test-form> </ak-property-mapping-test-form>
<button slot="trigger" class="pf-c-button pf-m-plain"> <button slot="trigger" class="pf-c-button pf-m-plain">
@ -145,7 +144,7 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Hide managed mappings`}</span> <span class="pf-c-switch__label">${msg("Hide managed mappings")}</span>
</label> </label>
</div> </div>
</div> </div>

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class PropertyMappingNotification extends ModelForm<NotificationWebhookMa
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated mapping.`; return msg("Successfully updated mapping.");
} else { } else {
return t`Successfully created mapping.`; return msg("Successfully created mapping.");
} }
} }
@ -43,7 +42,7 @@ export class PropertyMappingNotification extends ModelForm<NotificationWebhookMa
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -51,16 +50,20 @@ export class PropertyMappingNotification extends ModelForm<NotificationWebhookMa
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Expression`} ?required=${true} name="expression"> <ak-form-element-horizontal
label=${msg("Expression")}
?required=${true}
name="expression"
>
<ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${msg("Expression using Python.")}
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}" href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}"
> >
${t`See documentation for a list of all variables.`} ${msg("See documentation for a list of all variables.")}
</a> </a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class PropertyMappingSAMLForm extends ModelForm<SAMLPropertyMapping, stri
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated mapping.`; return msg("Successfully updated mapping.");
} else { } else {
return t`Successfully created mapping.`; return msg("Successfully created mapping.");
} }
} }
@ -43,7 +42,7 @@ export class PropertyMappingSAMLForm extends ModelForm<SAMLPropertyMapping, stri
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -52,7 +51,7 @@ export class PropertyMappingSAMLForm extends ModelForm<SAMLPropertyMapping, stri
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`SAML Attribute Name`} label=${msg("SAML Attribute Name")}
?required=${true} ?required=${true}
name="samlName" name="samlName"
> >
@ -63,29 +62,35 @@ export class PropertyMappingSAMLForm extends ModelForm<SAMLPropertyMapping, stri
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded.`} ${msg(
"Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Friendly Name`} name="friendlyName"> <ak-form-element-horizontal label=${msg("Friendly Name")} name="friendlyName">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.friendlyName || "")}" value="${ifDefined(this.instance?.friendlyName || "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Optionally set the 'FriendlyName' value of the Assertion attribute.`} ${msg("Optionally set the 'FriendlyName' value of the Assertion attribute.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Expression`} ?required=${true} name="expression"> <ak-form-element-horizontal
label=${msg("Expression")}
?required=${true}
name="expression"
>
<ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${msg("Expression using Python.")}
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}" href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}"
> >
${t`See documentation for a list of all variables.`} ${msg("See documentation for a list of all variables.")}
</a> </a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class PropertyMappingSCIMForm extends ModelForm<SCIMMapping, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated mapping.`; return msg("Successfully updated mapping.");
} else { } else {
return t`Successfully created mapping.`; return msg("Successfully created mapping.");
} }
} }
@ -43,7 +42,7 @@ export class PropertyMappingSCIMForm extends ModelForm<SCIMMapping, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -51,16 +50,20 @@ export class PropertyMappingSCIMForm extends ModelForm<SCIMMapping, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Expression`} ?required=${true} name="expression"> <ak-form-element-horizontal
label=${msg("Expression")}
?required=${true}
name="expression"
>
<ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${msg("Expression using Python.")}
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}" href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}"
> >
${t`See documentation for a list of all variables.`} ${msg("See documentation for a list of all variables.")}
</a> </a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -4,8 +4,7 @@ import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -22,9 +21,9 @@ export class PropertyMappingScopeForm extends ModelForm<ScopeMapping, string> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated mapping.`; return msg("Successfully updated mapping.");
} else { } else {
return t`Successfully created mapping.`; return msg("Successfully created mapping.");
} }
} }
@ -43,7 +42,7 @@ export class PropertyMappingScopeForm extends ModelForm<ScopeMapping, string> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -51,7 +50,11 @@ export class PropertyMappingScopeForm extends ModelForm<ScopeMapping, string> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Scope name`} ?required=${true} name="scopeName"> <ak-form-element-horizontal
label=${msg("Scope name")}
?required=${true}
name="scopeName"
>
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.scopeName)}" value="${ifDefined(this.instance?.scopeName)}"
@ -59,29 +62,35 @@ export class PropertyMappingScopeForm extends ModelForm<ScopeMapping, string> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Scope which the client can specify to access these properties.`} ${msg("Scope which the client can specify to access these properties.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Description`} name="description"> <ak-form-element-horizontal label=${msg("Description")} name="description">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.description)}" value="${ifDefined(this.instance?.description)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Description shown to the user when consenting. If left empty, the user won't be informed.`} ${msg(
"Description shown to the user when consenting. If left empty, the user won't be informed.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Expression`} ?required=${true} name="expression"> <ak-form-element-horizontal
label=${msg("Expression")}
?required=${true}
name="expression"
>
<ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${msg("Expression using Python.")}
<a <a
target="_blank" target="_blank"
href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}" href="${docLink("/docs/property-mappings/expression?utm_source=authentik")}"
> >
${t`See documentation for a list of all variables.`} ${msg("See documentation for a list of all variables.")}
</a> </a>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -6,8 +6,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import YAML from "yaml"; import YAML from "yaml";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -34,7 +33,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
request?: PolicyTestRequest; request?: PolicyTestRequest;
getSuccessMessage(): string { getSuccessMessage(): string {
return t`Successfully sent test-request.`; return msg("Successfully sent test-request.");
} }
async send(data: PolicyTestRequest): Promise<PropertyMappingTestResult> { async send(data: PolicyTestRequest): Promise<PropertyMappingTestResult> {
@ -48,7 +47,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
} }
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html`<ak-form-element-horizontal label=${t`Result`}> return html`<ak-form-element-horizontal label=${msg("Result")}>
${this.result?.successful ${this.result?.successful
? html`<ak-codemirror ? html`<ak-codemirror
mode="javascript" mode="javascript"
@ -65,7 +64,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
} }
renderExampleButtons(): TemplateResult { renderExampleButtons(): TemplateResult {
const header = html`<p>${t`Example context data`}</p>`; const header = html`<p>${msg("Example context data")}</p>`;
switch (this.mapping?.metaModelName) { switch (this.mapping?.metaModelName) {
case "authentik_sources_ldap.ldappropertymapping": case "authentik_sources_ldap.ldappropertymapping":
return html`${header}${this.renderExampleLDAP()}`; return html`${header}${this.renderExampleLDAP()}`;
@ -95,7 +94,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
}; };
}} }}
> >
${t`Active Directory User`} ${msg("Active Directory User")}
</button> </button>
<button <button
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-secondary"
@ -114,14 +113,14 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
}; };
}} }}
> >
${t`Active Directory Group`} ${msg("Active Directory Group")}
</button> </button>
`; `;
} }
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="user"> <ak-form-element-horizontal label=${msg("User")} ?required=${true} name="user">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<User[]> => { .fetchObjects=${async (query?: string): Promise<User[]> => {
const args: CoreUsersListRequest = { const args: CoreUsersListRequest = {
@ -148,7 +147,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
> >
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Context`} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value=${YAML.stringify(first(this.request?.context, {}))} value=${YAML.stringify(first(this.request?.context, {}))}

View File

@ -10,8 +10,7 @@ import "@goauthentik/elements/wizard/FormWizardPage";
import "@goauthentik/elements/wizard/Wizard"; import "@goauthentik/elements/wizard/Wizard";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { property } from "lit/decorators.js"; import { property } from "lit/decorators.js";
@ -31,7 +30,7 @@ export class InitialPropertyMappingWizardPage extends WizardPage {
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFForm, PFButton, PFRadio]; return [PFBase, PFForm, PFButton, PFRadio];
} }
sidebarLabel = () => t`Select type`; sidebarLabel = () => msg("Select type");
activeCallback: () => Promise<void> = async () => { activeCallback: () => Promise<void> = async () => {
this.host.isValid = false; this.host.isValid = false;
@ -90,8 +89,8 @@ export class PropertyMappingWizard extends AKElement {
return html` return html`
<ak-wizard <ak-wizard
.steps=${["initial"]} .steps=${["initial"]}
header=${t`New property mapping`} header=${msg("New property mapping")}
description=${t`Create a new property mapping.`} description=${msg("Create a new property mapping.")}
> >
<ak-property-mapping-wizard-initial <ak-property-mapping-wizard-initial
slot="initial" slot="initial"
@ -102,13 +101,13 @@ export class PropertyMappingWizard extends AKElement {
return html` return html`
<ak-wizard-page-form <ak-wizard-page-form
slot=${`type-${type.component}-${type.modelName}`} slot=${`type-${type.component}-${type.modelName}`}
.sidebarLabel=${() => t`Create ${type.name}`} .sidebarLabel=${() => msg(str`Create ${type.name}`)}
> >
<ak-proxy-form type=${type.component}></ak-proxy-form> <ak-proxy-form type=${type.component}></ak-proxy-form>
</ak-wizard-page-form> </ak-wizard-page-form>
`; `;
})} })}
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-wizard> </ak-wizard>
`; `;
} }

View File

@ -15,8 +15,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage"; import { TablePage } from "@goauthentik/elements/table/TablePage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -28,10 +27,10 @@ export class ProviderListPage extends TablePage<Provider> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return t`Providers`; return msg("Providers");
} }
pageDescription(): string { pageDescription(): string {
return t`Provide support for protocols like SAML and OAuth to assigned applications.`; return msg("Provide support for protocols like SAML and OAuth to assigned applications.");
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-integration"; return "pf-icon pf-icon-integration";
@ -53,17 +52,17 @@ export class ProviderListPage extends TablePage<Provider> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(t`Name`, "name"), new TableColumn(msg("Name"), "name"),
new TableColumn(t`Application`), new TableColumn(msg("Application")),
new TableColumn(t`Type`), new TableColumn(msg("Type")),
new TableColumn(t`Actions`), new TableColumn(msg("Actions")),
]; ];
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1; const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk return html`<ak-forms-delete-bulk
objectLabel=${t`Provider(s)`} objectLabel=${msg("Provider(s)")}
.objects=${this.selectedElements} .objects=${this.selectedElements}
.usedBy=${(item: Provider) => { .usedBy=${(item: Provider) => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllUsedByList({ return new ProvidersApi(DEFAULT_CONFIG).providersAllUsedByList({
@ -77,7 +76,7 @@ export class ProviderListPage extends TablePage<Provider> {
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${msg("Delete")}
</button> </button>
</ak-forms-delete-bulk>`; </ak-forms-delete-bulk>`;
} }
@ -85,20 +84,21 @@ export class ProviderListPage extends TablePage<Provider> {
rowApp(item: Provider): TemplateResult { rowApp(item: Provider): TemplateResult {
if (item.assignedApplicationName) { if (item.assignedApplicationName) {
return html`<i class="pf-icon pf-icon-ok pf-m-success"></i> return html`<i class="pf-icon pf-icon-ok pf-m-success"></i>
${t`Assigned to application `} ${msg("Assigned to application ")}
<a href="#/core/applications/${item.assignedApplicationSlug}" <a href="#/core/applications/${item.assignedApplicationSlug}"
>${item.assignedApplicationName}</a >${item.assignedApplicationName}</a
>`; >`;
} }
if (item.assignedBackchannelApplicationName) { if (item.assignedBackchannelApplicationName) {
return html`<i class="pf-icon pf-icon-ok pf-m-success"></i> return html`<i class="pf-icon pf-icon-ok pf-m-success"></i>
${t`Assigned to application (backchannel) `} ${msg("Assigned to application (backchannel) ")}
<a href="#/core/applications/${item.assignedBackchannelApplicationSlug}" <a href="#/core/applications/${item.assignedBackchannelApplicationSlug}"
>${item.assignedBackchannelApplicationName}</a >${item.assignedBackchannelApplicationName}</a
>`; >`;
} }
return html`<i class="pf-icon pf-icon-warning-triangle pf-m-warning"></i> return html`<i class="pf-icon pf-icon-warning-triangle pf-m-warning"></i> ${msg(
${t`Warning: Provider not assigned to any application.`}`; "Warning: Provider not assigned to any application.",
)}`;
} }
row(item: Provider): TemplateResult[] { row(item: Provider): TemplateResult[] {
@ -107,8 +107,8 @@ export class ProviderListPage extends TablePage<Provider> {
this.rowApp(item), this.rowApp(item),
html`${item.verboseName}`, html`${item.verboseName}`,
html`<ak-forms-modal> html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span> <span slot="header"> ${msg(str`Update ${item.verboseName}`)} </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{

View File

@ -11,8 +11,7 @@ import "@goauthentik/elements/wizard/FormWizardPage";
import "@goauthentik/elements/wizard/Wizard"; import "@goauthentik/elements/wizard/Wizard";
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { t } from "@lingui/macro"; import { msg, str } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { property } from "lit/decorators.js"; import { property } from "lit/decorators.js";
@ -33,7 +32,7 @@ export class InitialProviderWizardPage extends WizardPage {
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFForm, PFHint, PFButton, PFRadio]; return [PFBase, PFForm, PFHint, PFButton, PFRadio];
} }
sidebarLabel = () => t`Select type`; sidebarLabel = () => msg("Select type");
activeCallback: () => Promise<void> = async () => { activeCallback: () => Promise<void> = async () => {
this.host.isValid = false; this.host.isValid = false;
@ -48,9 +47,11 @@ export class InitialProviderWizardPage extends WizardPage {
renderHint(): TemplateResult { renderHint(): TemplateResult {
return html`<div class="pf-c-hint"> return html`<div class="pf-c-hint">
<div class="pf-c-hint__title">${t`Try the new application wizard`}</div> <div class="pf-c-hint__title">${msg("Try the new application wizard")}</div>
<div class="pf-c-hint__body"> <div class="pf-c-hint__body">
${t`The new application wizard greatly simplifies the steps required to create applications and providers.`} ${msg(
"The new application wizard greatly simplifies the steps required to create applications and providers.",
)}
</div> </div>
<div class="pf-c-hint__footer"> <div class="pf-c-hint__footer">
<a <a
@ -58,7 +59,7 @@ export class InitialProviderWizardPage extends WizardPage {
href=${paramURL("/core/applications", { href=${paramURL("/core/applications", {
createForm: true, createForm: true,
})} })}
>${t`Try it now`}</a >${msg("Try it now")}</a
> >
</div> </div>
</div> </div>
@ -94,7 +95,7 @@ export class ProviderWizard extends AKElement {
} }
@property() @property()
createText = t`Create`; createText = msg("Create");
@property({ attribute: false }) @property({ attribute: false })
providerTypes: TypeCreate[] = []; providerTypes: TypeCreate[] = [];
@ -114,8 +115,8 @@ export class ProviderWizard extends AKElement {
return html` return html`
<ak-wizard <ak-wizard
.steps=${["initial"]} .steps=${["initial"]}
header=${t`New provider`} header=${msg("New provider")}
description=${t`Create a new provider.`} description=${msg("Create a new provider.")}
.finalHandler=${() => { .finalHandler=${() => {
return this.finalHandler(); return this.finalHandler();
}} }}
@ -126,7 +127,7 @@ export class ProviderWizard extends AKElement {
return html` return html`
<ak-wizard-page-form <ak-wizard-page-form
slot=${`type-${type.component}`} slot=${`type-${type.component}`}
.sidebarLabel=${() => t`Create ${type.name}`} .sidebarLabel=${() => msg(str`Create ${type.name}`)}
> >
<ak-proxy-form type=${type.component}></ak-proxy-form> <ak-proxy-form type=${type.component}></ak-proxy-form>
</ak-wizard-page-form> </ak-wizard-page-form>

View File

@ -3,8 +3,7 @@ import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/Spinner";
import "@goauthentik/elements/forms/ModalForm"; import "@goauthentik/elements/forms/ModalForm";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -29,10 +28,10 @@ export class RelatedApplicationButton extends AKElement {
</a>`; </a>`;
} }
return html`<ak-forms-modal> return html`<ak-forms-modal>
<span slot="submit"> ${t`Create`} </span> <span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${t`Create Application`} </span> <span slot="header"> ${msg("Create Application")} </span>
<ak-application-form slot="form" .provider=${this.provider?.pk}> </ak-application-form> <ak-application-form slot="form" .provider=${this.provider?.pk}> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button> <button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal>`; </ak-forms-modal>`;
} }
} }

View File

@ -8,8 +8,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js"; import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -40,9 +39,9 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated provider.`; return msg("Successfully updated provider.");
} else { } else {
return t`Successfully created provider.`; return msg("Successfully created provider.");
} }
} }
@ -62,7 +61,7 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -71,7 +70,7 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Bind flow`} label=${msg("Bind flow")}
?required=${true} ?required=${true}
name="authorizationFlow" name="authorizationFlow"
> >
@ -105,9 +104,9 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
}} }}
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text">${t`Flow used for users to authenticate.`}</p> <p class="pf-c-form__helper-text">${msg("Flow used for users to authenticate.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Search group`} name="searchGroup"> <ak-form-element-horizontal label=${msg("Search group")} name="searchGroup">
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Group[]> => { .fetchObjects=${async (query?: string): Promise<Group[]> => {
const args: CoreGroupsListRequest = { const args: CoreGroupsListRequest = {
@ -132,57 +131,71 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed.`} ${msg(
"Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Bind mode`} name="bindMode"> <ak-form-element-horizontal label=${msg("Bind mode")} name="bindMode">
<ak-radio <ak-radio
.options=${[ .options=${[
{ {
label: t`Cached binding`, label: msg("Cached binding"),
value: LDAPAPIAccessMode.Cached, value: LDAPAPIAccessMode.Cached,
default: true, default: true,
description: html`${t`Flow is executed and session is cached in memory. Flow is executed when session expires`}`, description: html`${msg(
"Flow is executed and session is cached in memory. Flow is executed when session expires",
)}`,
}, },
{ {
label: t`Direct binding`, label: msg("Direct binding"),
value: LDAPAPIAccessMode.Direct, value: LDAPAPIAccessMode.Direct,
description: html`${t`Always execute the configured bind flow to authenticate the user`}`, description: html`${msg(
"Always execute the configured bind flow to authenticate the user",
)}`,
}, },
]} ]}
.value=${this.instance?.bindMode} .value=${this.instance?.bindMode}
> >
</ak-radio> </ak-radio>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how the outpost authenticates requests.`} ${msg("Configure how the outpost authenticates requests.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Search mode`} name="searchMode"> <ak-form-element-horizontal label=${msg("Search mode")} name="searchMode">
<ak-radio <ak-radio
.options=${[ .options=${[
{ {
label: t`Cached querying`, label: msg("Cached querying"),
value: LDAPAPIAccessMode.Cached, value: LDAPAPIAccessMode.Cached,
default: true, default: true,
description: html`${t`The outpost holds all users and groups in-memory and will refresh every 5 Minutes`}`, description: html`${msg(
"The outpost holds all users and groups in-memory and will refresh every 5 Minutes",
)}`,
}, },
{ {
label: t`Direct querying`, label: msg("Direct querying"),
value: LDAPAPIAccessMode.Direct, value: LDAPAPIAccessMode.Direct,
description: html`${t`Always returns the latest data, but slower than cached querying`}`, description: html`${msg(
"Always returns the latest data, but slower than cached querying",
)}`,
}, },
]} ]}
.value=${this.instance?.searchMode} .value=${this.instance?.searchMode}
> >
</ak-radio> </ak-radio>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how the outpost queries the core authentik server's users.`} ${msg("Configure how the outpost queries the core authentik server's users.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Protocol settings`} </span> <span slot="header"> ${msg("Protocol settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Base DN`} ?required=${true} name="baseDn"> <ak-form-element-horizontal
label=${msg("Base DN")}
?required=${true}
name="baseDn"
>
<input <input
type="text" type="text"
value="${first(this.instance?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}" value="${first(this.instance?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}"
@ -190,10 +203,12 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`LDAP DN under which bind requests and search requests can be made.`} ${msg(
"LDAP DN under which bind requests and search requests can be made.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Certificate`} name="certificate"> <ak-form-element-horizontal label=${msg("Certificate")} name="certificate">
<ak-search-select <ak-search-select
.fetchObjects=${async ( .fetchObjects=${async (
query?: string, query?: string,
@ -224,14 +239,18 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Due to protocol limitations, this certificate is only used when the outpost has a single provider, or all providers use the same certificate.`} ${msg(
"Due to protocol limitations, this certificate is only used when the outpost has a single provider, or all providers use the same certificate.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If multiple providers share an outpost, a self-signed certificate is used.`} ${msg(
"If multiple providers share an outpost, a self-signed certificate is used.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`UID start number`} label=${msg("UID start number")}
?required=${true} ?required=${true}
name="uidStartNumber" name="uidStartNumber"
> >
@ -242,11 +261,13 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber`} ${msg(
"The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`GID start number`} label=${msg("GID start number")}
?required=${true} ?required=${true}
name="gidStartNumber" name="gidStartNumber"
> >
@ -257,7 +278,9 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber`} ${msg(
"The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -10,8 +10,7 @@ import "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/ObjectChangelog"; import "@goauthentik/elements/events/ObjectChangelog";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -84,12 +83,12 @@ export class LDAPProviderViewPage extends AKElement {
return html``; return html``;
} }
return html` <ak-tabs> return html` <ak-tabs>
<section slot="page-overview" data-tab-title="${t`Overview`}"> <section slot="page-overview" data-tab-title="${msg("Overview")}">
${this.renderTabOverview()} ${this.renderTabOverview()}
</section> </section>
<section <section
slot="page-changelog" slot="page-changelog"
data-tab-title="${t`Changelog`}" data-tab-title="${msg("Changelog")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">
@ -113,7 +112,7 @@ export class LDAPProviderViewPage extends AKElement {
${ ${
this.provider?.outpostSet.length < 1 this.provider?.outpostSet.length < 1
? html`<div slot="header" class="pf-c-banner pf-m-warning"> ? html`<div slot="header" class="pf-c-banner pf-m-warning">
${t`Warning: Provider is not used by any Outpost.`} ${msg("Warning: Provider is not used by any Outpost.")}
</div>` </div>`
: html`` : html``
} }
@ -123,7 +122,7 @@ export class LDAPProviderViewPage extends AKElement {
<dl class="pf-c-description-list pf-m-3-col-on-lg"> <dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span> <span class="pf-c-description-list__text">${msg("Name")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -134,7 +133,7 @@ export class LDAPProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Assigned to application`}</span >${msg("Assigned to application")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -148,7 +147,7 @@ export class LDAPProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Base DN`}</span >${msg("Base DN")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -161,32 +160,32 @@ export class LDAPProviderViewPage extends AKElement {
</div> </div>
<div class="pf-c-card__footer"> <div class="pf-c-card__footer">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update LDAP Provider`} </span> <span slot="header"> ${msg("Update LDAP Provider")} </span>
<ak-provider-ldap-form slot="form" .instancePk=${this.provider.pk}> <ak-provider-ldap-form slot="form" .instancePk=${this.provider.pk}>
</ak-provider-ldap-form> </ak-provider-ldap-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${msg("Edit")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col"> <div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__title"> <div class="pf-c-card__title">
${t`How to connect`} ${msg("How to connect")}
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<p> <p>
${t`Connect to the LDAP Server on port 389:`} ${msg("Connect to the LDAP Server on port 389:")}
</p> </p>
<ul class="pf-c-list"> <ul class="pf-c-list">
<li>${t`Check the IP of the Kubernetes service, or`}</li> <li>${msg("Check the IP of the Kubernetes service, or")}</li>
<li>${t`The Host IP of the docker host`}</li> <li>${msg("The Host IP of the docker host")}</li>
</ul> </ul>
<form class="pf-c-form"> <form class="pf-c-form">
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Bind DN`}</span> <span class="pf-c-form__label-text">${msg("Bind DN")}</span>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
@ -199,7 +198,9 @@ export class LDAPProviderViewPage extends AKElement {
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Bind Password`}</span> <span class="pf-c-form__label-text">${msg(
"Bind Password",
)}</span>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
@ -210,7 +211,7 @@ export class LDAPProviderViewPage extends AKElement {
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Search base`}</span> <span class="pf-c-form__label-text">${msg("Search base")}</span>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"

View File

@ -8,8 +8,7 @@ import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import "@goauthentik/elements/utils/TimeDeltaHelp"; import "@goauthentik/elements/utils/TimeDeltaHelp";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -63,9 +62,9 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated provider.`; return msg("Successfully updated provider.");
} else { } else {
return t`Successfully created provider.`; return msg("Successfully created provider.");
} }
} }
@ -84,7 +83,7 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -92,7 +91,10 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
required required
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Authentication flow`} name="authenticationFlow"> <ak-form-element-horizontal
label=${msg("Authentication flow")}
name="authenticationFlow"
>
<ak-search-select <ak-search-select
.fetchObjects=${async (query?: string): Promise<Flow[]> => { .fetchObjects=${async (query?: string): Promise<Flow[]> => {
const args: FlowsInstancesListRequest = { const args: FlowsInstancesListRequest = {
@ -120,11 +122,11 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Flow used when a user access this provider and is not authenticated.`} ${msg("Flow used when a user access this provider and is not authenticated.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authorization flow`} label=${msg("Authorization flow")}
?required=${true} ?required=${true}
name="authorizationFlow" name="authorizationFlow"
> >
@ -155,15 +157,15 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`} ${msg("Flow used when authorizing this provider.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> ${t`Protocol settings`} </span> <span slot="header"> ${msg("Protocol settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Client type`} label=${msg("Client type")}
?required=${true} ?required=${true}
name="clientType" name="clientType"
> >
@ -177,15 +179,19 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
}} }}
.options=${[ .options=${[
{ {
label: t`Confidential`, label: msg("Confidential"),
value: ClientTypeEnum.Confidential, value: ClientTypeEnum.Confidential,
default: true, default: true,
description: html`${t`Confidential clients are capable of maintaining the confidentiality of their credentials such as client secrets`}`, description: html`${msg(
"Confidential clients are capable of maintaining the confidentiality of their credentials such as client secrets",
)}`,
}, },
{ {
label: t`Public`, label: msg("Public"),
value: ClientTypeEnum.Public, value: ClientTypeEnum.Public,
description: html`${t`Public clients are incapable of maintaining the confidentiality and should use methods like PKCE. `}`, description: html`${msg(
"Public clients are incapable of maintaining the confidentiality and should use methods like PKCE. ",
)}`,
}, },
]} ]}
.value=${this.instance?.clientType} .value=${this.instance?.clientType}
@ -193,7 +199,7 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
</ak-radio> </ak-radio>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Client ID`} label=${msg("Client ID")}
?required=${true} ?required=${true}
name="clientId" name="clientId"
> >
@ -209,7 +215,7 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
?hidden=${!this.showClientSecret} ?hidden=${!this.showClientSecret}
label=${t`Client Secret`} label=${msg("Client Secret")}
name="clientSecret" name="clientSecret"
> >
<input <input
@ -222,23 +228,29 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Redirect URIs/Origins (RegEx)`} label=${msg("Redirect URIs/Origins (RegEx)")}
name="redirectUris" name="redirectUris"
> >
<textarea class="pf-c-form-control"> <textarea class="pf-c-form-control">
${this.instance?.redirectUris}</textarea ${this.instance?.redirectUris}</textarea
> >
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.`} ${msg(
"Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved.`} ${msg(
"If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.`} ${msg(
'To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.',
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Signing Key`} name="signingKey"> <ak-form-element-horizontal label=${msg("Signing Key")} name="signingKey">
<ak-search-select <ak-search-select
.fetchObjects=${async ( .fetchObjects=${async (
query?: string, query?: string,
@ -275,16 +287,16 @@ ${this.instance?.redirectUris}</textarea
?blankable=${true} ?blankable=${true}
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text">${t`Key used to sign the tokens.`}</p> <p class="pf-c-form__helper-text">${msg("Key used to sign the tokens.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>
<ak-form-group> <ak-form-group>
<span slot="header"> ${t`Advanced protocol settings`} </span> <span slot="header"> ${msg("Advanced protocol settings")} </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Access code validity`} label=${msg("Access code validity")}
?required=${true} ?required=${true}
name="accessCodeValidity" name="accessCodeValidity"
> >
@ -295,12 +307,12 @@ ${this.instance?.redirectUris}</textarea
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how long access codes are valid for.`} ${msg("Configure how long access codes are valid for.")}
</p> </p>
<ak-utils-time-delta-help></ak-utils-time-delta-help> <ak-utils-time-delta-help></ak-utils-time-delta-help>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Access Token validity`} label=${msg("Access Token validity")}
?required=${true} ?required=${true}
name="accessTokenValidity" name="accessTokenValidity"
> >
@ -311,12 +323,12 @@ ${this.instance?.redirectUris}</textarea
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how long access tokens are valid for.`} ${msg("Configure how long access tokens are valid for.")}
</p> </p>
<ak-utils-time-delta-help></ak-utils-time-delta-help> <ak-utils-time-delta-help></ak-utils-time-delta-help>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Refresh Token validity`} label=${msg("Refresh Token validity")}
?required=${true} ?required=${true}
name="refreshTokenValidity" name="refreshTokenValidity"
> >
@ -327,11 +339,11 @@ ${this.instance?.redirectUris}</textarea
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how long refresh tokens are valid for.`} ${msg("Configure how long refresh tokens are valid for.")}
</p> </p>
<ak-utils-time-delta-help></ak-utils-time-delta-help> <ak-utils-time-delta-help></ak-utils-time-delta-help>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Scopes`} name="propertyMappings"> <ak-form-element-horizontal label=${msg("Scopes")} name="propertyMappings">
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
${this.propertyMappings?.results.map((scope) => { ${this.propertyMappings?.results.map((scope) => {
let selected = false; let selected = false;
@ -356,52 +368,60 @@ ${this.instance?.redirectUris}</textarea
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Select which scopes can be used by the client. The client still has to specify the scope to access the data.`} ${msg(
"Select which scopes can be used by the client. The client still has to specify the scope to access the data.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`} ${msg("Hold control/command to select multiple items.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Subject mode`} label=${msg("Subject mode")}
?required=${true} ?required=${true}
name="subMode" name="subMode"
> >
<ak-radio <ak-radio
.options=${[ .options=${[
{ {
label: t`Based on the User's hashed ID`, label: msg("Based on the User's hashed ID"),
value: SubModeEnum.HashedUserId, value: SubModeEnum.HashedUserId,
default: true, default: true,
}, },
{ {
label: t`Based on the User's ID`, label: msg("Based on the User's ID"),
value: SubModeEnum.UserId, value: SubModeEnum.UserId,
}, },
{ {
label: t`Based on the User's UUID`, label: msg("Based on the User's UUID"),
value: SubModeEnum.UserUuid, value: SubModeEnum.UserUuid,
}, },
{ {
label: t`Based on the User's username`, label: msg("Based on the User's username"),
value: SubModeEnum.UserUsername, value: SubModeEnum.UserUsername,
}, },
{ {
label: t`Based on the User's Email`, label: msg("Based on the User's Email"),
value: SubModeEnum.UserEmail, value: SubModeEnum.UserEmail,
description: html`${t`This is recommended over the UPN mode.`}`, description: html`${msg(
"This is recommended over the UPN mode.",
)}`,
}, },
{ {
label: t`Based on the User's UPN`, label: msg("Based on the User's UPN"),
value: SubModeEnum.UserUpn, value: SubModeEnum.UserUpn,
description: html`${t`Requires the user to have a 'upn' attribute set, and falls back to hashed user ID. Use this mode only if you have different UPN and Mail domains.`}`, description: html`${msg(
"Requires the user to have a 'upn' attribute set, and falls back to hashed user ID. Use this mode only if you have different UPN and Mail domains.",
)}`,
}, },
]} ]}
.value=${this.instance?.subMode} .value=${this.instance?.subMode}
> >
</ak-radio> </ak-radio>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure what data should be used as unique User Identifier. For most cases, the default should be fine.`} ${msg(
"Configure what data should be used as unique User Identifier. For most cases, the default should be fine.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="includeClaimsInIdToken"> <ak-form-element-horizontal name="includeClaimsInIdToken">
@ -416,26 +436,32 @@ ${this.instance?.redirectUris}</textarea
<i class="fas fa-check" aria-hidden="true"></i> <i class="fas fa-check" aria-hidden="true"></i>
</span> </span>
</span> </span>
<span class="pf-c-switch__label">${t`Include claims in id_token`}</span> <span class="pf-c-switch__label"
>${msg("Include claims in id_token")}</span
>
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.`} ${msg(
"Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Issuer mode`} label=${msg("Issuer mode")}
?required=${true} ?required=${true}
name="issuerMode" name="issuerMode"
> >
<ak-radio <ak-radio
.options=${[ .options=${[
{ {
label: t`Each provider has a different issuer, based on the application slug`, label: msg(
"Each provider has a different issuer, based on the application slug",
),
value: IssuerModeEnum.PerProvider, value: IssuerModeEnum.PerProvider,
default: true, default: true,
}, },
{ {
label: t`Same identifier is used for all providers`, label: msg("Same identifier is used for all providers"),
value: IssuerModeEnum.Global, value: IssuerModeEnum.Global,
}, },
]} ]}
@ -443,16 +469,21 @@ ${this.instance?.redirectUris}</textarea
> >
</ak-radio> </ak-radio>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Configure how the issuer field of the ID Token should be filled.`} ${msg(
"Configure how the issuer field of the ID Token should be filled.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>
<ak-form-group> <ak-form-group>
<span slot="header">${t`Machine-to-Machine authentication settings`}</span> <span slot="header">${msg("Machine-to-Machine authentication settings")}</span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Trusted OIDC Sources`} name="jwksSources"> <ak-form-element-horizontal
label=${msg("Trusted OIDC Sources")}
name="jwksSources"
>
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
${this.oauthSources?.results.map((source) => { ${this.oauthSources?.results.map((source) => {
const selected = (this.instance?.jwksSources || []).some((su) => { const selected = (this.instance?.jwksSources || []).some((su) => {
@ -464,10 +495,12 @@ ${this.instance?.redirectUris}</textarea
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.`} ${msg(
"JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`} ${msg("Hold control/command to select multiple items.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -13,8 +13,7 @@ import "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/ObjectChangelog"; import "@goauthentik/elements/events/ObjectChangelog";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
@ -88,7 +87,7 @@ export class OAuth2ProviderViewPage extends AKElement {
return html` <ak-tabs> return html` <ak-tabs>
<section <section
slot="page-overview" slot="page-overview"
data-tab-title="${t`Overview`}" data-tab-title="${msg("Overview")}"
@activate=${() => { @activate=${() => {
new ProvidersApi(DEFAULT_CONFIG) new ProvidersApi(DEFAULT_CONFIG)
.providersOauth2SetupUrlsRetrieve({ .providersOauth2SetupUrlsRetrieve({
@ -103,7 +102,7 @@ export class OAuth2ProviderViewPage extends AKElement {
</section> </section>
<section <section
slot="page-preview" slot="page-preview"
data-tab-title="${t`Preview`}" data-tab-title="${msg("Preview")}"
@activate=${() => { @activate=${() => {
new ProvidersApi(DEFAULT_CONFIG) new ProvidersApi(DEFAULT_CONFIG)
.providersOauth2PreviewUserRetrieve({ .providersOauth2PreviewUserRetrieve({
@ -116,7 +115,7 @@ export class OAuth2ProviderViewPage extends AKElement {
</section> </section>
<section <section
slot="page-changelog" slot="page-changelog"
data-tab-title="${t`Changelog`}" data-tab-title="${msg("Changelog")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">
@ -139,7 +138,7 @@ export class OAuth2ProviderViewPage extends AKElement {
return html` ${this.provider?.assignedApplicationName return html` ${this.provider?.assignedApplicationName
? html`` ? html``
: html`<div slot="header" class="pf-c-banner pf-m-warning"> : html`<div slot="header" class="pf-c-banner pf-m-warning">
${t`Warning: Provider is not used by an Application.`} ${msg("Warning: Provider is not used by an Application.")}
</div>`} </div>`}
<div class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter"> <div class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter">
<div <div
@ -149,7 +148,7 @@ export class OAuth2ProviderViewPage extends AKElement {
<dl class="pf-c-description-list"> <dl class="pf-c-description-list">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span> <span class="pf-c-description-list__text">${msg("Name")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -160,7 +159,7 @@ export class OAuth2ProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Assigned to application`}</span >${msg("Assigned to application")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -173,7 +172,7 @@ export class OAuth2ProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Client type`}</span >${msg("Client type")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -184,7 +183,9 @@ export class OAuth2ProviderViewPage extends AKElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Client ID`}</span> <span class="pf-c-description-list__text"
>${msg("Client ID")}</span
>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -195,7 +196,7 @@ export class OAuth2ProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Redirect URIs`}</span >${msg("Redirect URIs")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -208,15 +209,15 @@ export class OAuth2ProviderViewPage extends AKElement {
</div> </div>
<div class="pf-c-card__footer"> <div class="pf-c-card__footer">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update OAuth2 Provider`} </span> <span slot="header"> ${msg("Update OAuth2 Provider")} </span>
<ak-provider-oauth2-form <ak-provider-oauth2-form
slot="form" slot="form"
.instancePk=${this.provider.pk || 0} .instancePk=${this.provider.pk || 0}
> >
</ak-provider-oauth2-form> </ak-provider-oauth2-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${msg("Edit")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -227,83 +228,87 @@ export class OAuth2ProviderViewPage extends AKElement {
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text" <span class="pf-c-form__label-text"
>${t`OpenID Configuration URL`}</span >${msg("OpenID Configuration URL")}</span
> >
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.providerInfo || t`-`}" value="${this.providerUrls?.providerInfo || msg("-")}"
/> />
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text" <span class="pf-c-form__label-text"
>${t`OpenID Configuration Issuer`}</span >${msg("OpenID Configuration Issuer")}</span
> >
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.issuer || t`-`}" value="${this.providerUrls?.issuer || msg("-")}"
/> />
</div> </div>
<hr /> <hr />
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Authorize URL`}</span> <span class="pf-c-form__label-text"
>${msg("Authorize URL")}</span
>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.authorize || t`-`}" value="${this.providerUrls?.authorize || msg("-")}"
/> />
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Token URL`}</span> <span class="pf-c-form__label-text">${msg("Token URL")}</span>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.token || t`-`}" value="${this.providerUrls?.token || msg("-")}"
/> />
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Userinfo URL`}</span> <span class="pf-c-form__label-text"
>${msg("Userinfo URL")}</span
>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.userInfo || t`-`}" value="${this.providerUrls?.userInfo || msg("-")}"
/> />
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`Logout URL`}</span> <span class="pf-c-form__label-text">${msg("Logout URL")}</span>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.logout || t`-`}" value="${this.providerUrls?.logout || msg("-")}"
/> />
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label"> <label class="pf-c-form__label">
<span class="pf-c-form__label-text">${t`JWKS URL`}</span> <span class="pf-c-form__label-text">${msg("JWKS URL")}</span>
</label> </label>
<input <input
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value="${this.providerUrls?.jwks || t`-`}" value="${this.providerUrls?.jwks || msg("-")}"
/> />
</div> </div>
</form> </form>
@ -341,7 +346,7 @@ export class OAuth2ProviderViewPage extends AKElement {
> >
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__title"> <div class="pf-c-card__title">
${t`Example JWT payload (for currently authenticated user)`} ${msg("Example JWT payload (for currently authenticated user)")}
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.preview ${this.preview

View File

@ -7,8 +7,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import "@goauthentik/elements/utils/TimeDeltaHelp"; import "@goauthentik/elements/utils/TimeDeltaHelp";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, css } from "lit"; import { CSSResult, css } from "lit";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
@ -84,9 +83,9 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.instance) { if (this.instance) {
return t`Successfully updated provider.`; return msg("Successfully updated provider.");
} else { } else {
return t`Successfully created provider.`; return msg("Successfully created provider.");
} }
} }
@ -109,7 +108,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
renderHttpBasic(): TemplateResult { renderHttpBasic(): TemplateResult {
return html`<ak-form-element-horizontal return html`<ak-form-element-horizontal
label=${t`HTTP-Basic Username Key`} label=${msg("HTTP-Basic Username Key")}
name="basicAuthUserAttribute" name="basicAuthUserAttribute"
> >
<input <input
@ -118,11 +117,13 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used.`} ${msg(
"User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`HTTP-Basic Password Key`} label=${msg("HTTP-Basic Password Key")}
name="basicAuthPasswordAttribute" name="basicAuthPasswordAttribute"
> >
<input <input
@ -131,7 +132,9 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`User/Group Attribute used for the password part of the HTTP-Basic Header.`} ${msg(
"User/Group Attribute used for the password part of the HTTP-Basic Header.",
)}
</p> </p>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>`;
} }
@ -147,7 +150,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
this.mode = ProxyMode.Proxy; this.mode = ProxyMode.Proxy;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`Proxy`}</span> <span class="pf-c-toggle-group__text">${msg("Proxy")}</span>
</button> </button>
</div> </div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div> <div class="pf-c-divider pf-m-vertical" role="separator"></div>
@ -162,7 +165,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
}} }}
> >
<span class="pf-c-toggle-group__text" <span class="pf-c-toggle-group__text"
>${t`Forward auth (single application)`}</span >${msg("Forward auth (single application)")}</span
> >
</button> </button>
</div> </div>
@ -177,7 +180,9 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
this.mode = ProxyMode.ForwardDomain; this.mode = ProxyMode.ForwardDomain;
}} }}
> >
<span class="pf-c-toggle-group__text">${t`Forward auth (domain level)`}</span> <span class="pf-c-toggle-group__text"
>${msg("Forward auth (domain level)")}</span
>
</button> </button>
</div>`; </div>`;
} }
@ -186,10 +191,12 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
switch (this.mode) { switch (this.mode) {
case ProxyMode.Proxy: case ProxyMode.Proxy:
return html`<p class="pf-u-mb-xl"> return html`<p class="pf-u-mb-xl">
${t`This provider will behave like a transparent reverse-proxy, except requests must be authenticated. If your upstream application uses HTTPS, make sure to connect to the outpost using HTTPS as well.`} ${msg(
"This provider will behave like a transparent reverse-proxy, except requests must be authenticated. If your upstream application uses HTTPS, make sure to connect to the outpost using HTTPS as well.",
)}
</p> </p>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`External host`} label=${msg("External host")}
?required=${true} ?required=${true}
name="externalHost" name="externalHost"
> >
@ -200,11 +207,13 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`The external URL you'll access the application at. Include any non-standard port.`} ${msg(
"The external URL you'll access the application at. Include any non-standard port.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Internal host`} label=${msg("Internal host")}
?required=${true} ?required=${true}
name="internalHost" name="internalHost"
> >
@ -215,7 +224,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Upstream host that the requests are forwarded to.`} ${msg("Upstream host that the requests are forwarded to.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="internalHostSslValidation"> <ak-form-element-horizontal name="internalHostSslValidation">
@ -231,19 +240,21 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
</span> </span>
</span> </span>
<span class="pf-c-switch__label" <span class="pf-c-switch__label"
>${t`Internal host SSL Validation`}</span >${msg("Internal host SSL Validation")}</span
> >
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Validate SSL Certificates of upstream servers.`} ${msg("Validate SSL Certificates of upstream servers.")}
</p> </p>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>`;
case ProxyMode.ForwardSingle: case ProxyMode.ForwardSingle:
return html`<p class="pf-u-mb-xl"> return html`<p class="pf-u-mb-xl">
${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you).`} ${msg(
"Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you).",
)}
</p> </p>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`External host`} label=${msg("External host")}
?required=${true} ?required=${true}
name="externalHost" name="externalHost"
> >
@ -254,23 +265,29 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`The external URL you'll access the application at. Include any non-standard port.`} ${msg(
"The external URL you'll access the application at. Include any non-standard port.",
)}
</p> </p>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>`;
case ProxyMode.ForwardDomain: case ProxyMode.ForwardDomain:
return html`<p class="pf-u-mb-xl"> return html`<p class="pf-u-mb-xl">
${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application.`} ${msg(
"Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application.",
)}
</p> </p>
<div class="pf-u-mb-xl"> <div class="pf-u-mb-xl">
${t`An example setup can look like this:`} ${msg("An example setup can look like this:")}
<ul class="pf-c-list"> <ul class="pf-c-list">
<li>${t`authentik running on auth.example.com`}</li> <li>${msg("authentik running on auth.example.com")}</li>
<li>${t`app1 running on app1.example.com`}</li> <li>${msg("app1 running on app1.example.com")}</li>
</ul> </ul>
${t`In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com.`} ${msg(
"In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com.",
)}
</div> </div>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authentication URL`} label=${msg("Authentication URL")}
?required=${true} ?required=${true}
name="externalHost" name="externalHost"
> >
@ -281,11 +298,13 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`The external URL you'll authenticate at. The authentik core server should be reachable under this URL.`} ${msg(
"The external URL you'll authenticate at. The authentik core server should be reachable under this URL.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Cookie domain`} label=${msg("Cookie domain")}
name="cookieDomain" name="cookieDomain"
?required=${true} ?required=${true}
> >
@ -296,17 +315,19 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
required required
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.`} ${msg(
"Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.",
)}
</p> </p>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>`;
case ProxyMode.UnknownDefaultOpenApi: case ProxyMode.UnknownDefaultOpenApi:
return html`<p>${t`Unknown proxy mode`}</p>`; return html`<p>${msg("Unknown proxy mode")}</p>`;
} }
} }
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${ifDefined(this.instance?.name)}" value="${ifDefined(this.instance?.name)}"
@ -315,7 +336,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authentication flow`} label=${msg("Authentication flow")}
?required=${false} ?required=${false}
name="authenticationFlow" name="authenticationFlow"
> >
@ -346,11 +367,11 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Flow used when a user access this provider and is not authenticated.`} ${msg("Flow used when a user access this provider and is not authenticated.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authorization flow`} label=${msg("Authorization flow")}
?required=${true} ?required=${true}
name="authorizationFlow" name="authorizationFlow"
> >
@ -381,7 +402,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
> >
</ak-search-select> </ak-search-select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`} ${msg("Flow used when authorizing this provider.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -391,20 +412,22 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
</div> </div>
<div class="pf-c-card__footer">${this.renderSettings()}</div> <div class="pf-c-card__footer">${this.renderSettings()}</div>
</div> </div>
<ak-form-element-horizontal label=${t`Token validity`} name="accessTokenValidity"> <ak-form-element-horizontal label=${msg("Token validity")} name="accessTokenValidity">
<input <input
type="text" type="text"
value="${first(this.instance?.accessTokenValidity, "hours=24")}" value="${first(this.instance?.accessTokenValidity, "hours=24")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${t`Configure how long tokens are valid for.`}</p> <p class="pf-c-form__helper-text">
${msg("Configure how long tokens are valid for.")}
</p>
<ak-utils-time-delta-help></ak-utils-time-delta-help> <ak-utils-time-delta-help></ak-utils-time-delta-help>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group> <ak-form-group>
<span slot="header">${t`Advanced protocol settings`}</span> <span slot="header">${msg("Advanced protocol settings")}</span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Certificate`} name="certificate"> <ak-form-element-horizontal label=${msg("Certificate")} name="certificate">
<ak-search-select <ak-search-select
.fetchObjects=${async ( .fetchObjects=${async (
query?: string, query?: string,
@ -436,7 +459,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Additional scopes`} label=${msg("Additional scopes")}
name="propertyMappings" name="propertyMappings"
> >
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
@ -459,33 +482,37 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Additional scope mappings, which are passed to the proxy.`} ${msg("Additional scope mappings, which are passed to the proxy.")}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`} ${msg("Hold control/command to select multiple items.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label="${this.mode === ProxyMode.ForwardDomain label="${this.mode === ProxyMode.ForwardDomain
? t`Unauthenticated URLs` ? msg("Unauthenticated URLs")
: t`Unauthenticated Paths`}" : msg("Unauthenticated Paths")}"
name="skipPathRegex" name="skipPathRegex"
> >
<textarea class="pf-c-form-control"> <textarea class="pf-c-form-control">
${this.instance?.skipPathRegex}</textarea ${this.instance?.skipPathRegex}</textarea
> >
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Regular expressions for which authentication is not required. Each new line is interpreted as a new expression.`} ${msg(
"Regular expressions for which authentication is not required. Each new line is interpreted as a new expression.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When using proxy or forward auth (single application) mode, the requested URL Path is checked against the regular expressions. When using forward auth (domain mode), the full requested URL including scheme and host is matched against the regular expressions.`} ${msg(
"When using proxy or forward auth (single application) mode, the requested URL Path is checked against the regular expressions. When using forward auth (domain mode), the full requested URL including scheme and host is matched against the regular expressions.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>
<ak-form-group> <ak-form-group>
<span slot="header">${t`Authentication settings`}</span> <span slot="header">${msg("Authentication settings")}</span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="interceptHeaderAuth"> <ak-form-element-horizontal name="interceptHeaderAuth">
<label class="pf-c-switch"> <label class="pf-c-switch">
@ -500,11 +527,13 @@ ${this.instance?.skipPathRegex}</textarea
</span> </span>
</span> </span>
<span class="pf-c-switch__label" <span class="pf-c-switch__label"
>${t`Intercept header authentication`}</span >${msg("Intercept header authentication")}</span
> >
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`When enabled, authentik will intercept the Authorization header to authenticate the request.`} ${msg(
"When enabled, authentik will intercept the Authorization header to authenticate the request.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="basicAuthEnabled"> <ak-form-element-horizontal name="basicAuthEnabled">
@ -524,15 +553,20 @@ ${this.instance?.skipPathRegex}</textarea
</span> </span>
</span> </span>
<span class="pf-c-switch__label" <span class="pf-c-switch__label"
>${t`Send HTTP-Basic Authentication`}</span >${msg("Send HTTP-Basic Authentication")}</span
> >
</label> </label>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Send a custom HTTP-Basic Authentication header based on values from authentik.`} ${msg(
"Send a custom HTTP-Basic Authentication header based on values from authentik.",
)}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.showHttpBasic ? this.renderHttpBasic() : html``} ${this.showHttpBasic ? this.renderHttpBasic() : html``}
<ak-form-element-horizontal label=${t`Trusted OIDC Sources`} name="jwksSources"> <ak-form-element-horizontal
label=${msg("Trusted OIDC Sources")}
name="jwksSources"
>
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
${this.oauthSources?.results.map((source) => { ${this.oauthSources?.results.map((source) => {
const selected = (this.instance?.jwksSources || []).some((su) => { const selected = (this.instance?.jwksSources || []).some((su) => {
@ -544,10 +578,12 @@ ${this.instance?.skipPathRegex}</textarea
})} })}
</select> </select>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.`} ${msg(
"JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.",
)}
</p> </p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`} ${msg("Hold control/command to select multiple items.")}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -23,8 +23,7 @@ import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/ObjectChangelog"; import "@goauthentik/elements/events/ObjectChangelog";
import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; import { getURLParam } from "@goauthentik/elements/router/RouteMatch";
import { t } from "@lingui/macro"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -46,13 +45,13 @@ export function ModeToLabel(action?: ProxyMode): string {
if (!action) return ""; if (!action) return "";
switch (action) { switch (action) {
case ProxyMode.Proxy: case ProxyMode.Proxy:
return t`Proxy`; return msg("Proxy");
case ProxyMode.ForwardSingle: case ProxyMode.ForwardSingle:
return t`Forward auth (single application)`; return msg("Forward auth (single application)");
case ProxyMode.ForwardDomain: case ProxyMode.ForwardDomain:
return t`Forward auth (domain-level)`; return msg("Forward auth (domain-level)");
case ProxyMode.UnknownDefaultOpenApi: case ProxyMode.UnknownDefaultOpenApi:
return t`Unknown proxy mode`; return msg("Unknown proxy mode");
} }
} }
@ -114,31 +113,31 @@ export class ProxyProviderViewPage extends AKElement {
renderConfig(): TemplateResult { renderConfig(): TemplateResult {
const serves = [ const serves = [
{ {
label: t`Nginx (Ingress)`, label: msg("Nginx (Ingress)"),
md: MDNginxIngress, md: MDNginxIngress,
}, },
{ {
label: t`Nginx (Proxy Manager)`, label: msg("Nginx (Proxy Manager)"),
md: MDNginxPM, md: MDNginxPM,
}, },
{ {
label: t`Nginx (standalone)`, label: msg("Nginx (standalone)"),
md: MDNginxStandalone, md: MDNginxStandalone,
}, },
{ {
label: t`Traefik (Ingress)`, label: msg("Traefik (Ingress)"),
md: MDTraefikIngress, md: MDTraefikIngress,
}, },
{ {
label: t`Traefik (Compose)`, label: msg("Traefik (Compose)"),
md: MDTraefikCompose, md: MDTraefikCompose,
}, },
{ {
label: t`Traefik (Standalone)`, label: msg("Traefik (Standalone)"),
md: MDTraefikStandalone, md: MDTraefikStandalone,
}, },
{ {
label: t`Caddy (Standalone)`, label: msg("Caddy (Standalone)"),
md: MDCaddyStandalone, md: MDCaddyStandalone,
}, },
]; ];
@ -188,15 +187,15 @@ export class ProxyProviderViewPage extends AKElement {
return html``; return html``;
} }
return html` <ak-tabs> return html` <ak-tabs>
<section slot="page-overview" data-tab-title="${t`Overview`}"> <section slot="page-overview" data-tab-title="${msg("Overview")}">
${this.renderTabOverview()} ${this.renderTabOverview()}
</section> </section>
<section slot="page-authentication" data-tab-title="${t`Authentication`}"> <section slot="page-authentication" data-tab-title="${msg("Authentication")}">
${this.renderTabAuthentication()} ${this.renderTabAuthentication()}
</section> </section>
<section <section
slot="page-changelog" slot="page-changelog"
data-tab-title="${t`Changelog`}" data-tab-title="${msg("Changelog")}"
class="pf-c-page__main-section pf-m-no-padding-mobile" class="pf-c-page__main-section pf-m-no-padding-mobile"
> >
<div class="pf-c-card"> <div class="pf-c-card">
@ -224,7 +223,7 @@ export class ProxyProviderViewPage extends AKElement {
<dl class="pf-c-description-list pf-m-3-col-on-lg"> <dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Client ID`}</span> <span class="pf-c-description-list__text">${msg("Client ID")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -250,11 +249,11 @@ export class ProxyProviderViewPage extends AKElement {
return html`${this.provider?.assignedApplicationName return html`${this.provider?.assignedApplicationName
? html`` ? html``
: html`<div slot="header" class="pf-c-banner pf-m-warning"> : html`<div slot="header" class="pf-c-banner pf-m-warning">
${t`Warning: Provider is not used by an Application.`} ${msg("Warning: Provider is not used by an Application.")}
</div>`} </div>`}
${this.provider?.outpostSet.length < 1 ${this.provider?.outpostSet.length < 1
? html`<div slot="header" class="pf-c-banner pf-m-warning"> ? html`<div slot="header" class="pf-c-banner pf-m-warning">
${t`Warning: Provider is not used by any Outpost.`} ${msg("Warning: Provider is not used by any Outpost.")}
</div>` </div>`
: html``} : html``}
<div class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter"> <div class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter">
@ -263,7 +262,7 @@ export class ProxyProviderViewPage extends AKElement {
<dl class="pf-c-description-list pf-m-3-col-on-lg"> <dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span> <span class="pf-c-description-list__text">${msg("Name")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -274,7 +273,7 @@ export class ProxyProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Assigned to application`}</span >${msg("Assigned to application")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -288,7 +287,7 @@ export class ProxyProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Internal Host`}</span >${msg("Internal Host")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -300,7 +299,7 @@ export class ProxyProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`External Host`}</span >${msg("External Host")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -314,7 +313,7 @@ export class ProxyProviderViewPage extends AKElement {
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Basic-Auth`}</span >${msg("Basic-Auth")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -324,14 +323,16 @@ export class ProxyProviderViewPage extends AKElement {
? PFColor.Green ? PFColor.Green
: PFColor.Grey} : PFColor.Grey}
> >
${this.provider.basicAuthEnabled ? t`Yes` : t`No`} ${this.provider.basicAuthEnabled
? msg("Yes")
: msg("No")}
</ak-label> </ak-label>
</div> </div>
</dd> </dd>
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Mode`}</span> <span class="pf-c-description-list__text">${msg("Mode")}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
@ -343,27 +344,27 @@ export class ProxyProviderViewPage extends AKElement {
</div> </div>
<div class="pf-c-card__footer"> <div class="pf-c-card__footer">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span> <span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${t`Update Proxy Provider`} </span> <span slot="header"> ${msg("Update Proxy Provider")} </span>
<ak-provider-proxy-form <ak-provider-proxy-form
slot="form" slot="form"
.instancePk=${this.provider.pk || 0} .instancePk=${this.provider.pk || 0}
> >
</ak-provider-proxy-form> </ak-provider-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${msg("Edit")}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col"> <div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__title">${t`Protocol Settings`}</div> <div class="pf-c-card__title">${msg("Protocol Settings")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg"> <dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text" <span class="pf-c-description-list__text"
>${t`Allowed Redirect URIs`}</span >${msg("Allowed Redirect URIs")}</span
> >
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
@ -380,11 +381,11 @@ export class ProxyProviderViewPage extends AKElement {
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col"> <div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__title">${t`Setup`}</div> <div class="pf-c-card__title">${msg("Setup")}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${isForward(this.provider?.mode || ProxyMode.Proxy) ${isForward(this.provider?.mode || ProxyMode.Proxy)
? html` ${this.renderConfig()} ` ? html` ${this.renderConfig()} `
: html` <p>${t`No additional setup is required.`}</p> `} : html` <p>${msg("No additional setup is required.")}</p> `}
</div> </div>
</div> </div>
</div>`; </div>`;

Some files were not shown because too many files have changed in this diff Show More