#!/usr/bin/env bash # Script to merge individual FTL files or create legacy format # Handles the new structured directory format set -euo pipefail # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # Configuration PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" CONTENT_DIR="$PROJECT_ROOT/content" LEGACY_FILES=false CREATE_INDICES=false print_usage() { cat << EOF Usage: $0 [OPTIONS] [LANGUAGE] Merge structured FTL files into legacy format or manage directory structure. OPTIONS: --legacy Create legacy .ftl files from structure --indices Create index files for content directories --all Process both en and es languages -h, --help Show this help message EXAMPLES: $0 --legacy # Create content/en.ftl, content/es.ftl $0 --indices # Create index.json files $0 --legacy en # Create only content/en.ftl $0 --all --legacy # Process all languages and create legacy files ENVIRONMENT: PROJECT_ROOT Override project root directory EOF } log() { echo -e "${CYAN}[MERGE]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2 } log_success() { echo -e "${GREEN}[OK]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } # Generate prefix for key based on file structure generate_prefix() { local filepath="$1" local lang_dir="$2" local relative_path="${filepath#$lang_dir/}" relative_path="${relative_path%.*}" # Handle different directory structures case "$relative_path" in */*) local dir="$(dirname "$relative_path")" local file="$(basename "$relative_path")" if [[ "$dir" == "pages" ]]; then echo "" elif [[ "$dir" == "components" ]]; then echo "" else echo "${dir#pages/}${dir#components/}${dir#auth/}${dir#}" fi ;; *) echo "" ;; esac } # Merge FTL files from a directory merge_ftl_directory() { local lang_dir="$1" local output_file="$2" local lang="$(basename "$lang_dir")" log "Processing $lang directory..." # Find all FTL files local ftl_files=() while IFS= read -r -d '' file; do ftl_files+=("$file") done < <(find "$lang_dir" -name "*.ftl" -type f -print0) if [[ ${#ftl_files[@]} -eq 0 ]]; then log "No FTL files found in $lang_dir" return 1 fi log "Found ${#ftl_files[@]} FTL files to process" # Sort files for consistent ordering readarray -t ftl_files < <(printf '%s\0' "${ftl_files[@]}" | sort -z) : > "$output_file" # Clear output file for file in "${ftl_files[@]}"; do local relative_path="${file#$lang_dir/}" local prefix="" # Determine prefix based on file location case "$relative_path" in common.ftl|auth.ftl) prefix="" ;; pages/*.ftl) prefix="" ;; components/*.ftl) prefix="" ;; *) prefix="${relative_path%.ftl}-" prefix="${prefix#pages-}" prefix="${prefix#components-}" prefix="${prefix#common-}" prefix="${prefix#auth-}" ;; esac log "Processing: $relative_path" { echo "# === ${relative_path} ===" while IFS= read -r line; do line="${line%%$'\r\n'}" # Remove CRLF # Skip processing comment and empty lines if [[ -z "$line" ]] || [[ "$line" =~ ^[[:space:]]*# ]]; then echo "$line" continue fi # Handle key-value pairs if [[ "$line" == *"="* ]]; then local key="${line%%=*}" local value="${line#*=}" key="${key#${key%%[![:space:]]*}}" # trim leading key="${key%${key##*[![:space:]]}}" # trim trailing value="${value#${value%%[![:space:]]*}}" # trim leading value="${value%${value##*[![:space:]]}}" # trim trailing if [[ -n "$prefix" ]] && [[ "$key" != *"-"* ]]; then echo "${prefix}${key} = ${value}" else echo "$key = ${value}" fi else echo "$line" fi done < "$file" echo # Add empty line between files } >> "$output_file" done log_success "Created: $output_file (${#ftl_files[@]} files merged)" } # Create basic content indices create_content_indices() { local lang_dir="$1" local lang="$(basename "$lang_dir")" log "Creating indices for: $lang" local content_types=("blog" "recipes" "pages") for content_type in "${content_types[@]}"; do local type_dir="$CONTENT_DIR/$content_type/$lang" if [[ -d "$type_dir" ]]; then local index_file="$type_dir/index.json" if [[ ! -f "$index_file" ]]; then case "$content_type" in blog) echo '{"blog": []}' > "$index_file" ;; recipes) echo '{"recipes": []}' > "$index_file" ;; pages) echo '{"pages": []}' > "$index_file" ;; esac log_success "Created: $index_file" fi fi done } # Validate FTL file format validate_ftl_file() { local file="$1" local errors=0 # Check for basic syntax issues local brace_count brace_count=$(grep -Ec '[{}]' "$file" 2>/dev/null || echo 0) if [[ $brace_count -gt 0 ]]; then local open_braces local close_braces open_braces=$(grep -o '{' "$file" | wc -l) close_braces=$(grep -o '}' "$file" | wc -l) if [[ $open_braces -ne $close_braces ]]; then log_error "$file: Unbalanced braces ($open_braces open, $close_braces close)" return 1 fi fi # Check for empty messages if grep -q '^[a-zA-Z0-9_-][[:space:]]*=$' "$file"; then log_warning "$file: Contains empty message values" fi return 0 } # Process a single language check_subdirectories() { local lang="$1" local lang_dir="$CONTENT_DIR/$lang" echo log "=== Processing $lang directory ===" log "Directory: $lang_dir" # Check directory structure if [[ ! -d "$lang_dir" ]]; then log_warning "$lang_dir does not exist" return 1 fi echo "Subdirectories found:" find "$lang_dir" -type d -mindepth 1 -maxdepth 2 | head -10 echo "FTL files found:" find "$lang_dir" -name "*.ftl" -printf " %p\n" } # Main processing function main() { local LANGS=("en" "es") local PROCESS_LANG="" local ALL_LANGS=false # Parse arguments while [[ $# -gt 0 ]]; do case "$1" in --legacy) LEGACY_FILES=true shift ;; --indices) CREATE_INDICES=true shift ;; --all) ALL_LANGS=true shift ;; -h|--help) print_usage exit 0 ;; en|es) PROCESS_LANG="$1" shift ;; *) log_error "Unknown option: $1" print_usage exit 1 ;; esac done log "Starting FTL merge process" # Set languages to process if [[ -n "$PROCESS_LANG" ]]; then LANGS=("$PROCESS_LANG") fi # Process directories for lang in "${LANGS[@]}"; do lang_dir="$CONTENT_DIR/$lang" if [[ ! -d "$lang_dir" ]]; then log_warning "Directory not found: $lang_dir" continue fi # Show files being processed check_subdirectories "$lang" # Validate existing files log "Validating FTL files..." while IFS= read -r -d '' ftl_file; do validate_ftl_file "$ftl_file" done < <(find "$lang_dir" -name "*.ftl" -type f -print0) # Processing based on flags if [[ "$LEGACY_FILES" == "true" ]]; then local legacy_file="$CONTENT_DIR/$lang.ftl" merge_ftl_directory "$lang_dir" "$legacy_file" fi if [[ "$CREATE_INDICES" == "true" ]]; then create_content_indices "$lang_dir" fi done echo log_success "Processing complete!" if [[ "$LEGACY_FILES" == "true" ]]; then echo "Legacy files created:" for lang in "${LANGS[@]}"; do echo " - $CONTENT_DIR/$lang.ftl" done fi } # Run main function main "$@"