Notify language maintainers on PR merge

Close #46344

Signed-off-by: Alexander Schwartz <alexander.schwartz@ibm.com>
Signed-off-by: Alexander Schwartz <alexander.schwartz@gmx.net>
Co-authored-by: Robin Meese <39960884+robson90@users.noreply.github.com>
This commit is contained in:
Alexander Schwartz 2026-02-17 11:19:32 +01:00 committed by GitHub
parent f791337eec
commit ac83dfda42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 190 additions and 42 deletions

88
.github/language-maintainers.yml vendored Normal file
View file

@ -0,0 +1,88 @@
# Language maintainers for Keycloak translations
# This file maps language codes to their responsible maintainers. It is used to notify them once a translation changes.
# Format: language_code: [list of GitHub usernames]
languages:
ca:
name: Catalan
maintainers:
- jmallach
- Ecron
cs:
name: Czech
maintainers:
- pionl
- pschiffe
de:
name: German
maintainers:
- robson90
- ahus1
el:
name: Greek
maintainers:
- infl00p
- knaiskes
es:
name: Spanish
maintainers:
- herver1971
- anthieni
fr:
name: French
maintainers:
- Dodouce
- GitSpoon
it:
name: Italian
maintainers:
- GioviQ
- EdoardoTona
ja:
name: Japanese
maintainers:
- y-tabata
- wadahiro
- tnorimat
- k-tamura
nl:
name: Dutch
maintainers:
- janher
- edewit
pt_BR:
name: Portuguese (Brazil)
maintainers:
- rafaelrddc
- felipebz
- julianorodrigox
ro:
name: Romanian
maintainers:
- edwint88
- liviuroman
ru:
name: Russian
maintainers:
- petrov9
- pasternake
sl:
name: Slovenian
maintainers:
- mathmul
- SaraPristovnik
tr:
name: Turkish
maintainers:
- spctr
- ariferol
zh_Hans:
name: Simplified Chinese
maintainers:
- jasonqsong
- charliedcc
zh_Hant:
name: Traditional Chinese
maintainers:
- allen0099
- benwater12

View file

