Compare commits

...
8 Commits
Author SHA1 Message Date
jcoffey-dev 4bbfd7d455 Merge pull request 'Lowercase the tab title fallback' (#11) from fix/brand-lowercase-title into main
ci / version (push) Skipped
ci / node (push) Successful in 2m20s
ci / publish (push) Skipped
ci / docker-build (push) Successful in 17s
2026-09-22 22:24:12 +00:00
jcoffey-dev d0832013fe Lowercase the tab title's fallback name
ci / version (pull_request) Skipped
ci / node (pull_request) Successful in 1m46s
ci / publish (pull_request) Skipped
ci / docker-build (pull_request) Successful in 37s
The title the tab falls back to before the session names the app was the one
user-visible string the brand pass missed; setBaseTitle overwrites it as soon
as the session arrives, so it shows only for that first moment.
2026-09-22 15:21:35 -07:00
jcoffey-dev b79fdb8bab Merge pull request 'Write the name in lowercase where people see it' (#10) from fix/brand-lowercase into main
ci / version (push) Skipped
ci / node (push) Successful in 2m28s
ci / publish (push) Skipped
ci / docker-build (push) Successful in 16s
2026-09-22 22:18:06 +00:00
jcoffey-dev 8d717e0037 Write the name in lowercase where people see it
ci / version (pull_request) Skipped
ci / node (pull_request) Successful in 2m21s
ci / publish (pull_request) Skipped
ci / docker-build (pull_request) Successful in 1m10s
The brand is lowercase inbuxa. This changes what the app calls itself by
default, the wordmark's accessible name, the sign-in card's version line, the
installed app's name in the manifest, and the four translated strings that
name the console or the mail server.

Those four are source strings, so their catalog keys changed with them in all
nine languages; the translations keep their text with the name corrected. No
key was left behind, and no language falls back on more strings than before:
1643/1662 translated, 19 falling back, in each of the nine, unchanged.

Code identifiers, capability URNs, env var names and comments are untouched.
2026-09-22 15:13:53 -07:00
jcoffey-dev c2f13d6a1a Merge pull request 'ci: publish tagged releases as INBUXA's own image' (#9) from ci/inbuxa-release into main
ci / version (push) Successful in 1m24s
ci / node (push) Successful in 2m33s
ci / docker-build (push) Skipped
ci / publish (push) Successful in 5m41s
2026-09-22 16:58:24 +00:00
jcoffey-dev afb39fac20 ci: publish tagged releases as INBUXA's own image
ci / version (pull_request) Skipped
ci / node (pull_request) Successful in 1m15s
ci / publish (pull_request) Skipped
ci / docker-build (pull_request) Successful in 28s
A tag named inbuxa-v<version> (the tagged commit's own version from
scripts/version.mjs, '+' as '-') now builds a linux/amd64 + linux/arm64
image at <REGISTRY>/inbuxa/ihasmail-inbuxa, tagged with the version and
latest, links the package to the repository and creates the release.

The inbuxa- prefix keeps upstream ihasmail's v* tags, which this
repository carries on shared commits, from ever publishing under the
INBUXA name. The tag must name its commit's version and the commit must
be on main. No schedule yet: releases are cut by hand.
2026-09-22 09:56:09 -07:00
jcoffey-dev b514dab62a Merge pull request 'Point links at the new git host' (#8) from fix/links-after-move into main
ci / node (push) Successful in 3m15s
ci / docker-build (push) Successful in 58s
2026-09-22 16:09:58 +00:00
jcoffey-dev 2d7d8952ab Point links at the new git host
ci / docker-build (pull_request) Successful in 1m13s
ci / node (pull_request) Successful in 4m42s
GitHub went dark with the account suspension on 2026-09-20 and GitLab was
retired on 2026-09-22, so links to either no longer resolve. Repository,
file, release and download links now point at git.coffeylabs.org, images
at registry.coffeylabs.org, and old GitHub issue and pull request links at
coffey-labs/ihasmail-github-archive, whose numbers match GitHub's.
2026-09-22 09:03:00 -07:00
29 changed files with 155 additions and 63 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ APP_NAME=ihasmail
# you have patched it, point this at your own tree. Shown on the sign-in page
# and in Settings > About. INBUXA's webmail is itself a modified ihasmail, so
# the default is this fork.
SOURCE_URL=https://github.com/inbuxa/ihasmail-inbuxa
SOURCE_URL=https://git.coffeylabs.org/inbuxa/ihasmail-inbuxa
# ---- Settings this installation decides (all optional) ----
#
+100 -8
View File
@@ -2,14 +2,15 @@
# GitLab (2026-09-22). Gitea reads .gitea/workflows and ignores .github/ once
# this directory exists; .github/workflows stays as it was for GitHub.
#
# There is deliberately no publish job, although publish.yml is in the tree.
# Every tag in this repository is one of ihasmail's own upstream tags, the
# same commits, and at those tags publish.yml pushed to ihasmail's image, not
# an INBUXA one. A tag-driven publish here would ship plain ihasmail under the
# INBUXA name the moment upstream tags reached this project -- which happened
# once, by hand, and was deleted. Add one back only with a release scheme that
# produces tags this repository alone has.
#
# Releases are cut by pushing a tag named `inbuxa-v<version>`, where
# <version> is what scripts/version.mjs says for the tagged commit with the
# `+` turned into `-` (e.g. inbuxa-v2026.9.22-g1a2b3c4). The prefix matters:
# this repository carries upstream ihasmail's own `v...` tags, on commits it
# shares with upstream, and a publish keyed on `v*` would ship plain ihasmail
# under the INBUXA name the moment one arrived. Only `inbuxa-v` tags publish.
# A tag publishes only if it names its own commit's version and that commit is
# on main. There is no release schedule yet; tags are cut by hand.
# Every job runs in an image pinned by digest (tag in the trailing comment),
# and the only action used is coffey-labs/actions/checkout pinned by SHA. The
# instance resolves short `uses:` against itself, never GitHub, so nothing
@@ -85,3 +86,94 @@ jobs:
tag="ihasmail:ci-$(echo "$GITHUB_SHA" | cut -c1-8)"
docker build -t "$tag" .
docker image rm "$tag"
# ----------------------------------------------------------- release ------
# Only for `inbuxa-v` tags (see the top of this file). The tag has to name
# its own commit's version, so the image, the release and the About screen
# all agree, and the commit has to be on main, so a release never describes
# code that was not reviewed onto the default branch.
version:
if: ${{ startsWith(github.ref, 'refs/tags/inbuxa-v') }}
runs-on: light
container:
image: node:26-bookworm-slim@sha256:582460f614631b59b824ac6020533b9bf339c7fdf3a6d7db31abb6b4065f0212 # 26-bookworm-slim
outputs:
version: ${{ steps.v.outputs.VERSION }}
docker_tag: ${{ steps.v.outputs.DOCKER_TAG }}
steps:
- uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec
with:
fetch-depth: 0
- id: v
shell: bash
env:
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
V="$(node scripts/version.mjs)"
want="inbuxa-v${V/+/-}"
[ "$TAG" = "$want" ] || { echo "!! $TAG does not name this commit's version; expected $want"; exit 1; }
git merge-base --is-ancestor "$(git rev-parse "${TAG}^{commit}")" origin/main \
|| { echo "!! $TAG is not on main"; exit 1; }
echo "VERSION=$V" >> "$GITHUB_OUTPUT"
echo "DOCKER_TAG=${V/+/-}" >> "$GITHUB_OUTPUT"
echo "VERSION=$V DOCKER_TAG=${V/+/-}"
# Multi-arch image at <REGISTRY>/inbuxa/ihasmail-inbuxa, then the release.
# arm64 is built under QEMU on this amd64 host, which is slow but fine for
# a hand-cut release. PACKAGE_TOKEN (jcoffey-dev, write:package) logs in:
# the job's own token is refused by the container registry. The release is
# created last, so a release on the page always has its image behind it.
publish:
if: ${{ startsWith(github.ref, 'refs/tags/inbuxa-v') }}
needs: [node, version]
runs-on: docker
container:
image: docker:28-cli@sha256:625d9431a9f54c5a2bc90f24f0e1c3d55b1349fd857dd85035f98c2c9acbdd4d # 28-cli
volumes:
- /var/run/docker.sock:/var/run/docker.sock
env:
DOCKER_BUILDKIT: "1"
REGISTRY: ${{ vars.REGISTRY }}
IMAGE: ${{ vars.REGISTRY }}/${{ github.repository }}
VERSION: ${{ needs.version.outputs.version }}
DOCKER_TAG: ${{ needs.version.outputs.docker_tag }}
PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
steps:
- uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec
- run: |
test -n "$REGISTRY" && test -n "$VERSION" && test -n "$DOCKER_TAG"
test -n "$PACKAGE_TOKEN" || { echo "PACKAGE_TOKEN secret is not set on this repository" >&2; exit 1; }
echo "$PACKAGE_TOKEN" | docker login -u jcoffey-dev --password-stdin "$REGISTRY"
docker run --privileged --rm tonistiigi/binfmt --install arm64
docker buildx create --use --name gitea-builder --driver docker-container || docker buildx use gitea-builder
- run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--build-arg IHASMAIL_VERSION="$VERSION" \
--provenance=false --sbom=false \
--tag "$IMAGE:$DOCKER_TAG" \
--tag "$IMAGE:latest" \
--push .
docker buildx imagetools inspect "$IMAGE:$DOCKER_TAG"
# Show the package on the repository's Packages tab. Idempotent.
- run: |
apk add --no-cache -q curl
curl -fsS -o /dev/null -X POST -H "Authorization: token $PACKAGE_TOKEN" \
"$CI_SERVER_INTERNAL/api/v1/packages/${GITHUB_REPOSITORY%%/*}/container/${GITHUB_REPOSITORY#*/}/-/link/${GITHUB_REPOSITORY#*/}" \
|| echo "package already linked (or link refused); not fatal"
# The release, on the internal address. The job's own token may create
# releases; a tag it creates would not start a workflow, but this one
# already exists.
- env:
TAG: ${{ github.ref_name }}
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -eu
body="INBUXA webmail $VERSION.\n\nImage: \`$IMAGE:$DOCKER_TAG\` (linux/amd64, linux/arm64), also tagged \`latest\`."
curl -fsS -o /dev/null -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
--data "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"body\":\"$body\"}" \
"$CI_SERVER_INTERNAL/api/v1/repos/$GITHUB_REPOSITORY/releases"
echo "release $TAG created"
- if: always()
run: docker logout "$REGISTRY" || true
+1 -1
View File
@@ -16,7 +16,7 @@ By participating in this project, you agree to treat other contributors with res
### Reporting Bugs
Before opening a new issue, please search [existing issues](https://github.com/Coffey-Labs/ihasmail/issues) to see if it's already been reported. When filing a bug report, include:
Before opening a new issue, please search [existing issues](https://git.coffeylabs.org/coffey-labs/ihasmail/issues) to see if it's already been reported. When filing a bug report, include:
- A clear, descriptive title
- Steps to reproduce the issue
+2 -2
View File
@@ -70,7 +70,7 @@ docker compose up --build -d
## Source code
INBUXA webmail is a modified ihasmail, so the AGPL's offer is this fork:
<https://github.com/inbuxa/ihasmail-inbuxa>. The sign-in page and Settings
<https://git.coffeylabs.org/inbuxa/ihasmail-inbuxa>. The sign-in page and Settings
About link there, beside the version, which names the commit the running build
came from.
@@ -94,7 +94,7 @@ Architecture, the mock's switches and how versions are numbered are in
## Built on ihasmail
The INBUXA webmail is built on [ihasmail](https://github.com/Coffey-Labs/ihasmail),
The INBUXA webmail is built on [ihasmail](https://git.coffeylabs.org/coffey-labs/ihasmail),
Coffey Labs' own webmail, which stays an independent product. The public
repository is the remote `ihasmail`, fetch-only, and its `main` is merged in to
keep up. Nothing here is pushed there.
+1 -1
View File
@@ -29,7 +29,7 @@ services:
APP_SECRET: ${APP_SECRET:?set APP_SECRET in .env (openssl rand -base64 48)}
APP_NAME: ${APP_NAME:-ihasmail}
BASE_PATH: ${BASE_PATH:-}
SOURCE_URL: ${SOURCE_URL:-https://github.com/inbuxa/ihasmail-inbuxa}
SOURCE_URL: ${SOURCE_URL:-https://git.coffeylabs.org/inbuxa/ihasmail-inbuxa}
TRUST_PROXY: "1"
IMAGE_PROXY: "1"
volumes:
+2 -2
View File
@@ -278,7 +278,7 @@ if (oauthClientSecret && !publicUrl) {
export const config = {
isProd,
appName: env("APP_NAME", "INBUXA"),
appName: env("APP_NAME", "inbuxa"),
settingsPolicy: readSettingsPolicy(),
/**
* What this build calls itself: `2.16.57`. Set by the image build from
@@ -295,7 +295,7 @@ export const config = {
* ihasmail should point this at their own tree. ihasmail-inbuxa is itself
* such a tree, so the default is INBUXA's fork.
*/
sourceUrl: env("SOURCE_URL", "https://github.com/inbuxa/ihasmail-inbuxa"),
sourceUrl: env("SOURCE_URL", "https://git.coffeylabs.org/inbuxa/ihasmail-inbuxa"),
host: env("HOST", "0.0.0.0"),
port: int("PORT", 8080),
/**
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "INBUXA",
"short_name": "INBUXA",
"description": "INBUXA webmail",
"name": "inbuxa",
"short_name": "inbuxa",
"description": "inbuxa webmail",
"_comment": "JSON has no comments, so: every URL below is relative on purpose. Manifest members resolve against the manifest's own address, so these follow BASE_PATH with nothing substituted into them at build time. Root-absolute values pinned the installed app, its scope and its shortcuts to the domain root whatever the mount was.",
"_comment_id": "There is deliberately no `id`. It is the one member NOT resolved against this file's address -- the spec resolves it against the origin of start_url, so `./`, `mail` and `/mail` all mean the same thing at the domain root and none of them can name a subpath mount. Adding one would therefore break the same thing the note above describes. Worse, the default id IS start_url, which is already mount-correct: writing an id now would give every installed copy a new identity and orphan it as a second app rather than updating it. If one is ever wanted it has to be substituted at build time from BASE_PATH, and the changeover costs everybody their install.",
"start_url": "mail",
+2 -2
View File
@@ -12,9 +12,9 @@ import { useSession } from "@/store/session";
* One constant rather than the string written out at each of them, because
* three copies of a default is how two of them end up stale.
*/
// ihasmail-inbuxa: INBUXA's webmail goes by INBUXA, so it can't be taken for
// ihasmail-inbuxa: inbuxa's webmail goes by inbuxa, so it can't be taken for
// public ihasmail. APP_NAME still names a deployment whatever it likes.
export const DEFAULT_APP_NAME = "INBUXA";
export const DEFAULT_APP_NAME = "inbuxa";
/**
* What this instance calls itself, right now.
*
+1 -1
View File
@@ -49,7 +49,7 @@ export const UI_LANGUAGES: readonly UiLanguage[] = [
];
/** Where to report a bad translation. Beta languages depend on it. */
export const TRANSLATION_ISSUE_URL = "https://github.com/Coffey-Labs/ihasmail/issues/new?title=Translation%3A%20";
export const TRANSLATION_ISSUE_URL = "https://git.coffeylabs.org/coffey-labs/ihasmail/issues/new?title=Translation%3A%20";
export const DEFAULT_UI_LANGUAGE = "en";
+1 -1
View File
@@ -1,6 +1,6 @@
import { withBase } from "../basePath";
let baseTitle = "INBUXA";
let baseTitle = "inbuxa";
let faviconCanvas: HTMLCanvasElement | null = null;
let baseFavicon: HTMLImageElement | null = null;
+1 -1
View File
@@ -8,4 +8,4 @@
* ihasmail-inbuxa: INBUXA runs a modified ihasmail, so the offer is INBUXA's
* fork and not the project it came from.
*/
export const DEFAULT_SOURCE_URL = "https://github.com/inbuxa/ihasmail-inbuxa";
export const DEFAULT_SOURCE_URL = "https://git.coffeylabs.org/inbuxa/ihasmail-inbuxa";
+3 -3
View File
@@ -147,8 +147,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "Die Zahlen, die Ihre Rolle sehen darf, so wie der Server sie meldet.",
"Nothing to show": "Nichts anzuzeigen",
"Could not be loaded": "Konnte nicht geladen werden",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Detaillierte Metriken, die Zustellwarteschlange, Protokolle und Servereinstellungen finden Sie in INBUXA Admin.",
"Open INBUXA Admin": "INBUXA Admin öffnen",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Detaillierte Metriken, die Zustellwarteschlange, Protokolle und Servereinstellungen finden Sie in inbuxa Admin.",
"Open inbuxa Admin": "inbuxa Admin öffnen",
"Default group role": "Standardrolle für Gruppen",
"A group needs an address.": "Eine Gruppe braucht eine Adresse.",
"New group": "Neue Gruppe",
@@ -220,7 +220,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "Der Mailserver vergibt diese Rolle standardmäßig an {kinds}. Eine Änderung betrifft alle, die sie auf diesem Weg haben.",
"Builds on": "Baut auf",
"Permissions": "Berechtigungen",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "Der Mailserver vergibt diese Rolle standardmäßig, daher kann sie nicht gelöscht werden. Ändern Sie zuerst die Standardwerte in INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "Der Mailserver vergibt diese Rolle standardmäßig, daher kann sie nicht gelöscht werden. Ändern Sie zuerst die Standardwerte in inbuxa Admin.",
"This role carries permissions yours doesn't.": "Diese Rolle hat Berechtigungen, die Ihre nicht hat.",
"Create role": "Rolle anlegen",
"builds on this one": "baut auf dieser auf",
+3 -3
View File
@@ -139,8 +139,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "Las cifras que su rol puede ver, tal como las informa el servidor.",
"Nothing to show": "Nada que mostrar",
"Could not be loaded": "No se pudo cargar",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Las métricas detalladas, la cola de entrega, los registros y los ajustes del servidor están en INBUXA Admin.",
"Open INBUXA Admin": "Abrir INBUXA Admin",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Las métricas detalladas, la cola de entrega, los registros y los ajustes del servidor están en inbuxa Admin.",
"Open inbuxa Admin": "Abrir inbuxa Admin",
"Default group role": "Rol de grupo predeterminado",
"A group needs an address.": "Un grupo necesita una dirección.",
"New group": "Nuevo grupo",
@@ -212,7 +212,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "El servidor de correo asigna este rol de forma predeterminada a {kinds}. Un cambio aquí afecta a todos los que lo tienen así.",
"Builds on": "Se basa en",
"Permissions": "Permisos",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "El servidor de correo asigna este rol de forma predeterminada, así que no se puede eliminar. Cambie primero los valores predeterminados en INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "El servidor de correo asigna este rol de forma predeterminada, así que no se puede eliminar. Cambie primero los valores predeterminados en inbuxa Admin.",
"This role carries permissions yours doesn't.": "Este rol tiene permisos que el suyo no tiene.",
"Create role": "Crear rol",
"builds on this one": "se basa en este",
+3 -3
View File
@@ -144,8 +144,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "Les chiffres que votre rôle permet de voir, tels que le serveur les indique.",
"Nothing to show": "Rien à afficher",
"Could not be loaded": "Chargement impossible",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Les métriques détaillées, la file de distribution, les journaux et les réglages du serveur se trouvent dans INBUXA Admin.",
"Open INBUXA Admin": "Ouvrir INBUXA Admin",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Les métriques détaillées, la file de distribution, les journaux et les réglages du serveur se trouvent dans inbuxa Admin.",
"Open inbuxa Admin": "Ouvrir inbuxa Admin",
"Default group role": "Rôle de groupe par défaut",
"A group needs an address.": "Un groupe a besoin dune adresse.",
"New group": "Nouveau groupe",
@@ -217,7 +217,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "Le serveur de messagerie attribue ce rôle par défaut à {kinds}. Une modification ici sapplique à tous ceux qui lont ainsi.",
"Builds on": "Sappuie sur",
"Permissions": "Autorisations",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "Le serveur de messagerie attribue ce rôle par défaut : il ne peut donc pas être supprimé. Modifiez dabord les valeurs par défaut dans INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "Le serveur de messagerie attribue ce rôle par défaut : il ne peut donc pas être supprimé. Modifiez dabord les valeurs par défaut dans inbuxa Admin.",
"This role carries permissions yours doesn't.": "Ce rôle comporte des autorisations que le vôtre na pas.",
"Create role": "Créer le rôle",
"builds on this one": "sappuie sur celui-ci",
+3 -3
View File
@@ -138,8 +138,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "あなたのロールで見られる数値を、サーバーの報告どおりに表示します。",
"Nothing to show": "表示するものはありません",
"Could not be loaded": "読み込めませんでした",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "詳細なメトリクス、配信キュー、ログ、サーバー設定は INBUXA Admin にあります。",
"Open INBUXA Admin": "INBUXA Admin を開く",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "詳細なメトリクス、配信キュー、ログ、サーバー設定は inbuxa Admin にあります。",
"Open inbuxa Admin": "inbuxa Admin を開く",
"Default group role": "グループの既定ロール",
"A group needs an address.": "グループにはアドレスが必要です。",
"New group": "新しいグループ",
@@ -211,7 +211,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "メールサーバーはこのロールを既定で {kinds} に付与します。ここでの変更は、この方法でロールを持つ全員に反映されます。",
"Builds on": "継承元",
"Permissions": "権限",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "メールサーバーがこのロールを既定で付与するため、削除できません。先に INBUXA Admin で既定値を変更してください。",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "メールサーバーがこのロールを既定で付与するため、削除できません。先に inbuxa Admin で既定値を変更してください。",
"This role carries permissions yours doesn't.": "このロールにはあなたのロールにない権限があります。",
"Create role": "ロールを作成",
"builds on this one": "このロールを継承しています",
+3 -3
View File
@@ -134,8 +134,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "De cijfers die uw rol mag zien, zoals de server ze meldt.",
"Nothing to show": "Niets om te tonen",
"Could not be loaded": "Kon niet worden geladen",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Gedetailleerde statistieken, de bezorgwachtrij, logboeken en serverinstellingen vindt u in INBUXA Admin.",
"Open INBUXA Admin": "INBUXA Admin openen",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Gedetailleerde statistieken, de bezorgwachtrij, logboeken en serverinstellingen vindt u in inbuxa Admin.",
"Open inbuxa Admin": "inbuxa Admin openen",
"Default group role": "Standaardrol voor groepen",
"A group needs an address.": "Een groep heeft een adres nodig.",
"New group": "Nieuwe groep",
@@ -207,7 +207,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "De mailserver geeft deze rol standaard aan {kinds}. Een wijziging hier geldt voor iedereen die hem zo heeft.",
"Builds on": "Bouwt voort op",
"Permissions": "Rechten",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "De mailserver geeft standaard deze rol, dus hij kan niet worden verwijderd. Wijzig eerst de standaardwaarden in INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "De mailserver geeft standaard deze rol, dus hij kan niet worden verwijderd. Wijzig eerst de standaardwaarden in inbuxa Admin.",
"This role carries permissions yours doesn't.": "Deze rol heeft rechten die uw rol niet heeft.",
"Create role": "Rol aanmaken",
"builds on this one": "bouwt voort op deze",
+3 -3
View File
@@ -142,8 +142,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "Os números que sua função pode ver, como o servidor os informa.",
"Nothing to show": "Nada para mostrar",
"Could not be loaded": "Não foi possível carregar",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Métricas detalhadas, a fila de entrega, os registros e as configurações do servidor ficam no INBUXA Admin.",
"Open INBUXA Admin": "Abrir o INBUXA Admin",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Métricas detalhadas, a fila de entrega, os registros e as configurações do servidor ficam no inbuxa Admin.",
"Open inbuxa Admin": "Abrir o inbuxa Admin",
"Default group role": "Função padrão de grupo",
"A group needs an address.": "Um grupo precisa de um endereço.",
"New group": "Novo grupo",
@@ -215,7 +215,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "O servidor de e-mail atribui esta função por padrão a {kinds}. Uma alteração aqui vale para todos que a têm dessa forma.",
"Builds on": "Baseia-se em",
"Permissions": "Permissões",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "O servidor de e-mail atribui esta função por padrão, então ela não pode ser excluída. Altere primeiro os padrões no INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "O servidor de e-mail atribui esta função por padrão, então ela não pode ser excluída. Altere primeiro os padrões no inbuxa Admin.",
"This role carries permissions yours doesn't.": "Esta função tem permissões que a sua não tem.",
"Create role": "Criar função",
"builds on this one": "baseia-se nesta",
+3 -3
View File
@@ -141,8 +141,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "Показатели, доступные вашей роли, в том виде, в каком их сообщает сервер.",
"Nothing to show": "Нечего показать",
"Could not be loaded": "Не удалось загрузить",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Подробные метрики, очередь доставки, журналы и настройки сервера находятся в INBUXA Admin.",
"Open INBUXA Admin": "Открыть INBUXA Admin",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Подробные метрики, очередь доставки, журналы и настройки сервера находятся в inbuxa Admin.",
"Open inbuxa Admin": "Открыть inbuxa Admin",
"Default group role": "Роль группы по умолчанию",
"A group needs an address.": "Группе нужен адрес.",
"New group": "Новая группа",
@@ -214,7 +214,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "Почтовый сервер по умолчанию выдаёт эту роль: {kinds}. Изменение здесь затронет всех, кто получил её так.",
"Builds on": "Основана на",
"Permissions": "Разрешения",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "Почтовый сервер выдаёт эту роль по умолчанию, поэтому её нельзя удалить. Сначала измените значения по умолчанию в INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "Почтовый сервер выдаёт эту роль по умолчанию, поэтому её нельзя удалить. Сначала измените значения по умолчанию в inbuxa Admin.",
"This role carries permissions yours doesn't.": "У этой роли есть разрешения, которых нет у вашей.",
"Create role": "Создать роль",
"builds on this one": "основана на этой",
+3 -3
View File
@@ -135,8 +135,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "Показники, доступні вашій ролі, у тому вигляді, як їх повідомляє сервер.",
"Nothing to show": "Нічого показати",
"Could not be loaded": "Не вдалося завантажити",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "Докладні метрики, черга доставлення, журнали й налаштування сервера є в INBUXA Admin.",
"Open INBUXA Admin": "Відкрити INBUXA Admin",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "Докладні метрики, черга доставлення, журнали й налаштування сервера є в inbuxa Admin.",
"Open inbuxa Admin": "Відкрити inbuxa Admin",
"Default group role": "Роль групи за замовчуванням",
"A group needs an address.": "Групі потрібна адреса.",
"New group": "Нова група",
@@ -208,7 +208,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "Поштовий сервер типово надає цю роль: {kinds}. Зміна тут стосується всіх, хто отримав її так.",
"Builds on": "Базується на",
"Permissions": "Дозволи",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "Поштовий сервер типово надає цю роль, тому її не можна видалити. Спершу змініть типові значення в INBUXA Admin.",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "Поштовий сервер типово надає цю роль, тому її не можна видалити. Спершу змініть типові значення в inbuxa Admin.",
"This role carries permissions yours doesn't.": "Ця роль має дозволи, яких немає у вашої.",
"Create role": "Створити роль",
"builds on this one": "базується на цій",
+3 -3
View File
@@ -137,8 +137,8 @@ export const catalog: Catalog = {
"The numbers your role can see, as the server reports them.": "您的角色可以查看的数字,按服务器报告显示。",
"Nothing to show": "没有可显示的内容",
"Could not be loaded": "无法加载",
"Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.": "详细指标、投递队列、日志和服务器设置都在 INBUXA Admin 中。",
"Open INBUXA Admin": "打开 INBUXA Admin",
"Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.": "详细指标、投递队列、日志和服务器设置都在 inbuxa Admin 中。",
"Open inbuxa Admin": "打开 inbuxa Admin",
"Default group role": "默认群组角色",
"A group needs an address.": "群组需要一个地址。",
"New group": "新建群组",
@@ -210,7 +210,7 @@ export const catalog: Catalog = {
"The mail server gives this role by default to {kinds}. A change here reaches everyone who has it that way.": "邮件服务器默认将此角色授予{kinds}。在此处的更改会影响所有以此方式拥有该角色的人。",
"Builds on": "基于",
"Permissions": "权限",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.": "邮件服务器默认授予此角色,因此无法删除。请先在 INBUXA Admin 中更改默认设置。",
"The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.": "邮件服务器默认授予此角色,因此无法删除。请先在 inbuxa Admin 中更改默认设置。",
"This role carries permissions yours doesn't.": "此角色拥有您的角色所没有的权限。",
"Create role": "创建角色",
"builds on this one": "基于此角色",
+1 -1
View File
@@ -108,7 +108,7 @@ export function isOccurrence(event: CalendarEvent): boolean {
* before it is sent — rejected properties throw, inherited ones are reported to
* the caller — rather than being posted hopefully and believed.
*
* [#26]: https://github.com/Coffey-Labs/ihasmail/issues/26
* [#26]: https://git.coffeylabs.org/coffey-labs/ihasmail-github-archive/issues/26
*/
const OCCURRENCE_REJECTED = new Set([
"baseEventId", "calendarIds", "isDraft", "isOrigin", "utcStart", "utcEnd",
+1 -1
View File
@@ -26,7 +26,7 @@ import { useMail } from "./mail";
* `ContactCard/set` down they are the same" was always claiming and is now
* true of.
*
* [#173]: https://github.com/Coffey-Labs/ihasmail/issues/173
* [#173]: https://git.coffeylabs.org/coffey-labs/ihasmail-github-archive/issues/173
*/
/**
* The UIDs an address book already holds.
+1 -1
View File
@@ -15,7 +15,7 @@ export function InbuxaWordmark({ className, height }: { className?: string; heig
height={height}
width={(height * 488) / 112}
role="img"
aria-label="INBUXA"
aria-label="inbuxa"
className={`notranslate ${className ?? ""}`}
fill="currentColor"
>
+1 -1
View File
@@ -101,7 +101,7 @@ export interface DialogChoice {
* which is what "Discard changes" was, on a guard whose whole purpose is to
* stop you losing work ([#175]).
*
* [#175]: https://github.com/Coffey-Labs/ihasmail/issues/175
* [#175]: https://git.coffeylabs.org/coffey-labs/ihasmail-github-archive/issues/175
*/
primary?: boolean;
}
+1 -1
View File
@@ -153,7 +153,7 @@ export function LoginPage() {
margin-top, which a second paragraph would repeat as a gap.
*/}
{/* ihasmail-inbuxa: this build is INBUXA's webmail, and its site is INBUXA's. */}
<span className="notranslate" translate="no">INBUXA webmail v{APP_VERSION}</span>
<span className="notranslate" translate="no">inbuxa webmail v{APP_VERSION}</span>
<br />
<a href="https://inbuxa.org" target="_blank" rel="noopener noreferrer" className="notranslate" translate="no">inbuxa.org</a>
{" · "}
+2 -2
View File
@@ -126,12 +126,12 @@ export function AdminDashboard() {
more numbers will be: this is a glance, and operating the server is
Stalwart's own administration. The link is the operator's to give. */}
<p className="hint admin-dashboard-note">
{t("Detailed metrics, the delivery queue, logs and server settings are in INBUXA Admin.")}
{t("Detailed metrics, the delivery queue, logs and server settings are in inbuxa Admin.")}
{adminUrl && (
<>
{" "}
<a href={adminUrl} target="_blank" rel="noopener noreferrer">
{t("Open INBUXA Admin")} <ExternalLink size={13} aria-hidden="true" />
{t("Open inbuxa Admin")} <ExternalLink size={13} aria-hidden="true" />
</a>
</>
)}
+1 -1
View File
@@ -186,7 +186,7 @@ export function RoleSheet({ role, roles, defaults, entries, permissionsError, on
{!creating && can(perms, "Role", "Destroy") && (
<DeleteRole
role={role}
blocked={kinds.length ? t("The mail server gives this role by default, so it can't be deleted. Change the defaults in INBUXA Admin first.") : locked ? t("This role carries permissions yours doesn't.") : null}
blocked={kinds.length ? t("The mail server gives this role by default, so it can't be deleted. Change the defaults in inbuxa Admin first.") : locked ? t("This role carries permissions yours doesn't.") : null}
onDeleted={onDeleted}
/>
)}
@@ -112,7 +112,7 @@ describe("the Administration dashboard", () => {
});
});
describe("the pointer to INBUXA Admin", () => {
describe("the pointer to inbuxa Admin", () => {
let host: HTMLDivElement;
let root: Root;
beforeEach(() => {
@@ -136,7 +136,7 @@ describe("the pointer to INBUXA Admin", () => {
it("names it, and links it where the operator has said where it is", async () => {
await renderWith("https://admin.example.com");
const note = host.querySelector(".admin-dashboard-note")!;
expect(note.textContent).toContain("INBUXA Admin");
expect(note.textContent).toContain("inbuxa Admin");
const link = note.querySelector("a")!;
expect(link.getAttribute("href")).toBe("https://admin.example.com");
expect(link.getAttribute("rel")).toBe("noopener noreferrer");
@@ -144,7 +144,7 @@ describe("the pointer to INBUXA Admin", () => {
it("names it without a link where nobody has", async () => {
await renderWith(null);
expect(host.querySelector(".admin-dashboard-note")?.textContent).toContain("INBUXA Admin");
expect(host.querySelector(".admin-dashboard-note")?.textContent).toContain("inbuxa Admin");
expect(host.querySelector(".admin-dashboard-note a")).toBeNull();
});
});
+2 -2
View File
@@ -35,13 +35,13 @@ export function AboutSettings() {
<table className="sessions-table">
<tbody>
<tr><td>{t("Signed in as")}</td><td>{session?.username}</td></tr>
<tr><td>{t("Mail server")}</td><td className="notranslate" translate="no">INBUXA</td></tr>
<tr><td>{t("Mail server")}</td><td className="notranslate" translate="no">inbuxa</td></tr>
<tr><td>{t("Accounts")}</td><td>{Object.values(session?.accounts ?? {}).map((a) => a.name).join(", ")}</td></tr>
<tr><td>{t("Max upload")}</td><td>{t("{size} MB", { size: Math.round(client.maxSizeUpload / 1048576) })}</td></tr>
<tr><td>{t("Image privacy proxy")}</td><td>{session?.ihasmail?.imageProxy ? t("enabled") : t("disabled")}</td></tr>
</tbody>
</table>
<p className="hint" style={{ marginTop: 6 }}>{t("This webmail works with the INBUXA mail server, and sign-in refuses a server that doesn't offer what it needs.")}</p>
<p className="hint" style={{ marginTop: 6 }}>{t("This webmail works with the inbuxa mail server, and sign-in refuses a server that doesn't offer what it needs.")}</p>
<p className="hint">{tNode("{app}'s own version is the date of the commit it was built from, followed by where that commit came from: {example} was built from a commit dated the 30th of August 2026 that arrived through pull request 129. A commit that did not come through one carries its short SHA instead — {sha}. The version deliberately says nothing about the mail server; what this build needs from the server is the line above.", { example: <strong className="notranslate" translate="no">v2026.8.30+pr129</strong>, sha: <code>+g1fa6578</code> }, { app: appName })}</p>
<h2>{t("Server capabilities")}</h2>
<div className="row wrap gap-4">