Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6,536 changes: 6,536 additions & 0 deletions .github/translation-state.json

Large diffs are not rendered by default.

114 changes: 114 additions & 0 deletions .github/workflows/translate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Translate Strings

on:
# Only when the English source actually changes. Any other push is a no-op
# anyway, since the script would find nothing missing.
push:
branches:
- main
- feat/clean-port
paths:
- 'custom_components/opendisplay/translations/en.json'

# Allow manual trigger, optionally scoped to specific languages
workflow_dispatch:
inputs:
languages:
description: 'Comma-separated language codes (blank = all)'
required: false
default: ''

permissions:
contents: write
pull-requests: write
# Lets the built-in GITHUB_TOKEN call GitHub Models. No API key, no billing.
models: read

jobs:
translate:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Translate missing strings
id: translate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 scripts/translate.py \
${{ inputs.languages && format('--languages {0}', inputs.languages) || '' }}

- name: Verify generated files
if: steps.translate.outputs.changed == 'true'
run: python3 scripts/verify_translations.py

- name: Close existing automated PR
if: steps.translate.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
existing_prs=$(gh pr list --repo "${{ github.repository }}" --head "automated/translations" --state open --json number --jq '.[].number')
for pr_number in $existing_prs; do
echo "Closing existing PR #$pr_number"
gh pr close "$pr_number" --repo "${{ github.repository }}" --comment "Superseded by a newer automated update."
done

- name: Create Pull Request
if: steps.translate.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
# Target whichever branch triggered this run
base: ${{ github.ref_name }}
commit-message: 'chore: update translations'
title: 'chore: update translations'
body: |
`translations/en.json` changed, so the strings that were missing from
each language have been machine-translated using GitHub Models.
Existing translations were not re-sent to the model.

## Changes

${{ steps.translate.outputs.summary }}

## Review notes

- Placeholders such as `{name}` and `{number}` are validated
automatically: any translation that drops, renames, or adds one is
rejected rather than committed.
- Translations avoid the familiar/polite distinction (German du/Sie,
French tu/vous, ...) by using impersonal phrasing. Anything that
slipped through is flagged as a warning in the workflow log.
- Manual corrections are preserved. If you fix a translation by hand,
this workflow will not overwrite it, even when the English source
changes later. It reports it under "Needs review" instead.

---

*This PR was automatically created by the translate workflow*
branch: 'automated/translations'
delete-branch: true
add-paths: |
custom_components/opendisplay/translations/
.github/translation-state.json
labels: |
automated
translations

- name: Summary
run: |
if [ "${{ steps.translate.outputs.changed }}" == "true" ]; then
echo "Translations updated - PR opened against ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.translate.outputs.summary }}" >> $GITHUB_STEP_SUMMARY
else
echo "No missing translations - nothing to do" >> $GITHUB_STEP_SUMMARY
fi
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,32 @@ Devices should be automatically discovered after installation.
color: "black"
```

## Translations

The integration is available in Czech, Dutch, English, French, German, Italian,
Polish, Portuguese (European and Brazilian), and Spanish.

English is written by hand. **Every other language is machine-translated** and
has not been reviewed by a native speaker, so expect the occasional awkward or
plainly wrong phrasing. Corrections are very welcome, and they stick:

- Edit the relevant file in `custom_components/opendisplay/translations/` and
open a pull request. There is no need to touch anything else.
- **Your wording will not be overwritten.** The translation workflow records a
fingerprint of what it generated, so it can tell its own output from a human
edit. Once you have corrected a string it is treated as yours. If the English
source later changes, the workflow flags the string for review rather than
replacing your version.
- Only strings that are missing, or whose English source was reworded, are ever
sent to a model.

To add a language, add its code and name to `LANGUAGES` in
`scripts/translate.py` and open a pull request; the workflow fills in the file.

Translations deliberately avoid the familiar/polite distinction (German du/Sie,
French tu/vous, and so on) by using impersonal phrasing such as infinitives for
instructions. Please keep that style when correcting a string.

## Contributing
- Feature requests and bug reports are welcome! Please open an issue on GitHub
- Pull requests are encouraged
Expand Down
2 changes: 1 addition & 1 deletion custom_components/opendisplay/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
"message": "Failed to upload to the display: {error}"
},
"url_not_allowed": {
"message": "URL `{url}` is not allowed. Add it to `allowlist_external_urls` in your configuration.yaml."
"message": "URL `{url}` is not allowed. Add it to `allowlist_external_urls` in configuration.yaml."
}
},
"selector": {
Expand Down
Loading
Loading