Skip to content

Commit 5a3441b

Browse files
Merge pull request #672 from madeofpendletonwool/translation-system
Translation system
2 parents 6ebf4a9 + 158075c commit 5a3441b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+14523
-1148
lines changed

.github/workflows/build-helm-chart.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,8 @@ jobs:
2626
- name: Checkout code
2727
uses: actions/checkout@v4
2828
with:
29-
persist-credentials: false # This prevents the default token from being persisted in the local git config
30-
31-
- name: Setup Git for push
32-
run: |
33-
git config --global user.name "github-actions[bot]"
34-
git config --global user.email "github-actions[bot]@users.noreply.github.com"
35-
git remote set-url origin https://x-access-token:${{ secrets.PUSH_PAT }}@github.com/${{ github.repository }}.git
29+
token: ${{ secrets.PUSH_PAT }}
30+
persist-credentials: true
3631

3732
- name: Setup Helm
3833
uses: Azure/setup-helm@v4.2.0
@@ -84,4 +79,3 @@ jobs:
8479
committer_email: actions@github.com
8580
message: "Update Helm chart for release ${{ github.event.release.tag_name }}"
8681
add: "docs"
87-
push: "origin main"

database_functions/migration_definitions.py

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2563,6 +2563,59 @@ def migration_029_fix_people_episodes_table_schema(conn, db_type: str):
25632563
cursor.close()
25642564

25652565

