Enable TypeScript 7 RC side-by-side with TypeScript 6 #2433
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Translation Validation | |
| on: | |
| push: | |
| branches: [ main ] | |
| paths: | |
| - 'index*.html' | |
| - 'news/*.html' | |
| - 'scripts/validate-translations.js' | |
| - 'scripts/translation-dictionary.ts' | |
| - 'scripts/detect-swedish-leakage.ts' | |
| - '.github/workflows/translation-validation.yml' | |
| - 'TRANSLATION_GUIDE.md' | |
| pull_request: | |
| branches: [ main ] | |
| paths: | |
| - 'index*.html' | |
| - 'news/*.html' | |
| - 'scripts/validate-translations.js' | |
| - 'scripts/translation-dictionary.ts' | |
| - 'scripts/detect-swedish-leakage.ts' | |
| - '.github/workflows/translation-validation.yml' | |
| - 'TRANSLATION_GUIDE.md' | |
| permissions: | |
| contents: read | |
| jobs: | |
| validate-translations: | |
| runs-on: ubuntu-26.04 | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout repository | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '26' | |
| cache: 'npm' | |
| cache-dependency-path: | | |
| package-lock.json | |
| .github/workflows/translation-validation.yml | |
| - name: Validate all translation files | |
| id: validate | |
| run: | | |
| echo "🌐 Validating translations for all 14 languages..." | |
| echo "" | |
| npm run validate-translations | |
| - name: Count language files | |
| id: count | |
| run: | | |
| echo "" | |
| echo "📊 Language file statistics:" | |
| echo "" | |
| echo "Total language files: $(ls -1 index*.html | wc -l)" | |
| echo "" | |
| for file in index*.html; do | |
| size=$(wc -c < "$file" | numfmt --to=iec) | |
| lines=$(wc -l < "$file") | |
| echo " $file: $size ($lines lines)" | |
| done | |
| - name: Verify RTL languages | |
| id: rtl | |
| run: | | |
| echo "" | |
| echo "🔄 Verifying RTL (Right-to-Left) language support:" | |
| echo "" | |
| # Check Arabic | |
| if grep -q 'lang="ar" dir="rtl"' index_ar.html; then | |
| echo "✅ Arabic (ar): RTL support confirmed" | |
| else | |
| echo "❌ Arabic (ar): RTL support MISSING" | |
| exit 1 | |
| fi | |
| # Check Hebrew | |
| if grep -q 'lang="he" dir="rtl"' index_he.html; then | |
| echo "✅ Hebrew (he): RTL support confirmed" | |
| else | |
| echo "❌ Hebrew (he): RTL support MISSING" | |
| exit 1 | |
| fi | |
| - name: Verify hreflang tags | |
| id: hreflang | |
| run: | | |
| echo "" | |
| echo "🔗 Verifying hreflang tags for SEO:" | |
| echo "" | |
| for file in index*.html; do | |
| count=$(grep -c 'hreflang=' "$file" || echo 0) | |
| if [ "$count" -ge 14 ]; then | |
| echo "✅ $file: $count hreflang tags (sufficient)" | |
| else | |
| echo "⚠️ $file: $count hreflang tags (should be 14+)" | |
| fi | |
| done | |
| - name: Validate news article language purity | |
| id: news_purity | |
| run: | | |
| echo "" | |
| echo "📰 Validating news article language purity..." | |
| echo "" | |
| PURITY_ERRORS=0 | |
| ARTICLES_CHECKED=0 | |
| # Check each non-Swedish news article for Swedish content leakage | |
| for lang_code in en da no fi de fr es nl ar he ja ko zh; do | |
| for article in news/*-${lang_code}.html; do | |
| if [ ! -f "$article" ]; then continue; fi | |
| ARTICLES_CHECKED=$((ARTICLES_CHECKED + 1)) | |
| # Check for untranslated data-translate markers | |
| if grep -q 'data-translate="true"' "$article"; then | |
| echo " ❌ UNTRANSLATED content in: $(basename $article)" | |
| grep -n 'data-translate="true"' "$article" | head -3 | |
| PURITY_ERRORS=$((PURITY_ERRORS + 1)) | |
| fi | |
| # Check for Swedish characters in h3 tags (document titles) | |
| # å, ä, ö are strong indicators of untranslated Swedish | |
| swedish_h3=$(grep -oP '<h3[^>]*>[^<]*[åäöÅÄÖ][^<]*</h3>' "$article" 2>/dev/null | wc -l) | |
| if [ "$swedish_h3" -gt 0 ]; then | |
| echo " ⚠️ Possible Swedish in <h3> of: $(basename $article) ($swedish_h3 matches)" | |
| PURITY_ERRORS=$((PURITY_ERRORS + 1)) | |
| fi | |
| done | |
| done | |
| echo "" | |
| echo " Articles checked: $ARTICLES_CHECKED" | |
| if [ $PURITY_ERRORS -gt 0 ]; then | |
| echo " ⚠️ Language purity issues: $PURITY_ERRORS (warning only)" | |
| else | |
| echo " ✅ Language purity: All articles clean" | |
| fi | |
| - name: Run Swedish leakage detector | |
| id: leakage_detector | |
| if: hashFiles('news/*.html') != '' | |
| continue-on-error: true # Advisory until existing article leakage is fixed | |
| run: | | |
| echo "" | |
| echo "🔍 Running Swedish leakage detector on translated articles..." | |
| echo "" | |
| npx tsx scripts/detect-swedish-leakage.ts --dir news/ --threshold 5 | |
| - name: Validate BCP-47 consistency | |
| id: bcp47 | |
| run: | | |
| echo "" | |
| echo "🏷️ Validating BCP-47 language tag consistency..." | |
| echo "" | |
| BCP47_ERRORS=0 | |
| # Norwegian articles must use lang="nb" (not "no") | |
| for article in news/*-no.html; do | |
| if [ ! -f "$article" ]; then continue; fi | |
| if grep -q '<html lang="no"' "$article"; then | |
| echo " ❌ $(basename $article): html lang=\"no\" should be lang=\"nb\"" | |
| BCP47_ERRORS=$((BCP47_ERRORS + 1)) | |
| fi | |
| if grep -q '"inLanguage": "no"' "$article"; then | |
| echo " ❌ $(basename $article): inLanguage \"no\" should be \"nb\"" | |
| BCP47_ERRORS=$((BCP47_ERRORS + 1)) | |
| fi | |
| done | |
| # RTL articles must have dir="rtl" | |
| for article in news/*-ar.html; do | |
| if [ ! -f "$article" ]; then continue; fi | |
| if ! grep -q 'dir="rtl"' "$article"; then | |
| echo " ❌ $(basename $article): missing dir=\"rtl\"" | |
| BCP47_ERRORS=$((BCP47_ERRORS + 1)) | |
| fi | |
| done | |
| for article in news/*-he.html; do | |
| if [ ! -f "$article" ]; then continue; fi | |
| if ! grep -q 'dir="rtl"' "$article"; then | |
| echo " ❌ $(basename $article): missing dir=\"rtl\"" | |
| BCP47_ERRORS=$((BCP47_ERRORS + 1)) | |
| fi | |
| done | |
| if [ $BCP47_ERRORS -gt 0 ]; then | |
| echo "" | |
| echo " ❌ BCP-47 consistency: $BCP47_ERRORS error(s)" | |
| exit 1 | |
| else | |
| echo " ✅ BCP-47 consistency: All articles consistent" | |
| fi | |
| - name: Translation validation summary | |
| if: always() | |
| run: | | |
| echo "" | |
| echo "==========================================" | |
| echo " Translation Validation Summary" | |
| echo "==========================================" | |
| echo "" | |
| # Check outcomes of previous steps | |
| if [ "${{ steps.validate.outcome }}" = "success" ]; then | |
| echo "✅ Translation validation: PASSED" | |
| else | |
| echo "❌ Translation validation: FAILED" | |
| fi | |
| if [ "${{ steps.count.outcome }}" = "success" ]; then | |
| echo "✅ Language file count: PASSED" | |
| else | |
| echo "❌ Language file count: FAILED" | |
| fi | |
| if [ "${{ steps.rtl.outcome }}" = "success" ]; then | |
| echo "✅ RTL support: PASSED" | |
| else | |
| echo "❌ RTL support: FAILED" | |
| fi | |
| if [ "${{ steps.hreflang.outcome }}" = "success" ]; then | |
| echo "✅ Hreflang tags: PASSED" | |
| else | |
| echo "❌ Hreflang tags: FAILED" | |
| fi | |
| if [ "${{ steps.news_purity.outcome }}" = "success" ]; then | |
| echo "✅ News article language purity: PASSED" | |
| else | |
| echo "⚠️ News article language purity: WARNINGS" | |
| fi | |
| if [ "${{ steps.leakage_detector.outcome }}" = "success" ]; then | |
| echo "✅ Swedish leakage detector: PASSED" | |
| elif [ "${{ steps.leakage_detector.outcome }}" = "skipped" ]; then | |
| echo "⏭️ Swedish leakage detector: SKIPPED (no news articles)" | |
| else | |
| echo "⚠️ Swedish leakage detector: WARNINGS" | |
| fi | |
| if [ "${{ steps.bcp47.outcome }}" = "success" ]; then | |
| echo "✅ BCP-47 consistency: PASSED" | |
| else | |
| echo "❌ BCP-47 consistency: FAILED" | |
| fi | |
| echo "" | |
| echo "Languages: EN, SV, DA, NO, FI, DE, FR, ES, NL, AR, HE, JA, KO, ZH" | |
| echo "" | |
| echo "==========================================" |