347 lines
9 KiB
Bash
347 lines
9 KiB
Bash
|
|
#!/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 "$@"
|