various improvements to make release 1 complete

This commit is contained in:
Reindl David (IT-PTR-CEN2-SL10)
2026-03-27 13:59:28 +01:00
parent 9ea962131a
commit 6b9c3fefa1
37 changed files with 7695 additions and 1803 deletions
+111
View File
@@ -0,0 +1,111 @@
#!/bin/bash
# Swiss Football Matchdata - Distribution Package Builder
# This script creates a distribution-ready ZIP package excluding development files
set -e # Exit on error
# Get the directory where this script is located
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_ROOT="$(dirname "$SCRIPT_DIR")"
PLUGIN_NAME="swiss-football-matchdata"
DIST_DIR="$PLUGIN_ROOT/dist"
# Colors for output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}=== Building Distribution Package ===${NC}"
# Create distribution directory
echo "Creating distribution directory..."
mkdir -p "$DIST_DIR"
# Check if plugin root has package.json
if [ ! -f "$PLUGIN_ROOT/package.json" ]; then
echo "Error: package.json not found in $PLUGIN_ROOT"
exit 1
fi
# Clean up any previous distribution
echo "Cleaning up previous distribution..."
rm -rf "$DIST_DIR/$PLUGIN_NAME" "$DIST_DIR/$PLUGIN_NAME.zip"
# Copy all plugin files, excluding development artifacts
echo "Copying plugin files (excluding development files)..."
rsync -av "$PLUGIN_ROOT/" \
--exclude='.git' \
--exclude='node_modules' \
--exclude='.npm-cache' \
--exclude='package.json' \
--exclude='package-lock.json' \
--exclude='.gitignore' \
--exclude='README-DEV.md' \
--exclude='DEV-README.md' \
--exclude='.DS_Store' \
--exclude='*.swp' \
--exclude='.idea/' \
--exclude='test/' \
--exclude='src/' \
--exclude='webpack.config.js' \
--exclude='dev-scripts/' \
--exclude='dev-docs/' \
--exclude='dist/' \
"$DIST_DIR/$PLUGIN_NAME/" \
> /dev/null 2>&1 || true
# Verify essential files are present
echo "Verifying distribution contents..."
if [ ! -f "$DIST_DIR/$PLUGIN_NAME/swiss-football-matchdata.php" ]; then
echo "Error: Main plugin file not found in distribution"
exit 1
fi
if [ ! -f "$DIST_DIR/$PLUGIN_NAME/assets/build/editor-blocks.js" ]; then
echo "Error: Compiled editor bundle not found. Run 'npm run build' first."
exit 1
fi
# Create ZIP archive
echo "Creating ZIP archive..."
(cd "$DIST_DIR" && zip -r -q "$PLUGIN_NAME.zip" "$PLUGIN_NAME/")
# Get file sizes
DIST_SIZE=$(du -sh "$DIST_DIR/$PLUGIN_NAME" | cut -f1)
ZIP_SIZE=$(ls -lh "$DIST_DIR/$PLUGIN_NAME.zip" | awk '{print $5}')
echo -e "${GREEN}✓ Distribution package created successfully!${NC}"
echo ""
echo "📦 Distribution Summary:"
echo " Location: $DIST_DIR/$PLUGIN_NAME.zip"
echo " Uncompressed size: $DIST_SIZE"
echo " Compressed ZIP size: $ZIP_SIZE"
echo ""
# List key files included
echo "📋 Key files included:"
echo " ✓ swiss-football-matchdata.php (main plugin file)"
echo " ✓ assets/build/editor-blocks.js (compiled editor bundle)"
echo " ✓ includes/* (PHP backend files)"
echo " ✓ blocks/* (block metadata)"
echo " ✓ languages/* (i18n translations)"
echo " ✓ README.md (user documentation)"
echo ""
# List what was excluded
echo "🚫 Excluded from distribution:"
echo " ✗ node_modules/ (development dependencies)"
echo " ✗ src/ (source files)"
echo " ✗ test/ (test files)"
echo " ✗ dev-scripts/ (scripts for development)"
echo " ✗ dev-docs/ (development documentation)"
echo " ✗ package.json / package-lock.json"
echo " ✗ webpack.config.js"
echo " ✗ README-DEV.md"
echo " ✗ .git (git history)"
echo ""
echo -e "${GREEN}Ready to distribute!${NC}"
echo "Install by uploading $DIST_DIR/$PLUGIN_NAME.zip to WordPress Admin → Plugins → Add New → Upload"
+522
View File
@@ -0,0 +1,522 @@
#!/bin/bash
################################################################################
# Swiss Football Matchdata - i18n Management Script
#
# Complete i18n workflow using wp-cli:
# 1. Extract strings from PHP/JS to .pot file
# 2. Translate .pot to specified languages
# 3. Generate .mo files from .po files
# 4. Clean up regional language variants
#
# Usage:
# ./dev-scripts/i18n-manage.sh [extract|translate|build|clean|all]
#
# Commands:
# extract - Extract i18n strings and generate .pot file
# translate - Generate .po files for all languages (requires jq)
# build - Generate .mo files from .po files
# clean - Remove regional language variants
# all - Run all steps: extract → translate → build → clean
#
# Configuration:
# Modify the CONFIG section below to match your environment
#
# Dependencies:
# - wp-cli (via docker compose when WP_CLI_WRAPPER is used)
# - jq (for JSON translation data handling)
# - msgfmt (for generating .mo files)
#
################################################################################
set -e
################################################################################
# CONFIGURATION - Modify these values for your environment
################################################################################
# WordPress CLI command wrapper (for docker environments)
# Use local wp-cli: WP_CLI_CMD="wp"
# Use docker compose with working directory: WP_CLI_CMD="docker compose -f ~/Development/wordpress-dev/wp-dev-compose.yml run -w /var/www/html/wp-content/plugins/swiss-football-matchdata --rm wp-cli"
WP_CLI_CMD="docker compose -f ~/Development/wordpress-dev/wp-dev-compose.yml run -w /var/www/html/wp-content/plugins/swiss-football-matchdata --rm wp-cli"
# Plugin slug
PLUGIN_SLUG="swi_foot_matchdata"
# Text domain (must match in plugin)
TEXT_DOMAIN="swi_foot_matchdata"
# Languages to support: language_code:language_name
# Format: LANGUAGE_CODE|LANGUAGE_NAME (space-separated for compatibility)
LANGUAGES="de_DE:German fr_FR:French it_IT:Italian en_US:English"
# Regional variants to clean up (remove if they exist)
# These will be removed to keep only the main language codes
REGIONAL_VARIANTS=(
"de_AT" # Austrian German
"de_CH" # Swiss German
)
################################################################################
# COLORS & OUTPUT
################################################################################
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() {
echo -e "${BLUE}ℹ${NC} $1"
}
log_success() {
echo -e "${GREEN}✓${NC} $1"
}
log_warning() {
echo -e "${YELLOW}⚠${NC} $1"
}
log_error() {
echo -e "${RED}✗${NC} $1"
}
log_section() {
echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
}
################################################################################
# UTILITY FUNCTIONS
################################################################################
check_dependencies() {
local missing_deps=0
# Check for wp-cli
if ! eval "$WP_CLI_CMD --version" &>/dev/null; then
log_error "wp-cli not found or not accessible via: $WP_CLI_CMD"
missing_deps=1
fi
# Check for msgfmt (gettext tools)
if ! command -v msgfmt &>/dev/null; then
log_error "msgfmt not found. Install gettext tools:"
echo " macOS: brew install gettext"
echo " Ubuntu: sudo apt-get install gettext"
missing_deps=1
fi
# Check for jq (optional but recommended)
if ! command -v jq &>/dev/null; then
log_warning "jq not installed (optional). Install for better translation support:"
echo " macOS: brew install jq"
echo " Ubuntu: sudo apt-get install jq"
fi
if [[ $missing_deps -eq 1 ]]; then
return 1
fi
return 0
}
get_language_name() {
local code=$1
for pair in $LANGUAGES; do
local lang_code="${pair%:*}"
local lang_name="${pair#*:}"
if [[ "$lang_code" == "$code" ]]; then
echo "$lang_name"
return 0
fi
done
echo "Unknown"
}
################################################################################
# EXTRACTION
################################################################################
extract_strings() {
log_section "Extracting i18n Strings"
local pot_file="languages/${PLUGIN_SLUG}.pot"
local exclude_patterns="node_modules,vendor,assets/build,wp-json"
log_info "Extracting strings to: $pot_file"
# Create languages directory if it doesn't exist
mkdir -p languages
# Use wp-cli to extract strings
# Note: wp-cli automatically handles:
# - Translators comments (/* translators: ... */)
# - Multiple placeholders with ordered syntax (%1$d, %2$s, etc.)
# - WordPress i18n functions (__, _e, _x, _n, etc.)
# Syntax: wp i18n make-pot <source-directory> <output-file-path>
log_info "Running wp-cli extraction command..."
log_info " Working directory (Docker): /var/www/html/wp-content/plugins/swiss-football-matchdata"
log_info " Plugin directory (local): $(pwd)"
# Execute the extraction with proper output handling
# WP_CLI_CMD is already configured with -w flag, so . refers to the plugin directory
local extract_output
extract_output=$(eval "$WP_CLI_CMD i18n make-pot --exclude=$exclude_patterns --domain=$TEXT_DOMAIN . languages/${PLUGIN_SLUG}.pot 2>&1" || echo "FAILED")
# Small delay to ensure file is written
sleep 1
# Check if extraction was successful by verifying the file exists
local retries=3
local pot_exists=0
while [[ $retries -gt 0 ]] && [[ $pot_exists -eq 0 ]]; do
if [[ -f "$pot_file" ]]; then
pot_exists=1
break
fi
((retries--))
if [[ $retries -gt 0 ]]; then
log_warning "Pot file not found yet, retrying... ($retries attempts left)"
sleep 1
fi
done
if [[ $pot_exists -eq 1 ]]; then
log_success "Extracted strings to: $pot_file"
# Show statistics
local string_count=$(grep -c "^msgid \"" "$pot_file" 2>/dev/null || echo "0")
string_count=$(echo "$string_count" | tr -d ' \n')
log_info "Total strings found: $string_count"
# Check for obsolete entries
local obsolete_count=$(grep -c "^#~" "$pot_file" 2>/dev/null || echo "0")
obsolete_count=$(echo "$obsolete_count" | tr -d ' \n')
if [[ $obsolete_count -gt 0 ]]; then
log_warning "Found $obsolete_count obsolete entries (marked with #~)"
fi
return 0
else
log_error "Failed to generate .pot file"
log_error "wp-cli output: $extract_output"
log_error "Checked path: $pot_file (local filesystem)"
log_info "Directory context:"
log_info " • Local plugin dir: $(pwd)"
log_info " • Docker plugin dir: /var/www/html/wp-content/plugins/swiss-football-matchdata"
log_info " • Expected output (local): $(pwd)/languages/${PLUGIN_SLUG}.pot"
log_info ""
log_info "If the file exists in Docker but not locally, verify:"
log_info " 1. Docker volume mounting is correct"
log_info " 2. Run: docker compose -f ~/Development/wordpress-dev/wp-dev-compose.yml exec wp-cli ls -la /var/www/html/wp-content/plugins/swiss-football-matchdata/"
return 1
fi
}
################################################################################
# TRANSLATION
################################################################################
translate_strings() {
log_section "Generating .po files from .pot"
local pot_file="languages/${PLUGIN_SLUG}.pot"
if [[ ! -f "$pot_file" ]]; then
log_error ".pot file not found: $pot_file"
log_info "Run 'extract' command first"
return 1
fi
local created_count=0
for pair in $LANGUAGES; do
local lang_code="${pair%:*}"
local lang_name="${pair#*:}"
local po_file="languages/${PLUGIN_SLUG}-${lang_code}.po"
log_info "Processing: $lang_name ($lang_code)"
if [[ -f "$po_file" ]]; then
# Update existing .po file
log_info " Updating existing .po file..."
eval "$WP_CLI_CMD i18n update-po languages/${PLUGIN_SLUG}.pot languages/${PLUGIN_SLUG}-${lang_code}.po 2>/dev/null" || true
log_success " Updated: $po_file"
else
# Create new .po file from .pot
log_info " Creating new .po file..."
cp "$pot_file" "$po_file"
# Update language headers in .po file
sed -i.bak "s/Language: /Language: ${lang_code}/" "$po_file"
rm -f "${po_file}.bak"
log_success " Created: $po_file"
((created_count++))
fi
done
log_success "Created/Updated $created_count translation files"
return 0
}
################################################################################
# BUILD .MO FILES
################################################################################
build_mo_files() {
log_section "Generating .mo files"
local compiled_count=0
local errors=0
for pair in $LANGUAGES; do
local lang_code="${pair%:*}"
local lang_name="${pair#*:}"
local po_file="languages/${PLUGIN_SLUG}-${lang_code}.po"
local mo_file="languages/${PLUGIN_SLUG}-${lang_code}.mo"
if [[ -f "$po_file" ]]; then
log_info "Compiling: $lang_name ($lang_code)"
if msgfmt -o "$mo_file" "$po_file" 2>/dev/null; then
log_success " Generated: $mo_file"
((compiled_count++))
else
log_error " Failed to compile: $po_file"
((errors++))
fi
else
log_warning " .po file not found: $po_file"
fi
done
log_success "Compiled $compiled_count .mo files"
if [[ $errors -gt 0 ]]; then
log_warning "Encountered $errors errors during compilation"
return 1
fi
return 0
}
################################################################################
# CLEANUP
################################################################################
cleanup_regional_variants() {
log_section "Cleaning up regional language variants"
local removed_count=0
for variant in "${REGIONAL_VARIANTS[@]}"; do
# Check for .po files
local po_file="languages/${PLUGIN_SLUG}-${variant}.po"
if [[ -f "$po_file" ]]; then
log_info "Removing: $po_file"
rm -f "$po_file"
((removed_count++))
fi
# Check for .mo files
local mo_file="languages/${PLUGIN_SLUG}-${variant}.mo"
if [[ -f "$mo_file" ]]; then
log_info "Removing: $mo_file"
rm -f "$mo_file"
((removed_count++))
fi
# Also check for backup files created by sed
local po_backup="${po_file}.bak"
if [[ -f "$po_backup" ]]; then
rm -f "$po_backup"
fi
done
if [[ $removed_count -eq 0 ]]; then
log_info "No regional variants found to remove"
else
log_success "Removed $removed_count regional variant files"
fi
return 0
}
################################################################################
# DISPLAY SUMMARY
################################################################################
show_summary() {
log_section "i18n Management Summary"
echo -e "${YELLOW}📁 Language Files:${NC}\n"
for pair in $LANGUAGES; do
local lang_code="${pair%:*}"
local lang_name="${pair#*:}"
local po_file="languages/${PLUGIN_SLUG}-${lang_code}.po"
local mo_file="languages/${PLUGIN_SLUG}-${lang_code}.mo"
printf " %-20s %-20s " "$lang_code" "$lang_name"
if [[ -f "$po_file" ]] && [[ -f "$mo_file" ]]; then
local po_size=$(du -h "$po_file" | cut -f1)
local mo_size=$(du -h "$mo_file" | cut -f1)
echo -e "${GREEN}✓${NC} PO: $po_size, MO: $mo_size"
elif [[ -f "$po_file" ]]; then
local po_size=$(du -h "$po_file" | cut -f1)
echo -e "${YELLOW}⚠${NC} PO: $po_size (no .mo)"
else
echo -e "${RED}✗${NC} Missing files"
fi
done
local lang_count=$(echo "$LANGUAGES" | wc -w)
echo -e "\n${YELLOW}Configuration:${NC}\n"
echo " Plugin slug: $PLUGIN_SLUG"
echo " Text domain: $TEXT_DOMAIN"
echo " Languages: $lang_count"
echo " Languages dir: languages/"
echo -e "\n${YELLOW}Next Steps:${NC}\n"
echo " • Verify .po files contain all necessary translations"
echo " • Update empty translation entries in .po files"
echo " • Re-run 'build' to regenerate .mo files after translations"
echo ""
}
################################################################################
# HELP
################################################################################
show_help() {
cat << 'EOF'
Usage: ./dev-scripts/i18n-manage.sh [COMMAND]
COMMANDS:
extract Extract i18n strings from PHP/JS files to .pot
translate Generate .po files for all configured languages
build Compile .po files to .mo files
clean Remove regional language variants
all Run all steps: extract → translate → build → clean
help Show this help message
EXAMPLES:
# Extract strings and generate translations
./dev-scripts/i18n-manage.sh extract
# Generate .po files for translation
./dev-scripts/i18n-manage.sh translate
# Compile .po to .mo files
./dev-scripts/i18n-manage.sh build
# Run complete workflow
./dev-scripts/i18n-manage.sh all
# Clean up regional variants
./dev-scripts/i18n-manage.sh clean
CONFIGURATION:
Edit the script's CONFIG section to adjust:
- WP_CLI_CMD: WordPress CLI command wrapper
- LANGUAGES: Supported language codes
- REGIONAL_VARIANTS: Language variants to remove
TRANSLATORS COMMENTS:
In PHP code, add translators comments above i18n functions:
/* translators: %s is the error message from the API */
__('Error loading teams: %s', 'swi_foot_matchdata')
For multiple placeholders, use ordered syntax:
/* translators: %1$d is count, %2$d is duration in seconds */
__('Currently caching %1$d records with %2$d second duration.', 'swi_foot_matchdata')
SUPPORTED LANGUAGES (default):
de_DE - German
fr_FR - French
it_IT - Italian
en_US - English (US)
DEPENDENCIES:
- wp-cli (WordPress CLI)
- msgfmt (gettext tools)
- jq (optional, for translation management)
EOF
}
################################################################################
# MAIN
################################################################################
main() {
local command="${1:-all}"
# Show banner
echo -e "${CYAN}╔════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ Swiss Football Matchdata - i18n Management ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════╝${NC}\n"
# Check dependencies
log_info "Checking dependencies..."
if ! check_dependencies; then
log_error "Missing required dependencies. Please install and try again."
exit 1
fi
log_success "All dependencies available\n"
# Execute command
case "$command" in
extract)
extract_strings
;;
translate)
translate_strings
show_summary
;;
build)
build_mo_files
show_summary
;;
clean)
cleanup_regional_variants
;;
all)
extract_strings && \
translate_strings && \
build_mo_files && \
cleanup_regional_variants && \
show_summary
;;
help|--help|-h)
show_help
;;
*)
log_error "Unknown command: $command"
echo ""
show_help
exit 1
;;
esac
local exit_code=$?
if [[ $exit_code -eq 0 ]]; then
log_success "\nTask completed successfully!"
else
log_error "\nTask failed with exit code $exit_code"
fi
exit $exit_code
}
# Run main function with all arguments
main "$@"