@ -0,0 +1,92 @@
name: Translation Maintainer Notification
on:
pull_request:
types: [closed]
paths:
- 'themes/**/messages_*.properties'
- 'js/**/messages_*.properties'
defaults:
run:
shell: bash
permissions:
pull-requests: write
jobs:
notify-maintainers:
name: Notify language maintainers of changes
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Yq
run: sudo snap install yq
- name: Get changed language files and notify maintainers
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
# language=bash
run: |
# Get the list of changed files in this PR
CHANGED_FILES=$(gh pr view "$PR_NUMBER" --json files --jq '.files[].path' | grep 'messages_.*\.properties' || true)
if [ -z "$CHANGED_FILES" ]; then
echo "No translation files changed"
exit 0
fi
echo "Changed files:"
echo "$CHANGED_FILES"
# Extract unique language codes from filenames
declare -A languages
while IFS= read -r file; do
# Extract language code from messages_XX.properties or messages_XX_YY.properties
if [[ $file =~ messages_([a-z]{2}(_[A-Z][a-z]+)?)\.properties ]]; then
lang_code="${BASH_REMATCH[1]}"
# Skip English language
if [ "$lang_code" != "en" ]; then
languages["$lang_code"]=1
fi
fi
done <<< "$CHANGED_FILES"
if [ ${#languages[@]} -eq 0 ]; then
echo "No non-English language codes found in changed files"
exit 0
fi
echo "Languages changed: ${!languages[@]}"
# Read maintainers file and build comment
COMMENT="## Translation Changes Notification\n\n"
COMMENT+="*Language maintainers:* Please review the translation changes in your language in [Weblate](https://hosted.weblate.org/projects/keycloak/).\n\n"
COMMENT+="The following languages have been updated in this PR:\n\n"
# Sort languages for deterministic output
for lang_code in $(printf '%s\n' "${!languages[@]}" | sort); do
# Look up maintainers in the YAML file
yaml_key="$lang_code"
LANG_NAME=$(yq eval ".languages.\"${yaml_key}\".name // \"Unknown\"" .github/language-maintainers.yml)
MAINTAINERS=$(yq eval ".languages.\"${yaml_key}\".maintainers // [] | join(\", @\")" .github/language-maintainers.yml)
if [ "$MAINTAINERS" != "" ] && [ "$MAINTAINERS" != "null" ]; then
COMMENT+="### ${LANG_NAME} (\`${lang_code}\`)\n"
COMMENT+="@${MAINTAINERS}\n\n"
else
COMMENT+="### \`${lang_code}\`\n"
COMMENT+="No maintainers configured for this language.\n\n"
fi
COMMENT+="[Changes waiting for approval.](https://hosted.weblate.org/translate/keycloak/-/${lang_code}/?q=state:translated)\n\n"
done
# Post comment to PR
echo -e "$COMMENT" | gh pr comment "$PR_NUMBER" --body-file -

View file

@ -78,31 +78,16 @@ Keycloak uses [Weblate](https://hosted.weblate.org/projects/keycloak/), a web-ba
It allows for notifications when the original string changes, and keeps track of missing translations. It also allows contributors without knowledge of Git to contribute to the translations.
The following translations are available in Weblate. If you have any questions or need assistance, feel free to reach out to the language maintainers listed below:
See here for a [list of all translations available in Weblate and their status](https://www.keycloak.org/translations).
* German: [Robin Meese](https://github.com/robson90) && [Alexander Schwartz](https://github.com/ahus1)
* Dutch: [janher](https://github.com/janher) && [Erik Jan de wit](https://github.com/edewit)
* Japanese: [y-tabata](https://github.com/y-tabata) && [wadahiro](https://github.com/wadahiro) && [tnorimat](https://github.com/tnorimat) && [k-tamura](https://github.com/k-tamura)
* Catalan: [jmallach](https://github.com/jmallach) && [Ecron](https://github.com/Ecron)
* Spanish: [herver1971](https://github.com/herver1971) && [anthieni](https://github.com/anthieni)
* Slovenian: [mathmul](https://github.com/mathmul) && [SaraPristovnik](https://github.com/SaraPristovnik)
* Italian: [GioviQ](https://github.com/GioviQ) && [EdoardoTona](https://github.com/EdoardoTona)
* Romanian: [edwint88](https://github.com/edwint88) && [liviuroman](https://github.com/liviuroman)
* Portuguese (Brazil): [rafaelrddc](https://github.com/rafaelrddc) && [felipebz](https://github.com/felipebz) && [julianorodrigox](https://github.com/julianorodrigox)
* French: [Dodouce](https://github.com/Dodouce) && [GitSpoon](https://github.com/GitSpoon)
* Russian: [petrov9](https://github.com/petrov9) && [pasternake](https://github.com/pasternake)
* Traditional Chinese: [allen0099](https://github.com/allen0099) && [benwater12](https://github.com/benwater12)
* Greek: [infl00p](https://github.com/infl00p) && [knaiskes](https://github.com/knaiskes)
* Turkish: [spctr](https://github.com/spctr) && [ariferol](https://github.com/ariferol)
* Czech: [pionl](https://github.com/pionl) && [pschiffe](https://github.com/pschiffe)
* Simplified Chinese: [jasonqsong](https://github.com/jasonqsong) && [charliedcc](https://github.com/charliedcc)
If you have any questions or need assistance, feel free to reach out to the language maintainers listed in [the language maintainers file](../.github/language-maintainers.yml).
To add a new language, see the section "Steps to Add a new language to Weblate" below.
**Tasks of the translator:**
1. Sign Up: Visit Weblate to create an account.
2. Configuration: After signing up, configure your Weblate account settings according to your preferences.
2. Configuration: After signing up, configure your Weblate account settings according to your preferences.
Please note that the committer email is set to the login email address by default. You can adjust this in your Weblate profile under Account settings.
3. Navigate to [Keycloak on Weblate](https://hosted.weblate.org/projects/keycloak/), confirm the contribution agreement, and start contributing translations.
4. For all untranslated and not-yet-approved keys you can directly add or update the translation.
@ -143,28 +128,11 @@ the [localization platform discussion](https://github.com/keycloak/keycloak/disc
- Each language requires **two volunteers**
- Volunteers should comment on the discussion thread to confirm their participation.
- The Keycloak-Team will then
- enable the specific language
- invite the two volunteers
- comment on discussion thread, that the language has been enabled
- in Weblate:
- Enable the specific language.
- Invite the two volunteers,
- on GitHub:
- Comment on discussion thread, that the language has been enabled
- Update [the language maintainers file](../.github/language-maintainers.yml) with the GitHub handles of the language mainatainers to enable notifications on updated files on GitHub.
- If it is a language that wasn't translated before, update the `theme.properties` files to include the new language.
- Weblate synchronizes daily, so it may take up to 24 hours after enabling the language before you can start your first translations
## Weblate Translation status
| Language | Account UI | Admin UI | Theme base/account | Theme base/admin | Theme base/email | Theme base/login | Overall |
|--------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
| [German](https://hosted.weblate.org/projects/keycloak/-/de/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/de/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/de/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/de/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/de/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/de/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/de/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/de/svg-badge.svg) |
| [Dutch](https://hosted.weblate.org/projects/keycloak/-/nl/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/nl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/nl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/nl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/nl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/nl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/nl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/nl/svg-badge.svg) |
| [Japanese](https://hosted.weblate.org/projects/keycloak/-/ja/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/ja/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/ja/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/ja/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/ja/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/ja/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/ja/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/ja/svg-badge.svg) |
| [Catalan](https://hosted.weblate.org/projects/keycloak/-/ca/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/ca/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/ca/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/ca/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/ca/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/ca/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/ca/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/ca/svg-badge.svg) |
| [Spanish](https://hosted.weblate.org/projects/keycloak/-/es/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/es/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/es/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/es/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/es/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/es/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/es/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/es/svg-badge.svg) |
| [Slovenian](https://hosted.weblate.org/projects/keycloak/-/sl/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/sl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/sl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/sl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/sl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/sl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/sl/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/sl/svg-badge.svg) |
| [Italian](https://hosted.weblate.org/projects/keycloak/-/it/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/it/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/it/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/it/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/it/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/it/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/it/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/it/svg-badge.svg) |
| [Romanian](https://hosted.weblate.org/projects/keycloak/-/ro/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/ro/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/ro/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/ro/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/ro/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/ro/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/ro/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/ro/svg-badge.svg) |
| [Portuguese (Brazil)](https://hosted.weblate.org/projects/keycloak/-/pt_BR/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/pt_BR/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/pt_BR/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/pt_BR/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/pt_BR/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/pt_BR/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/pt_BR/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/pt_BR/svg-badge.svg) |
| [French](https://hosted.weblate.org/projects/keycloak/-/fr/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/fr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/fr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/fr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/fr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/fr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/fr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/fr/svg-badge.svg) |
| [Russian](https://hosted.weblate.org/projects/keycloak/-/ru/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/ru/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/ru/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/ru/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/ru/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/ru/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/ru/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/ru/svg-badge.svg) |
| [Traditional Chinese](https://hosted.weblate.org/projects/keycloak/-/zh_hant/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/zh_hant/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/zh_hant/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/zh_hant/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/zh_hant/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/zh_hant/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/zh_hant/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/zh_hant/svg-badge.svg) |
| [Greek](https://hosted.weblate.org/projects/keycloak/-/el/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/el/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/el/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/el/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/el/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/el/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/el/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/el/svg-badge.svg) |
| [Turkish](https://hosted.weblate.org/projects/keycloak/-/tr/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/tr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/tr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/tr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/tr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/tr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/tr/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/tr/svg-badge.svg) |
| [Czech](https://hosted.weblate.org/projects/keycloak/-/cz/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/cz/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/cz/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/cz/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/cz/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/cz/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/cz/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/cz/svg-badge.svg) |
| [Simplified Chinese](https://hosted.weblate.org/projects/keycloak/-/zh_Hans/) | ![Translation status](https://hosted.weblate.org/widget/keycloak/account-ui/zh_Hans/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/admin-ui/zh_Hans/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseaccount/zh_Hans/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseadmin/zh_Hans/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baseemail/zh_Hans/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/theme-baselogin/zh_Hans/svg-badge.svg) | ![Translation status](https://hosted.weblate.org/widget/keycloak/-/zh_Hans/svg-badge.svg) |