mirror of
https://github.com/stenzek/duckstation.git
synced 2026-10-12 02:23:23 +00:00
CI: Ensure translations are cleaned on pull request
This commit is contained in:
@@ -4,14 +4,20 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/duckstation-qt/translations/*.ts'
|
||||
- 'src/duckstation-qt/translations/*.sh'
|
||||
- 'src/duckstation-qt/translations/*.bat'
|
||||
- 'scripts/translation/**'
|
||||
- '.github/workflows/translation-lint.yml'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
paths:
|
||||
- 'src/duckstation-qt/translations/*.ts'
|
||||
- 'src/duckstation-qt/translations/*.sh'
|
||||
- 'src/duckstation-qt/translations/*.bat'
|
||||
- 'scripts/translation/**'
|
||||
- '.github/workflows/translation-lint.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -29,20 +35,27 @@ jobs:
|
||||
- name: Test Translation Tools
|
||||
run: python -m unittest discover -s scripts/translation/tests -v
|
||||
|
||||
- name: Check Translation Placeholders
|
||||
- name: Check Translation Catalogs
|
||||
shell: bash
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
BEFORE_SHA: ${{ github.event.before }}
|
||||
AFTER_SHA: ${{ github.sha }}
|
||||
run: |
|
||||
if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
||||
mapfile -t files < <(
|
||||
git diff --name-only --diff-filter=ACMRT "$BASE_SHA...$HEAD_SHA" -- \
|
||||
'src/duckstation-qt/translations/*.ts'
|
||||
)
|
||||
elif [[ "$EVENT_NAME" == "push" ]]; then
|
||||
mapfile -t files < <(
|
||||
git diff --name-only --diff-filter=ACMRT "$BEFORE_SHA..$AFTER_SHA" -- \
|
||||
'src/duckstation-qt/translations/*.ts'
|
||||
)
|
||||
else
|
||||
files=(src/duckstation-qt/translations/*.ts)
|
||||
files=()
|
||||
fi
|
||||
|
||||
if (( ${#files[@]} == 0 )); then
|
||||
@@ -51,5 +64,6 @@ jobs:
|
||||
fi
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
python scripts/translation/validate_ts.py "$file"
|
||||
python scripts/translation/validate_ts.py \
|
||||
--reject-obsolete --reject-locations "$file"
|
||||
done
|
||||
|
||||
@@ -549,6 +549,18 @@ class TranslationToolTests(unittest.TestCase):
|
||||
strict = self.run_validator(catalog, "--strict-required-tags", expect=1)
|
||||
self.assertIn("missing rich-text tags", strict.stdout)
|
||||
|
||||
def test_validation_can_reject_locations_and_old_messages(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
catalog = Path(directory) / "catalog.ts"
|
||||
catalog.write_text(FIXTURE, encoding="utf-8")
|
||||
|
||||
locations = self.run_validator(catalog, "--reject-locations", expect=1)
|
||||
self.assertIn("source location information is not permitted", locations.stdout)
|
||||
|
||||
obsolete = self.run_validator(catalog, "--reject-obsolete", expect=1)
|
||||
self.assertIn("vanished message is not permitted", obsolete.stdout)
|
||||
self.assertIn("obsolete message is not permitted", obsolete.stdout)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate Qt TS structure, completeness, placeholders, plurals, and rich text."""
|
||||
"""Validate Qt TS structure, metadata, completeness, placeholders, plurals, and rich text."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -44,6 +44,16 @@ def parse_args() -> argparse.Namespace:
|
||||
help="treat missing or unbalanced rich-text tags as errors",
|
||||
)
|
||||
parser.add_argument("--strict-extra-tags", action="store_true", help="treat added rich-text tags as errors")
|
||||
parser.add_argument(
|
||||
"--reject-obsolete",
|
||||
action="store_true",
|
||||
help="fail if the catalog contains obsolete or vanished messages",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reject-locations",
|
||||
action="store_true",
|
||||
help="fail if the catalog contains source location information",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -90,12 +100,16 @@ def main() -> int:
|
||||
type_counts: collections.Counter[str] = collections.Counter()
|
||||
for message in messages:
|
||||
type_counts[message.translation_type] += 1
|
||||
label = diagnostic_label(args.catalog, message)
|
||||
if args.reject_obsolete and message.translation_type in SKIPPED_TYPES:
|
||||
errors.append(f"{label}: {message.translation_type} message is not permitted")
|
||||
if args.reject_locations and message.locations:
|
||||
errors.append(f"{label}: source location information is not permitted")
|
||||
if message.translation_type in SKIPPED_TYPES:
|
||||
continue
|
||||
if selected_ids is not None and message.identifier not in selected_ids:
|
||||
continue
|
||||
checked += 1
|
||||
label = diagnostic_label(args.catalog, message)
|
||||
if not args.placeholders_only:
|
||||
if message.identity.numerus and not message.plural_translations:
|
||||
errors.append(f"{label}: numerus message has no <numerusform> forms")
|
||||
|
||||
Reference in New Issue
Block a user