2566+
@register_migration("030", "add_user_language_preference", "Add Language column to Users table for user-specific language preferences", requires=["001"])
2567+
def migration_030_add_user_language_preference(conn, db_type: str):
2568+
"""Add Language column to Users table for user-specific language preferences"""
2569+
cursor = conn.cursor()
2570+
2571+
try:
2572+
# Get the default language from environment variable, fallback to 'en'
2573+
default_language = os.environ.get("DEFAULT_LANGUAGE", "en")
2574+
2575+
# Validate language code (basic validation)
2576+
if not default_language or len(default_language) > 10:
2577+
default_language = "en"
2578+
2579+
logger.info(f"Adding Language column to Users table with default '{default_language}'")
2580+
2581+
if db_type == 'postgresql':
2582+
# Add Language column with default from environment variable
2583+
safe_execute_sql(cursor, f'''
2584+
ALTER TABLE "Users"
2585+
ADD COLUMN IF NOT EXISTS Language VARCHAR(10) DEFAULT '{default_language}'
2586+
''', conn=conn)
2587+
2588+
# Add comment to document the column
2589+
safe_execute_sql(cursor, '''
2590+
COMMENT ON COLUMN "Users".Language IS 'ISO 639-1 language code for user interface language preference'
2591+
''', conn=conn)
2592+
2593+
else: # mysql/mariadb
2594+
# Check if column exists first
2595+
cursor.execute("""
2596+
SELECT COUNT(*)
2597+
FROM INFORMATION_SCHEMA.COLUMNS
2598+
WHERE TABLE_SCHEMA = DATABASE()
2599+
AND TABLE_NAME = 'Users'
2600+
AND COLUMN_NAME = 'Language'
2601+
""")
2602+
2603+
if cursor.fetchone()[0] == 0:
2604+
safe_execute_sql(cursor, f'''
2605+
ALTER TABLE Users
2606+
ADD COLUMN Language VARCHAR(10) DEFAULT '{default_language}'
2607+
COMMENT 'ISO 639-1 language code for user interface language preference'
2608+
''', conn=conn)
2609+
2610+
logger.info(f"Successfully added Language column to Users table with default '{default_language}'")
2611+
2612+
except Exception as e:
2613+
logger.error(f"Error in migration 030: {e}")
2614+
raise
2615+
finally:
2616+
cursor.close()
2617+
2618+
25662619
# ============================================================================
25672620
# GPODDER SYNC MIGRATIONS
25682621
# These migrations match the gpodder-api service migrations from Go code
@@ -3043,14 +3096,77 @@ def migration_105_optimize_episode_actions_performance(conn, db_type: str):
30433096
''', conn=conn)
30443097

30453098
logger.info("Successfully added episode actions performance indexes")
3046-
3099+
30473100
except Exception as e:
30483101
logger.error(f"Error in gpodder migration 105: {e}")
30493102
raise
30503103
finally:
30513104
cursor.close()
30523105

30533106

3107+
@register_migration("106", "optimize_subscription_sync_performance", "Add missing indexes for subscription sync queries", requires=["103"])
3108+
def migration_106_optimize_subscription_sync_performance(conn, db_type: str):
3109+
"""Add critical indexes for subscription sync performance to prevent AntennaPod timeouts"""
3110+
cursor = conn.cursor()
3111+
3112+
try:
3113+
logger.info("Adding performance indexes for subscription sync...")
3114+
3115+
if db_type == 'postgresql':
3116+
# Critical indexes for subscription sync performance
3117+
safe_execute_sql(cursor, '''
3118+
CREATE INDEX IF NOT EXISTS idx_gpodder_sync_subs_user_device_timestamp
3119+
ON "GpodderSyncSubscriptions"(UserID, DeviceID, Timestamp DESC)
3120+
''', conn=conn)
3121+
3122+
safe_execute_sql(cursor, '''
3123+
CREATE INDEX IF NOT EXISTS idx_gpodder_sync_subs_user_action_timestamp
3124+
ON "GpodderSyncSubscriptions"(UserID, Action, Timestamp DESC)
3125+
''', conn=conn)
3126+
3127+
safe_execute_sql(cursor, '''
3128+
CREATE INDEX IF NOT EXISTS idx_gpodder_sync_subs_podcast_url_user
3129+
ON "GpodderSyncSubscriptions"(UserID, PodcastURL, Timestamp DESC)
3130+
''', conn=conn)
3131+
3132+
# Optimize subscription change queries with compound index
3133+
safe_execute_sql(cursor, '''
3134+
CREATE INDEX IF NOT EXISTS idx_gpodder_sync_subs_complex_query
3135+
ON "GpodderSyncSubscriptions"(UserID, DeviceID, Action, Timestamp DESC, PodcastURL)
3136+
''', conn=conn)
3137+
3138+
else: # mysql/mariadb
3139+
# Critical indexes for subscription sync performance
3140+
safe_execute_sql(cursor, '''
3141+
CREATE INDEX idx_gpodder_sync_subs_user_device_timestamp
3142+
ON GpodderSyncSubscriptions(UserID, DeviceID, Timestamp DESC)
3143+
''', conn=conn)
3144+
3145+
safe_execute_sql(cursor, '''
3146+
CREATE INDEX idx_gpodder_sync_subs_user_action_timestamp
3147+
ON GpodderSyncSubscriptions(UserID, Action, Timestamp DESC)
3148+
''', conn=conn)
3149+
3150+
safe_execute_sql(cursor, '''
3151+
CREATE INDEX idx_gpodder_sync_subs_podcast_url_user
3152+
ON GpodderSyncSubscriptions(UserID, PodcastURL(255), Timestamp DESC)
3153+
''', conn=conn)
3154+
3155+
# Optimize subscription change queries with compound index
3156+
safe_execute_sql(cursor, '''
3157+
CREATE INDEX idx_gpodder_sync_subs_complex_query
3158+
ON GpodderSyncSubscriptions(UserID, DeviceID, Action, Timestamp DESC, PodcastURL(255))
3159+
''', conn=conn)
3160+
3161+
logger.info("Successfully added subscription sync performance indexes")
3162+
3163+
except Exception as e:
3164+
logger.error(f"Error in gpodder migration 106: {e}")
3165+
raise
3166+
finally:
3167+
cursor.close()
3168+
3169+
30543170
if __name__ == "__main__":
30553171
# Register all migrations and run them
30563172
register_all_migrations()

deployment/docker/compose-files/docker-compose-mysql/docker-compose.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ services:
4242
PGID: ${GID:-911}
4343
# Add timezone configuration
4444
TZ: "America/New_York"
45+
# Language Configuration
46+
DEFAULT_LANGUAGE: "en"
47+
volumes:
48+
# Mount the download and the backup location on the server if you want to. You could mount a nas to the downloads folder or something like that.
49+
# The backups directory is used if backups are made on the web version on pinepods. When taking backups on the client version it downloads them locally.
4550

4651
volumes:
4752
# Mount the download and backup locations on the server

deployment/docker/compose-files/docker-compose-postgres/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ services:
4040
PGID: ${GID:-911}
4141
# Add timezone configuration
4242
TZ: "America/New_York"
43+
# Language Configuration
44+
DEFAULT_LANGUAGE: "en"
4345
volumes:
4446
# Mount the download and backup locations on the server
4547
- /home/user/pinepods/downloads:/opt/pinepods/downloads

dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ ENV TZ=UTC
117117
COPY --from=python-builder /build/dist/pinepods-db-setup /usr/local/bin/
118118
# Copy built files from the builder stage to the Nginx serving directory
119119
COPY --from=builder /app/dist /var/www/html/
120+
# Copy translation files for the Rust API to access
121+
COPY ./web/src/translations /var/www/html/static/translations
120122
# Copy Go API binary from the go-builder stage
121123
COPY --from=go-builder /gpodder-api/gpodder-api /usr/local/bin/
122124
# Copy Rust API binary from the rust-api-builder stage

dockerfile-arm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ ENV TZ=UTC
141141
COPY --from=python-builder /build/dist/pinepods-db-setup /usr/local/bin/
142142
# Copy built files from the builder stage to the Nginx serving directory
143143
COPY --from=builder /app/dist /var/www/html/
144+
# Copy translation files for the Rust API to access
145+
COPY ./web/src/translations /var/www/html/static/translations
144146
# Copy Go API binary from the go-builder stage
145147
COPY --from=go-builder /gpodder-api/gpodder-api /usr/local/bin/
146148
# Copy Rust API binary from the rust-api-builder stage

0 commit comments

Comments
 (0)