diff --git a/Makefile b/Makefile index 7790c4170..1943e85b4 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ lint: migrate: python -m lifecycle.migrate -i18n-extract: i18n-extract-core web-extract +i18n-extract: i18n-extract-core web-i18n-extract i18n-extract-core: ak makemessages --ignore web --ignore internal --ignore web --ignore web-api --ignore website -l en @@ -150,7 +150,7 @@ web-lint: web-check-compile: cd web && npm run tsc -web-extract: +web-i18n-extract: cd web && npm run extract ######################### diff --git a/authentik/crypto/builder.py b/authentik/crypto/builder.py index b3ffc9e55..d560901bd 100644 --- a/authentik/crypto/builder.py +++ b/authentik/crypto/builder.py @@ -7,7 +7,7 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa -from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES +from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes from cryptography.x509.oid import NameOID from authentik import __version__ @@ -40,7 +40,7 @@ class CertificateBuilder: self.cert.save() return self.cert - def generate_private_key(self) -> PRIVATE_KEY_TYPES: + def generate_private_key(self) -> PrivateKeyTypes: """Generate private key""" if self._use_ec_private_key: return ec.generate_private_key(curve=ec.SECP256R1) diff --git a/authentik/crypto/models.py b/authentik/crypto/models.py index ecba00901..d6543fe31 100644 --- a/authentik/crypto/models.py +++ b/authentik/crypto/models.py @@ -6,7 +6,7 @@ from uuid import uuid4 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES, PUBLIC_KEY_TYPES +from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes, PublicKeyTypes from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.x509 import Certificate, load_pem_x509_certificate from django.db import models @@ -37,8 +37,8 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): ) _cert: Optional[Certificate] = None - _private_key: Optional[PRIVATE_KEY_TYPES] = None - _public_key: Optional[PUBLIC_KEY_TYPES] = None + _private_key: Optional[PrivateKeyTypes] = None + _public_key: Optional[PublicKeyTypes] = None @property def serializer(self) -> Serializer: @@ -56,7 +56,7 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): return self._cert @property - def public_key(self) -> Optional[PUBLIC_KEY_TYPES]: + def public_key(self) -> Optional[PublicKeyTypes]: """Get public key of the private key""" if not self._public_key: self._public_key = self.private_key.public_key() @@ -65,7 +65,7 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): @property def private_key( self, - ) -> Optional[PRIVATE_KEY_TYPES]: + ) -> Optional[PrivateKeyTypes]: """Get python cryptography PrivateKey instance""" if not self._private_key and self.key_data != "": try: diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index d0a2e8ecc..837940832 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -9,7 +9,7 @@ from urllib.parse import urlparse, urlunparse from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey -from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES +from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes from dacite.core import from_dict from django.db import models from django.http import HttpRequest @@ -215,7 +215,7 @@ class OAuth2Provider(Provider): ) @cached_property - def jwt_key(self) -> tuple[str | PRIVATE_KEY_TYPES, str]: + def jwt_key(self) -> tuple[str | PrivateKeyTypes, str]: """Get either the configured certificate or the client secret""" if not self.signing_key: # No Certificate at all, assume HS256 diff --git a/web/.eslintignore b/web/.eslintignore index 537b7fae4..ff0b2d3a3 100644 --- a/web/.eslintignore +++ b/web/.eslintignore @@ -4,3 +4,4 @@ node_modules dist # don't lint nyc coverage output coverage +src/locale-codes.ts diff --git a/web/.eslintrc.json b/web/.eslintrc.json index c3943c953..5629ffda8 100644 --- a/web/.eslintrc.json +++ b/web/.eslintrc.json @@ -18,7 +18,7 @@ "rules": { "indent": "off", "linebreak-style": ["error", "unix"], - "quotes": ["error", "double"], + "quotes": ["error", "double", { "avoidEscape": true }], "semi": ["error", "always"], "@typescript-eslint/ban-ts-comment": "off" } diff --git a/web/.prettierignore b/web/.prettierignore index bbc64fc00..00c1e6be0 100644 --- a/web/.prettierignore +++ b/web/.prettierignore @@ -6,3 +6,4 @@ dist coverage # Import order matters poly.ts +src/locale-codes.ts diff --git a/web/.prettierrc.json b/web/.prettierrc.json index 831f9f928..cc4ea8ee1 100644 --- a/web/.prettierrc.json +++ b/web/.prettierrc.json @@ -15,7 +15,7 @@ "trailingComma": "all", "useTabs": false, "vueIndentScriptAndStyle": false, - "importOrder": ["^@lingui/(.*)$", "^(@?)lit(.*)$", "\\.css$", "^@goauthentik/api$", "^[./]"], + "importOrder": ["^(@?)lit(.*)$", "\\.css$", "^@goauthentik/api$", "^[./]"], "importOrderSeparation": true, "importOrderSortSpecifiers": true, "importOrderParserPlugins": ["typescript", "classProperties", "decorators-legacy"] diff --git a/web/lingui.config.js b/web/lingui.config.js deleted file mode 100644 index 590808fb8..000000000 --- a/web/lingui.config.js +++ /dev/null @@ -1,31 +0,0 @@ -import { formatter } from "@lingui/format-po-gettext"; - -export default { - sourceLocale: "en", - locales: [ - "en", - "pseudo-LOCALE", - "fr_FR", - "tr", - "es", - "pl", - "zh_TW", - "zh-Hans", - "zh-Hant", - "de", - ], - pseudoLocale: "pseudo-LOCALE", - fallbackLocales: { - "pseudo-LOCALE": "en", - "default": "en", - }, - compileNamespace: "ts", - catalogs: [ - { - path: "src/locales/{locale}", - include: ["src"], - exclude: ["**/node_modules/**", "**/dist/**"], - }, - ], - format: formatter({ lineNumbers: false }), -}; diff --git a/web/package.json b/web/package.json index 0f79ab6ba..89ed39859 100644 --- a/web/package.json +++ b/web/package.json @@ -5,9 +5,8 @@ "license": "MIT", "scripts": { "extract-locales": "lit-localize extract", - "build-locales": "run-s build-locales:build build-locales:repair", + "build-locales": "run-s build-locales:build", "build-locales:build": "lit-localize build", - "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", diff --git a/web/src/locale-codes.ts b/web/src/locale-codes.ts index 8417252f6..affe2b48a 100644 --- a/web/src/locale-codes.ts +++ b/web/src/locale-codes.ts @@ -4,38 +4,38 @@ /** * The locale code that templates in this source code are written in. */ -export const sourceLocale = "en"; +export const sourceLocale = `en`; /** * The other locale codes that this application is localized into. Sorted * lexicographically. */ export const targetLocales = [ - "de", - "en", - "es", - "fr_FR", - "pl", - "pseudo-LOCALE", - "tr", - "zh_TW", - "zh-Hans", - "zh-Hant", + `de`, + `en`, + `es`, + `fr_FR`, + `pl`, + `pseudo-LOCALE`, + `tr`, + `zh_TW`, + `zh-Hans`, + `zh-Hant`, ] as const; /** * All valid project locale codes. Sorted lexicographically. */ export const allLocales = [ - "de", - "en", - "en", - "es", - "fr_FR", - "pl", - "pseudo-LOCALE", - "tr", - "zh_TW", - "zh-Hans", - "zh-Hant", + `de`, + `en`, + `en`, + `es`, + `fr_FR`, + `pl`, + `pseudo-LOCALE`, + `tr`, + `zh_TW`, + `zh-Hans`, + `zh-Hant`, ] as const; diff --git a/website/developer-docs/translation.md b/website/developer-docs/translation.md index 3d532aca5..d5bf286fd 100644 --- a/website/developer-docs/translation.md +++ b/website/developer-docs/translation.md @@ -4,7 +4,7 @@ title: Translations Translation in authentik is done in two places. Most of the text is defined in the frontend in `web/`, and a subset of messages is defined in the backend. -The frontend uses [lingui](https://lingui.js.org/), and the backend uses the built-in django translation tools. +The frontend uses [@lit/localize](https://lit.dev/docs/localization/overview/), and the backend uses the built-in django translation tools. :::info Please review the [Writing documentation](./docs/writing-documentation) guidelines as they apply to documentation too. @@ -24,22 +24,21 @@ To simplify translation you can use https://www.transifex.com/authentik/authenti Run `npm i` in the `/web` folder to install all dependencies. -Ensure the language code is in the `package.json` file in `web/`: +Ensure the language code is in the `lit-localize.json` file in `web/`: ```json // [...] - "lingui": { + "targetLocales": [ + "en", + "pseudo-LOCALE", + "a-new-locale" // [...] - "locales": [ - "en", - "pseudo-LOCALE", - "a-new-locale" - ], + ], // [...] ``` -Afterwards, run `npx lingui extract` to generate a base .po file. +Afterwards, run `make web-i18n-extract` to generate a base .xlf file. -The .po files can be edited by any text editor, or using a tool such as [POEdit](https://poedit.net/). +The .xlf files can be edited by any text editor, or using a tool such as [POEdit](https://poedit.net/). -To see the change, run `npm run watch` in the `web/` directory. +To see the change, run `make web-watch` in the root directory of the repository.