Compare commits

..

1 Commits

Author SHA1 Message Date
Markos Gogoulos 66e67c751e Docker story refactoring 2025-11-17 11:09:38 +02:00
430 changed files with 10591 additions and 38552 deletions
+113
View File
@@ -0,0 +1,113 @@
FROM python:3.13.5-slim-bookworm AS build-image
# Install system dependencies needed for downloading and extracting
RUN apt-get update -y && \
apt-get install -y --no-install-recommends wget xz-utils unzip && \
rm -rf /var/lib/apt/lists/* && \
apt-get purge --auto-remove && \
apt-get clean
RUN wget -q https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
RUN mkdir -p ffmpeg-tmp && \
tar -xf ffmpeg-release-amd64-static.tar.xz --strip-components 1 -C ffmpeg-tmp && \
cp -v ffmpeg-tmp/ffmpeg ffmpeg-tmp/ffprobe ffmpeg-tmp/qt-faststart /usr/local/bin && \
rm -rf ffmpeg-tmp ffmpeg-release-amd64-static.tar.xz
# Install Bento4 in the specified location
RUN mkdir -p /home/mediacms.io/bento4 && \
wget -q http://zebulon.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip && \
unzip Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip -d /home/mediacms.io/bento4 && \
mv /home/mediacms.io/bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux/* /home/mediacms.io/bento4/ && \
rm -rf /home/mediacms.io/bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux && \
rm -rf /home/mediacms.io/bento4/docs && \
rm Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip
############ BASE RUNTIME IMAGE ############
FROM python:3.13.5-slim-bookworm AS base
SHELL ["/bin/bash", "-c"]
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV CELERY_APP='cms'
ENV VIRTUAL_ENV=/home/mediacms.io
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# Install system dependencies first
RUN apt-get update -y && \
apt-get -y upgrade && \
apt-get install --no-install-recommends -y \
supervisor \
nginx \
imagemagick \
procps \
build-essential \
pkg-config \
zlib1g-dev \
zlib1g \
libxml2-dev \
libxmlsec1-dev \
libxmlsec1-openssl \
libpq-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set up virtualenv first
RUN mkdir -p /home/mediacms.io/mediacms/{logs} && \
cd /home/mediacms.io && \
python3 -m venv $VIRTUAL_ENV
# Copy requirements files
COPY requirements.txt requirements-dev.txt ./
# Install Python dependencies using pip (within virtualenv)
ARG DEVELOPMENT_MODE=False
RUN pip install --no-cache-dir uv && \
uv pip install --no-binary lxml --no-binary xmlsec -r requirements.txt && \
if [ "$DEVELOPMENT_MODE" = "True" ]; then \
echo "Installing development dependencies..." && \
uv pip install -r requirements-dev.txt; \
fi && \
apt-get purge -y --auto-remove \
build-essential \
pkg-config \
libxml2-dev \
libxmlsec1-dev \
libpq-dev
# Copy ffmpeg and Bento4 from build image
COPY --from=build-image /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
COPY --from=build-image /usr/local/bin/ffprobe /usr/local/bin/ffprobe
COPY --from=build-image /usr/local/bin/qt-faststart /usr/local/bin/qt-faststart
COPY --from=build-image /home/mediacms.io/bento4 /home/mediacms.io/bento4
# Copy application files
COPY . /home/mediacms.io/mediacms
WORKDIR /home/mediacms.io/mediacms
# required for sprite thumbnail generation for large video files
COPY deploy/docker/policy.xml /etc/ImageMagick-6/policy.xml
# Set process control environment variables
ENV ENABLE_UWSGI='yes' \
ENABLE_NGINX='yes' \
ENABLE_CELERY_BEAT='yes' \
ENABLE_CELERY_SHORT='yes' \
ENABLE_CELERY_LONG='yes' \
ENABLE_MIGRATIONS='yes'
EXPOSE 9000 80
RUN chmod +x ./deploy/docker/entrypoint.sh
ENTRYPOINT ["./deploy/docker/entrypoint.sh"]
CMD ["./deploy/docker/start.sh"]
############ FULL IMAGE ############
FROM base AS full
COPY requirements-full.txt ./
RUN mkdir -p /root/.cache/ && \
chmod go+rwx /root/ && \
chmod go+rwx /root/.cache/
RUN uv pip install -r requirements-full.txt
+119
View File
@@ -0,0 +1,119 @@
version: "3"
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- dhparam:/etc/nginx/dhparam
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./deploy/docker/reverse_proxy/client_max_body_size.conf:/etc/nginx/conf.d/client_max_body_size.conf:ro
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
volumes_from:
- nginx-proxy
volumes:
- certs:/etc/nginx/certs:rw
- acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
migrations:
image: mediacms/mediacms:latest
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_CELERY_BEAT: 'no'
ADMIN_USER: 'admin'
ADMIN_EMAIL: 'Y'
ADMIN_PASSWORD: 'X'
command: "./deploy/docker/prestart.sh"
restart: on-failure
depends_on:
redis:
condition: service_healthy
db:
condition: service_healthy
web:
image: mediacms/mediacms:latest
deploy:
replicas: 1
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_CELERY_BEAT: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_MIGRATIONS: 'no'
VIRTUAL_HOST: 'X.mediacms.io'
LETSENCRYPT_HOST: 'X.mediacms.io'
LETSENCRYPT_EMAIL: 'X'
depends_on:
- migrations
celery_beat:
image: mediacms/mediacms:latest
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- redis
celery_worker:
image: mediacms/mediacms:full
deploy:
replicas: 1
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_BEAT: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- migrations
db:
image: postgres:17.2-alpine
volumes:
- ../postgres_data:/var/lib/postgresql/data/
restart: always
environment:
POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: "redis:alpine"
restart: always
healthcheck:
test: ["CMD", "redis-cli","ping"]
interval: 10s
timeout: 5s
retries: 3
volumes:
conf:
vhost:
html:
dhparam:
certs:
acme:
+89
View File
@@ -0,0 +1,89 @@
version: "3"
services:
migrations:
build:
context: .
dockerfile: ./Dockerfile
target: base
args:
- DEVELOPMENT_MODE=True
image: mediacms/mediacms-dev:latest
volumes:
- ./:/home/mediacms.io/mediacms/
command: "./deploy/docker/prestart.sh"
environment:
DEVELOPMENT_MODE: True
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_CELERY_BEAT: 'no'
ADMIN_USER: 'admin'
ADMIN_EMAIL: 'admin@localhost'
ADMIN_PASSWORD: 'admin'
restart: on-failure
depends_on:
redis:
condition: service_healthy
db:
condition: service_healthy
frontend:
image: node:20
volumes:
- ${PWD}/frontend:/home/mediacms.io/mediacms/frontend/
working_dir: /home/mediacms.io/mediacms/frontend/
command: bash -c "npm install && npm run start"
env_file:
- ${PWD}/frontend/.env
ports:
- "8088:8088"
depends_on:
- web
web:
image: mediacms/mediacms-dev:latest
command: "python manage.py runserver 0.0.0.0:80"
environment:
DEVELOPMENT_MODE: True
ports:
- "80:80"
volumes:
- ./:/home/mediacms.io/mediacms/
depends_on:
- migrations
db:
image: postgres:17.2-alpine
volumes:
- ../postgres_data:/var/lib/postgresql/data/
restart: always
environment:
POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: "redis:alpine"
restart: always
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
celery_worker:
image: mediacms/mediacms-dev:latest
deploy:
replicas: 1
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_BEAT: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- web
+86
View File
@@ -0,0 +1,86 @@
version: "3"
services:
migrations:
image: mediacms/mediacms:latest
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_CELERY_BEAT: 'no'
ADMIN_USER: 'admin'
ADMIN_EMAIL: 'admin@localhost'
# ADMIN_PASSWORD: 'uncomment_and_set_password_here'
command: "./deploy/docker/prestart.sh"
restart: on-failure
depends_on:
redis:
condition: service_healthy
db:
condition: service_healthy
web:
image: mediacms/mediacms:latest
deploy:
replicas: 1
ports:
- "80:80"
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_CELERY_BEAT: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- migrations
celery_beat:
image: mediacms/mediacms:latest
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- redis
celery_worker:
image: mediacms/mediacms:latest
deploy:
replicas: 1
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_BEAT: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- migrations
db:
image: postgres:17.2-alpine
volumes:
- ../postgres_data:/var/lib/postgresql/data/
restart: always
environment:
POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms
TZ: Europe/London
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: "redis:alpine"
restart: always
healthcheck:
test: ["CMD", "redis-cli","ping"]
interval: 10s
timeout: 5s
retries: 3
+30 -62
View File
@@ -1,69 +1,37 @@
# Node.js/JavaScript dependencies and artifacts # Dependencies
**/node_modules node_modules
**/npm-debug.log* npm-debug.log
**/yarn-debug.log*
**/yarn-error.log*
**/.yarn/cache
**/.yarn/unplugged
**/package-lock.json
**/.npm
**/.cache
**/.parcel-cache
**/dist
**/build
**/*.tsbuildinfo
# Python bytecode and cache # Local development files - exclude uploaded content but keep placeholder images
**/__pycache__ media_files/*
**/*.py[cod] !media_files/userlogos/
**/*$py.class media_files/userlogos/*
**/*.so !media_files/userlogos/*.jpg
**/.Python logs
**/pip-log.txt static_collected
**/pip-delete-this-directory.txt
**/.pytest_cache
**/.coverage
**/htmlcov
**/.tox
**/.mypy_cache
**/.ruff_cache
# Version control # Version control
**/.git .git
**/.gitignore .github
**/.gitattributes .gitignore
# IDE and editor files # Development/testing
**/.DS_Store .pytest_cache
**/.vscode .qodo
**/.idea .claude
**/*.swp
**/*.swo
**/*~
# Logs and runtime files # Docker
**/logs .dockerignore
**/*.log Dockerfile
**/celerybeat-schedule* docker-compose*.yml
**/.env .docker-backup
**/.env.*
# Media files and data directories (should not be in image) # Documentation (if you don't need it in the image)
media_files/** docs
postgres_data/**
pids/**
# Static files collected at runtime # Other
static_collected/** *.pyc
__pycache__
# Documentation and development files .env
**/.github .vscode
**/CHANGELOG.md .idea
# Test files and directories
**/tests
**/test_*.py
**/*_test.py
# Frontend build artifacts (built separately)
frontend/dist/**
+1
View File
@@ -24,6 +24,7 @@ If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):** **Environment (please complete the following information):**
- OS: [e.g. Ubuntu Linux] - OS: [e.g. Ubuntu Linux]
- Installation method: [Docker install, or single server install]
- Browser, if applicable - Browser, if applicable
**Additional context** **Additional context**
+75 -19
View File
@@ -21,8 +21,8 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker meta for base image - name: Docker meta for web image
id: meta-base id: meta-web
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
with: with:
images: | images: |
@@ -40,39 +40,95 @@ jobs:
org.opencontainers.image.source=https://github.com/mediacms-io/mediacms org.opencontainers.image.source=https://github.com/mediacms-io/mediacms
org.opencontainers.image.licenses=AGPL-3.0 org.opencontainers.image.licenses=AGPL-3.0
- name: Docker meta for full image - name: Build and push web image
id: meta-full uses: docker/build-push-action@v4
with:
context: .
target: web
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta-web.outputs.tags }}
labels: ${{ steps.meta-web.outputs.labels }}
- name: Docker meta for worker image
id: meta-worker
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
with: with:
images: | images: |
mediacms/mediacms mediacms/mediacms-worker
tags: | tags: |
type=raw,value=full,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=semver,pattern={{version}}-full type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}-full type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}-full type=semver,pattern={{major}}
labels: | labels: |
org.opencontainers.image.title=MediaCMS Full org.opencontainers.image.title=MediaCMS Worker
org.opencontainers.image.description=MediaCMS is a modern, fully featured open source video and media CMS, written in Python/Django and React, featuring a REST API. This is the full version with additional dependencies. org.opencontainers.image.description=MediaCMS Celery worker for background task processing.
org.opencontainers.image.vendor=MediaCMS org.opencontainers.image.vendor=MediaCMS
org.opencontainers.image.url=https://mediacms.io/ org.opencontainers.image.url=https://mediacms.io/
org.opencontainers.image.source=https://github.com/mediacms-io/mediacms org.opencontainers.image.source=https://github.com/mediacms-io/mediacms
org.opencontainers.image.licenses=AGPL-3.0 org.opencontainers.image.licenses=AGPL-3.0
- name: Build and push full image - name: Build and push worker image
uses: docker/build-push-action@v4 uses: docker/build-push-action@v4
with: with:
context: . context: .
target: full target: worker
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta-full.outputs.tags }} tags: ${{ steps.meta-worker.outputs.tags }}
labels: ${{ steps.meta-full.outputs.labels }} labels: ${{ steps.meta-worker.outputs.labels }}
- name: Build and push base image - name: Docker meta for worker-full image
id: meta-worker-full
uses: docker/metadata-action@v4
with:
images: |
mediacms/mediacms-worker
tags: |
type=raw,value=latest-full,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=semver,pattern={{version}}-full
type=semver,pattern={{major}}.{{minor}}-full
type=semver,pattern={{major}}-full
labels: |
org.opencontainers.image.title=MediaCMS Worker Full
org.opencontainers.image.description=MediaCMS Celery worker with additional codecs for advanced transcoding features.
org.opencontainers.image.vendor=MediaCMS
org.opencontainers.image.url=https://mediacms.io/
org.opencontainers.image.source=https://github.com/mediacms-io/mediacms
org.opencontainers.image.licenses=AGPL-3.0
- name: Build and push worker-full image
uses: docker/build-push-action@v4 uses: docker/build-push-action@v4
with: with:
context: . context: .
target: base target: worker-full
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta-base.outputs.tags }} tags: ${{ steps.meta-worker-full.outputs.tags }}
labels: ${{ steps.meta-base.outputs.labels }} labels: ${{ steps.meta-worker-full.outputs.labels }}
- name: Docker meta for nginx image
id: meta-nginx
uses: docker/metadata-action@v4
with:
images: |
mediacms/mediacms-nginx
tags: |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
labels: |
org.opencontainers.image.title=MediaCMS Nginx
org.opencontainers.image.description=Nginx web server for MediaCMS, serving static and media files.
org.opencontainers.image.vendor=MediaCMS
org.opencontainers.image.url=https://mediacms.io/
org.opencontainers.image.source=https://github.com/mediacms-io/mediacms
org.opencontainers.image.licenses=AGPL-3.0
- name: Build and push nginx image
uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile.nginx
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta-nginx.outputs.tags }}
labels: ${{ steps.meta-nginx.outputs.labels }}
@@ -1,42 +0,0 @@
name: Frontend build and test
on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build-and-test:
strategy:
matrix:
os: [ubuntu-latest]
node: [20]
runs-on: ${{ matrix.os }}
name: '${{ matrix.os }} - node v${{ matrix.node }}'
permissions:
contents: read
defaults:
run:
working-directory: ./frontend
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: npm install
- name: Build script
run: npm run dist
- name: Test script
run: npm run test
@@ -1,22 +0,0 @@
name: "Lint PR"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
- reopened
permissions:
pull-requests: read
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
environment: dev
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-47
View File
@@ -1,47 +0,0 @@
name: Semantic Release
on:
push:
branches:
- main
permissions:
contents: write
issues: write
jobs:
semantic-release:
runs-on: ubuntu-latest
environment: dev
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Setup SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.GA_DEPLOY_KEY }}
# use SSH url to ensure git commit using a deploy key bypasses the main
# branch protection rule
- name: Configure Git for SSH Push
run: git remote set-url origin "git@github.com:${{ github.repository }}.git"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
- name: Install Dependencies
run: npm clean-install
- name: Verify the integrity of provenance attestations and registry signatures for installed dependencies
run: npm audit signatures
- name: Run Semantic Release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+10 -8
View File
@@ -1,14 +1,18 @@
cli-tool/.env cli-tool/.env
frontend/package-lock.json frontend/package-lock.json
custom/local_settings.py
custom/static/images/*
!custom/static/images/.gitkeep
custom/static/css/*
!custom/static/css/.gitkeep
media_files/encoded/ media_files/encoded/
media_files/original/ media_files/original/
media_files/hls/ media_files/hls/
media_files/chunks/ media_files/chunks/
media_files/uploads/ media_files/uploads/
media_files/tinymce_media/ media_files/tinymce_media/
media_files/userlogos/
postgres_data/ postgres_data/
celerybeat-schedule* celerybeat-schedule
logs/ logs/
pids/ pids/
static/admin/ static/admin/
@@ -18,10 +22,10 @@ static/mptt/
static/rest_framework/ static/rest_framework/
static/drf-yasg static/drf-yasg
cms/local_settings.py cms/local_settings.py
deploy/docker/local_settings.py config/local_settings.py
yt.readme.md yt.readme.md
# Node.js dependencies (covers all node_modules directories, including frontend-tools) /frontend-tools/video-editor/node_modules
**/node_modules/ /frontend-tools/video-editor/client/node_modules
/static_collected /static_collected
/frontend-tools/video-editor-v1 /frontend-tools/video-editor-v1
frontend-tools/.DS_Store frontend-tools/.DS_Store
@@ -36,6 +40,4 @@ frontend-tools/video-editor/client/public/videos/sample-video.mp3
frontend-tools/chapters-editor/client/public/videos/sample-video.mp3 frontend-tools/chapters-editor/client/public/videos/sample-video.mp3
static/chapters_editor/videos/sample-video.mp3 static/chapters_editor/videos/sample-video.mp3
static/video_editor/videos/sample-video.mp3 static/video_editor/videos/sample-video.mp3
templates/todo-MS4.md backups/
.secret_key
.secret_key.lock
+2 -1
View File
@@ -9,7 +9,8 @@ repos:
- id: isort - id: isort
args: ["--profile", "black"] args: ["--profile", "black"]
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 24.10.0 rev: 23.1.0
hooks: hooks:
- id: black - id: black
language_version: python3 language_version: python3
additional_dependencies: [ 'click==8.0.4' ]
-1
View File
@@ -1,4 +1,3 @@
/templates/cms/* /templates/cms/*
/templates/*.html /templates/*.html
*.scss *.scss
/frontend/
-100
View File
@@ -1,100 +0,0 @@
{
"branches": [
"main"
],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits"
}
],
[
"@semantic-release/release-notes-generator",
{
"preset": "conventionalcommits",
"presetConfig": {
"types": [
{
"type": "feat",
"section": "Features"
},
{
"type": "fix",
"section": "Bug Fixes"
},
{
"type": "chore",
"hidden": true
},
{
"type": "docs",
"section": "Documentation"
},
{
"type": "style",
"hidden": true
},
{
"type": "refactor",
"section": "Refactors"
},
{
"type": "perf",
"section": "Performance"
},
{
"type": "test",
"hidden": true
},
{
"type": "depr",
"section": "Deprecations"
}
]
}
}
],
[
"semantic-release-replace-plugin",
{
"replacements": [
{
"files": [
"package.json"
],
"from": "\"version\": \".*\"",
"to": "\"version\": \"${nextRelease.version}\"",
"results": [
{
"file": "package.json",
"hasChanged": true,
"numMatches": 1,
"numReplacements": 1
}
],
"countMatches": true
}
]
}
],
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md",
"changelogTitle": "# Changelog"
}
],
"@semantic-release/github",
[
"@semantic-release/git",
{
"assets": [
"package.json",
"CHANGELOG.md"
],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
]
}
-116
View File
@@ -1,116 +0,0 @@
# Changelog
## [8.1.3](https://github.com/mediacms-io/mediacms/compare/v8.1.2...v8.1.3) (2026-05-19)
### Bug Fixes
* django connection settings ([#1529](https://github.com/mediacms-io/mediacms/issues/1529)) ([e89c4a3](https://github.com/mediacms-io/mediacms/commit/e89c4a3c8523574b5852a434ed67e281b6290584))
* prestart.sh loaddata re-runs on every container restart ([#1502](https://github.com/mediacms-io/mediacms/issues/1502)) ([777b06b](https://github.com/mediacms-io/mediacms/commit/777b06bbebf141e5b1cb27e17533fe65d57eb6cd))
## [8.1.2](https://github.com/mediacms-io/mediacms/compare/v8.1.1...v8.1.2) (2026-05-18)
### Bug Fixes
* remove redundant check ([#1528](https://github.com/mediacms-io/mediacms/issues/1528)) ([c7a673b](https://github.com/mediacms-io/mediacms/commit/c7a673bbbf46efc37621dc4a5109a85fc10e1317))
## [8.1.1](https://github.com/mediacms-io/mediacms/compare/v8.1.0...v8.1.1) (2026-05-18)
### Bug Fixes
* x-accell headers on uploaded poster ([#1526](https://github.com/mediacms-io/mediacms/issues/1526)) ([ae63a5a](https://github.com/mediacms-io/mediacms/commit/ae63a5af647c8865b96e6e50dda1ea9d29b5bd0b))
## [8.1.0](https://github.com/mediacms-io/mediacms/compare/v8.0.8...v8.1.0) (2026-05-17)
### Features
* introduce x-accell headers ([9302559](https://github.com/mediacms-io/mediacms/commit/9302559d4bb3e4d0adb299ed37438b04c39e1864))
## [8.0.8](https://github.com/mediacms-io/mediacms/compare/v8.0.7...v8.0.8) (2026-05-13)
### Bug Fixes
* update documentation and fix smaller issues ([#1520](https://github.com/mediacms-io/mediacms/issues/1520)) ([d6a1151](https://github.com/mediacms-io/mediacms/commit/d6a11514e54b9341ec8a306a259adce6b4199d42))
## [8.0.7](https://github.com/mediacms-io/mediacms/compare/v8.0.6...v8.0.7) (2026-05-12)
### Bug Fixes
* bring related items back ([#1515](https://github.com/mediacms-io/mediacms/issues/1515)) ([6ee5bef](https://github.com/mediacms-io/mediacms/commit/6ee5bef6ce31cf849941f65d0817e53b8f03362f))
## [8.0.6](https://github.com/mediacms-io/mediacms/compare/v8.0.5...v8.0.6) (2026-05-11)
### Bug Fixes
* better place secret key settings ([4f11add](https://github.com/mediacms-io/mediacms/commit/4f11addcfd6657e7e63eed0570b1d4d9bca75698))
## [8.0.5](https://github.com/mediacms-io/mediacms/compare/v8.0.4...v8.0.5) (2026-05-11)
### Bug Fixes
* add secret key to gitignore ([b6da9c4](https://github.com/mediacms-io/mediacms/commit/b6da9c4662b3fba234b8dc69700ffa44fced7482))
## [8.0.4](https://github.com/mediacms-io/mediacms/compare/v8.0.3...v8.0.4) (2026-05-11)
### Bug Fixes
* docker compose settings, provide key ([318dad0](https://github.com/mediacms-io/mediacms/commit/318dad0e5d2512d68068c019eb87f942f83318e9))
## [8.0.3](https://github.com/mediacms-io/mediacms/compare/v8.0.2...v8.0.3) (2026-05-11)
### Bug Fixes
* secret key ([559977f](https://github.com/mediacms-io/mediacms/commit/559977f9bc74412739784926862b94a558e6fd84))
## [8.0.2](https://github.com/mediacms-io/mediacms/compare/v8.0.1...v8.0.2) (2026-05-11)
### Bug Fixes
* provide Bento4 url ([c19c520](https://github.com/mediacms-io/mediacms/commit/c19c5207e907cbd7d0c968d8cd8caaec20706277))
## [7.7.0](https://github.com/mediacms-io/mediacms/compare/v7.6.0...v7.7.0) (2026-05-11)
### Features
* LTI support and Moodle plugin ([55ab7ff](https://github.com/mediacms-io/mediacms/commit/55ab7ff34fcd05806b845cf958f07841a7cdfc78))
## [7.6.0](https://github.com/mediacms-io/mediacms/compare/v7.5.0...v7.6.0) (2026-02-07)
### Features
* Create SECURITY.md ([#1485](https://github.com/mediacms-io/mediacms/issues/1485)) ([11449c2](https://github.com/mediacms-io/mediacms/commit/11449c2187d0f450b86915d88f92595a1825e4cf))
## [7.5.0](https://github.com/mediacms-io/mediacms/compare/v7.4.0...v7.5.0) (2026-02-06)
### Features
* bump version ([36d815c](https://github.com/mediacms-io/mediacms/commit/36d815c0cfbe21d3136541d410d545742b9ebecd))
## [7.4.0](https://github.com/mediacms-io/mediacms/compare/v7.3.0...v7.4.0) (2026-02-06)
### Features
* Add video player context menu with share/embed options ([#1472](https://github.com/mediacms-io/mediacms/issues/1472)) ([74952f6](https://github.com/mediacms-io/mediacms/commit/74952f68d79bc67617edb38eac62d2f5e7457565))
## [7.3.0](https://github.com/mediacms-io/mediacms/compare/v7.2.0...v7.3.0) (2026-02-06)
### Features
* add package json for semantic release ([b405a04](https://github.com/mediacms-io/mediacms/commit/b405a04e346ca81b7d3f4e099eb984e7785cdd0f))
* add semantic release github actions ([76a27ae](https://github.com/mediacms-io/mediacms/commit/76a27ae25609178c1bd47c947b9f1a082c791d61))
* frontend unit tests ([1c15880](https://github.com/mediacms-io/mediacms/commit/1c15880ae3ef1ce77f53d5b473dfc0cc448b4977))
* Implement persistent "Embed Mode" to hide UI shell via Session Storage ([#1484](https://github.com/mediacms-io/mediacms/issues/1484)) ([223e870](https://github.com/mediacms-io/mediacms/commit/223e87073f7d5e44130c9976854cac670db0ae66))
* Improve Visual Distinction Between Trim and Chapters Editors ([#1445](https://github.com/mediacms-io/mediacms/issues/1445)) ([d9b1d6c](https://github.com/mediacms-io/mediacms/commit/d9b1d6cab1d2bdfc16f799a0a27b64313e2e0d22))
* semantic release ([b76282f](https://github.com/mediacms-io/mediacms/commit/b76282f9e465a39c2da5e9a22184d1db23de3f56))
### Bug Fixes
* add delay to task creation ([1b3cdfd](https://github.com/mediacms-io/mediacms/commit/1b3cdfd302abc5e69ebe01ca52b5091f3b24c0b2))
* Add regex denoter and improve celerybeat gitignore ([#1446](https://github.com/mediacms-io/mediacms/issues/1446)) ([90331f3](https://github.com/mediacms-io/mediacms/commit/90331f3b4a2a5737de9dd75ab45c096944813c42))
* adjust poster url for audio ([01912ea](https://github.com/mediacms-io/mediacms/commit/01912ea1f99ef43793a65712539d6264f1f6410f))
* Chapter numbering and preserve custom titles on segment reorder ([#1435](https://github.com/mediacms-io/mediacms/issues/1435)) ([cd7dd4f](https://github.com/mediacms-io/mediacms/commit/cd7dd4f72c9f0bac466c680f686a9ecfdd3a38dd))
* Show default chapter names in textarea instead of placeholder text ([#1428](https://github.com/mediacms-io/mediacms/issues/1428)) ([5eb6faf](https://github.com/mediacms-io/mediacms/commit/5eb6fafb8c6928b8bc3fe5f0c7af315273f78a55))
* static files ([#1429](https://github.com/mediacms-io/mediacms/issues/1429)) ([ba2c31b](https://github.com/mediacms-io/mediacms/commit/ba2c31b1e65b7f508dee598b1f2d86f01f9bf036))
### Documentation
* update page link ([aeef828](https://github.com/mediacms-io/mediacms/commit/aeef8284bfba2a9a7f69c684f96c54f0e0e0cf92))
+441
View File
@@ -0,0 +1,441 @@
# MediaCMS Docker Restructure Summary - Version 7.3
## Overview
MediaCMS 7.3 introduces a complete Docker architecture restructure, moving from a monolithic supervisord-based setup to modern microservices with proper separation of concerns.
**⚠️ BREAKING CHANGES** - See [`UPGRADE_TO_7.3.md`](./UPGRADE_TO_7.3.md) for migration guide.
## Architecture Comparison
### Before (7.x) - Monolithic
```
┌─────────────────────────────────────┐
│ Single Container │
│ ┌──────────┐ │
│ │Supervisor│ │
│ └────┬─────┘ │
│ ├─── nginx (port 80) │
│ ├─── uwsgi (Django) │
│ ├─── celery beat │
│ ├─── celery workers │
│ └─── migrations │
│ │
│ Volumes: ./ mounted to container │
└─────────────────────────────────────┘
```
### After (7.3) - Microservices
```
┌────────┐ ┌─────┐ ┌───────────┐ ┌──────────┐
│ nginx │→ │ web │ │celery_beat│ │ celery │
│ │ │uwsgi│ │ │ │ workers │
└────────┘ └─────┘ └───────────┘ └──────────┘
┌───────┴────────┐
│ db │ redis │
└───────┴────────┘
Volumes: Named volumes + custom/ bind mount
```
## What Changed
### 1. Container Services
| Component | Before (7.x) | After (7.3) |
|-----------|-------------|-------------|
| **nginx** | Inside main container | Separate container |
| **Django/uWSGI** | Inside main container | Dedicated `web` container |
| **Celery Beat** | Inside main container | Dedicated container |
| **Celery Workers** | Inside main container | Separate containers (short/long) |
| **Migrations** | Via environment flag | Init container (runs once) |
### 2. Volume Strategy
| Data | Before (7.x) | After (7.3) |
|------|-------------|-------------|
| **Application code** | Bind mount `./` | **Built into image** |
| **Media files** | `./media_files` | **Named volume** `media_files` |
| **Static files** | `./static` | **Built into image** (collectstatic at build) |
| **Logs** | `./logs` | **Named volume** `logs` |
| **PostgreSQL** | `../postgres_data` | **Named volume** `postgres_data` |
| **Custom config** | `cms/local_settings.py` | **Bind mount** `./custom/` |
### 3. Removed Components
- ❌ supervisord and all supervisord configs
- ❌ docker-entrypoint.sh (permission fixing script)
-`ENABLE_*` environment variables
- ❌ Runtime collectstatic
- ❌ nginx from base image
### 4. New Components
-`custom/` directory for user customizations
- ✅ Multi-stage Dockerfile (base, web, worker, worker-full)
- ✅ Separate nginx image (`Dockerfile.nginx`)
- ✅ Build-time collectstatic
- ✅ USER www-data (non-root containers)
- ✅ Health checks for all services
- ✅ Makefile with common tasks
## Key Improvements
### Security
- ✅ Containers run as `www-data` (UID 33), not root
- ✅ Read-only mounts where possible
- ✅ Smaller attack surface per container
- ✅ No privilege escalation needed
### Performance
- ✅ Named volumes have better I/O than bind mounts
- ✅ Static files built into image (no runtime collection)
- ✅ Faster container startups
- ✅ No chown on millions of files at startup
### Scalability
- ✅ Scale web and workers independently
- ✅ Ready for load balancing
- ✅ Can use Docker Swarm or Kubernetes
- ✅ Horizontal scaling: `docker compose scale celery_short=3`
### Maintainability
- ✅ One process per container (proper separation)
- ✅ Clear service dependencies
- ✅ Standard Docker patterns
- ✅ Easier debugging (service-specific logs)
- ✅ Immutable images
### Developer Experience
- ✅ Separate dev compose with hot reload
-`custom/` directory for all customizations
- ✅ Clear documentation and examples
- ✅ Makefile targets for common tasks
## New Customization System
### The `custom/` Directory
All user customizations now go in a dedicated directory:
```
custom/
├── README.md # Full documentation
├── local_settings.py.example # Template file
├── local_settings.py # Your Django settings (gitignored)
└── static/
├── images/ # Custom logos (gitignored)
│ └── logo_dark.png
└── css/ # Custom CSS (gitignored)
└── custom.css
```
**Benefits:**
- Clear separation from core code
- Works out-of-box (empty directory is fine)
- Gitignored customizations
- Well documented with examples
See [`custom/README.md`](./custom/README.md) for usage guide.
## Docker Images
### Images to Build
```bash
# Web image (Django + uWSGI)
docker build --target web -t mediacms/mediacms:7.3 .
# Worker image (Celery)
docker build --target worker -t mediacms/mediacms-worker:7.3 .
# Worker-full image (Celery with extra codecs)
docker build --target worker-full -t mediacms/mediacms-worker:7.3-full .
# Nginx image
docker build -f Dockerfile.nginx -t mediacms/mediacms-nginx:7.3 .
```
### Image Sizes
| Image | Approximate Size |
|-------|-----------------|
| mediacms:7.3 | ~800MB |
| mediacms-worker:7.3 | ~800MB |
| mediacms-worker:7.3-full | ~1.2GB |
| mediacms-nginx:7.3 | ~50MB |
## Deployment Scenarios
### 1. Development
```bash
docker compose -f docker-compose-dev.yaml up
```
**Features:**
- File mounts for live editing
- Django runserver with DEBUG=True
- Frontend hot reload
- Immediate code changes
### 2. Production (HTTP)
```bash
docker compose up -d
```
**Features:**
- Immutable images
- Named volumes for data
- Production-ready
- Port 80
### 3. Production (HTTPS with Let's Encrypt)
```bash
docker compose -f docker-compose.yaml -f docker-compose-cert.yaml up -d
```
**Features:**
- Automatic SSL certificates
- Auto-renewal
- nginx-proxy + acme-companion
- Production-ready
## Minimal Deployment (No Code Required!)
**Version 7.3 requires ONLY:**
1.`docker-compose.yaml` file
2. ✅ Docker images (from Docker Hub)
3. ⚠️ `custom/` directory (optional, only if customizing)
**No git repo needed!** Download docker-compose.yaml from release/docs and start.
## Migration Requirements
### Breaking Changes
⚠️ **Not backward compatible** - Manual migration required
**What needs migration:**
1. ✅ PostgreSQL database (dump and restore)
2. ✅ Media files (copy to named volume)
3. ✅ Custom settings → `custom/local_settings.py` (if you had them)
4. ✅ Custom logos/CSS → `custom/static/` (if you had them)
5. ⚠️ Backup scripts (new volume paths)
6. ⚠️ Monitoring (new container names)
### Migration Steps
See [`UPGRADE_TO_7.3.md`](./UPGRADE_TO_7.3.md) for complete guide.
**Quick overview:**
```bash
# 1. Backup
docker compose exec db pg_dump -U mediacms mediacms > backup.sql
tar -czf media_backup.tar.gz media_files/
cp docker-compose.yaml docker-compose.yaml.old
# 2. Download new docker-compose.yaml
wget https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose.yaml
# 3. Create custom/ if needed
mkdir -p custom/static/{images,css}
# Copy your old settings/logos if you had them
# 4. Pull images and start
docker compose pull
docker compose up -d
# 5. Restore data
cat backup.sql | docker compose exec -T db psql -U mediacms mediacms
# (See full guide for media migration)
```
## Configuration Files
### Created/Reorganized
```
├── Dockerfile # Multi-stage (base, web, worker)
├── Dockerfile.nginx # Nginx image
├── docker-compose.yaml # Production
├── docker-compose-cert.yaml # Production + HTTPS
├── docker-compose-dev.yaml # Development
├── Makefile # Common tasks
├── custom/ # User customizations
│ ├── README.md
│ ├── local_settings.py.example
│ └── static/
├── config/
│ ├── imagemagick/policy.xml
│ ├── nginx/
│ │ ├── nginx.conf
│ │ └── site.conf
│ ├── nginx-proxy/
│ │ └── client_max_body_size.conf
│ └── uwsgi/
│ └── uwsgi.ini
└── scripts/
└── run-migrations.sh
```
## Makefile Targets
New Makefile with common operations:
```bash
make backup-db # PostgreSQL dump with timestamp
make admin-shell # Quick Django shell access
make build-frontend # Rebuild frontend assets
make test # Run test suite
```
## Rollback Strategy
If migration fails:
```bash
# 1. Stop new version
docker compose down
# 2. Checkout old version
git checkout main
# 3. Restore old compose
git checkout main docker-compose.yaml
# 4. Restore data from backups
# (See UPGRADE_TO_7.3.md for details)
# 5. Start old version
docker compose up -d
```
## Testing Checklist
Before production deployment:
- [ ] Migrations run successfully
- [ ] Static files load correctly
- [ ] Media files upload/download work
- [ ] Video transcoding works (check celery_long logs)
- [ ] Admin panel accessible
- [ ] Custom settings loaded (if using custom/)
- [ ] Database persists across restarts
- [ ] Media persists across restarts
- [ ] Logs accessible via `docker compose logs`
- [ ] Health checks pass: `docker compose ps`
## Common Post-Upgrade Tasks
### View Logs
```bash
# Before: tail -f logs/uwsgi.log
# After:
docker compose logs -f web
docker compose logs -f celery_long
```
### Access Shell
```bash
# Before: docker exec -it <container> bash
# After:
make admin-shell
# Or: docker compose exec web bash
```
### Restart Service
```bash
# Before: docker restart <container>
# After:
docker compose restart web
```
### Scale Workers
```bash
# New capability:
docker compose up -d --scale celery_short=3 --scale celery_long=2
```
### Database Backup
```bash
# Before: Custom script
# After:
make backup-db
```
## Performance Considerations
### Startup Time
- **Before**: Slower (chown on all files)
- **After**: Faster (no permission fixing)
### I/O Performance
- **Before**: Bind mount overhead
- **After**: Named volumes (better performance)
### Memory Usage
- **Before**: Single large container
- **After**: Multiple smaller containers (better resource allocation)
## New Volume Management
### List Volumes
```bash
docker volume ls | grep mediacms
```
### Inspect Volume
```bash
docker volume inspect mediacms_media_files
```
### Backup Volume
```bash
docker run --rm \
-v mediacms_media_files:/data:ro \
-v $(pwd):/backup \
alpine tar czf /backup/media_backup.tar.gz -C /data .
```
## Documentation
- **Upgrade Guide**: [`UPGRADE_TO_7.3.md`](./UPGRADE_TO_7.3.md)
- **Customization**: [`custom/README.md`](./custom/README.md)
- **Admin Docs**: `docs/admins_docs.md`
## Timeline Estimates
| Instance Size | Expected Migration Time |
|---------------|------------------------|
| Small (<100 videos) | 30-60 minutes |
| Medium (100-1000 videos) | 1-3 hours |
| Large (>1000 videos) | 3-8 hours |
**Plan accordingly and schedule during low-traffic periods!**
## Getting Help
1. Read [`UPGRADE_TO_7.3.md`](./UPGRADE_TO_7.3.md) thoroughly
2. Check [`custom/README.md`](./custom/README.md) for customization
3. Search GitHub Issues
4. Test in staging first
5. Keep backups for at least 1 week post-upgrade
## Next Steps
1. ✅ Read [`UPGRADE_TO_7.3.md`](./UPGRADE_TO_7.3.md)
2. ✅ Test in development: `docker compose -f docker-compose-dev.yaml up`
3. ✅ Backup production data
4. ✅ Test migration in staging
5. ✅ Plan maintenance window
6. ✅ Execute migration
7. ✅ Monitor for 24-48 hours
---
**Ready to upgrade?** Start with: [`UPGRADE_TO_7.3.md`](./UPGRADE_TO_7.3.md)
+48 -35
View File
@@ -1,6 +1,5 @@
FROM python:3.13.5-slim-bookworm AS build-image FROM python:3.13.5-slim-bookworm AS build-image
# Install system dependencies needed for downloading and extracting
RUN apt-get update -y && \ RUN apt-get update -y && \
apt-get install -y --no-install-recommends wget xz-utils unzip && \ apt-get install -y --no-install-recommends wget xz-utils unzip && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
@@ -14,9 +13,8 @@ RUN mkdir -p ffmpeg-tmp && \
cp -v ffmpeg-tmp/ffmpeg ffmpeg-tmp/ffprobe ffmpeg-tmp/qt-faststart /usr/local/bin && \ cp -v ffmpeg-tmp/ffmpeg ffmpeg-tmp/ffprobe ffmpeg-tmp/qt-faststart /usr/local/bin && \
rm -rf ffmpeg-tmp ffmpeg-release-amd64-static.tar.xz rm -rf ffmpeg-tmp ffmpeg-release-amd64-static.tar.xz
# Install Bento4 in the specified location
RUN mkdir -p /home/mediacms.io/bento4 && \ RUN mkdir -p /home/mediacms.io/bento4 && \
wget -q --tries=5 --waitretry=10 --timeout=30 https://www.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip && \ wget -q http://zebulon.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip && \
unzip Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip -d /home/mediacms.io/bento4 && \ unzip Bento4-SDK-1-6-0-637.x86_64-unknown-linux.zip -d /home/mediacms.io/bento4 && \
mv /home/mediacms.io/bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux/* /home/mediacms.io/bento4/ && \ mv /home/mediacms.io/bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux/* /home/mediacms.io/bento4/ && \
rm -rf /home/mediacms.io/bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux && \ rm -rf /home/mediacms.io/bento4/Bento4-SDK-1-6-0-637.x86_64-unknown-linux && \
@@ -26,20 +24,21 @@ RUN mkdir -p /home/mediacms.io/bento4 && \
############ BASE RUNTIME IMAGE ############ ############ BASE RUNTIME IMAGE ############
FROM python:3.13.5-slim-bookworm AS base FROM python:3.13.5-slim-bookworm AS base
LABEL org.opencontainers.image.version="7.3"
LABEL org.opencontainers.image.title="MediaCMS"
LABEL org.opencontainers.image.description="Modern, scalable and open source video platform"
SHELL ["/bin/bash", "-c"] SHELL ["/bin/bash", "-c"]
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1 \
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONDONTWRITEBYTECODE=1 \
ENV CELERY_APP='cms' CELERY_APP='cms' \
ENV VIRTUAL_ENV=/home/mediacms.io VIRTUAL_ENV=/home/mediacms.io \
ENV PATH="$VIRTUAL_ENV/bin:$PATH" PATH="$VIRTUAL_ENV/bin:$PATH"
# Install system dependencies first
RUN apt-get update -y && \ RUN apt-get update -y && \
apt-get -y upgrade && \ apt-get -y upgrade && \
apt-get install --no-install-recommends -y \ apt-get install --no-install-recommends -y \
supervisor \
nginx \
imagemagick \ imagemagick \
procps \ procps \
build-essential \ build-essential \
@@ -50,18 +49,16 @@ RUN apt-get update -y && \
libxmlsec1-dev \ libxmlsec1-dev \
libxmlsec1-openssl \ libxmlsec1-openssl \
libpq-dev \ libpq-dev \
gosu \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Set up virtualenv first RUN mkdir -p /home/mediacms.io/mediacms/{logs,media_files,static} && \
RUN mkdir -p /home/mediacms.io/mediacms/{logs} && \
cd /home/mediacms.io && \ cd /home/mediacms.io && \
python3 -m venv $VIRTUAL_ENV python3 -m venv $VIRTUAL_ENV
# Copy requirements files
COPY requirements.txt requirements-dev.txt ./ COPY requirements.txt requirements-dev.txt ./
# Install Python dependencies using pip (within virtualenv)
ARG DEVELOPMENT_MODE=False ARG DEVELOPMENT_MODE=False
RUN pip install --no-cache-dir uv && \ RUN pip install --no-cache-dir uv && \
uv pip install --no-binary lxml --no-binary xmlsec -r requirements.txt && \ uv pip install --no-binary lxml --no-binary xmlsec -r requirements.txt && \
@@ -76,38 +73,54 @@ RUN pip install --no-cache-dir uv && \
libxmlsec1-dev \ libxmlsec1-dev \
libpq-dev libpq-dev
# Copy ffmpeg and Bento4 from build image
COPY --from=build-image /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg COPY --from=build-image /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
COPY --from=build-image /usr/local/bin/ffprobe /usr/local/bin/ffprobe COPY --from=build-image /usr/local/bin/ffprobe /usr/local/bin/ffprobe
COPY --from=build-image /usr/local/bin/qt-faststart /usr/local/bin/qt-faststart COPY --from=build-image /usr/local/bin/qt-faststart /usr/local/bin/qt-faststart
COPY --from=build-image /home/mediacms.io/bento4 /home/mediacms.io/bento4 COPY --from=build-image /home/mediacms.io/bento4 /home/mediacms.io/bento4
# Copy application files COPY --chown=www-data:www-data . /home/mediacms.io/mediacms
COPY . /home/mediacms.io/mediacms
WORKDIR /home/mediacms.io/mediacms WORKDIR /home/mediacms.io/mediacms
# required for sprite thumbnail generation for large video files # Copy imagemagick policy for sprite thumbnail generation
COPY deploy/docker/policy.xml /etc/ImageMagick-6/policy.xml COPY config/imagemagick/policy.xml /etc/ImageMagick-6/policy.xml
# Set process control environment variables # Create www-data user directories and set permissions
ENV ENABLE_UWSGI='yes' \ RUN mkdir -p /var/run/mediacms && \
ENABLE_NGINX='yes' \ chown -R www-data:www-data /home/mediacms.io/mediacms/logs \
ENABLE_CELERY_BEAT='yes' \ /home/mediacms.io/mediacms/media_files \
ENABLE_CELERY_SHORT='yes' \ /home/mediacms.io/mediacms/static \
ENABLE_CELERY_LONG='yes' \ /var/run/mediacms
ENABLE_MIGRATIONS='yes'
EXPOSE 9000 80 # Collect static files during build
RUN python manage.py collectstatic --noinput && \
chown -R www-data:www-data /home/mediacms.io/mediacms/static
RUN chmod +x ./deploy/docker/entrypoint.sh # Run container as www-data user
USER www-data
ENTRYPOINT ["./deploy/docker/entrypoint.sh"] ############ WEB IMAGE (Django/uWSGI) ############
CMD ["./deploy/docker/start.sh"] FROM base AS web
# Install uWSGI
RUN uv pip install uwsgi
# Copy uWSGI configuration
COPY config/uwsgi/uwsgi.ini /home/mediacms.io/mediacms/uwsgi.ini
EXPOSE 9000
CMD ["/home/mediacms.io/bin/uwsgi", "--ini", "/home/mediacms.io/mediacms/uwsgi.ini"]
############ WORKER IMAGE (Celery) ############
FROM base AS worker
# CMD will be overridden in docker-compose for different worker types
############ FULL WORKER IMAGE (Celery with extra codecs) ############
FROM worker AS worker-full
############ FULL IMAGE ############
FROM base AS full
COPY requirements-full.txt ./ COPY requirements-full.txt ./
RUN mkdir -p /root/.cache/ && \ RUN mkdir -p /root/.cache/ && \
chmod go+rwx /root/ && \ chmod go+rwx /root/ && \
chmod go+rwx /root/.cache/ chmod go+rwx /root/.cache/ && \
RUN uv pip install -r requirements-full.txt uv pip install -r requirements-full.txt
+18
View File
@@ -0,0 +1,18 @@
FROM nginx:alpine
LABEL org.opencontainers.image.version="7.3"
LABEL org.opencontainers.image.title="MediaCMS Nginx"
LABEL org.opencontainers.image.description="Nginx server for MediaCMS"
# Copy nginx configurations
COPY config/nginx/nginx.conf /etc/nginx/nginx.conf
COPY config/nginx/site.conf /etc/nginx/conf.d/default.conf
COPY config/nginx/uwsgi_params /etc/nginx/uwsgi_params
# Create directories for static and media files (will be volumes)
RUN mkdir -p /var/www/media /var/www/static && \
chown -R nginx:nginx /var/www
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+23
View File
@@ -0,0 +1,23 @@
# History
## 3.0.0
### Features
- Updates Python/Django requirements and Dockerfile to use latest 3.11 Python - https://github.com/mediacms-io/mediacms/pull/826/files. This update requires some manual steps, for existing (not new) installations. Check the update section under the [Admin docs](https://github.com/mediacms-io/mediacms/blob/main/docs/admins_docs.md#2-server-installation), either for single server or for Docker Compose installations
- Upgrade postgres on Docker Compose - https://github.com/mediacms-io/mediacms/pull/749
### Fixes
- video player options for HLS - https://github.com/mediacms-io/mediacms/pull/832
- AVI videos not correctly recognised as videos - https://github.com/mediacms-io/mediacms/pull/833
## 2.1.0
### Fixes
- Increase uwsgi buffer-size parameter. This prevents an error by uwsgi with large headers - [#5b60](https://github.com/mediacms-io/mediacms/commit/5b601698a41ad97f08c1830e14b1c18f73ab8315)
- Fix issues with comments. These were not reported on the tracker but it is certain that they would not show comments on media files (non videos but also videos). Unfortunately this reverts work done with Timestamps on comments + Mentions on comments, more on PR [#802](https://github.com/mediacms-io/mediacms/pull/802)
### Features
- Allow tags to contains other characters too, not only English alphabet ones [#801](https://github.com/mediacms-io/mediacms/pull/801)
- Add simple cookie consent code [#799](https://github.com/mediacms-io/mediacms/pull/799)
- Allow password reset & email verify pages on global login required [#790](https://github.com/mediacms-io/mediacms/pull/790)
- Add api_url field to search api [#692](https://github.com/mediacms-io/mediacms/pull/692)
-1
View File
@@ -1 +0,0 @@
Django admin → /admin/lti/ltiplatform/ --> Change to: https://YOUR_MOODLE/filter/mediacms/lti_auth.php
+14 -1
View File
@@ -1,4 +1,4 @@
.PHONY: admin-shell build-frontend .PHONY: admin-shell build-frontend backup-db
admin-shell: admin-shell:
@container_id=$$(docker compose ps -q web); \ @container_id=$$(docker compose ps -q web); \
@@ -17,3 +17,16 @@ build-frontend:
test: test:
docker compose -f docker-compose-dev.yaml exec --env TESTING=True -T web pytest docker compose -f docker-compose-dev.yaml exec --env TESTING=True -T web pytest
backup-db:
@echo "Creating PostgreSQL database dump..."
@mkdir -p backups
@timestamp=$$(date +%Y%m%d_%H%M%S); \
dump_file="backups/mediacms_dump_$${timestamp}.sql"; \
docker compose exec -T db pg_dump -U mediacms -d mediacms > "$${dump_file}"; \
if [ $$? -eq 0 ]; then \
echo "Database dump created successfully: $${dump_file}"; \
else \
echo "Database dump failed"; \
exit 1; \
fi
+292
View File
@@ -0,0 +1,292 @@
# MediaCMS 7.3 - Quick Start
## Minimal Deployment (No Code Required!)
MediaCMS 7.3 can be deployed with **just 2 files**:
1. `docker-compose.yaml`
2. `custom/` directory (optional)
**No git repo, no code checkout needed!** Everything runs from Docker images.
---
## Fresh Installation
### 1. Create deployment directory
```bash
mkdir mediacms && cd mediacms
```
### 2. Download docker-compose.yaml
```bash
wget https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose.yaml
```
Or with curl:
```bash
curl -O https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose.yaml
```
### 3. Start MediaCMS
```bash
docker compose up -d
```
### 4. Access your site
- **Frontend**: http://localhost
- **Admin**: http://localhost/admin
- Username: `admin`
- Password: Check logs for auto-generated password:
```bash
docker compose logs migrations | grep "password:"
```
**That's it!** 🎉
---
## Optional: Customization
### Add Custom Settings
```bash
# 1. Create custom directory
mkdir -p custom/static/{images,css}
# 2. Download example template
wget -O custom/local_settings.py.example \
https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/custom/local_settings.py.example
# 3. Copy and edit
cp custom/local_settings.py.example custom/local_settings.py
nano custom/local_settings.py
```
Example customizations:
```python
# custom/local_settings.py
DEBUG = False
ALLOWED_HOSTS = ['media.example.com']
PORTAL_NAME = "My Media Portal"
```
### Add Custom Logo
```bash
# 1. Copy your logo
cp ~/my-logo.png custom/static/images/logo_dark.png
# 2. Reference in settings
cat >> custom/local_settings.py <<EOF
PORTAL_LOGO_DARK_PNG = "/custom/static/images/logo_dark.png"
EOF
# 3. Restart (no rebuild needed!)
docker compose restart web
```
### Add Custom CSS
```bash
# 1. Create CSS file
cat > custom/static/css/custom.css <<EOF
body {
font-family: 'Arial', sans-serif;
}
EOF
# 2. Reference in settings
cat >> custom/local_settings.py <<EOF
EXTRA_CSS_PATHS = ["/custom/static/css/custom.css"]
EOF
# 3. Restart (no rebuild needed!)
docker compose restart web
```
**Note**: Both settings AND static files only need restart - nginx serves custom/ files directly!
---
## HTTPS with Let's Encrypt
### 1. Download cert overlay
```bash
wget https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose-cert.yaml
```
### 2. Edit domains
```bash
nano docker-compose-cert.yaml
```
Change these lines:
```yaml
VIRTUAL_HOST: 'media.example.com' # Your domain
LETSENCRYPT_HOST: 'media.example.com' # Your domain
LETSENCRYPT_EMAIL: 'admin@example.com' # Your email
```
### 3. Start with SSL
```bash
docker compose -f docker-compose.yaml -f docker-compose-cert.yaml up -d
```
**SSL certificates are issued automatically!**
---
## File Structure
Your deployment directory:
```
mediacms/
├── docker-compose.yaml # Required
├── docker-compose-cert.yaml # Optional (for HTTPS)
└── custom/ # Optional (for customizations)
├── local_settings.py # Django settings
└── static/
├── images/ # Custom logos
└── css/ # Custom CSS
```
**Named volumes** (managed by Docker):
- `mediacms_postgres_data` - Database
- `mediacms_media_files` - Uploaded media
- `mediacms_static_files` - Static assets
- `mediacms_logs` - Application logs
---
## Common Commands
### View logs
```bash
docker compose logs -f web
docker compose logs -f celery_long
```
### Access Django shell
```bash
docker compose exec web python manage.py shell
```
### Create admin user
```bash
docker compose exec web python manage.py createsuperuser
```
### Restart service
```bash
docker compose restart web
```
### Stop everything
```bash
docker compose down
```
### Update to newer version
```bash
docker compose pull
docker compose up -d
```
---
## Backup
### Database backup
```bash
docker compose exec db pg_dump -U mediacms mediacms > backup_$(date +%Y%m%d).sql
```
### Media files backup
```bash
docker run --rm \
-v mediacms_media_files:/data:ro \
-v $(pwd):/backup \
alpine tar czf /backup/media_backup_$(date +%Y%m%d).tar.gz -C /data .
```
---
## Upgrading from 7.x?
If you're upgrading from an older MediaCMS version, see:
- **[UPGRADE_TO_7.3.md](./UPGRADE_TO_7.3.md)** - Complete migration guide
- **[DOCKER_RESTRUCTURE_SUMMARY.md](./DOCKER_RESTRUCTURE_SUMMARY.md)** - What changed
---
## Documentation
- **Customization**: Download [`custom/README.md`](https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/custom/README.md)
- **Upgrade Guide**: [UPGRADE_TO_7.3.md](./UPGRADE_TO_7.3.md)
- **Architecture**: [DOCKER_RESTRUCTURE_SUMMARY.md](./DOCKER_RESTRUCTURE_SUMMARY.md)
- **Project Docs**: https://docs.mediacms.io
---
## Troubleshooting
### Can't access the site?
Check services are running:
```bash
docker compose ps
```
All services should be "Up" or "Exited (0)" for migrations.
### Forgot admin password?
Check logs:
```bash
docker compose logs migrations | grep "password:"
```
Or create new admin:
```bash
docker compose exec web python manage.py createsuperuser
```
### Videos not encoding?
Check celery workers:
```bash
docker compose logs celery_long
docker compose logs celery_short
```
### Port 80 already in use?
Edit docker-compose.yaml to use different port:
```yaml
nginx:
ports:
- "8080:80" # Use port 8080 instead
```
Then access at http://localhost:8080
---
## Support
- **Issues**: https://github.com/mediacms-io/mediacms/issues
- **Discussions**: https://github.com/mediacms-io/mediacms/discussions
- **Docs**: https://docs.mediacms.io
---
**🎉 Enjoy MediaCMS!**
+4 -4
View File
@@ -30,7 +30,6 @@ A demo is available at https://demo.mediacms.io
- **Multiple media types support**: video, audio, image, pdf - **Multiple media types support**: video, audio, image, pdf
- **Multiple media classification options**: categories, tags and custom - **Multiple media classification options**: categories, tags and custom
- **Multiple media sharing options**: social media share, videos embed code generation - **Multiple media sharing options**: social media share, videos embed code generation
- **Use in LMS**: LTI 1.3 support plus a Moodle plugin for embeding media in LMS
- **Video Trimmer**: trim video, replace, save as new or create segments - **Video Trimmer**: trim video, replace, save as new or create segments
- **SAML support**: with ability to add mappings to system roles and groups - **SAML support**: with ability to add mappings to system roles and groups
- **Easy media searching**: enriched with live search functionality - **Easy media searching**: enriched with live search functionality
@@ -43,7 +42,7 @@ A demo is available at https://demo.mediacms.io
- **Multiple transcoding profiles**: sane defaults for multiple dimensions (144p, 240p, 360p, 480p, 720p, 1080p) and multiple profiles (h264, h265, vp9) - **Multiple transcoding profiles**: sane defaults for multiple dimensions (144p, 240p, 360p, 480p, 720p, 1080p) and multiple profiles (h264, h265, vp9)
- **Adaptive video streaming**: possible through HLS protocol - **Adaptive video streaming**: possible through HLS protocol
- **Subtitles/CC**: support for multilingual subtitle files - **Subtitles/CC**: support for multilingual subtitle files
- **Scalable transcoding**: transcoding through priorities. - **Scalable transcoding**: transcoding through priorities. Experimental support for remote workers
- **Chunked file uploads**: for pausable/resumable upload of content - **Chunked file uploads**: for pausable/resumable upload of content
- **REST API**: Documented through Swagger - **REST API**: Documented through Swagger
- **Translation**: Most of the CMS is translated to a number of languages - **Translation**: Most of the CMS is translated to a number of languages
@@ -70,7 +69,7 @@ Copyright Markos Gogoulos.
## Support and paid services ## Support and paid services
We provide custom installations, development of extra functionality, migration from existing systems, integrations with legacy systems, training and support. Checkout our [services page](https://mediacms.io/#services/) for more information. We provide custom installations, development of extra functionality, migration from existing systems, integrations with legacy systems, training and support. Contact us at info@mediacms.io for more information.
### Commercial Hostings ### Commercial Hostings
**Elestio** **Elestio**
@@ -91,6 +90,7 @@ In order to support automatic transcriptions through Whisper, consider more CPUs
There are two ways to run MediaCMS, through Docker Compose and through installing it on a server via an automation script that installs and configures all needed services. Find the related pages: There are two ways to run MediaCMS, through Docker Compose and through installing it on a server via an automation script that installs and configures all needed services. Find the related pages:
- [Single Server](docs/admins_docs.md#2-server-installation) page
- [Docker Compose](docs/admins_docs.md#3-docker-installation) page - [Docker Compose](docs/admins_docs.md#3-docker-installation) page
A complete guide can be found on the blog post [How to self-host and share your videos in 2021](https://medium.com/@MediaCMS.io/how-to-self-host-and-share-your-videos-in-2021-14067e3b291b). A complete guide can be found on the blog post [How to self-host and share your videos in 2021](https://medium.com/@MediaCMS.io/how-to-self-host-and-share-your-videos-in-2021-14067e3b291b).
@@ -108,7 +108,7 @@ There are two ways to run MediaCMS, through Docker Compose and through installin
## Technology ## Technology
This software uses the following list of awesome technologies: Python, Django, Django Rest Framework, Celery, PostgreSQL, Redis, Nginx, Gunicorn, React, Fine Uploader, video.js, FFMPEG, Bento4 This software uses the following list of awesome technologies: Python, Django, Django Rest Framework, Celery, PostgreSQL, Redis, Nginx, uWSGI, React, Fine Uploader, video.js, FFMPEG, Bento4
## Who is using it ## Who is using it
-54
View File
@@ -1,54 +0,0 @@
# Security Policy
Thank you for helping improve the security of MediaCMS.
We take security vulnerabilities seriously and appreciate responsible disclosure.
---
## Reporting a Vulnerability
If you discover a security vulnerability in MediaCMS, **please do not open a public GitHub issue**.
Instead, report it using one of the following methods:
- **GitHub Security Advisories (preferred)**
Use the "Report a vulnerability" feature in this repository.
- **Contact Form**
Submit details via the official contact page:
https://mediacms.io/contact/
Please include as much of the following information as possible:
- Affected version(s)
- Detailed description of the issue
- Steps to reproduce (PoC if available)
- Impact assessment (e.g. RCE, XSS, privilege escalation)
- Any potential mitigations you are aware of
---
## Supported Versions
Security updates are provided for the **latest stable release** of MediaCMS.
Older versions may not receive security patches.
---
## Disclosure Policy
- We aim to acknowledge reports within **7 days**
- We aim to provide a fix or mitigation within **90 days**, depending on severity
- Please allow us time to investigate before any public disclosure
We follow responsible disclosure practices and will coordinate disclosure timelines when appropriate.
---
## Recognition
At this time, MediaCMS does not operate a formal bug bounty program.
However, we are happy to acknowledge valid security reports in release notes or advisories (with your permission).
---
Thank you for helping keep MediaCMS secure.
+477
View File
@@ -0,0 +1,477 @@
# Upgrade Guide: MediaCMS 7.x to 7.3
**IMPORTANT: This is a major architectural change. Read this entire guide before upgrading.**
---
## 🎯 Fresh Install (Not Upgrading)?
If you're starting fresh with 7.3, you don't need this guide!
**All you need:**
```bash
# 1. Download docker-compose.yaml
wget https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose.yaml
# 2. Start (creates everything automatically)
docker compose up -d
# 3. Done! Visit http://localhost
```
**Optional: Add customizations**
```bash
# Create custom/ directory
mkdir -p custom/static/{images,css}
# Download example settings
wget -O custom/local_settings.py.example \
https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/custom/local_settings.py.example
# Edit and use
cp custom/local_settings.py.example custom/local_settings.py
nano custom/local_settings.py
# Restart
docker compose restart web
```
See [`custom/README.md`](https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/custom/README.md) for customization options.
---
## ⚠️ Upgrading from 7.x? Continue reading...
## What Changed in 7.3
### Architecture Changes
- **Before**: Monolithic container (supervisor + nginx + uwsgi + celery in one)
- **After**: Microservices (separate nginx, web, celery_beat, celery_short, celery_long containers)
### Volume Strategy Changes
- **Before**: Entire project directory mounted (`./:/home/mediacms.io/mediacms/`)
- **After**: Named volumes for data, bind mount only for `custom/` directory
### Specific Changes
| Component | Before (7.x) | After (7.3) |
|-----------|-------------|-------------|
| media_files | Bind mount `./media_files` | Named volume `media_files` |
| static files | Bind mount `./static` | Named volume `static_files` (built into image) |
| logs | Bind mount `./logs` | Named volume `logs` |
| postgres_data | `../postgres_data` | Named volume `postgres_data` |
| Custom config | `cms/local_settings.py` in mounted dir | `custom/local_settings.py` bind mount |
| Static collection | Runtime (via entrypoint) | Build time (in Dockerfile) |
| User | Root with gosu switch | www-data from start |
## What You Need for 7.3
**Minimal deployment - NO CODE REQUIRED:**
1.`docker-compose.yaml` (download from release or docs)
2. ✅ Docker images (pulled from Docker Hub)
3. ⚠️ `custom/` directory (only if you have customizations)
**That's it!** No git repo, no code checkout needed.
## Pre-Upgrade Checklist
### 1. Backup Everything
```bash
# Stop services
docker compose down
# Backup media files
tar -czf backup_media_$(date +%Y%m%d).tar.gz media_files/
# Backup database
docker compose up -d db
docker compose exec db pg_dump -U mediacms mediacms > backup_db_$(date +%Y%m%d).sql
docker compose down
# Backup logs (optional)
tar -czf backup_logs_$(date +%Y%m%d).tar.gz logs/
# Backup local settings if you had them
cp cms/local_settings.py backup_local_settings.py 2>/dev/null || echo "No local_settings.py found"
# Backup current docker-compose.yaml
cp docker-compose.yaml docker-compose.yaml.old
```
### 2. Document Current Setup
```bash
# Save current docker-compose version
git branch backup-pre-7.3-upgrade
# Document current state
docker compose ps > pre_upgrade_state.txt
docker compose config > pre_upgrade_config.yaml
df -h > pre_upgrade_disk_usage.txt
```
### 3. Check Disk Space
You'll need enough space for:
- Existing data (media_files, postgres_data)
- New Docker volumes (will copy data here)
- Database dump
```bash
du -sh media_files/ postgres_data/ logs/
df -h .
```
## Upgrade Methods
### Method 1: Clean Migration (Recommended)
This method migrates your data to the new volume structure.
#### Step 1: Get New docker-compose.yaml
**Option A: Download from release**
```bash
# Download docker-compose.yaml for 7.3
wget https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose.yaml
# Or using curl
curl -O https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose.yaml
# Optional: Download HTTPS version
wget https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/docker-compose-cert.yaml
```
**Option B: Copy from docs/release notes**
- Copy the docker-compose.yaml content from release notes
- Save as `docker-compose.yaml` in your deployment directory
#### Step 2: Prepare Custom Configuration (if needed)
```bash
# Create custom directory structure (only if you need customizations)
mkdir -p custom/static/{images,css}
touch custom/static/{images,css}/.gitkeep
# If you had local_settings.py, create it in custom/
if [ -f backup_local_settings.py ]; then
# Copy your old settings
cp backup_local_settings.py custom/local_settings.py
echo "✓ Migrated local_settings.py"
else
# Download example template (optional)
wget -O custom/local_settings.py.example \
https://raw.githubusercontent.com/mediacms-io/mediacms/v7.3/custom/local_settings.py.example
echo "Downloaded example template to custom/local_settings.py.example"
fi
# Copy any custom logos/css you had
# (adjust paths as needed for your old setup)
# cp my-old-logo.png custom/static/images/logo_dark.png
# cp my-custom.css custom/static/css/custom.css
```
#### Step 3: Start New Stack (Without Data)
```bash
# Pull new images
docker compose pull
# Start database first
docker compose up -d db redis
# Wait for DB to be ready
sleep 10
```
#### Step 4: Restore Database
```bash
# Copy backup into container
docker compose cp backup_db_*.sql db:/tmp/backup.sql
# Restore database
docker compose exec db psql -U mediacms mediacms < /tmp/backup.sql
# Or from host:
cat backup_db_*.sql | docker compose exec -T db psql -U mediacms mediacms
```
#### Step 5: Restore Media Files
```bash
# Start all services (will create volumes)
docker compose up -d
# Find the volume name
docker volume ls | grep media_files
# Copy media files to volume
# Method A: Using a temporary container
docker run --rm \
-v $(pwd)/media_files:/source:ro \
-v mediacms_media_files:/dest \
alpine sh -c "cp -av /source/* /dest/"
# Method B: Using existing container
docker compose exec web sh -c "exit" # Ensure web is running
# Then copy from host
tar -C media_files -cf - . | docker compose exec -T web tar -C /home/mediacms.io/mediacms/media_files -xf -
```
#### Step 6: Verify and Test
```bash
# Check logs
docker compose logs -f web
# Verify media files are accessible
docker compose exec web ls -la /home/mediacms.io/mediacms/media_files/
# Check database connection
docker compose exec web python manage.py dbshell
# Access the site
curl http://localhost
# Check admin panel
# Visit http://localhost/admin
```
### Method 2: In-Place Migration with Symlinks (Advanced)
**Warning**: This is more complex but avoids data copying.
#### Step 1: Keep Old Data Locations
```bash
# Modify docker-compose.yaml to mount old locations temporarily
# Add to appropriate services:
volumes:
- ./media_files:/home/mediacms.io/mediacms/media_files
- ./logs:/home/mediacms.io/mediacms/logs
# Instead of named volumes
```
#### Step 2: Gradually Migrate
After confirming everything works:
1. Copy data to named volumes
2. Remove bind mounts
3. Switch to named volumes
### Method 3: Fresh Install (If Possible)
If your MediaCMS instance is new or test:
```bash
# Backup what you need
# ...
# Clean slate
docker compose down -v
rm -rf media_files/ logs/ static/
# Fresh start
docker compose up -d
```
## Post-Upgrade Steps
### 1. Verify Everything Works
```bash
# Check all services are running
docker compose ps
# Should see: migrations (exited 0), web, nginx, celery_beat, celery_short, celery_long, db, redis
# Check logs for errors
docker compose logs web
docker compose logs nginx
# Test upload functionality
# Test video encoding (check celery_long logs)
# Test frontend
```
### 2. Verify Media Files
```bash
# Check media files are accessible
docker compose exec web ls -lh /home/mediacms.io/mediacms/media_files/
# Check file counts match
# Old: ls media_files/ | wc -l
# New: docker compose exec web sh -c "ls /home/mediacms.io/mediacms/media_files/ | wc -l"
```
### 3. Verify Database
```bash
# Check users
docker compose exec db psql -U mediacms mediacms -c "SELECT count(*) FROM users_user;"
# Check videos
docker compose exec db psql -U mediacms mediacms -c "SELECT count(*) FROM files_media;"
```
### 4. Update Backups
```bash
# Update your backup scripts for new volume locations
# Use: make backup-db (if Makefile target exists)
# Or: docker compose exec db pg_dump ...
```
## Rollback Procedure
If something goes wrong:
### Quick Rollback
```bash
# Stop new version
docker compose down
# Restore old docker-compose file
mv docker-compose.yaml.old docker-compose.yaml
# Pull old images (if you had old image tags documented)
docker compose pull
# Start old version
docker compose up -d
```
### Full Rollback with Data Restore
```bash
# Stop everything
docker compose down -v
# Restore old docker-compose
mv docker-compose.yaml.old docker-compose.yaml
# Restore backups
tar -xzf backup_media_*.tar.gz -C ./media_files
cat backup_db_*.sql | docker compose exec -T db psql -U mediacms mediacms
# Start old version
docker compose up -d
```
## Common Issues & Solutions
### Issue: "Volume not found"
**Solution**: Volumes are created with project name prefix. Check:
```bash
docker volume ls
# Look for: mediacms_media_files, mediacms_static_files, etc.
```
### Issue: "Permission denied" on media files
**Solution**: Files must be owned by www-data (UID 33)
```bash
docker compose exec web chown -R www-data:www-data /home/mediacms.io/mediacms/media_files
```
### Issue: Static files not loading
**Solution**: Rebuild image (collectstatic runs at build time)
```bash
docker compose down
docker compose build --no-cache web
docker compose up -d
```
### Issue: Database connection refused
**Solution**: Check database is healthy
```bash
docker compose logs db
docker compose exec db pg_isready -U mediacms
```
### Issue: Custom settings not loading
**Solution**: Check custom/local_settings.py exists and syntax
```bash
docker compose exec web cat /home/mediacms.io/mediacms/custom/local_settings.py
docker compose exec web python -m py_compile /home/mediacms.io/mediacms/custom/local_settings.py
```
## Performance Considerations
### New Volume Performance
Named volumes are typically faster than bind mounts:
- **Before**: Filesystem overhead on host
- **After**: Direct container filesystem (better I/O)
### Monitoring Volume Usage
```bash
# Check volume sizes
docker system df -v
# Check specific volume
docker volume inspect mediacms_media_files
```
## New Backup Strategy
With named volumes, backups change:
```bash
# Database backup
docker compose exec db pg_dump -U mediacms mediacms > backup.sql
# Media files backup
docker run --rm \
-v mediacms_media_files:/data:ro \
-v $(pwd):/backup \
alpine tar czf /backup/media_backup_$(date +%Y%m%d).tar.gz -C /data .
```
Or use the Makefile:
```bash
make backup-db
```
## Getting Help
If you encounter issues:
1. **Check logs**: `docker compose logs <service>`
2. **Check GitHub Issues**: Search for similar problems
3. **Rollback**: Use the rollback procedure above
4. **Report**: Open an issue with:
- Your docker-compose.yaml
- Output of `docker compose ps`
- Relevant logs
- Steps to reproduce
## Summary of Benefits
After upgrading to 7.3:
**Better separation of concerns** - each service has one job
**Easier scaling** - scale web/workers independently
**Better security** - containers run as www-data, not root
**Faster deployments** - static files built into image
**Cleaner customization** - dedicated custom/ directory
**Easier SSL setup** - docker-compose-cert.yaml overlay
**Better volume management** - named volumes instead of bind mounts
## Timeline Recommendation
- **Small instance** (<100 videos): 30-60 minutes
- **Medium instance** (100-1000 videos): 1-3 hours
- **Large instance** (>1000 videos): Plan for several hours
Schedule during low-traffic period!
-12
View File
@@ -3,9 +3,7 @@ from __future__ import absolute_import
import os import os
from celery import Celery from celery import Celery
from celery.signals import worker_process_init
from django.conf import settings from django.conf import settings
from django.db import connections
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cms.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cms.settings")
app = Celery("cms") app = Celery("cms")
@@ -22,13 +20,3 @@ app.conf.task_always_eager = settings.CELERY_TASK_ALWAYS_EAGER
app.conf.worker_prefetch_multiplier = 1 app.conf.worker_prefetch_multiplier = 1
@worker_process_init.connect
def close_db_pool_on_fork(**_):
# psycopg3's ConnectionPool is not fork-safe: children inherit dead sockets
# from the parent's pool and block on getconn() until PoolTimeout. Dispose
# the inherited pool here so each prefork child opens its own on first use.
# NB: plain conn.close() would only putconn() back into the broken pool.
for conn in connections.all():
conn.close_pool()
-1
View File
@@ -24,7 +24,6 @@ INSTALLED_APPS = [
"actions.apps.ActionsConfig", "actions.apps.ActionsConfig",
"rbac.apps.RbacConfig", "rbac.apps.RbacConfig",
"identity_providers.apps.IdentityProvidersConfig", "identity_providers.apps.IdentityProvidersConfig",
"lti.apps.LtiConfig",
"debug_toolbar", "debug_toolbar",
"mptt", "mptt",
"crispy_forms", "crispy_forms",
+51 -95
View File
@@ -112,18 +112,22 @@ SITE_ID = 1
# set new paths for svg or png if you want to override # set new paths for svg or png if you want to override
# svg has priority over png, so if you want to use # svg has priority over png, so if you want to use
# custom pngs and not svgs, remove the lines with svgs # custom pngs and not svgs, remove the lines with svgs
# or set as empty strings # Logo paths (served from /static/)
# Default logos are built into the image
# To customize: place files in custom/static/images/ and reference as /custom/static/images/file.png
# or set as empty strings to disable
# example: # example:
# PORTAL_LOGO_DARK_PNG = "/custom/static/images/my-logo.png"
# PORTAL_LOGO_DARK_SVG = "" # PORTAL_LOGO_DARK_SVG = ""
# PORTAL_LOGO_LIGHT_SVG = ""
# place the files on static/images folder
PORTAL_LOGO_DARK_SVG = "/static/images/logo_dark.svg" PORTAL_LOGO_DARK_SVG = "/static/images/logo_dark.svg"
PORTAL_LOGO_DARK_PNG = "/static/images/logo_dark.png" PORTAL_LOGO_DARK_PNG = "/static/images/logo_dark.png"
PORTAL_LOGO_LIGHT_SVG = "/static/images/logo_light.svg" PORTAL_LOGO_LIGHT_SVG = "/static/images/logo_light.svg"
PORTAL_LOGO_LIGHT_PNG = "/static/images/logo_dark.png" PORTAL_LOGO_LIGHT_PNG = "/static/images/logo_dark.png"
# paths to extra css files to be included, eg "/static/css/custom.css" # Extra CSS files to include in templates
# place css inside static/css folder # To add custom CSS: place files in custom/static/css/ and add paths here
# Use /custom/static/ prefix for files in custom/ directory
# Example: EXTRA_CSS_PATHS = ["/custom/static/css/custom.css"]
EXTRA_CSS_PATHS = [] EXTRA_CSS_PATHS = []
# protection agains anonymous users # protection agains anonymous users
# per ip address limit, for actions as like/dislike/report # per ip address limit, for actions as like/dislike/report
@@ -171,25 +175,18 @@ REST_FRAMEWORK = {
} }
# In docker, deploy/docker/entrypoint.sh ensures the SECRET_KEY env var is SECRET_KEY = "2dii4cog7k=5n37$fz)8dst)kg(s3&10)^qa*gv(kk+nv-z&cu"
# set (generating .secret_key once on first start if needed). Outside docker, # TODO: this needs to be changed!
# either set SECRET_KEY in the environment or create a .secret_key file at the
# project root, e.g.:
# python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' > .secret_key
SECRET_KEY = os.getenv('SECRET_KEY')
if not SECRET_KEY:
_secret_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.secret_key')
if os.path.exists(_secret_path):
with open(_secret_path) as _f:
SECRET_KEY = _f.read().strip()
if not SECRET_KEY:
raise RuntimeError("SECRET_KEY is not set. Set the SECRET_KEY env var or create a .secret_key file at the project root.")
TEMP_DIRECTORY = "/tmp" # Don't use a temp directory inside BASE_DIR!!! TEMP_DIRECTORY = "/tmp" # Don't use a temp directory inside BASE_DIR!!!
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = "/static/" # where js/css files are stored on the filesystem STATIC_URL = "/static/" # where js/css files are stored on the filesystem
MEDIA_URL = "/media/" # URL where static files are served from the server MEDIA_URL = "/media/" # URL where static files are served from the server
STATIC_ROOT = BASE_DIR + "/static/" STATIC_ROOT = BASE_DIR + "/static/"
# Additional locations for static files
# Note: custom/static is NOT included here because it's served directly by nginx
# at /custom/static/ and doesn't need collectstatic
STATICFILES_DIRS = []
# where uploaded + encoded media are stored # where uploaded + encoded media are stored
MEDIA_ROOT = BASE_DIR + "/media_files/" MEDIA_ROOT = BASE_DIR + "/media_files/"
@@ -202,15 +199,6 @@ THUMBNAIL_UPLOAD_DIR = f"{MEDIA_UPLOAD_DIR}/thumbnails/"
SUBTITLES_UPLOAD_DIR = f"{MEDIA_UPLOAD_DIR}/subtitles/" SUBTITLES_UPLOAD_DIR = f"{MEDIA_UPLOAD_DIR}/subtitles/"
HLS_DIR = os.path.join(MEDIA_ROOT, "hls/") HLS_DIR = os.path.join(MEDIA_ROOT, "hls/")
# Protect media files via nginx auth_request
# When True, nginx delegates authorization for /media/<protected>/... to a
# Django endpoint that checks the Media's state and the user's access.
USE_X_ACCEL_REDIRECT = True
# Subdirectories of MEDIA_ROOT that should be gated. "chunks" is intentionally
# omitted (upload state, not playback).
X_ACCEL_PROTECTED_PATHS = ["encoded", "hls", "original"]
X_ACCEL_AUTH_CACHE_SECONDS = 300
FFMPEG_COMMAND = "ffmpeg" # this is the path FFMPEG_COMMAND = "ffmpeg" # this is the path
FFPROBE_COMMAND = "ffprobe" # this is the path FFPROBE_COMMAND = "ffprobe" # this is the path
MP4HLS = "mp4hls" MP4HLS = "mp4hls"
@@ -273,7 +261,22 @@ POST_UPLOAD_AUTHOR_MESSAGE_UNLISTED_NO_COMMENTARY = ""
CANNOT_ADD_MEDIA_MESSAGE = "User cannot add media, or maximum number of media uploads has been reached." CANNOT_ADD_MEDIA_MESSAGE = "User cannot add media, or maximum number of media uploads has been reached."
# mp4hls command, part of Bento4 # mp4hls command, part of Bento4
MP4HLS_COMMAND = "/home/mediacms.io/mediacms/Bento4-SDK-1-6-0-637.x86_64-unknown-linux/bin/mp4hls" MP4HLS_COMMAND = "/home/mediacms.io/bento4/bin/mp4hls"
# highly experimental, related with remote workers
ADMIN_TOKEN = ""
# this is used by remote workers to push
# encodings once they are done
# USE_BASIC_HTTP = True
# BASIC_HTTP_USER_PAIR = ('user', 'password')
# specify basic auth user/password pair for use with the
# remote workers, if nginx basic auth is setup
# apache2-utils need be installed
# then run
# htpasswd -c /home/mediacms.io/mediacms/deploy/.htpasswd user
# and set a password
# edit /etc/nginx/sites-enabled/mediacms.io and
# uncomment the two lines related to htpasswd
AUTH_USER_MODEL = "users.User" AUTH_USER_MODEL = "users.User"
@@ -305,7 +308,6 @@ INSTALLED_APPS = [
"actions.apps.ActionsConfig", "actions.apps.ActionsConfig",
"rbac.apps.RbacConfig", "rbac.apps.RbacConfig",
"identity_providers.apps.IdentityProvidersConfig", "identity_providers.apps.IdentityProvidersConfig",
"lti.apps.LtiConfig",
"debug_toolbar", "debug_toolbar",
"mptt", "mptt",
"crispy_forms", "crispy_forms",
@@ -376,59 +378,30 @@ FILE_UPLOAD_HANDLERS = [
"django.core.files.uploadhandler.TemporaryFileUploadHandler", "django.core.files.uploadhandler.TemporaryFileUploadHandler",
] ]
LOGS_DIR = os.path.join(BASE_DIR, "logs")
error_filename = os.path.join(LOGS_DIR, "debug.log")
if not os.path.exists(LOGS_DIR):
try:
os.mkdir(LOGS_DIR)
except PermissionError:
pass
if not os.path.isfile(error_filename):
open(error_filename, 'a').close()
LOGGING = { LOGGING = {
"version": 1, "version": 1,
"disable_existing_loggers": False, "disable_existing_loggers": False,
"formatters": {
"verbose": {
"format": "%(levelname)s %(asctime)s %(module)s "
"%(process)d %(thread)d %(message)s"
}
},
"handlers": { "handlers": {
"file": { "console": {
"level": "ERROR", "level": "DEBUG",
"class": "logging.FileHandler", "class": "logging.StreamHandler",
"filename": error_filename, "formatter": "verbose",
},
},
"loggers": {
"django": {
"handlers": ["file"],
"level": "ERROR",
"propagate": True,
},
},
}
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "mediacms",
"HOST": "127.0.0.1",
"PORT": "5432",
"USER": "mediacms",
"PASSWORD": "mediacms",
"OPTIONS": {
"pool": {
"min_size": 2,
"max_size": 8,
"timeout": 10,
"max_lifetime": 30 * 60,
"max_idle": 10 * 60,
} }
}, },
} "root": {"level": "INFO", "handlers": ["console"]},
} }
DATABASES = {"default": {"ENGINE": "django.db.backends.postgresql", "NAME": "mediacms", "HOST": "db", "PORT": "5432", "USER": "mediacms", "PASSWORD": "mediacms", "OPTIONS": {'pool': True}}}
REDIS_LOCATION = "redis://127.0.0.1:6379/1"
REDIS_LOCATION = "redis://redis:6379/1"
CACHES = { CACHES = {
"default": { "default": {
"BACKEND": "django_redis.cache.RedisCache", "BACKEND": "django_redis.cache.RedisCache",
@@ -579,7 +552,6 @@ DJANGO_ADMIN_URL = "admin/"
USE_SAML = False USE_SAML = False
USE_RBAC = False USE_RBAC = False
USE_IDENTITY_PROVIDERS = False USE_IDENTITY_PROVIDERS = False
USE_LTI = False # Enable LTI 1.3 integration
JAZZMIN_UI_TWEAKS = {"theme": "flatly"} JAZZMIN_UI_TWEAKS = {"theme": "flatly"}
USE_ROUNDED_CORNERS = True USE_ROUNDED_CORNERS = True
@@ -588,8 +560,7 @@ ALLOW_VIDEO_TRIMMER = True
ALLOW_CUSTOM_MEDIA_URLS = False ALLOW_CUSTOM_MEDIA_URLS = False
ALLOW_MEDIA_REPLACEMENT = False # Whether to allow anonymous users to list all users
ALLOW_ANONYMOUS_USER_LISTING = True ALLOW_ANONYMOUS_USER_LISTING = True
# Who can see the members page # Who can see the members page
@@ -626,13 +597,15 @@ WHISPER_MODEL = "base"
SIDEBAR_FOOTER_TEXT = "" SIDEBAR_FOOTER_TEXT = ""
try: try:
# keep a local_settings.py file for local overrides # Load custom settings from custom/local_settings.py
from .local_settings import * # noqa import sys
sys.path.insert(0, BASE_DIR)
from custom.local_settings import * # noqa
# ALLOWED_HOSTS needs a url/ip # ALLOWED_HOSTS needs a url/ip
ALLOWED_HOSTS.append(FRONTEND_HOST.replace("http://", "").replace("https://", "")) ALLOWED_HOSTS.append(FRONTEND_HOST.replace("http://", "").replace("https://", ""))
except ImportError: except ImportError:
# local_settings not in use # custom/local_settings.py not in use or empty
pass pass
# Don't add new settings below that could be overridden in local_settings.py!!! # Don't add new settings below that could be overridden in local_settings.py!!!
@@ -675,20 +648,3 @@ if USERS_NEEDS_TO_BE_APPROVED:
) )
auth_index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware") auth_index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware")
MIDDLEWARE.insert(auth_index + 1, "cms.middleware.ApprovalMiddleware") MIDDLEWARE.insert(auth_index + 1, "cms.middleware.ApprovalMiddleware")
# LTI 1.3 Integration Settings
if USE_LTI:
# Session timeout for LTI launches (seconds)
LTI_SESSION_TIMEOUT = 3600 # 1 hour
# Cookie settings required for iframe embedding from LMS
# IMPORTANT: Requires HTTPS to be enabled!
SESSION_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SECURE = True
RELATED_MEDIA_STRATEGY = "no_related"
# Whether LMS course categories appear in the public
# category list.
SHOW_LMS_COURSES_IN_CATEGORIES = False
-1
View File
@@ -25,7 +25,6 @@ urlpatterns = [
re_path(r"^", include("files.urls")), re_path(r"^", include("files.urls")),
re_path(r"^", include("users.urls")), re_path(r"^", include("users.urls")),
re_path(r"^accounts/", include("allauth.urls")), re_path(r"^accounts/", include("allauth.urls")),
re_path(r"^lti/", include("lti.urls")),
re_path(r"^api-auth/", include("rest_framework.urls")), re_path(r"^api-auth/", include("rest_framework.urls")),
path(settings.DJANGO_ADMIN_URL, admin.site.urls), path(settings.DJANGO_ADMIN_URL, admin.site.urls),
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
+1 -1
View File
@@ -1 +1 @@
VERSION = "8.1.2" VERSION = "7.2.1"
+41
View File
@@ -0,0 +1,41 @@
user nginx;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 10240;
}
worker_rlimit_nofile 20000; #each connection needs a filehandle (or 2 if you are proxying)
http {
proxy_connect_timeout 75;
proxy_read_timeout 12000;
client_max_body_size 5800M;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 10;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/mediacms/nginx-main.access.log;
error_log /var/log/mediacms/nginx-main.error.log;
gzip on;
gzip_disable "msie6";
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
+38
View File
@@ -0,0 +1,38 @@
server {
listen 80 ;
gzip on;
access_log /var/log/mediacms/nginx.access.log;
error_log /var/log/mediacms/nginx.error.log warn;
location /static {
alias /var/www/static ;
}
location /custom/static {
alias /var/www/custom ;
}
location /media/original {
alias /var/www/media/original;
}
location /media {
alias /var/www/media ;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
include /etc/nginx/uwsgi_params;
uwsgi_pass web:9000;
}
}
+16
View File
@@ -0,0 +1,16 @@
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
+24
View File
@@ -0,0 +1,24 @@
[uwsgi]
chdir = /home/mediacms.io/mediacms/
virtualenv = /home/mediacms.io
module = cms.wsgi
uid=www-data
gid=www-data
processes = 2
threads = 2
master = true
socket = 0.0.0.0:9000
workers = 2
vacuum = true
hook-master-start = unix_signal:15 gracefully_kill_them_all
need-app = true
die-on-term = true
buffer-size=32768
+238
View File
@@ -0,0 +1,238 @@
# Custom Configuration
This directory allows you to customize MediaCMS without modifying the codebase or rebuilding images.
## How It Works - Production Ready!
**The Flow:**
```
1. CI/CD builds base image: docker build (no custom files)
Pushes to Docker Hub
2. Production pulls image: docker compose pull
Mounts custom/ directory
3. You add files: custom/static/css/custom.css
custom/static/images/logo.png
Nginx serves directly!
4. You reference in settings: EXTRA_CSS_PATHS = ["/custom/static/css/custom.css"]
PORTAL_LOGO_DARK_PNG = "/custom/static/images/logo.png"
Restart containers
5. Done! No rebuild needed!
```
**Key Points:**
- ✅ Files go in `custom/static/` on your host
- ✅ Nginx serves them directly from `/custom/static/` URL
-**NO rebuild needed** - just restart containers!
- ✅ Works with pre-built images from Docker Hub
- ✅ Perfect for production deployments
## Quick Start
### Option 1: No Customization (Default)
Just run docker compose - everything works out of the box:
```bash
docker compose up -d
```
### Option 2: With Customization
Add your custom files, then restart:
```bash
# 1. Copy example settings
cp custom/local_settings.py.example custom/local_settings.py
# 2. Edit settings
nano custom/local_settings.py
# 3. Restart containers (no rebuild!)
docker compose restart web celery_beat celery_short celery_long
```
## Customization Options
### 1. Django Settings (`local_settings.py`)
**Create the file:**
```bash
cp custom/local_settings.py.example custom/local_settings.py
```
**Edit with your settings:**
```python
# custom/local_settings.py
DEBUG = False
ALLOWED_HOSTS = ['example.com']
PORTAL_NAME = "My Media Site"
```
**Apply changes (restart only - no rebuild):**
```bash
docker compose restart web celery_beat celery_short celery_long
```
### 2. Custom Logo
**Add your logo:**
```bash
cp ~/my-logo.png custom/static/images/logo_dark.png
```
**Reference it in settings:**
```bash
cat >> custom/local_settings.py <<EOF
PORTAL_LOGO_DARK_PNG = "/custom/static/images/logo_dark.png"
EOF
```
**Restart (no rebuild needed!):**
```bash
docker compose restart web
```
### 3. Custom CSS
**Create CSS file:**
```bash
cat > custom/static/css/custom.css <<EOF
body {
font-family: 'Arial', sans-serif;
}
.header {
background-color: #333;
}
EOF
```
**Reference it in settings:**
```bash
cat >> custom/local_settings.py <<EOF
EXTRA_CSS_PATHS = ["/custom/static/css/custom.css"]
EOF
```
**Restart (no rebuild needed!):**
```bash
docker compose restart web
```
## Directory Structure
```
custom/
├── README.md # This file
├── local_settings.py.example # Template (copy to local_settings.py)
├── local_settings.py # Your settings (gitignored)
└── static/
├── images/ # Custom logos (gitignored)
│ └── logo_dark.png
└── css/ # Custom CSS (gitignored)
└── custom.css
```
## Important Notes
**No rebuild needed** - nginx serves custom/ files directly
**Works with pre-built images** - perfect for production
**Files are gitignored** - your customizations won't be committed
**Settings need restart only** - just restart containers
**Static files also just restart** - served directly by nginx
## Complete Example
```bash
# 1. Create settings file
cp custom/local_settings.py.example custom/local_settings.py
# 2. Add custom logo
cp ~/logo.png custom/static/images/logo_dark.png
# 3. Add custom CSS
echo "body { background: #f5f5f5; }" > custom/static/css/custom.css
# 4. Configure settings to use them
cat >> custom/local_settings.py <<EOF
# Custom branding
PORTAL_NAME = "My Media Portal"
PORTAL_LOGO_DARK_PNG = "/custom/static/images/logo_dark.png"
EXTRA_CSS_PATHS = ["/custom/static/css/custom.css"]
# Security
DEBUG = False
ALLOWED_HOSTS = ['media.example.com']
EOF
# 5. Apply changes (just restart!)
docker compose restart web
# Done! No rebuild needed.
```
## URL Paths Explained
| Your file | nginx serves at | You reference as |
|-----------|----------------|------------------|
| `custom/static/css/custom.css` | `http://localhost/custom/static/css/custom.css` | `"/custom/static/css/custom.css"` |
| `custom/static/images/logo.png` | `http://localhost/custom/static/images/logo.png` | `"/custom/static/images/logo.png"` |
**Why `/custom/static/`?**
- Distinguishes from core `/static/` (built into image)
- Allows nginx to serve from different mount point
- No rebuild needed when files change
## Troubleshooting
**Changes not appearing?**
- Restart containers: `docker compose restart web nginx`
- Check nginx has custom/ mounted: `docker compose exec nginx ls /var/www/custom`
- Check file exists: `docker compose exec nginx ls /var/www/custom/css/`
- Test URL: `curl http://localhost/custom/static/css/custom.css`
**Import errors?**
- Make sure `local_settings.py` has valid Python syntax
- Check logs: `docker compose logs web`
**Logo not showing?**
- Verify file is in `custom/static/images/`
- Check path in `local_settings.py` uses `/custom/static/` prefix
- Restart web container: `docker compose restart web`
## Advanced: Multiple CSS Files
```python
# custom/local_settings.py
EXTRA_CSS_PATHS = [
"/custom/static/css/colors.css",
"/custom/static/css/fonts.css",
"/custom/static/css/layout.css",
]
```
## Advanced: Environment-Specific Settings
```python
# custom/local_settings.py
import os
if os.getenv('ENVIRONMENT') == 'production':
DEBUG = False
ALLOWED_HOSTS = ['media.example.com']
else:
DEBUG = True
ALLOWED_HOSTS = ['*']
```
Then set in docker-compose.yaml:
```yaml
web:
environment:
ENVIRONMENT: production
```
+57
View File
@@ -0,0 +1,57 @@
# MediaCMS Local Settings Example
# Copy this file to local_settings.py and customize as needed:
# cp custom/local_settings.py.example custom/local_settings.py
# ===== Basic Settings =====
# DEBUG = False
# ALLOWED_HOSTS = ['example.com', 'www.example.com']
# PORTAL_NAME = "My Media Portal"
# ===== Database Settings =====
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.postgresql',
# 'NAME': 'mediacms',
# 'USER': 'mediacms',
# 'PASSWORD': 'mediacms',
# 'HOST': 'db',
# 'PORT': '5432',
# }
# }
# ===== Custom Branding =====
# Custom logos (place files in custom/static/images/)
# Nginx serves these directly from /custom/static/ (no rebuild needed!)
# PORTAL_LOGO_DARK_SVG = "/custom/static/images/logo_dark.svg"
# PORTAL_LOGO_DARK_PNG = "/custom/static/images/logo_dark.png"
# PORTAL_LOGO_LIGHT_SVG = "/custom/static/images/logo_light.svg"
# PORTAL_LOGO_LIGHT_PNG = "/custom/static/images/logo_light.png"
# Custom CSS (place files in custom/static/css/)
# Nginx serves these directly from /custom/static/ (no rebuild needed!)
# EXTRA_CSS_PATHS = ["/custom/static/css/custom.css"]
# ===== Email Settings =====
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# EMAIL_HOST = 'smtp.gmail.com'
# EMAIL_PORT = 587
# EMAIL_USE_TLS = True
# EMAIL_HOST_USER = 'your-email@example.com'
# EMAIL_HOST_PASSWORD = 'your-password'
# DEFAULT_FROM_EMAIL = 'noreply@example.com'
# ===== Security Settings =====
# SECRET_KEY = 'your-secret-key-here'
# SECURE_SSL_REDIRECT = True
# SESSION_COOKIE_SECURE = True
# CSRF_COOKIE_SECURE = True
# ===== Other Settings =====
# Any other Django setting can be overridden here
# See cms/settings.py for available settings
View File
View File
View File
+1 -6
View File
@@ -1,7 +1,7 @@
# MediaCMS: Document Changes for DEIC # MediaCMS: Document Changes for DEIC
## Configuration Changes ## Configuration Changes
The following changes are required in `deploy/docker/local_settings.py`: The following changes are required in `config/local_settings.py`:
```python ```python
@@ -73,8 +73,3 @@ Can be set through the SAML Configurations tab:
3. **Group Role Mapping**: Maps the role returned by SAML (as set in the SAML Configuration tab) with the role in groups that user will be added 3. **Group Role Mapping**: Maps the role returned by SAML (as set in the SAML Configuration tab) with the role in groups that user will be added
4. **Group mapping**: This creates groups associated with this IDP. Group ids as they come from SAML, associated with MediaCMS groups 4. **Group mapping**: This creates groups associated with this IDP. Group ids as they come from SAML, associated with MediaCMS groups
5. **Category Mapping**: This maps a group id (from SAML response) with a category in MediaCMS 5. **Category Mapping**: This maps a group id (from SAML response) with a category in MediaCMS
## More options
USER_SEARCH_FIELD = "name_username_email"
ALLOW_MEDIA_REPLACEMENT = True
-3
View File
@@ -1,3 +0,0 @@
# MediaCMS on Docker
See: [Details](../../docs/Docker_deployment.md)
-63
View File
@@ -1,63 +0,0 @@
#!/bin/bash
set -e
# forward request and error logs to docker log collector
ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log && \
ln -sf /dev/stdout /var/log/nginx/mediacms.io.access.log && ln -sf /dev/stderr /var/log/nginx/mediacms.io.error.log
cp /home/mediacms.io/mediacms/deploy/docker/local_settings.py /home/mediacms.io/mediacms/cms/local_settings.py
mkdir -p /home/mediacms.io/mediacms/{logs,media_files/hls}
touch /home/mediacms.io/mediacms/logs/debug.log
mkdir -p /var/run/mediacms
chown www-data:www-data /var/run/mediacms
TARGET_GID=$(stat -c "%g" /home/mediacms.io/mediacms/)
EXISTS=$(cat /etc/group | grep $TARGET_GID | wc -l)
# Create new group using target GID and add www-data user
if [ $EXISTS == "0" ]; then
groupadd -g $TARGET_GID tempgroup
usermod -a -G tempgroup www-data
else
# GID exists, find group name and add
GROUP=$(getent group $TARGET_GID | cut -d: -f1)
usermod -a -G $GROUP www-data
fi
# We should do this only for folders that have a different owner, since it is an expensive operation
# Also ignoring .git folder to fix this issue https://github.com/mediacms-io/mediacms/issues/934
# Exclude package-lock.json files that may not exist or be removed during frontend setup
find /home/mediacms.io/mediacms ! \( -path "*.git*" -o -name "package-lock.json" \) -exec chown www-data:$TARGET_GID {} + 2>/dev/null || true
chmod +x /home/mediacms.io/mediacms/deploy/docker/start.sh /home/mediacms.io/mediacms/deploy/docker/prestart.sh
# Generate or read SECRET_KEY once, shared across all containers via the
# host-mounted project volume. Atomic create-or-read so parallel container
# starts (web + celery_worker + celery_beat + migrations) can't race.
# Uses `mkdir` as the lock primitive (POSIX-atomic, no dependency on flock).
SECRET_KEY_FILE="${SECRET_KEY_FILE:-/home/mediacms.io/mediacms/.secret_key}"
SECRET_KEY_LOCK="${SECRET_KEY_FILE}.lock"
if [ -z "${SECRET_KEY:-}" ]; then
if [ ! -s "$SECRET_KEY_FILE" ]; then
# Spin-acquire the lock. mkdir is atomic; first caller wins, others retry.
while ! mkdir "$SECRET_KEY_LOCK" 2>/dev/null; do
sleep 0.2
done
# Re-check inside the lock: another container may have just written it.
if [ ! -s "$SECRET_KEY_FILE" ]; then
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' > "$SECRET_KEY_FILE"
chown www-data:www-data "$SECRET_KEY_FILE"
chmod 600 "$SECRET_KEY_FILE"
echo "entrypoint.sh: generated new SECRET_KEY at $SECRET_KEY_FILE"
fi
rmdir "$SECRET_KEY_LOCK"
fi
export SECRET_KEY="$(cat "$SECRET_KEY_FILE")"
fi
exec "$@"
-43
View File
@@ -1,43 +0,0 @@
import os
FRONTEND_HOST = os.getenv('FRONTEND_HOST', 'http://localhost')
PORTAL_NAME = os.getenv('PORTAL_NAME', 'MediaCMS')
REDIS_LOCATION = os.getenv('REDIS_LOCATION', 'redis://redis:6379/1')
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv('POSTGRES_NAME', 'mediacms'),
"HOST": os.getenv('POSTGRES_HOST', 'db'),
"PORT": os.getenv('POSTGRES_PORT', '5432'),
"USER": os.getenv('POSTGRES_USER', 'mediacms'),
"PASSWORD": os.getenv('POSTGRES_PASSWORD', 'mediacms'),
"OPTIONS": {
"pool": {
"min_size": 2,
"max_size": 8,
"timeout": 10,
"max_lifetime": 30 * 60,
"max_idle": 10 * 60,
}
},
}
}
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_LOCATION,
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
# CELERY STUFF
BROKER_URL = REDIS_LOCATION
CELERY_RESULT_BACKEND = BROKER_URL
MP4HLS_COMMAND = "/home/mediacms.io/bento4/bin/mp4hls"
DEBUG = os.getenv('DEBUG', 'False') == 'True'
-61
View File
@@ -1,61 +0,0 @@
# Use existing X-Forwarded-Proto from reverse proxy if present, otherwise use $scheme
map $http_x_forwarded_proto $forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
server {
listen 80 ;
gzip on;
access_log /var/log/nginx/mediacms.io.access.log;
error_log /var/log/nginx/mediacms.io.error.log warn;
location /static {
alias /home/mediacms.io/mediacms/static ;
}
location = /_media_auth {
internal;
proxy_pass http://127.0.0.1:9000/api/v1/media-auth;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Host $host;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
proxy_set_header Cookie $http_cookie;
}
location ~ ^/media/(encoded|hls|original)/(.*)$ {
auth_request /_media_auth;
alias /home/mediacms.io/mediacms/media_files/$1/$2;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
location /media {
alias /home/mediacms.io/mediacms/media_files ;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
}
}
-70
View File
@@ -1,70 +0,0 @@
#!/bin/bash
RANDOM_ADMIN_PASS=`python -c "import secrets;chars = 'abcdefghijklmnopqrstuvwxyz0123456789';print(''.join(secrets.choice(chars) for i in range(10)))"`
ADMIN_PASSWORD=${ADMIN_PASSWORD:-$RANDOM_ADMIN_PASS}
if [ X"$ENABLE_MIGRATIONS" = X"yes" ]; then
echo "Running migrations service"
python manage.py migrate
EXISTING_INSTALLATION=`echo "from users.models import User; print(User.objects.exists())" |python manage.py shell 2>/dev/null | tail -1`
if [ "$EXISTING_INSTALLATION" = "True" ]; then
echo "Loaddata has already run"
else
echo "Running loaddata and creating admin user"
python manage.py loaddata fixtures/encoding_profiles.json
python manage.py loaddata fixtures/categories.json
# post_save, needs redis to succeed (ie. migrate depends on redis)
DJANGO_SUPERUSER_PASSWORD=$ADMIN_PASSWORD python manage.py createsuperuser \
--no-input \
--username=$ADMIN_USER \
--email=$ADMIN_EMAIL \
--database=default || true
echo "Created admin user with password: $ADMIN_PASSWORD"
fi
echo "RUNNING COLLECTSTATIC"
python manage.py collectstatic --noinput
# echo "Updating hostname ..."
# TODO: Get the FRONTEND_HOST from cms/local_settings.py
# echo "from django.contrib.sites.models import Site; Site.objects.update(name='$FRONTEND_HOST', domain='$FRONTEND_HOST')" | python manage.py shell
fi
# Setting up internal nginx server
# HTTPS setup is delegated to a reverse proxy running infront of the application
cp deploy/docker/nginx_http_only.conf /etc/nginx/sites-available/default
cp deploy/docker/nginx_http_only.conf /etc/nginx/sites-enabled/default
cp deploy/docker/nginx.conf /etc/nginx/
#### Supervisord Configurations #####
cp deploy/docker/supervisord/supervisord-debian.conf /etc/supervisor/conf.d/supervisord-debian.conf
if [ X"$ENABLE_UWSGI" = X"yes" ] ; then
echo "Enabling gunicorn app server"
cp deploy/docker/supervisord/supervisord-gunicorn.conf /etc/supervisor/conf.d/supervisord-gunicorn.conf
fi
if [ X"$ENABLE_NGINX" = X"yes" ] ; then
echo "Enabling nginx as gunicorn app proxy and media server"
cp deploy/docker/supervisord/supervisord-nginx.conf /etc/supervisor/conf.d/supervisord-nginx.conf
fi
if [ X"$ENABLE_CELERY_BEAT" = X"yes" ] ; then
echo "Enabling celery-beat scheduling server"
cp deploy/docker/supervisord/supervisord-celery_beat.conf /etc/supervisor/conf.d/supervisord-celery_beat.conf
fi
if [ X"$ENABLE_CELERY_SHORT" = X"yes" ] ; then
echo "Enabling celery-short task worker"
cp deploy/docker/supervisord/supervisord-celery_short.conf /etc/supervisor/conf.d/supervisord-celery_short.conf
fi
if [ X"$ENABLE_CELERY_LONG" = X"yes" ] ; then
echo "Enabling celery-long task worker"
cp deploy/docker/supervisord/supervisord-celery_long.conf /etc/supervisor/conf.d/supervisord-celery_long.conf
rm /var/run/mediacms/* -f # remove any stale id, so that on forced restarts of celery workers there are no stale processes that prevent new ones
fi
@@ -1,17 +0,0 @@
-----BEGIN CERTIFICATE-----
MIICwzCCAaugAwIBAgIJAOyvdwguJQd+MA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
BAMTCWxvY2FsaG9zdDAeFw0yMTAxMjQxMjUwMzFaFw0zMTAxMjIxMjUwMzFaMBQx
EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAONswEwBzkgoO+lkewiKUnwvYqC54qleCUg9hidqjoyzd5XWKh1mIF7aaSCG
rJGSxCce8CbqAqGkpvsgXzwwbY72l7FwmAXFHO5ObQfpmFhjt2fsKRM9MTCo/UyU
liuhgP+Q+BNzUontTUC40NVHs8R7IHG4z8unB7qB/7zGK2tfilLB8JDqPTkc22vN
C4P1YxiGyY5bm37wQrroC9zPJ8bqanrF9Y90QJHubibnPWqnZvK2HkDWjp5LYkn8
IuzBycs1cLd8eMjU9aT72kweykvnGDDc3YbXFzT2zBTGSFEBROsVdPrNF9PaeE3j
pu4UZ8Ge3Fp3VYd+04DnWtbQq0MCAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxo
b3N0MA0GCSqGSIb3DQEBBQUAA4IBAQAdm2aGn4evosbdWgBHgzr6oYWBIiPpf1SA
GXizuf5OaMActFP0rZ0mogndLH5d51J2qqSfOtaWSA5qwlPvDSTn1nvJeHoVLfZf
kQHaB7/DaOPGsZCQBELPhYHwl7+Ej3HYE+siiaRfjC2NVgf8P/pAsTlKbe2e+34l
GwWSFol24w5xAmUezCF41JiZbqHoZhSh7s/PuJnK2RvhpjkrIot8GvxnbvOcKDIv
JzEKo3qPq8pc5RBkpP7Kp2+EgAYn1xAn0CekxZracW/MY+tg2mCeFucZW2V1iwVs
LpAw6GJnjYz5mbrQskPbrJ9t78JGUKQ0kL/VUTfryUHMHYCiJlvd
-----END CERTIFICATE-----
@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA42zATAHOSCg76WR7CIpSfC9ioLniqV4JSD2GJ2qOjLN3ldYq
HWYgXtppIIaskZLEJx7wJuoCoaSm+yBfPDBtjvaXsXCYBcUc7k5tB+mYWGO3Z+wp
Ez0xMKj9TJSWK6GA/5D4E3NSie1NQLjQ1UezxHsgcbjPy6cHuoH/vMYra1+KUsHw
kOo9ORzba80Lg/VjGIbJjlubfvBCuugL3M8nxupqesX1j3RAke5uJuc9aqdm8rYe
QNaOnktiSfwi7MHJyzVwt3x4yNT1pPvaTB7KS+cYMNzdhtcXNPbMFMZIUQFE6xV0
+s0X09p4TeOm7hRnwZ7cWndVh37TgOda1tCrQwIDAQABAoIBAQCmKKyOW7tlCNBN
AzbI1JbTWKOMnoM2DxhlCV5cqgOgVPcIKEL428bGxniMZRjr+vkJRBddtxdZFj1R
uSMbjJ5fF1dZMtQ/UvaCPhZ283p1CdXUPbz863ZnAPCf5Oea1RK0piw5ucYSM6h/
owgg65Qx92uK6uYW+uAwqg440+ihNvnaZoVTx5CjZbL9KISkrlNJnuYiB5vzOD0i
UVklO5Qz8VCuOcOVGZCA2SxHm4HAbg/aiQnpaUa9de4TsZ4ygF66pZh77T0wNOos
sS1riKtHQpX+osJyoTI/rIKFAhycsZ+AA7Qpu6GW4xQlNS6K8vRiIbktwkC+IT0O
RSn8Dg7BAoGBAPe5R8SpgXx9jKdA1eFa/Vjx5bmB96r2MviIOIWF8rs2K33xe+rj
v+BZ2ZjdpVjcm2nRMf9r/eDq2ScNFWmKoZsUmdyT84Qq9yLcTSUdno+zCy+L0LNH
DqJq5jIxJaV7amHeR/w10BVuiDmzhSsTmhfnXTUGRO/h2PjRyC3yEYdxAoGBAOsF
2+gTsdOGlq6AVzW5MLZkreq8WCU2wWpZRiCPh6HJa8htuynYxO5AWUiNUbYKddj2
0za9DFiXgH+Oo8wrkTYLEdN0T5/o+ScL5t3VG3m9R6pnuudLC2vmGQP0hNuZUpnF
7FzdJ85h6taR2bM1zFzOfl81K0BhTHGxTU2r70vzAoGAVXuLJ3LyqtnMKn72DzDN
0d6PTkdqBoW0qwyerHy/eRjFQ02MXE7BDJMUwmphv1tJCefVX/WNAwsnahFavTPI
dnJSccpgMtB8vXvV5yPkbmPzTTHrD6JKi4Nl8hYBjqwa1rDUmFSdfHfK7FZlcqrt
9qexAzYpnbmKnLoPYMNyhxECgYEAm5OCUeuPoL2MS7GLiXWwyFx3QFczZlcLzBGS
uYUpvLBwF/qDlhz3p9uS/tMFzyK3hktF4Ate+9o2ZroOtd31PzgusbJh7zIylGVt
i1VB3eGtaiFGeUuVIPTthE++Dvw80KxTXdnMOvNYmHduDBLF2H2c6/tvSSvfhbdf
u9XgD38CgYAiLcVySxMKNpsXatuC31wjT+rnaH22SD/7pXe2q6MRW/s+bGOspu0v
NeJSLoM98v8F99q0W0lgqesYJVI20Frru0DfXIp60ryaDolzve3Iwk8SOJUlcnUG
cCtmPUkjyr18QAlrcCB4PozJGjpPWyabaY8gGwo8wAEpJWHrIJlHew==
-----END RSA PRIVATE KEY-----
-17
View File
@@ -1,17 +0,0 @@
#! /usr/bin/env sh
set -e
# If there's a prestart.sh script in the /app directory, run it before starting
PRE_START_PATH=deploy/docker/prestart.sh
echo "Checking for script in $PRE_START_PATH"
if [ -f $PRE_START_PATH ] ; then
echo "Running script $PRE_START_PATH"
. $PRE_START_PATH
else
echo "There is no script $PRE_START_PATH"
fi
# Start Supervisor, with Nginx and Gunicorn
echo "Starting server using supervisord..."
exec /usr/bin/supervisord
@@ -1,12 +0,0 @@
[program:celery_beat]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
startsecs=0
numprocs=1
user=www-data
directory=/home/mediacms.io/mediacms
priority=300
startinorder=true
command=/home/mediacms.io/bin/celery beat --pidfile=/var/run/mediacms/beat%%n.pid --loglevel=INFO --logfile=/home/mediacms.io/mediacms/logs/celery_beat.log
@@ -1,13 +0,0 @@
[program:celery_long]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
startsecs=10
numprocs=1
user=www-data
directory=/home/mediacms.io/mediacms
priority=500
startinorder=true
startsecs=0
command=/home/mediacms.io/bin/celery multi start long1 --pidfile=/var/run/mediacms/%%n.pid --loglevel=INFO --logfile=/home/mediacms.io/mediacms/logs/celery_long.log -Ofair --prefetch-multiplier=1 -Q long_tasks
@@ -1,12 +0,0 @@
[program:celery_short]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
startsecs=0
numprocs=1
user=www-data
directory=/home/mediacms.io/mediacms
priority=400
startinorder=true
command=/home/mediacms.io/bin/celery multi start short1 short2 --pidfile=/var/run/mediacms/%%n.pid --loglevel=INFO --logfile=/home/mediacms.io/mediacms/logs/celery_short.log --soft-time-limit=300 -c10 -Q short_tasks
@@ -1,2 +0,0 @@
[supervisord]
nodaemon=true
@@ -1,9 +0,0 @@
[program:gunicorn]
command=/home/mediacms.io/bin/gunicorn cms.wsgi:application --workers=2 --threads=2 --worker-class=gthread --bind=127.0.0.1:9000 --user=www-data --group=www-data --timeout=120 --keep-alive=5 --max-requests=1000 --max-requests-jitter=50 --access-logfile=- --error-logfile=- --log-level=info --chdir=/home/mediacms.io/mediacms
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=100
startinorder=true
startsecs=0
@@ -1,11 +0,0 @@
[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=200
startinorder=true
startsecs=0
# Graceful stop, see http://nginx.org/en/docs/control.html
stopsignal=QUIT
+22
View File
@@ -0,0 +1,22 @@
[Unit]
Description=MediaCMS celery beat
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
Restart=always
RestartSec=10
WorkingDirectory=/home/mediacms.io/mediacms
Environment=CELERY_BIN="/home/mediacms.io/bin/celery"
Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/beat%n.pid"
Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/beat%N.log"
Environment=CELERYD_LOG_LEVEL="INFO"
ExecStart=/bin/sh -c '${CELERY_BIN} -A cms beat --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL}'
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
+29
View File
@@ -0,0 +1,29 @@
[Unit]
Description=MediaCMS celery long queue
After=network.target
[Service]
Type=forking
User=www-data
Group=www-data
Restart=always
RestartSec=10
WorkingDirectory=/home/mediacms.io/mediacms
Environment=CELERYD_NODES="long1"
Environment=CELERY_QUEUE="long_tasks"
Environment=CELERY_BIN="/home/mediacms.io/bin/celery"
Environment=CELERYD_MULTI="multi"
Environment=CELERYD_OPTS="-Ofair --prefetch-multiplier=1"
Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/%n.pid"
Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/%N.log"
Environment=CELERYD_LOG_LEVEL="INFO"
ExecStart=/bin/sh -c '${CELERY_BIN} -A cms multi start ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
ExecStop=/bin/sh -c '${CELERY_BIN} -A cms multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} -A cms multi restart ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
[Install]
WantedBy=multi-user.target
+39
View File
@@ -0,0 +1,39 @@
[Unit]
Description=MediaCMS celery short queue
After=network.target
[Service]
Type=forking
User=www-data
Group=www-data
Restart=always
RestartSec=10
WorkingDirectory=/home/mediacms.io/mediacms
Environment=CELERYD_NODES="short1 short2"
Environment=CELERY_QUEUE="short_tasks"
# Absolute or relative path to the 'celery' command:
Environment=CELERY_BIN="/home/mediacms.io/bin/celery"
# App instance to use
# comment out this line if you don't use an app
# or fully qualified:
#CELERY_APP="proj.tasks:app"
# How to call manage.py
Environment=CELERYD_MULTI="multi"
# Extra command-line arguments to the worker
Environment=CELERYD_OPTS="--soft-time-limit=300 -c10"
# - %n will be replaced with the first part of the nodename.
# - %I will be replaced with the current child process index
# and is important when using the prefork pool to avoid race conditions.
Environment=CELERYD_PID_FILE="/home/mediacms.io/mediacms/pids/%n.pid"
Environment=CELERYD_LOG_FILE="/home/mediacms.io/mediacms/logs/%N.log"
Environment=CELERYD_LOG_LEVEL="INFO"
ExecStart=/bin/sh -c '${CELERY_BIN} -A cms multi start ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
ExecStop=/bin/sh -c '${CELERY_BIN} -A cms multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} -A cms multi restart ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS} -Q ${CELERY_QUEUE}'
[Install]
WantedBy=multi-user.target
+13
View File
@@ -0,0 +1,13 @@
-----BEGIN DH PARAMETERS-----
MIICCAKCAgEAo3MMiEY/fNbu+usIM0cDi6x8G3JBApv0Lswta4kiyedWT1WN51iQ
9zhOFpmcu6517f/fR9MUdyhVKHxxSqWQTcmTEFtz4P3VLTS/W1N5VbKE2VEMLpIi
wr350aGvV1Er0ujcp5n4O4h0I1tn4/fNyDe7+pHCdwM+hxe8hJ3T0/tKtad4fnIs
WHDjl4f7m7KuFfheiK7Efb8MsT64HDDAYXn+INjtDZrbE5XPw20BqyWkrf07FcPx
8o9GW50Ox7/FYq7jVMI/skEu0BRc8u6uUD9+UOuWUQpdeHeFcvLOgW53Z03XwWuX
RXosUKzBPuGtUDAaKD/HsGW6xmGr2W9yRmu27jKpfYLUb/eWbbnRJwCw04LdzPqv
jmtq02Gioo3lf5H5wYV9IYF6M8+q/slpbttsAcKERimD1273FBRt5VhSugkXWKjr
XDhoXu6vZgj8Opei38qPa8pI1RUFoXHFlCe6WpZQmU8efL8gAMrJr9jUIY8eea1n
u20t5B9ueb9JMjrNafcq6QkKhZLi6fRDDTUyeDvc0dN9R/3Yts97SXfdi1/lX7HS
Ht4zXd5hEkvjo8GcnjsfZpAC39QfHWkDaeUGEqsl3jXjVMfkvoVY51OuokPWZzrJ
M5+wyXNpfGbH67dPk7iHgN7VJvgX0SYscDPTtms50Vk7RwEzLeGuSHMCAQI=
-----END DH PARAMETERS-----
+84
View File
@@ -0,0 +1,84 @@
server {
listen 80 ;
server_name localhost;
gzip on;
access_log /var/log/nginx/mediacms.io.access.log;
error_log /var/log/nginx/mediacms.io.error.log warn;
# # redirect to https if logged in
# if ($http_cookie ~* "sessionid") {
# rewrite ^/(.*)$ https://localhost/$1 permanent;
# }
# # redirect basic forms to https
# location ~ (login|login_form|register|mail_password_form)$ {
# rewrite ^/(.*)$ https://localhost/$1 permanent;
# }
location /static {
alias /home/mediacms.io/mediacms/static ;
}
location /media/original {
alias /home/mediacms.io/mediacms/media_files/original;
}
location /media {
alias /home/mediacms.io/mediacms/media_files ;
}
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
include /etc/nginx/sites-enabled/uwsgi_params;
uwsgi_pass 127.0.0.1:9000;
}
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate_key /etc/letsencrypt/live/localhost/privkey.pem;
ssl_certificate /etc/letsencrypt/live/localhost/fullchain.pem;
ssl_dhparam /etc/nginx/dhparams/dhparams.pem;
ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_ecdh_curve secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
gzip on;
access_log /var/log/nginx/mediacms.io.access.log;
error_log /var/log/nginx/mediacms.io.error.log warn;
location /static {
alias /home/mediacms.io/mediacms/static ;
}
location /media/original {
alias /home/mediacms.io/mediacms/media_files/original;
#auth_basic "auth protected area";
#auth_basic_user_file /home/mediacms.io/mediacms/deploy/local_install/.htpasswd;
}
location /media {
alias /home/mediacms.io/mediacms/media_files ;
}
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
include /etc/nginx/sites-enabled/uwsgi_params;
uwsgi_pass 127.0.0.1:9000;
}
}
@@ -0,0 +1,58 @@
-----BEGIN CERTIFICATE-----
MIIFTjCCBDagAwIBAgISBNOUeDlerH9MkKmHLvZJeMYgMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDAzMTAxNzUxNDFaFw0y
MDA2MDgxNzUxNDFaMBYxFDASBgNVBAMTC21lZGlhY21zLmlvMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAps5Jn18nW2tq/LYFDgQ1YZGLlpF/B2AAPvvH
3yuD+AcT4skKdZouVL/a5pXrptuYL5lthO9dlcja2tuO2ltYrb7Dp01dAIFaJE8O
DKd+Sv5wr8VWQZykqzMiMBgviml7TBvUHQjvCJg8UwmnN0XSUILCttd6u4qOzS7d
lKMMsKpYzLhElBT0rzhhsWulDiy6aAZbMV95bfR74nIWsBJacy6jx3jvxAuvCtkB
OVdOoVL6BPjDE3SNEk53bAZGIb5A9ri0O5jh/zBFT6tQSjUhAUTkmv9oZP547RnV
fDj+rdvCVk/fE+Jno36mcT183Qd/Ty3fWuqFoM5g/luhnfvWEwIDAQABo4ICYDCC
AlwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTd5EZBt74zu5XxT1uXQs6oM8qOuDAf
BgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEw
LgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcw
LwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcv
MBYGA1UdEQQPMA2CC21lZGlhY21zLmlvMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcG
CysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5
cHQub3JnMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYAXqdz+d9WwOe1Nkh90Eng
MnqRmgyEoRIShBh1loFxRVgAAAFwxcnL+AAABAMARzBFAiAb3yeBuW3j9MxcRc0T
icUBvEa/rH7Fv2eB0oQlnZ1exQIhAPf+CtTXmzxoeT/BBiivj4AmGDsq4xWhe/U6
BytYrKLeAHYAB7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohwAAAFwxcnM
HAAABAMARzBFAiAuP5gKyyaT0LVXxwjYD9zhezvxf4Icx0P9pk75c5ao+AIhAK0+
fSJv+WTXciMT6gA1sk/tuCHuDFAuexSA/6TcRXcVMA0GCSqGSIb3DQEBCwUAA4IB
AQCPCYBU4Q/ro2MUkjDPKGmeqdxQycS4R9WvKTG/nmoahKNg30bnLaDPUcpyMU2k
sPDemdZ7uTGLZ3ZrlIva8DbrnJmrTPf9BMwaM6j+ZV/QhxvKZVIWkLkZrwiVI57X
Ba+rs5IEB4oWJ0EBaeIrzeKG5zLMkRcIdE4Hlhuwu3zGG56c+wmAPuvpIDlYoO6o
W22xRdxoTIHBvkzwonpVYUaRcaIw+48xnllxh1dHO+X69DT45wlF4tKveOUi+L50
4GWJ8Vjv7Fot/WNHEM4Mnmw0jHj9TPkIZKnPNRMdHmJ5CF/FJFDiptOeuzbfohG+
mdvuInb8JDc0XBE99Gf/S4/y
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCmzkmfXydba2r8
tgUOBDVhkYuWkX8HYAA++8ffK4P4BxPiyQp1mi5Uv9rmleum25gvmW2E712VyNra
247aW1itvsOnTV0AgVokTw4Mp35K/nCvxVZBnKSrMyIwGC+KaXtMG9QdCO8ImDxT
Cac3RdJQgsK213q7io7NLt2UowywqljMuESUFPSvOGGxa6UOLLpoBlsxX3lt9Hvi
chawElpzLqPHeO/EC68K2QE5V06hUvoE+MMTdI0STndsBkYhvkD2uLQ7mOH/MEVP
q1BKNSEBROSa/2hk/njtGdV8OP6t28JWT98T4mejfqZxPXzdB39PLd9a6oWgzmD+
W6Gd+9YTAgMBAAECggEADnEJuryYQbf5GUwBAAepP3tEZJLQNqk/HDTcRxwTXuPt
+tKBD1F79WZu40vTjSyx7l0QOFQo/BDZsd0Ubx89fD1p3xA5nxOT5FTb2IifzIpe
4zjokOGo+BGDQjq10vvy6tH1+VWOrGXRwzawvX5UCRhpFz9sptQGLQmDsZy0Oo9B
LtavYVUqsbyqRWlzaclHgbythegIACWkqcalOzOtx+l6TGBRjej+c7URcwYBfr7t
XTAzbP+vnpaJovZyZT1eekr0OLzMpnjx4HvRvzL+NxauRpn6KfabsTfZlk8nrs4I
UdSjeukj1Iz8rGQilHdN/4dVJ3KzrlHVkVTBSjmMUQKBgQDaVXZnhAScfdiKeZbO
rdUAWcnwfkDghtRuAmzHaRM/FhFBEoVhdSbBuu+OUyBnIw/Ra4o2ePuEBcKIUiQO
w2tnE1CY5PPAcjw+OCSpvzy5xxjaqaRbm9BJp3FTeEYGLXERnchPpHg/NpexuF22
QOJ+FrysPyNMxuQp47ZwO9WT3QKBgQDDlSGjq/eeWxemwf7ZqMVlRyqsdJsgnCew
DkC62IGiYCBDfeEmndN+vcA/uzJHYV4iXiqS3aYJCWGaZFMhdIhIn5MgULvO1j5G
u/MxuzaaNPz22FlNCWTLBw4T1HOOvyTL+nLtZDKJ/BHxgHCmur1kiGvvZWrcCthD
afLEmseqrwKBgBuLZKCymxJTHhp6NHhmndSpfzyD8RNibzJhw+90ZiUzV4HqIEGn
Ufhm6Qn/mrroRXqaIpm0saZ6Q4yHMF1cchRS73wahlXlE4yV8KopojOd1pjfhgi4
o5JnOXjaV5s36GfcjATgLvtqm8CkDc6MaQaXP75LSNzKysYuIDoQkmVRAoGAAghF
rja2Pv4BU+lGJarcSj4gEmSvy/nza5/qSka/qhlHnIvtUAJp1TJRkhf24MkBOmgy
Fw6YkBV53ynVt05HsEGAPOC54t9VDFUdpNGmMpoEWuhKnUNQuc9b9RbLEJup3TjA
Avl8kPR+lzzXbtQX7biBLp6mKp0uPB0YubRGCN8CgYA0JMxK0x38Q2x3AQVhOmZh
YubtIa0JqVJhvpweOCFnkq3ebBpLsWYwiLTn86vuD0jupe5M3sxtefjkJmAKd8xY
aBU7QWhjh1fX4mzmggnbjcrIFbkIHsxwMeg567U/4AGxOOUsv9QUn37mqycqRKEn
YfUyYNLM6F3MmQAOs2kaHw==
-----END PRIVATE KEY-----
+13
View File
@@ -0,0 +1,13 @@
[Unit]
Description=MediaCMS uwsgi
[Service]
ExecStart=/home/mediacms.io/bin/uwsgi --ini /home/mediacms.io/mediacms/deploy/local_install/uwsgi.ini
ExecStop=/usr/bin/killall -9 uwsgi
RestartSec=3
#ExecRestart=killall -9 uwsgi; sleep 5; /home/sss/bin/uwsgi --ini /home/sss/wordgames/uwsgi.ini
Restart=always
[Install]
WantedBy=multi-user.target
+7
View File
@@ -0,0 +1,7 @@
/home/mediacms.io/mediacms/logs/*.log {
weekly
missingok
rotate 7
compress
notifempty
}
@@ -20,9 +20,6 @@ http {
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
default_type application/octet-stream; default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log; access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log; error_log /var/log/nginx/error.log;
+34
View File
@@ -0,0 +1,34 @@
module selinux-mediacms 1.0;
require {
type init_t;
type var_t;
type redis_port_t;
type postgresql_port_t;
type httpd_t;
type httpd_sys_content_t;
type httpd_sys_rw_content_t;
class file { append create execute execute_no_trans getattr ioctl lock open read rename setattr unlink write };
class dir { add_name remove_name rmdir };
class tcp_socket name_connect;
class lnk_file read;
}
#============= httpd_t ==============
allow httpd_t var_t:file { getattr open read };
#============= init_t ==============
allow init_t postgresql_port_t:tcp_socket name_connect;
allow init_t redis_port_t:tcp_socket name_connect;
allow init_t httpd_sys_content_t:dir rmdir;
allow init_t httpd_sys_content_t:file { append create execute execute_no_trans ioctl lock open read rename setattr unlink write };
allow init_t httpd_sys_content_t:lnk_file read;
allow init_t httpd_sys_rw_content_t:dir { add_name remove_name rmdir };
allow init_t httpd_sys_rw_content_t:file { create ioctl lock open read setattr unlink write };
+27
View File
@@ -0,0 +1,27 @@
[uwsgi]
chdir = /home/mediacms.io/mediacms/
virtualenv = /home/mediacms.io
module = cms.wsgi
uid=www-data
gid=www-data
processes = 2
threads = 2
master = true
socket = 127.0.0.1:9000
#socket = /home/mediacms.io/mediacms/deploy/uwsgi.sock
workers = 2
vacuum = true
logto = /home/mediacms.io/mediacms/logs/errorlog.txt
disable-logging = true
buffer-size=32768
+16
View File
@@ -0,0 +1,16 @@
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
+62
View File
@@ -0,0 +1,62 @@
version: "3.8"
# HTTPS/SSL certificate overlay for docker-compose.yaml
# Uses nginx-proxy with Let's Encrypt via acme-companion
#
# Usage:
# docker compose -f docker-compose.yaml -f docker-compose-cert.yaml up -d
#
# Before running:
# 1. Change VIRTUAL_HOST to your domain
# 2. Change LETSENCRYPT_HOST to your domain
# 3. Change LETSENCRYPT_EMAIL to your email
services:
# Reverse proxy with automatic SSL
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- dhparam:/etc/nginx/dhparam
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./config/nginx-proxy/client_max_body_size.conf:/etc/nginx/conf.d/client_max_body_size.conf:ro
# Let's Encrypt certificate manager
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
restart: unless-stopped
volumes_from:
- nginx-proxy
volumes:
- certs:/etc/nginx/certs:rw
- acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
# Override nginx to work with nginx-proxy
nginx:
expose:
- "80"
ports: [] # Remove ports, nginx-proxy handles external access
environment:
# CHANGE THESE VALUES:
VIRTUAL_HOST: 'mediacms.example.com'
LETSENCRYPT_HOST: 'mediacms.example.com'
LETSENCRYPT_EMAIL: 'admin@example.com'
volumes:
# nginx-proxy volumes
conf:
vhost:
html:
dhparam:
certs:
acme:
+100 -53
View File
@@ -1,4 +1,7 @@
version: "3" version: "3.8"
# Development setup with hot-reload and file mounts
# This is the ONLY compose file that mounts the source code
services: services:
migrations: migrations:
@@ -8,82 +11,126 @@ services:
target: base target: base
args: args:
- DEVELOPMENT_MODE=True - DEVELOPMENT_MODE=True
image: mediacms/mediacms-dev:latest image: mediacms/mediacms-dev:7.3
volumes: command: ["/bin/bash", "/home/mediacms.io/mediacms/scripts/run-migrations.sh"]
- ./:/home/mediacms.io/mediacms/
command: "./deploy/docker/prestart.sh"
environment: environment:
DEVELOPMENT_MODE: True DEVELOPMENT_MODE: 'True'
ENABLE_UWSGI: 'no' DEBUG: 'True'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_CELERY_BEAT: 'no'
ADMIN_USER: 'admin' ADMIN_USER: 'admin'
ADMIN_EMAIL: 'admin@localhost' ADMIN_EMAIL: 'admin@localhost'
ADMIN_PASSWORD: 'admin' ADMIN_PASSWORD: 'admin'
restart: on-failure restart: "no"
depends_on: depends_on:
redis: redis:
condition: service_healthy condition: service_healthy
db: db:
condition: service_healthy condition: service_healthy
frontend:
image: node:20
volumes:
- ${PWD}/frontend:/home/mediacms.io/mediacms/frontend/
working_dir: /home/mediacms.io/mediacms/frontend/
command: bash -c "npm install && npm run start"
env_file:
- ${PWD}/frontend/.env
ports:
- "8088:8088"
depends_on:
- web
web:
image: mediacms/mediacms-dev:latest
command: "python manage.py runserver 0.0.0.0:80"
environment:
DEVELOPMENT_MODE: True
ports:
- "80:80"
volumes: volumes:
- ./:/home/mediacms.io/mediacms/ - ./:/home/mediacms.io/mediacms/
web:
image: mediacms/mediacms-dev:7.3
restart: unless-stopped
ports:
- "80:8000"
command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
environment:
DEVELOPMENT_MODE: 'True'
DEBUG: 'True'
depends_on: depends_on:
- migrations migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
db:
condition: service_healthy
volumes:
- ./:/home/mediacms.io/mediacms/
frontend:
image: node:20-alpine
working_dir: /home/mediacms.io/mediacms/frontend/
command: sh -c "npm install && npm run start"
ports:
- "8088:8088"
environment:
- NODE_ENV=development
env_file:
- ./frontend/.env
volumes:
- ./frontend:/home/mediacms.io/mediacms/frontend/
depends_on:
- web
celery_beat:
image: mediacms/mediacms-dev:7.3
restart: unless-stopped
command: ["/home/mediacms.io/bin/celery", "-A", "cms", "beat", "--loglevel=INFO"]
environment:
DEVELOPMENT_MODE: 'True'
DEBUG: 'True'
depends_on:
migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
volumes:
- ./:/home/mediacms.io/mediacms/
celery_short:
image: mediacms/mediacms-dev:7.3
restart: unless-stopped
command: ["/home/mediacms.io/bin/celery", "-A", "cms", "worker", "-Q", "short_tasks", "-c", "10", "--soft-time-limit=300", "--loglevel=INFO", "-n", "short@%h"]
environment:
DEVELOPMENT_MODE: 'True'
DEBUG: 'True'
depends_on:
migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
volumes:
- ./:/home/mediacms.io/mediacms/
celery_long:
image: mediacms/mediacms-dev:7.3
restart: unless-stopped
command: ["/home/mediacms.io/bin/celery", "-A", "cms", "worker", "-Q", "long_tasks", "-c", "1", "-Ofair", "--prefetch-multiplier=1", "--loglevel=INFO", "-n", "long@%h"]
environment:
DEVELOPMENT_MODE: 'True'
DEBUG: 'True'
depends_on:
migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
volumes:
- ./:/home/mediacms.io/mediacms/
db: db:
image: postgres:17.2-alpine image: postgres:17.2-alpine
volumes: restart: unless-stopped
- ../postgres_data:/var/lib/postgresql/data/
restart: always
environment: environment:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London TZ: Europe/London
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}", "--host=db", "--dbname=$POSTGRES_DB", "--username=$POSTGRES_USER"] test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
redis: redis:
image: "redis:alpine" image: redis:alpine
restart: always restart: unless-stopped
healthcheck: healthcheck:
test: ["CMD", "redis-cli", "ping"] test: ["CMD", "redis-cli", "ping"]
interval: 30s interval: 10s
timeout: 10s timeout: 5s
retries: 3 retries: 3
celery_worker:
image: mediacms/mediacms-dev:latest volumes:
deploy: postgres_data:
replicas: 1
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_BEAT: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on:
- web
+90 -50
View File
@@ -1,86 +1,126 @@
version: "3" version: "3.8"
services: services:
migrations: migrations:
image: mediacms/mediacms:latest image: mediacms/mediacms:7.3
volumes: command: ["/bin/bash", "/home/mediacms.io/mediacms/scripts/run-migrations.sh"]
- ./:/home/mediacms.io/mediacms/
environment: environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_CELERY_BEAT: 'no'
ADMIN_USER: 'admin' ADMIN_USER: 'admin'
ADMIN_EMAIL: 'admin@localhost' ADMIN_EMAIL: 'admin@localhost'
# ADMIN_PASSWORD: 'uncomment_and_set_password_here' ADMIN_PASSWORD: # ADMIN_PASSWORD: 'uncomment_and_set_password_here'
command: "./deploy/docker/prestart.sh" restart: "no"
restart: on-failure
depends_on: depends_on:
redis: redis:
condition: service_healthy condition: service_healthy
db: db:
condition: service_healthy condition: service_healthy
volumes:
- ./custom:/home/mediacms.io/mediacms/custom:ro
- static_files:/home/mediacms.io/mediacms/static
- media_files:/home/mediacms.io/mediacms/media_files
- logs:/home/mediacms.io/mediacms/logs
web: web:
image: mediacms/mediacms:latest image: mediacms/mediacms:7.3
deploy: restart: unless-stopped
replicas: 1 expose:
- "9000"
depends_on:
migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
db:
condition: service_healthy
volumes:
- ./custom:/home/mediacms.io/mediacms/custom:ro
- static_files:/home/mediacms.io/mediacms/static
- media_files:/home/mediacms.io/mediacms/media_files
- logs:/home/mediacms.io/mediacms/logs
nginx:
image: mediacms/mediacms-nginx:7.3
restart: unless-stopped
ports: ports:
- "80:80" - "80:80"
volumes:
- ./:/home/mediacms.io/mediacms/
environment:
ENABLE_CELERY_BEAT: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on: depends_on:
- migrations - web
volumes:
- ./custom/static:/var/www/custom:ro
- static_files:/var/www/static:ro
- media_files:/var/www/media:ro
- logs:/var/log/mediacms
celery_beat: celery_beat:
image: mediacms/mediacms:latest image: mediacms/mediacms-worker:7.3
volumes: restart: unless-stopped
- ./:/home/mediacms.io/mediacms/ command: ["/home/mediacms.io/bin/celery", "-A", "cms", "beat", "--loglevel=INFO", "--schedule=/home/mediacms.io/mediacms/logs/celerybeat-schedule"]
environment:
ENABLE_UWSGI: 'no'
ENABLE_NGINX: 'no'
ENABLE_CELERY_SHORT: 'no'
ENABLE_CELERY_LONG: 'no'
ENABLE_MIGRATIONS: 'no'
depends_on: depends_on:
- redis migrations:
celery_worker: condition: service_completed_successfully
image: mediacms/mediacms:latest redis:
deploy: condition: service_healthy
replicas: 1
volumes: volumes:
- ./:/home/mediacms.io/mediacms/ - ./custom:/home/mediacms.io/mediacms/custom:ro
environment: - media_files:/home/mediacms.io/mediacms/media_files
ENABLE_UWSGI: 'no' - logs:/home/mediacms.io/mediacms/logs
ENABLE_NGINX: 'no'
ENABLE_CELERY_BEAT: 'no' celery_short:
ENABLE_MIGRATIONS: 'no' image: mediacms/mediacms-worker:7.3
restart: unless-stopped
command: ["/home/mediacms.io/bin/celery", "-A", "cms", "worker", "-Q", "short_tasks", "-c", "10", "--soft-time-limit=300", "--loglevel=INFO", "-n", "short@%h"]
depends_on: depends_on:
- migrations migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
volumes:
- ./custom:/home/mediacms.io/mediacms/custom:ro
- media_files:/home/mediacms.io/mediacms/media_files
- logs:/home/mediacms.io/mediacms/logs
celery_long:
image: mediacms/mediacms-worker:7.3
# To use extra codecs, change image to: mediacms/mediacms-worker:7.3-full
restart: unless-stopped
command: ["/home/mediacms.io/bin/celery", "-A", "cms", "worker", "-Q", "long_tasks", "-c", "1", "-Ofair", "--prefetch-multiplier=1", "--loglevel=INFO", "-n", "long@%h"]
depends_on:
migrations:
condition: service_completed_successfully
redis:
condition: service_healthy
volumes:
- ./custom:/home/mediacms.io/mediacms/custom:ro
- media_files:/home/mediacms.io/mediacms/media_files
- logs:/home/mediacms.io/mediacms/logs
db: db:
image: postgres:17.2-alpine image: postgres:17.2-alpine
volumes: restart: unless-stopped
- ../postgres_data:/var/lib/postgresql/data/
restart: always
environment: environment:
POSTGRES_USER: mediacms POSTGRES_USER: mediacms
POSTGRES_PASSWORD: mediacms POSTGRES_PASSWORD: mediacms
POSTGRES_DB: mediacms POSTGRES_DB: mediacms
TZ: Europe/London TZ: Europe/London
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
redis: redis:
image: "redis:alpine" image: redis:alpine
restart: always restart: unless-stopped
healthcheck: healthcheck:
test: ["CMD", "redis-cli","ping"] test: ["CMD", "redis-cli", "ping"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
volumes:
postgres_data:
static_files:
media_files:
logs:
+367
View File
@@ -0,0 +1,367 @@
# MediaCMS 7.3 Docker Architecture Migration Guide
## Overview
MediaCMS 7.3 introduces a modernized Docker architecture that removes supervisord and implements Docker best practices with one process per container.
## What Changed
### Old Architecture (pre-7.3)
- Single multi-purpose image with supervisord
- Environment variables (`ENABLE_UWSGI`, `ENABLE_NGINX`, etc.) to control services
- All services bundled in `deploy/docker/` folder
- File mounts required for all deployments
### New Architecture (7.3+)
- **Dedicated images** for each service:
- `mediacms/mediacms:7.3` - Django/uWSGI application
- `mediacms/mediacms-worker:7.3` - Celery workers
- `mediacms/mediacms-worker:7.3-full` - Celery workers with extra codecs
- `mediacms/mediacms-nginx:7.3` - Nginx web server
- **No supervisord** - Native Docker process management
- **Separated services**:
- `migrations` - Runs database migrations on every startup
- `nginx` - Serves static/media files and proxies to Django
- `web` - Django application (uWSGI)
- `celery_short` - Short-running tasks (thumbnails, etc.)
- `celery_long` - Long-running tasks (video encoding)
- `celery_beat` - Task scheduler
- **No ENABLE_* environment variables**
- **Config centralized** in `config/` directory
- **File mounts only for development** (`docker-compose-dev.yaml`)
## Directory Structure
```
config/
├── nginx/
│ ├── nginx.conf # Main nginx config
│ ├── site.conf # Virtual host config
│ └── uwsgi_params # uWSGI parameters
├── nginx-proxy/
│ └── client_max_body_size.conf # For production HTTPS proxy
├── uwsgi/
│ └── uwsgi.ini # uWSGI configuration
└── imagemagick/
└── policy.xml # ImageMagick policy
scripts/
├── entrypoint-web.sh # Web container entrypoint
├── entrypoint-worker.sh # Worker container entrypoint
└── run-migrations.sh # Migration script
Dockerfile.new # Main Dockerfile (base, web, worker, worker-full)
Dockerfile.nginx # Nginx Dockerfile
docker-compose.yaml # Production deployment
docker-compose-cert.yaml # Production with HTTPS
docker-compose-dev.yaml # Development with file mounts
```
## Migration Steps
### For Existing Production Systems
#### Step 1: Backup your data
```bash
# Backup database
docker exec mediacms_db_1 pg_dump -U mediacms mediacms > backup.sql
# Backup media files
cp -r media_files media_files.backup
```
#### Step 2: Update configuration location
```bash
# The client_max_body_size.conf has moved
# No action needed if you haven't customized it
```
#### Step 3: Pull latest images
```bash
docker pull mediacms/mediacms:7.3
docker pull mediacms/mediacms-worker:7.3
docker pull mediacms/mediacms-nginx:7.3
```
#### Step 4: Update docker-compose file
If using **docker-compose.yaml**:
- No changes needed, just use the new version
If using **docker-compose-cert.yaml** (HTTPS):
- Update `VIRTUAL_HOST`, `LETSENCRYPT_HOST`, and `LETSENCRYPT_EMAIL` in the nginx service
- Update the path to client_max_body_size.conf:
```yaml
- ./config/nginx-proxy/client_max_body_size.conf:/etc/nginx/conf.d/client_max_body_size.conf:ro
```
#### Step 5: Restart services
```bash
docker compose down
docker compose up -d
```
### For Development Systems
Development now requires the `-dev` compose file:
```bash
# Old way (no longer works)
docker compose up
# New way (development)
docker compose -f docker-compose-dev.yaml up
```
## Deployment Options
### Standard Deployment (HTTP)
**File**: `docker-compose.yaml`
**Command**:
```bash
docker compose up -d
```
**Features**:
- Self-contained images (no file mounts)
- Nginx serves on port 80
- Separate containers for each service
- Named volumes for persistence
**Architecture**:
```
Client → nginx:80 → web:9000 (uWSGI)
static_files (volume)
media_files (volume)
```
### Production Deployment (HTTPS with Let's Encrypt)
**File**: `docker-compose-cert.yaml`
**Prerequisites**:
1. Domain name pointing to your server
2. Ports 80 and 443 open
**Setup**:
```bash
# 1. Edit docker-compose-cert.yaml
# Update these values in the nginx service:
# VIRTUAL_HOST: 'your-domain.com'
# LETSENCRYPT_HOST: 'your-domain.com'
# LETSENCRYPT_EMAIL: 'your-email@example.com'
# 2. Start services
docker compose -f docker-compose-cert.yaml up -d
# 3. Check logs
docker compose -f docker-compose-cert.yaml logs -f nginx-proxy acme-companion
```
**Features**:
- Automatic HTTPS via Let's Encrypt
- Certificate auto-renewal
- Reverse proxy handles SSL termination
**Architecture**:
```
Client → nginx-proxy:443 (HTTPS) → nginx:80 → web:9000 (uWSGI)
```
### Development Deployment
**File**: `docker-compose-dev.yaml`
**Command**:
```bash
docker compose -f docker-compose-dev.yaml up
```
**Features**:
- Source code mounted for live editing
- Django debug mode enabled
- Django's `runserver` instead of uWSGI
- Frontend hot-reload on port 8088
- No nginx (direct Django access on port 80)
**Ports**:
- `80` - Django API
- `8088` - Frontend dev server
## Configuration
### Environment Variables
All configuration is done via environment variables or `cms/local_settings.py`.
**Key Variables**:
- `FRONTEND_HOST` - Your domain (e.g., `https://mediacms.example.com`)
- `PORTAL_NAME` - Your portal name
- `SECRET_KEY` - Django secret key
- `POSTGRES_*` - Database credentials
- `REDIS_LOCATION` - Redis connection string
- `DEBUG` - Enable debug mode (development only)
**Setting variables**:
Option 1: In docker-compose file:
```yaml
environment:
FRONTEND_HOST: 'https://mediacms.example.com'
PORTAL_NAME: 'My MediaCMS'
```
Option 2: Using .env file (recommended):
```bash
# Create .env file
cat > .env << EOF
FRONTEND_HOST=https://mediacms.example.com
PORTAL_NAME=My MediaCMS
SECRET_KEY=your-secret-key-here
EOF
```
### Customizing Settings
For advanced customization, you can build a custom image:
```dockerfile
# Dockerfile.custom
FROM mediacms/mediacms:7.3
COPY my_local_settings.py /home/mediacms.io/mediacms/cms/local_settings.py
```
## Celery Workers
### Standard Workers
By default, `celery_long` uses the standard image:
```yaml
celery_long:
image: mediacms/mediacms-worker:7.3
```
### Full Workers (Extra Codecs)
To enable extra codecs for better transcoding (including Whisper for subtitles):
**Edit docker-compose file**:
```yaml
celery_long:
image: mediacms/mediacms-worker:7.3-full # Changed from :7.3
```
**Then restart**:
```bash
docker compose up -d celery_long
```
### Scaling Workers
You can scale workers independently:
```bash
# Scale short task workers
docker compose up -d --scale celery_short=3
# Scale long task workers
docker compose up -d --scale celery_long=2
```
## Troubleshooting
### Migrations not running
```bash
# Check migrations container logs
docker compose logs migrations
# Manually run migrations
docker compose run --rm migrations
```
### Static files not loading
```bash
# Ensure migrations completed (it runs collectstatic)
docker compose logs migrations
# Check nginx can access volumes
docker compose exec nginx ls -la /var/www/static
```
### Permission issues
```bash
# Check volume ownership
docker compose exec web ls -la /home/mediacms.io/mediacms/media_files
# If needed, rebuild images
docker compose build --no-cache
```
### Celery workers not processing tasks
```bash
# Check worker logs
docker compose logs celery_short celery_long
# Check Redis connection
docker compose exec redis redis-cli ping
# Restart workers
docker compose restart celery_short celery_long celery_beat
```
## Removed Components
The following are **no longer used** in 7.3:
- ❌ `deploy/docker/supervisord/` - Supervisord configs
- ❌ `deploy/docker/start.sh` - Start script
- ❌ `deploy/docker/entrypoint.sh` - Old entrypoint
- ❌ Environment variables: `ENABLE_UWSGI`, `ENABLE_NGINX`, `ENABLE_CELERY_BEAT`, `ENABLE_CELERY_SHORT`, `ENABLE_CELERY_LONG`, `ENABLE_MIGRATIONS`
**These are still available but moved**:
- ✅ `config/nginx/` - Nginx configs (moved from `deploy/docker/`)
- ✅ `config/uwsgi/` - uWSGI config (moved from `deploy/docker/`)
- ✅ `config/nginx-proxy/` - Reverse proxy config (moved from `deploy/docker/reverse_proxy/`)
## Persistent Volumes
MediaCMS 7.3 uses Docker named volumes for data persistence:
- **`media_files`** - All uploaded media (videos, images, thumbnails, HLS streams)
- Mounted on: migrations, web, nginx, celery_beat, celery_short, celery_long
- Persists across container restarts, updates, and image removals
- **`logs`** - Application and nginx logs
- Mounted on: migrations, web, nginx, celery_beat, celery_short, celery_long
- Nginx logs: `/var/log/mediacms/nginx.access.log`, `/var/log/mediacms/nginx.error.log`
- Django/Celery logs: `/home/mediacms.io/mediacms/logs/`
- Persists across container restarts, updates, and image removals
- **`static_files`** - Django static files (CSS, JS, images)
- Mounted on: migrations, web, nginx
- Regenerated during migrations via `collectstatic`
- **`postgres_data`** - PostgreSQL database
- Mounted on: db
- Persists across container restarts, updates, and image removals
**Important**: Use `docker compose down -v` to remove volumes (⚠️ causes data loss!)
## Benefits of New Architecture
1. **Better resource management** - Scale services independently
2. **Easier debugging** - Clear separation of concerns
3. **Faster restarts** - Restart only affected services
4. **Production-ready** - No file mounts, immutable images
5. **Standard Docker practices** - One process per container
6. **Clearer logs** - Each service has isolated logs, persistent storage
7. **Better health checks** - Per-service monitoring
8. **Data persistence** - media_files and logs survive all container operations
## Support
For issues or questions:
- GitHub Issues: https://github.com/mediacms-io/mediacms/issues
- Documentation: https://docs.mediacms.io
+180 -34
View File
@@ -2,6 +2,7 @@
## Table of contents ## Table of contents
- [1. Welcome](#1-welcome) - [1. Welcome](#1-welcome)
- [2. Single Server Installaton](#2-single-server-installation)
- [3. Docker Installation](#3-docker-installation) - [3. Docker Installation](#3-docker-installation)
- [4. Docker Deployment options](#4-docker-deployment-options) - [4. Docker Deployment options](#4-docker-deployment-options)
- [5. Configuration](#5-configuration) - [5. Configuration](#5-configuration)
@@ -33,6 +34,58 @@
## 1. Welcome ## 1. Welcome
This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications. This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications.
## 2. Single Server Installation
The core dependencies are python3, Django, celery, PostgreSQL, redis, ffmpeg. Any system that can have these dependencies installed, can run MediaCMS. But the install.sh is only tested in Linux Ubuntu 24 and 22 versions.
Installation on an Ubuntu 22/24 system with git utility installed should be completed in a few minutes with the following steps.
Make sure you run it as user root, on a clear system, since the automatic script will install and configure the following services: Celery/PostgreSQL/Redis/Nginx and will override any existing settings.
```bash
mkdir /home/mediacms.io && cd /home/mediacms.io/
git clone https://github.com/mediacms-io/mediacms
cd /home/mediacms.io/mediacms/ && bash ./install.sh
```
The script will ask if you have a URL where you want to deploy MediaCMS, otherwise it will use localhost. If you provide a URL, it will use Let's Encrypt service to install a valid ssl certificate.
### Update
If you've used the above way to install MediaCMS, update with the following:
```bash
cd /home/mediacms.io/mediacms # enter mediacms directory
source /home/mediacms.io/bin/activate # use virtualenv
git pull # update code
pip install -r requirements.txt -U # run pip install to update
python manage.py migrate # run Django migrations
sudo systemctl restart mediacms celery_long celery_short # restart services
```
### Update from version 2 to version 3
Version 3 is using Django 4 and Celery 5, and needs a recent Python 3.x version. If you are updating from an older version, make sure Python is updated first. Version 2 could run on Python 3.6, but version 3 needs Python3.8 and higher.
The syntax for starting Celery has also changed, so you have to copy the celery related systemctl files and restart
```
# cp deploy/local_install/celery_long.service /etc/systemd/system/celery_long.service
# cp deploy/local_install/celery_short.service /etc/systemd/system/celery_short.service
# cp deploy/local_install/celery_beat.service /etc/systemd/system/celery_beat.service
# systemctl daemon-reload
# systemctl start celery_long celery_short celery_beat
```
### Configuration
Checkout the configuration section here.
### Maintenance
Database can be backed up with pg_dump and media_files on /home/mediacms.io/mediacms/media_files include original files and encoded/transcoded versions
## 3. Docker Installation ## 3. Docker Installation
@@ -111,53 +164,123 @@ Database is stored on ../postgres_data/ and media_files on media_files/
## 4. Docker Deployment options ## 4. Docker Deployment options
The mediacms image is built to use supervisord as the main process, which manages one or more services required to run mediacms. We can toggle which services are run in a given container by setting the environment variables below to `yes` or `no`: **⚠️ IMPORTANT**: MediaCMS 7.3 introduces a new Docker architecture. If you're upgrading from an earlier version, please see the [Migration Guide](DOCKER_V7.3_MIGRATION.md).
* ENABLE_UWSGI ### Architecture Overview
* ENABLE_NGINX
* ENABLE_CELERY_BEAT
* ENABLE_CELERY_SHORT
* ENABLE_CELERY_LONG
* ENABLE_MIGRATIONS
By default, all these services are enabled, but in order to create a scaleable deployment, some of them can be disabled, splitting the service up into smaller services. MediaCMS 7.3+ uses a modern microservices architecture with dedicated containers:
Also see the `Dockerfile` for other environment variables which you may wish to override. Application settings, eg. `FRONTEND_HOST` can also be overridden by updating the `deploy/docker/local_settings.py` file. - **nginx** - Web server for static/media files and reverse proxy
- **web** - Django application (uWSGI)
- **celery_short** - Short-running background tasks
- **celery_long** - Long-running tasks (video encoding)
- **celery_beat** - Task scheduler
- **migrations** - Database migrations (runs on startup)
- **db** - PostgreSQL database
- **redis** - Cache and message broker
To run, update the configs above if necessary, build the image by running `docker compose build`, then run `docker compose run` ### Key Changes from Previous Versions
### Simple Deployment, accessed as http://localhost -**No supervisord** - Native Docker process management
-**Dedicated images** per service
-**No ENABLE_* environment variables** - Services are separated into individual containers
-**Production images** don't mount source code (immutable)
-**config/** directory for centralized configuration
-**Separate celery workers** for short and long tasks
The main container runs migrations, mediacms_web, celery_beat, celery_workers (celery_short and celery_long services), exposed on port 80 supported by redis and postgres database. ### Configuration
The FRONTEND_HOST in `deploy/docker/local_settings.py` is configured as http://localhost, on the docker host machine. Application settings can be overridden using environment variables in your docker-compose file or by building a custom image with a modified `cms/local_settings.py` file.
### Server with ssl certificate through letsencrypt service, accessed as https://my_domain.com Key environment variables:
Before trying this out make sure the ip points to my_domain.com. - `FRONTEND_HOST` - Your domain (e.g., `https://mediacms.example.com`)
- `PORTAL_NAME` - Portal name
- `SECRET_KEY` - Django secret key
- `DEBUG` - Enable debug mode (development only)
- Database and Redis connection settings
With this method [this deployment](../docker-compose-letsencrypt.yaml) is used. See the [Migration Guide](DOCKER_V7.3_MIGRATION.md) for detailed configuration options
Edit this file and set `VIRTUAL_HOST` as my_domain.com, `LETSENCRYPT_HOST` as my_domain.com, and your email on `LETSENCRYPT_EMAIL` ### Simple Deployment (HTTP)
Edit `deploy/docker/local_settings.py` and set https://my_domain.com as `FRONTEND_HOST` Use `docker-compose.yaml` for a standard HTTP deployment on port 80:
Now run `docker compose -f docker-compose-letsencrypt.yaml up`, when installation finishes you will be able to access https://my_domain.com using a valid Letsencrypt certificate! ```bash
docker compose up -d
```
### Advanced Deployment, accessed as http://localhost:8000 This starts all services (nginx, web, celery workers, database, redis) with the nginx container exposed on port 80. Access at http://localhost or http://your-server-ip.
Here we can run 1 mediacms_web instance, with the FRONTEND_HOST in `deploy/docker/local_settings.py` configured as http://localhost:8000. This is bootstrapped by a single migrations instance and supported by a single celery_beat instance and 1 or more celery_worker instances. Redis and postgres containers are also used for persistence. Clients can access the service on http://localhost:8000, on the docker host machine. This is similar to [this deployment](../docker-compose.yaml), with a `port` defined in FRONTEND_HOST. **Features:**
- Production-ready with immutable images
- Named volumes for data persistence
- Separate containers for each service
### Advanced Deployment, with reverse proxy, accessed as http://mediacms.io ### Production Deployment with HTTPS (Let's Encrypt)
Here we can use `jwilder/nginx-proxy` to reverse proxy to 1 or more instances of mediacms_web supported by other services as mentioned in the previous deployment. The FRONTEND_HOST in `deploy/docker/local_settings.py` is configured as http://mediacms.io, nginx-proxy has port 80 exposed. Clients can access the service on http://mediacms.io (Assuming DNS or the hosts file is setup correctly to point to the IP of the nginx-proxy instance). This is similar to [this deployment](../docker-compose-http-proxy.yaml). Use `docker-compose-cert.yaml` for automatic HTTPS with Let's Encrypt:
### Advanced Deployment, with reverse proxy, accessed as https://localhost **Prerequisites:**
- Domain name pointing to your server
- Ports 80 and 443 open
The reverse proxy (`jwilder/nginx-proxy`) can be configured to provide SSL termination using self-signed certificates, letsencrypt or CA signed certificates (see: https://hub.docker.com/r/jwilder/nginx-proxy or [LetsEncrypt Example](https://www.singularaspect.com/use-nginx-proxy-and-letsencrypt-companion-to-host-multiple-websites/) ). In this case the FRONTEND_HOST should be set to https://mediacms.io. This is similar to [this deployment](../docker-compose-http-proxy.yaml). **Setup:**
1. Edit `docker-compose-cert.yaml` and update:
- `VIRTUAL_HOST` - Your domain
- `LETSENCRYPT_HOST` - Your domain
- `LETSENCRYPT_EMAIL` - Your email
2. Run:
```bash
docker compose -f docker-compose-cert.yaml up -d
```
This uses `nginxproxy/nginx-proxy` with `acme-companion` for automatic HTTPS certificate management. Access at https://your-domain.com.
### Development Deployment
Use `docker-compose-dev.yaml` for development with live code reloading:
```bash
docker compose -f docker-compose-dev.yaml up
```
**Features:**
- Source code mounted for live editing
- Django debug mode enabled
- Frontend dev server on port 8088
- Direct Django access (no nginx) on port 80
### Scaling Workers
Scale celery workers independently based on load:
```bash
# Scale short task workers to 3 instances
docker compose up -d --scale celery_short=3
# Scale long task workers to 2 instances
docker compose up -d --scale celery_long=2
```
### Using Extra Codecs (Full Image)
For advanced transcoding features (including Whisper for automatic subtitles), use the full worker image:
Edit your docker-compose file:
```yaml
celery_long:
image: mediacms/mediacms-worker:7.3-full # Changed from :7.3
```
Then restart:
```bash
docker compose up -d celery_long
```
### A Scaleable Deployment Architecture (Docker, Swarm, Kubernetes) ### A Scaleable Deployment Architecture (Docker, Swarm, Kubernetes)
The architecture below generalises all the deployment scenarios above, and provides a conceptual design for other deployments based on kubernetes and docker swarm. It allows for horizontal scaleability through the use of multiple mediacms_web instances and celery_workers. For large deployments, managed postgres, redis and storage may be adopted. The architecture below provides a conceptual design for deployments based on kubernetes and docker swarm. It allows for horizontal scaleability through the use of multiple web instances and celery workers. For large deployments, managed postgres, redis and storage may be adopted.
![MediaCMS](images/architecture.png) ![MediaCMS](images/architecture.png)
@@ -165,20 +288,36 @@ The architecture below generalises all the deployment scenarios above, and provi
## 5. Configuration ## 5. Configuration
Several options are available on `cms/settings.py`, most of the things that are allowed or should be disallowed are described there. Several options are available on `cms/settings.py`, most of the things that are allowed or should be disallowed are described there.
It is advisable to override any of them by adding it to `local_settings.py` . It is advisable to override any of them by adding it to `local_settings.py`.
In case of a docker compose installation, add to `deploy/docker/local_settings.py` . This will automatically overwrite `cms/local_settings.py` . **Single server installation:** edit `cms/local_settings.py`, make changes and restart MediaCMS:
Any change needs restart of MediaCMS in order to take effect.
```bash ```bash
#systemctl restart mediacms systemctl restart mediacms celery_beat celery_short celery_long
``` ```
Docker Compose installation: edit `deploy/docker/local_settings.py`, make a change and restart MediaCMS containers **Docker installation:** Configuration can be done in two ways:
1. **Environment variables** (recommended for simple changes):
Add to your docker-compose file:
```yaml
environment:
FRONTEND_HOST: 'https://mediacms.example.com'
PORTAL_NAME: 'My MediaCMS'
```
2. **Custom image with local_settings.py** (for complex changes):
- Create a custom Dockerfile:
```dockerfile
FROM mediacms/mediacms:7.3
COPY my_custom_settings.py /home/mediacms.io/mediacms/cms/local_settings.py
```
- Build and use your custom image
After changes, restart the affected containers:
```bash ```bash
#docker compose restart web celery_worker celery_beat docker compose restart web celery_short celery_long celery_beat
``` ```
### 5.1 Change portal logo ### 5.1 Change portal logo
@@ -738,7 +877,14 @@ Instructions contributed by @alberto98fx
On the [Configuration](https://github.com/mediacms-io/mediacms/blob/main/docs/admins_docs.md#5-configuration) section of this guide we've see how to edit the email settings. On the [Configuration](https://github.com/mediacms-io/mediacms/blob/main/docs/admins_docs.md#5-configuration) section of this guide we've see how to edit the email settings.
In case we are yet unable to receive email from MediaCMS, the following may help us debug the issue - in most cases it is an issue of setting the correct username, password or TLS option In case we are yet unable to receive email from MediaCMS, the following may help us debug the issue - in most cases it is an issue of setting the correct username, password or TLS option
Enter the Django shell and inside the shell Enter the Django shell, example if you're using the Single Server installation:
```bash
source /home/mediacms.io/bin/activate
python manage.py shell
```
and inside the shell
```bash ```bash
from django.core.mail import EmailMessage from django.core.mail import EmailMessage
+1 -1
View File
@@ -23,7 +23,7 @@ and will start all services required for MediaCMS, as Celery/Redis for asynchron
For Django, the changes from the image produced by docker-compose.yaml are these: For Django, the changes from the image produced by docker-compose.yaml are these:
* Django runs in debug mode, with `python manage.py runserver` * Django runs in debug mode, with `python manage.py runserver`
* gunicorn and nginx are not run * uwsgi and nginx are not run
* Django runs in Debug mode, with Debug Toolbar * Django runs in Debug mode, with Debug Toolbar
* Static files (js/css) are loaded from static/ folder * Static files (js/css) are loaded from static/ folder
* corsheaders is installed and configured to allow all origins * corsheaders is installed and configured to allow all origins
+2 -2
View File
@@ -46,7 +46,7 @@ Before beginning, ensure the following:
## Step 1: Configure MediaCMS for SAML ## Step 1: Configure MediaCMS for SAML
The first step in enabling SAML authentication is to modify the `local_settings.py` (for Docker: `./deploy/docker/local_settings.py`) file of your MediaCMS deployment. Add the following configuration block to enable SAML support, role-based access control (RBAC), and enforce secure communication settings: The first step in enabling SAML authentication is to modify the `local_settings.py` (for Docker: `./config/local_settings.py`) file of your MediaCMS deployment. Add the following configuration block to enable SAML support, role-based access control (RBAC), and enforce secure communication settings:
```python ```python
USE_RBAC = True USE_RBAC = True
@@ -292,7 +292,7 @@ Another issue you might encounter is an **infinite redirect loop**. This can hap
https://<MyDomainName>/accounts/saml/mediacms_entraid/login/ https://<MyDomainName>/accounts/saml/mediacms_entraid/login/
``` ```
* Add the following line to `./deploy/docker/local_settings.py`: * Add the following line to `./config/local_settings.py`:
```python ```python
LOGIN_URL = "/accounts/saml/mediacms_entraid/login/" LOGIN_URL = "/accounts/saml/mediacms_entraid/login/"
+4 -17
View File
@@ -65,7 +65,6 @@ class CategoryAdminForm(forms.ModelForm):
class Meta: class Meta:
model = Category model = Category
# LTI fields will be shown as read-only when USE_LTI is enabled
fields = '__all__' fields = '__all__'
def clean(self): def clean(self):
@@ -136,7 +135,7 @@ class CategoryAdmin(admin.ModelAdmin):
list_display = ["title", "user", "add_date", "media_count"] list_display = ["title", "user", "add_date", "media_count"]
list_filter = [] list_filter = []
ordering = ("-add_date",) ordering = ("-add_date",)
readonly_fields = ("user", "media_count", "lti_platform", "lti_context_id") readonly_fields = ("user", "media_count")
change_form_template = 'admin/files/category/change_form.html' change_form_template = 'admin/files/category/change_form.html'
def get_list_filter(self, request): def get_list_filter(self, request):
@@ -146,8 +145,6 @@ class CategoryAdmin(admin.ModelAdmin):
list_filter.insert(0, "is_rbac_category") list_filter.insert(0, "is_rbac_category")
if getattr(settings, 'USE_IDENTITY_PROVIDERS', False): if getattr(settings, 'USE_IDENTITY_PROVIDERS', False):
list_filter.insert(-1, "identity_provider") list_filter.insert(-1, "identity_provider")
if getattr(settings, 'USE_LTI', False):
list_filter.append("is_lms_course")
return list_filter return list_filter
@@ -157,8 +154,6 @@ class CategoryAdmin(admin.ModelAdmin):
list_display.insert(-1, "is_rbac_category") list_display.insert(-1, "is_rbac_category")
if getattr(settings, 'USE_IDENTITY_PROVIDERS', False): if getattr(settings, 'USE_IDENTITY_PROVIDERS', False):
list_display.insert(-1, "identity_provider") list_display.insert(-1, "identity_provider")
if getattr(settings, 'USE_LTI', False):
list_display.insert(-1, "is_lms_course")
return list_display return list_display
@@ -172,14 +167,6 @@ class CategoryAdmin(admin.ModelAdmin):
), ),
] ]
additional_fieldsets = []
if getattr(settings, 'USE_LTI', False):
lti_fieldset = [
('LTI Integration', {'fields': ['lti_platform', 'lti_context_id'], 'classes': ['tab'], 'description': 'LTI/LMS integration settings (automatically managed by LTI provisioning)'}),
]
additional_fieldsets.extend(lti_fieldset)
if getattr(settings, 'USE_RBAC', False): if getattr(settings, 'USE_RBAC', False):
rbac_fieldset = [ rbac_fieldset = [
('RBAC Settings', {'fields': ['is_rbac_category'], 'classes': ['tab'], 'description': 'Role-Based Access Control settings'}), ('RBAC Settings', {'fields': ['is_rbac_category'], 'classes': ['tab'], 'description': 'Role-Based Access Control settings'}),
@@ -190,9 +177,9 @@ class CategoryAdmin(admin.ModelAdmin):
('RBAC Settings', {'fields': ['is_rbac_category', 'identity_provider'], 'classes': ['tab'], 'description': 'Role-Based Access Control settings'}), ('RBAC Settings', {'fields': ['is_rbac_category', 'identity_provider'], 'classes': ['tab'], 'description': 'Role-Based Access Control settings'}),
('Group Access', {'fields': ['rbac_groups'], 'description': 'Select the Groups that have access to category'}), ('Group Access', {'fields': ['rbac_groups'], 'description': 'Select the Groups that have access to category'}),
] ]
additional_fieldsets.extend(rbac_fieldset) return basic_fieldset + rbac_fieldset
else:
return basic_fieldset + additional_fieldsets return basic_fieldset
class TagAdmin(admin.ModelAdmin): class TagAdmin(admin.ModelAdmin):
-7
View File
@@ -58,16 +58,9 @@ def stuff(request):
ret["USE_RBAC"] = settings.USE_RBAC ret["USE_RBAC"] = settings.USE_RBAC
ret["USE_ROUNDED_CORNERS"] = settings.USE_ROUNDED_CORNERS ret["USE_ROUNDED_CORNERS"] = settings.USE_ROUNDED_CORNERS
ret["INCLUDE_LISTING_NUMBERS"] = settings.INCLUDE_LISTING_NUMBERS ret["INCLUDE_LISTING_NUMBERS"] = settings.INCLUDE_LISTING_NUMBERS
ret["ALLOW_MEDIA_REPLACEMENT"] = getattr(settings, 'ALLOW_MEDIA_REPLACEMENT', False)
ret["VERSION"] = VERSION ret["VERSION"] = VERSION
if request.user.is_superuser: if request.user.is_superuser:
ret["DJANGO_ADMIN_URL"] = settings.DJANGO_ADMIN_URL ret["DJANGO_ADMIN_URL"] = settings.DJANGO_ADMIN_URL
if getattr(settings, 'USE_LTI', False):
lti_session = request.session.get('lti_session')
if lti_session and request.user.is_authenticated:
ret['lti_session'] = lti_session
return ret return ret
+30 -96
View File
@@ -1,5 +1,3 @@
from pathlib import Path
from crispy_forms.bootstrap import FormActions from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Field, Layout, Submit from crispy_forms.layout import HTML, Field, Layout, Submit
@@ -7,10 +5,7 @@ from django import forms
from django.conf import settings from django.conf import settings
from .methods import get_next_state, is_mediacms_editor from .methods import get_next_state, is_mediacms_editor
from .models import MEDIA_STATES, Category, Media, MediaPermission, Subtitle from .models import MEDIA_STATES, Category, Media, Subtitle
from .widgets import CategoryModalWidget
_PUBLISH_STATE_HTML = (Path(__file__).parent.parent / 'templates/cms/partials/media_publish_state.html').read_text()
class CustomField(Field): class CustomField(Field):
@@ -120,29 +115,19 @@ class MediaMetadataForm(forms.ModelForm):
class MediaPublishForm(forms.ModelForm): class MediaPublishForm(forms.ModelForm):
confirm_state = forms.BooleanField(required=False, initial=False, label="Acknowledge sharing status", help_text="") confirm_state = forms.BooleanField(required=False, initial=False, label="Acknowledge sharing status", help_text="")
shared = forms.BooleanField(required=False, initial=False, label="Shared")
class Meta: class Meta:
model = Media model = Media
fields = ("category", "state", "featured", "reported_times", "is_reviewed", "allow_download") fields = ("category", "state", "featured", "reported_times", "is_reviewed", "allow_download")
widgets = { widgets = {
"category": CategoryModalWidget(), "category": MultipleSelect(),
"state": forms.RadioSelect(),
} }
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
self.user = user self.user = user
self.request = kwargs.pop('request', None)
super(MediaPublishForm, self).__init__(*args, **kwargs) super(MediaPublishForm, self).__init__(*args, **kwargs)
self.was_shared = self.instance.is_shared if self.instance.pk else False
self.had_explicit_permission = self.instance.permissions.exists() if self.instance.pk else False
is_embed_mode = self._check_embed_mode()
self.fields["shared"].initial = self.was_shared
self.initial["shared"] = self.was_shared
if not is_mediacms_editor(user): if not is_mediacms_editor(user):
for field in ["featured", "reported_times", "is_reviewed"]: for field in ["featured", "reported_times", "is_reviewed"]:
self.fields[field].disabled = True self.fields[field].disabled = True
@@ -171,14 +156,6 @@ class MediaPublishForm(forms.ModelForm):
self.fields['category'].queryset = Category.objects.filter(id__in=combined_category_ids).order_by('title') self.fields['category'].queryset = Category.objects.filter(id__in=combined_category_ids).order_by('title')
# Filter for LMS courses only when in embed mode
if is_embed_mode and 'category' in self.fields:
current_queryset = self.fields['category'].queryset
self.fields['category'].queryset = current_queryset.filter(is_lms_course=True)
self.fields['category'].label = 'Course'
self.fields['category'].help_text = 'Media can be shared with one or more courses'
self.fields['category'].widget.is_lms_mode = True
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_tag = True self.helper.form_tag = True
self.helper.form_class = 'post-form' self.helper.form_class = 'post-form'
@@ -187,7 +164,7 @@ class MediaPublishForm(forms.ModelForm):
self.helper.form_show_errors = False self.helper.form_show_errors = False
self.helper.layout = Layout( self.helper.layout = Layout(
CustomField('category'), CustomField('category'),
HTML(_PUBLISH_STATE_HTML), CustomField('state'),
CustomField('featured'), CustomField('featured'),
CustomField('reported_times'), CustomField('reported_times'),
CustomField('is_reviewed'), CustomField('is_reviewed'),
@@ -196,53 +173,42 @@ class MediaPublishForm(forms.ModelForm):
self.helper.layout.append(FormActions(Submit('submit', 'Publish Media', css_class='primaryAction'))) self.helper.layout.append(FormActions(Submit('submit', 'Publish Media', css_class='primaryAction')))
def _check_embed_mode(self):
"""Check if the current request is in embed mode"""
if not self.request:
return False
# Check query parameter
mode = self.request.GET.get('mode', '')
if mode == 'lms_embed_mode':
return True
# Check session storage
if self.request.session.get('lms_embed_mode') == 'true':
return True
return False
def clean(self): def clean(self):
cleaned_data = super().clean() cleaned_data = super().clean()
shared = cleaned_data.get("shared") state = cleaned_data.get("state")
categories = cleaned_data.get("category")
if self.was_shared and not shared and not cleaned_data.get('confirm_state'): if state in ['private', 'unlisted']:
self.add_error('confirm_state', "I understand that unchecking Shared will remove all existing sharing for this media.") custom_permissions = self.instance.permissions.exists()
rbac_categories = categories.filter(is_rbac_category=True).values_list('title', flat=True)
if rbac_categories or custom_permissions:
self.fields['confirm_state'].widget = forms.CheckboxInput()
state_index = None
for i, layout_item in enumerate(self.helper.layout):
if isinstance(layout_item, CustomField) and layout_item.fields[0] == 'state':
state_index = i
break
if state_index:
layout_items = list(self.helper.layout)
layout_items.insert(state_index + 1, CustomField('confirm_state'))
self.helper.layout = Layout(*layout_items)
if not cleaned_data.get('confirm_state'):
if rbac_categories:
error_message = f"I understand that although media state is {state}, the media is also shared with users that have access to categories: {', '.join(rbac_categories)}"
self.add_error('confirm_state', error_message)
if custom_permissions:
error_message = f"I understand that although media state is {state}, the media is also shared by me with other users, that I can see in the 'Shared by me' page"
self.add_error('confirm_state', error_message)
return cleaned_data return cleaned_data
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
data = self.cleaned_data data = self.cleaned_data
state = data.get("state") state = data.get("state")
shared = data.get("shared") if state != self.initial["state"]:
self.instance.state = get_next_state(self.user, self.initial["state"], self.instance.state)
if shared:
if self.request:
submitted_categories = self.cleaned_data.get('category', [])
submitted_has_rbac = any(cat.is_rbac_category for cat in submitted_categories)
if self.had_explicit_permission or (not self.was_shared and not submitted_has_rbac):
MediaPermission.objects.get_or_create(
media=self.instance,
user=self.request.user,
defaults={'owner_user': self.request.user, 'permission': 'owner'},
)
elif not shared:
self.instance.permissions.all().delete()
rbac_cats = self.instance.category.filter(is_rbac_category=True)
self.instance.category.remove(*rbac_cats)
if state != self.initial.get("state"):
self.instance.state = get_next_state(self.user, self.initial.get("state"), self.instance.state)
media = super(MediaPublishForm, self).save(*args, **kwargs) media = super(MediaPublishForm, self).save(*args, **kwargs)
@@ -367,35 +333,3 @@ class ContactForm(forms.Form):
if user.is_authenticated: if user.is_authenticated:
self.fields.pop("name") self.fields.pop("name")
self.fields.pop("from_email") self.fields.pop("from_email")
class ReplaceMediaForm(forms.Form):
new_media_file = forms.FileField(
required=True,
label="New Media File",
help_text="Select a new file to replace the current media",
)
def __init__(self, media_instance, *args, **kwargs):
self.media_instance = media_instance
super(ReplaceMediaForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = True
self.helper.form_class = 'post-form'
self.helper.form_method = 'post'
self.helper.form_enctype = "multipart/form-data"
self.helper.form_show_errors = False
self.helper.layout = Layout(
CustomField('new_media_file'),
)
self.helper.layout.append(FormActions(Submit('submit', 'Replace Media', css_class='primaryAction')))
def clean_new_media_file(self):
file = self.cleaned_data.get("new_media_file", False)
if file:
if file.size > settings.UPLOAD_MAX_SIZE:
max_size_mb = settings.UPLOAD_MAX_SIZE / (1024 * 1024)
raise forms.ValidationError(f"File too large. Maximum size: {max_size_mb:.0f}MB")
return file
+1 -1
View File
@@ -57,4 +57,4 @@ def translate_string(language_code, string):
if not check_language_code(language_code): if not check_language_code(language_code):
return string return string
return translation_strings[language_code].get(string) or string return translation_strings[language_code].get(string, string)
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "حذف الوسائط", "DELETE MEDIA": "حذف الوسائط",
"DOWNLOAD": "تحميل", "DOWNLOAD": "تحميل",
"DURATION": "المدة", "DURATION": "المدة",
"Delete Comments": "",
"Delete Media": "حذف الوسائط", "Delete Media": "حذف الوسائط",
"Delete media": "حذف الوسائط", "Delete media": "حذف الوسائط",
"Disable Comments": "تعطيل التعليقات", "Disable Comments": "تعطيل التعليقات",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "فشل تغيير المالك. يرجى المحاولة مرة أخرى.", "Failed to change owner. Please try again.": "فشل تغيير المالك. يرجى المحاولة مرة أخرى.",
"Failed to copy media.": "فشل نسخ الوسائط.", "Failed to copy media.": "فشل نسخ الوسائط.",
"Failed to create playlist": "فشل إنشاء قائمة التشغيل", "Failed to create playlist": "فشل إنشاء قائمة التشغيل",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "فشل حذف الوسائط. يرجى المحاولة مرة أخرى.", "Failed to delete media. Please try again.": "فشل حذف الوسائط. يرجى المحاولة مرة أخرى.",
"Failed to disable comments.": "فشل تعطيل التعليقات.", "Failed to disable comments.": "فشل تعطيل التعليقات.",
"Failed to disable download.": "فشل تعطيل التنزيل.", "Failed to disable download.": "فشل تعطيل التنزيل.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "تصفية المستخدمين الموجودين...", "Filter existing users...": "تصفية المستخدمين الموجودين...",
"Filter playlists...": "تصفية قوائم التشغيل...", "Filter playlists...": "تصفية قوائم التشغيل...",
"Filters": "الفلاتر", "Filters": "الفلاتر",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "اذهب", "Go": "اذهب",
"History": "التاريخ", "History": "التاريخ",
"Home": "الرئيسية", "Home": "الرئيسية",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "إدارة التعليقات", "Manage comments": "إدارة التعليقات",
"Manage media": "إدارة الوسائط", "Manage media": "إدارة الوسائط",
"Manage users": "إدارة المستخدمين", "Manage users": "إدارة المستخدمين",
"Management": "",
"Media": "وسائط", "Media": "وسائط",
"Media I own": "الوسائط التي أمتلكها", "Media I own": "الوسائط التي أمتلكها",
"Media was edited": "تم تعديل الوسائط", "Media was edited": "تم تعديل الوسائط",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "لا توجد نتائج لـ", "No results for": "لا توجد نتائج لـ",
"No tags": "لا توجد علامات", "No tags": "لا توجد علامات",
"No users to add": "لا يوجد مستخدمون لإضافتهم", "No users to add": "لا يوجد مستخدمون لإضافتهم",
"Organization": "",
"PLAYLISTS": "قوائم التشغيل", "PLAYLISTS": "قوائم التشغيل",
"PUBLISH STATE": "حالة النشر", "PUBLISH STATE": "حالة النشر",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "نشر في", "Published on": "نشر في",
"Recent uploads": "التحميلات الأخيرة", "Recent uploads": "التحميلات الأخيرة",
"Recommended": "موصى به", "Recommended": "موصى به",
"Record": "",
"Record Screen": "تسجيل الشاشة", "Record Screen": "تسجيل الشاشة",
"Record Screen with Audio": "",
"Register": "تسجيل", "Register": "تسجيل",
"Remove category": "إزالة الفئة", "Remove category": "إزالة الفئة",
"Remove from list": "إزالة من القائمة", "Remove from list": "إزالة من القائمة",
"Remove tag": "إزالة العلامة", "Remove tag": "إزالة العلامة",
"Remove user": "إزالة المستخدم", "Remove user": "إزالة المستخدم",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "حفظ", "SAVE": "حفظ",
"SEARCH": "بحث", "SEARCH": "بحث",
"SHARE": "مشاركة", "SHARE": "مشاركة",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "تحديد جميع الوسائط", "Select all media": "تحديد جميع الوسائط",
"Select publish state:": "اختر حالة النشر:", "Select publish state:": "اختر حالة النشر:",
"Selected": "محدد", "Selected": "محدد",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "مشاركة مني", "Shared by me": "مشاركة مني",
"Shared with me": "مشاركة معي", "Shared with me": "مشاركة معي",
"Sharing": "",
"Sign in": "تسجيل الدخول", "Sign in": "تسجيل الدخول",
"Sign out": "تسجيل الخروج", "Sign out": "تسجيل الخروج",
"Sort By": "ترتيب حسب", "Sort By": "ترتيب حسب",
"Start Recording": "بدء التسجيل", "Start Recording": "بدء التسجيل",
"Start uploading media and sharing your work. Media that you upload will show up here.": "ابدأ في تحميل الوسائط ومشاركة عملك. ستظهر الوسائط التي تحملها هنا.", "Start uploading media and sharing your work. Media that you upload will show up here.": "ابدأ في تحميل الوسائط ومشاركة عملك. ستظهر الوسائط التي تحملها هنا.",
"Stop Recording": "إيقاف التسجيل", "Stop Recording": "إيقاف التسجيل",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "إرسال", "Submit": "إرسال",
"Subtitle was added": "تمت إضافة الترجمة", "Subtitle was added": "تمت إضافة الترجمة",
"Subtitles": "ترجمات", "Subtitles": "ترجمات",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "تم تفعيل التعليقات بنجاح", "Successfully Enabled comments": "تم تفعيل التعليقات بنجاح",
"Successfully changed owner": "تم تغيير المالك بنجاح", "Successfully changed owner": "تم تغيير المالك بنجاح",
"Successfully deleted": "تم الحذف بنجاح", "Successfully deleted": "تم الحذف بنجاح",
"Successfully deleted comments": "",
"Successfully updated": "تم التحديث بنجاح", "Successfully updated": "تم التحديث بنجاح",
"Successfully updated categories": "تم تحديث الفئات بنجاح", "Successfully updated categories": "تم تحديث الفئات بنجاح",
"Successfully updated playlist membership": "تم تحديث عضوية قائمة التشغيل بنجاح", "Successfully updated playlist membership": "تم تحديث عضوية قائمة التشغيل بنجاح",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "رفع الوسائط", "Upload media": "رفع الوسائط",
"Uploads": "التحميلات", "Uploads": "التحميلات",
"Users": "المستخدمون", "Users": "المستخدمون",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "عرض الكل", "VIEW ALL": "عرض الكل",
"Video": "فيديو", "Video": "فيديو",
"View all": "عرض الكل", "View all": "عرض الكل",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "مرحباً", "Welcome": "مرحباً",
"You are going to copy": "سوف تقوم بالنسخ", "You are going to copy": "سوف تقوم بالنسخ",
"You are going to delete": "سوف تقوم بالحذف", "You are going to delete": "سوف تقوم بالحذف",
"You are going to delete all comments from": "",
"You are going to disable comments to": "سوف تقوم بتعطيل التعليقات لـ", "You are going to disable comments to": "سوف تقوم بتعطيل التعليقات لـ",
"You are going to disable download for": "سوف تقوم بتعطيل التنزيل لـ", "You are going to disable download for": "سوف تقوم بتعطيل التنزيل لـ",
"You are going to enable comments to": "سوف تقوم بتفعيل التعليقات لـ", "You are going to enable comments to": "سوف تقوم بتفعيل التعليقات لـ",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "মিডিয়া মুছুন", "DELETE MEDIA": "মিডিয়া মুছুন",
"DOWNLOAD": "ডাউনলোড", "DOWNLOAD": "ডাউনলোড",
"DURATION": "সময়কাল", "DURATION": "সময়কাল",
"Delete Comments": "",
"Delete Media": "", "Delete Media": "",
"Delete media": "মিডিয়া মুছুন", "Delete media": "মিডিয়া মুছুন",
"Disable Comments": "", "Disable Comments": "",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "", "Failed to change owner. Please try again.": "",
"Failed to copy media.": "মিডিয়া কপি করতে ব্যর্থ হয়েছে।", "Failed to copy media.": "মিডিয়া কপি করতে ব্যর্থ হয়েছে।",
"Failed to create playlist": "", "Failed to create playlist": "",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "মিডিয়া মুছতে ব্যর্থ হয়েছে। দয়া করে আবার চেষ্টা করুন।", "Failed to delete media. Please try again.": "মিডিয়া মুছতে ব্যর্থ হয়েছে। দয়া করে আবার চেষ্টা করুন।",
"Failed to disable comments.": "মন্তব্য নিষ্ক্রিয় করতে ব্যর্থ হয়েছে।", "Failed to disable comments.": "মন্তব্য নিষ্ক্রিয় করতে ব্যর্থ হয়েছে।",
"Failed to disable download.": "ডাউনলোড নিষ্ক্রিয় করতে ব্যর্থ হয়েছে।", "Failed to disable download.": "ডাউনলোড নিষ্ক্রিয় করতে ব্যর্থ হয়েছে।",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "", "Filter existing users...": "",
"Filter playlists...": "", "Filter playlists...": "",
"Filters": "ফিল্টার", "Filters": "ফিল্টার",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "যাও", "Go": "যাও",
"History": "ইতিহাস", "History": "ইতিহাস",
"Home": "বাড়ি", "Home": "বাড়ি",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "মন্তব্য পরিচালনা করুন", "Manage comments": "মন্তব্য পরিচালনা করুন",
"Manage media": "মিডিয়া পরিচালনা করুন", "Manage media": "মিডিয়া পরিচালনা করুন",
"Manage users": "ব্যবহারকারীদের পরিচালনা করুন", "Manage users": "ব্যবহারকারীদের পরিচালনা করুন",
"Management": "",
"Media": "মিডিয়া", "Media": "মিডিয়া",
"Media I own": "", "Media I own": "",
"Media was edited": "মিডিয়া সম্পাদিত হয়েছে", "Media was edited": "মিডিয়া সম্পাদিত হয়েছে",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "এর জন্য কোন ফলাফল নেই", "No results for": "এর জন্য কোন ফলাফল নেই",
"No tags": "", "No tags": "",
"No users to add": "", "No users to add": "",
"Organization": "",
"PLAYLISTS": "প্লেলিস্ট", "PLAYLISTS": "প্লেলিস্ট",
"PUBLISH STATE": "প্রকাশের অবস্থা", "PUBLISH STATE": "প্রকাশের অবস্থা",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "প্রকাশিত", "Published on": "প্রকাশিত",
"Recent uploads": "সাম্প্রতিক আপলোড", "Recent uploads": "সাম্প্রতিক আপলোড",
"Recommended": "প্রস্তাবিত", "Recommended": "প্রস্তাবিত",
"Record": "",
"Record Screen": "স্ক্রিন রেকর্ড করুন", "Record Screen": "স্ক্রিন রেকর্ড করুন",
"Record Screen with Audio": "",
"Register": "নিবন্ধন করুন", "Register": "নিবন্ধন করুন",
"Remove category": "", "Remove category": "",
"Remove from list": "", "Remove from list": "",
"Remove tag": "", "Remove tag": "",
"Remove user": "", "Remove user": "",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "সংরক্ষণ করুন", "SAVE": "সংরক্ষণ করুন",
"SEARCH": "অনুসন্ধান", "SEARCH": "অনুসন্ধান",
"SHARE": "শেয়ার করুন", "SHARE": "শেয়ার করুন",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "", "Select all media": "",
"Select publish state:": "", "Select publish state:": "",
"Selected": "", "Selected": "",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "আমার দ্বারা শেয়ার করা", "Shared by me": "আমার দ্বারা শেয়ার করা",
"Shared with me": "আমার সাথে শেয়ার করা", "Shared with me": "আমার সাথে শেয়ার করা",
"Sharing": "",
"Sign in": "সাইন ইন করুন", "Sign in": "সাইন ইন করুন",
"Sign out": "সাইন আউট করুন", "Sign out": "সাইন আউট করুন",
"Sort By": "সাজান", "Sort By": "সাজান",
"Start Recording": "রেকর্ডিং শুরু করুন", "Start Recording": "রেকর্ডিং শুরু করুন",
"Start uploading media and sharing your work. Media that you upload will show up here.": "মিডিয়া আপলোড করা এবং আপনার কাজ শেয়ার করা শুরু করুন। আপনি যে মিডিয়া আপলোড করবেন তা এখানে প্রদর্শিত হবে।", "Start uploading media and sharing your work. Media that you upload will show up here.": "মিডিয়া আপলোড করা এবং আপনার কাজ শেয়ার করা শুরু করুন। আপনি যে মিডিয়া আপলোড করবেন তা এখানে প্রদর্শিত হবে।",
"Stop Recording": "রেকর্ডিং বন্ধ করুন", "Stop Recording": "রেকর্ডিং বন্ধ করুন",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "", "Submit": "",
"Subtitle was added": "সাবটাইটেল যোগ করা হয়েছে", "Subtitle was added": "সাবটাইটেল যোগ করা হয়েছে",
"Subtitles": "সাবটাইটেল", "Subtitles": "সাবটাইটেল",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "মন্তব্য সফলভাবে সক্রিয় হয়েছে", "Successfully Enabled comments": "মন্তব্য সফলভাবে সক্রিয় হয়েছে",
"Successfully changed owner": "", "Successfully changed owner": "",
"Successfully deleted": "সফলভাবে মুছে ফেলা হয়েছে", "Successfully deleted": "সফলভাবে মুছে ফেলা হয়েছে",
"Successfully deleted comments": "",
"Successfully updated": "", "Successfully updated": "",
"Successfully updated categories": "", "Successfully updated categories": "",
"Successfully updated playlist membership": "", "Successfully updated playlist membership": "",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "মিডিয়া আপলোড করুন", "Upload media": "মিডিয়া আপলোড করুন",
"Uploads": "আপলোডসমূহ", "Uploads": "আপলোডসমূহ",
"Users": "", "Users": "",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "সব দেখুন", "VIEW ALL": "সব দেখুন",
"Video": "ভিডিও", "Video": "ভিডিও",
"View all": "সব দেখুন", "View all": "সব দেখুন",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "স্বাগতম", "Welcome": "স্বাগতম",
"You are going to copy": "আপনি কপি করতে চলেছেন", "You are going to copy": "আপনি কপি করতে চলেছেন",
"You are going to delete": "আপনি মুছে ফেলতে চলেছেন", "You are going to delete": "আপনি মুছে ফেলতে চলেছেন",
"You are going to delete all comments from": "",
"You are going to disable comments to": "আপনি মন্তব্য নিষ্ক্রিয় করতে চলেছেন", "You are going to disable comments to": "আপনি মন্তব্য নিষ্ক্রিয় করতে চলেছেন",
"You are going to disable download for": "আপনি ডাউনলোড নিষ্ক্রিয় করতে চলেছেন", "You are going to disable download for": "আপনি ডাউনলোড নিষ্ক্রিয় করতে চলেছেন",
"You are going to enable comments to": "আপনি মন্তব্য সক্রিয় করতে চলেছেন", "You are going to enable comments to": "আপনি মন্তব্য সক্রিয় করতে চলেছেন",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "SLET MEDIE", "DELETE MEDIA": "SLET MEDIE",
"DOWNLOAD": "HENT", "DOWNLOAD": "HENT",
"DURATION": "VARIGHED", "DURATION": "VARIGHED",
"Delete Comments": "",
"Delete Media": "Slet Medie", "Delete Media": "Slet Medie",
"Delete media": "Slet medie", "Delete media": "Slet medie",
"Disable Comments": "Deaktiver Kommentarer", "Disable Comments": "Deaktiver Kommentarer",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Ændring af ejer mislykkedes. Prøv venligst igen.", "Failed to change owner. Please try again.": "Ændring af ejer mislykkedes. Prøv venligst igen.",
"Failed to copy media.": "Kopiering af medie mislykkedes.", "Failed to copy media.": "Kopiering af medie mislykkedes.",
"Failed to create playlist": "Oprettelse af playliste mislykkedes", "Failed to create playlist": "Oprettelse af playliste mislykkedes",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Sletning af medie mislykkedes. Prøv venligst igen.", "Failed to delete media. Please try again.": "Sletning af medie mislykkedes. Prøv venligst igen.",
"Failed to disable comments.": "Deaktivering af kommentarer mislykkedes.", "Failed to disable comments.": "Deaktivering af kommentarer mislykkedes.",
"Failed to disable download.": "Deaktivering af download mislykkedes.", "Failed to disable download.": "Deaktivering af download mislykkedes.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Filtrer eksisterende brugere...", "Filter existing users...": "Filtrer eksisterende brugere...",
"Filter playlists...": "Filtrer playlister...", "Filter playlists...": "Filtrer playlister...",
"Filters": "Filtre", "Filters": "Filtre",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Vælg", "Go": "Vælg",
"History": "Historik", "History": "Historik",
"Home": "Hjem", "Home": "Hjem",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Administrer kommentarer", "Manage comments": "Administrer kommentarer",
"Manage media": "Administrer medier", "Manage media": "Administrer medier",
"Manage users": "Administrer brugere", "Manage users": "Administrer brugere",
"Management": "",
"Media": "Medier", "Media": "Medier",
"Media I own": "Medier jeg ejer", "Media I own": "Medier jeg ejer",
"Media was edited": "Mediet er blevet redigeret", "Media was edited": "Mediet er blevet redigeret",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Ingen resultater for", "No results for": "Ingen resultater for",
"No tags": "Ingen tags", "No tags": "Ingen tags",
"No users to add": "Ingen brugere at tilføje", "No users to add": "Ingen brugere at tilføje",
"Organization": "",
"PLAYLISTS": "PLAYLISTER", "PLAYLISTS": "PLAYLISTER",
"PUBLISH STATE": "PUBLICERINGSSTATUS", "PUBLISH STATE": "PUBLICERINGSSTATUS",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Udgivet på", "Published on": "Udgivet på",
"Recent uploads": "Nylige uploads", "Recent uploads": "Nylige uploads",
"Recommended": "Anbefalet", "Recommended": "Anbefalet",
"Record": "",
"Record Screen": "Optag skærm", "Record Screen": "Optag skærm",
"Record Screen with Audio": "",
"Register": "Registrer", "Register": "Registrer",
"Remove category": "Fjern kategori", "Remove category": "Fjern kategori",
"Remove from list": "Fjern fra liste", "Remove from list": "Fjern fra liste",
"Remove tag": "Fjern tag", "Remove tag": "Fjern tag",
"Remove user": "Fjern bruger", "Remove user": "Fjern bruger",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "GEM", "SAVE": "GEM",
"SEARCH": "SØG", "SEARCH": "SØG",
"SHARE": "DEL", "SHARE": "DEL",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Vælg alle medier", "Select all media": "Vælg alle medier",
"Select publish state:": "Vælg publiceringsstatus:", "Select publish state:": "Vælg publiceringsstatus:",
"Selected": "Valgt", "Selected": "Valgt",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Delt af mig", "Shared by me": "Delt af mig",
"Shared with me": "Delt med mig", "Shared with me": "Delt med mig",
"Sharing": "",
"Sign in": "Log ind", "Sign in": "Log ind",
"Sign out": "Log ud", "Sign out": "Log ud",
"Sort By": "Sorter efter", "Sort By": "Sorter efter",
"Start Recording": "Start optagelse", "Start Recording": "Start optagelse",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Begynd at uploade medier og dele dit arbejde. Medier, du uploader, vil blive vist her.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Begynd at uploade medier og dele dit arbejde. Medier, du uploader, vil blive vist her.",
"Stop Recording": "Stop optagelse", "Stop Recording": "Stop optagelse",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Indsend", "Submit": "Indsend",
"Subtitle was added": "Undertekster tilføjet", "Subtitle was added": "Undertekster tilføjet",
"Subtitles": "Undertekster", "Subtitles": "Undertekster",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Kommentarer aktiveret med succes", "Successfully Enabled comments": "Kommentarer aktiveret med succes",
"Successfully changed owner": "Ejer ændret med succes", "Successfully changed owner": "Ejer ændret med succes",
"Successfully deleted": "Slettet med succes", "Successfully deleted": "Slettet med succes",
"Successfully deleted comments": "",
"Successfully updated": "Opdateret med succes", "Successfully updated": "Opdateret med succes",
"Successfully updated categories": "Kategorier opdateret med succes", "Successfully updated categories": "Kategorier opdateret med succes",
"Successfully updated playlist membership": "Playlistemedlemskab opdateret med succes", "Successfully updated playlist membership": "Playlistemedlemskab opdateret med succes",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Upload medie", "Upload media": "Upload medie",
"Uploads": "Uploads", "Uploads": "Uploads",
"Users": "Brugere", "Users": "Brugere",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "SE ALLE", "VIEW ALL": "SE ALLE",
"Video": "Video", "Video": "Video",
"View all": "Se alle", "View all": "Se alle",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Velkommen", "Welcome": "Velkommen",
"You are going to copy": "Du er ved at kopiere", "You are going to copy": "Du er ved at kopiere",
"You are going to delete": "Du er ved at slette", "You are going to delete": "Du er ved at slette",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Du er ved at deaktivere kommentarer til", "You are going to disable comments to": "Du er ved at deaktivere kommentarer til",
"You are going to disable download for": "Du er ved at deaktivere download for", "You are going to disable download for": "Du er ved at deaktivere download for",
"You are going to enable comments to": "Du er ved at aktivere kommentarer til", "You are going to enable comments to": "Du er ved at aktivere kommentarer til",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "MEDIEN LÖSCHEN", "DELETE MEDIA": "MEDIEN LÖSCHEN",
"DOWNLOAD": "HERUNTERLADEN", "DOWNLOAD": "HERUNTERLADEN",
"DURATION": "DAUER", "DURATION": "DAUER",
"Delete Comments": "",
"Delete Media": "Medien löschen", "Delete Media": "Medien löschen",
"Delete media": "Medien löschen", "Delete media": "Medien löschen",
"Disable Comments": "Kommentare deaktivieren", "Disable Comments": "Kommentare deaktivieren",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Fehler beim Ändern des Eigentümers. Bitte versuchen Sie es erneut.", "Failed to change owner. Please try again.": "Fehler beim Ändern des Eigentümers. Bitte versuchen Sie es erneut.",
"Failed to copy media.": "Fehler beim Kopieren der Medien.", "Failed to copy media.": "Fehler beim Kopieren der Medien.",
"Failed to create playlist": "Fehler beim Erstellen der Playlist", "Failed to create playlist": "Fehler beim Erstellen der Playlist",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Fehler beim Löschen der Medien. Bitte versuchen Sie es erneut.", "Failed to delete media. Please try again.": "Fehler beim Löschen der Medien. Bitte versuchen Sie es erneut.",
"Failed to disable comments.": "Fehler beim Deaktivieren der Kommentare.", "Failed to disable comments.": "Fehler beim Deaktivieren der Kommentare.",
"Failed to disable download.": "Fehler beim Deaktivieren des Downloads.", "Failed to disable download.": "Fehler beim Deaktivieren des Downloads.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Vorhandene Benutzer filtern...", "Filter existing users...": "Vorhandene Benutzer filtern...",
"Filter playlists...": "Playlists filtern...", "Filter playlists...": "Playlists filtern...",
"Filters": "Filter", "Filters": "Filter",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Los", "Go": "Los",
"History": "Verlauf", "History": "Verlauf",
"Home": "Startseite", "Home": "Startseite",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Kommentare verwalten", "Manage comments": "Kommentare verwalten",
"Manage media": "Medien verwalten", "Manage media": "Medien verwalten",
"Manage users": "Benutzer verwalten", "Manage users": "Benutzer verwalten",
"Management": "",
"Media": "Medien", "Media": "Medien",
"Media I own": "Medien, die mir gehören", "Media I own": "Medien, die mir gehören",
"Media was edited": "Medien wurden bearbeitet", "Media was edited": "Medien wurden bearbeitet",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Keine Ergebnisse für", "No results for": "Keine Ergebnisse für",
"No tags": "Keine Tags", "No tags": "Keine Tags",
"No users to add": "Keine Benutzer hinzuzufügen", "No users to add": "Keine Benutzer hinzuzufügen",
"Organization": "",
"PLAYLISTS": "PLAYLISTS", "PLAYLISTS": "PLAYLISTS",
"PUBLISH STATE": "VERÖFFENTLICHUNGSSTATUS", "PUBLISH STATE": "VERÖFFENTLICHUNGSSTATUS",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Veröffentlicht am", "Published on": "Veröffentlicht am",
"Recent uploads": "Neue Uploads", "Recent uploads": "Neue Uploads",
"Recommended": "Empfohlen", "Recommended": "Empfohlen",
"Record": "",
"Record Screen": "Bildschirm aufnehmen", "Record Screen": "Bildschirm aufnehmen",
"Record Screen with Audio": "",
"Register": "Registrieren", "Register": "Registrieren",
"Remove category": "Kategorie entfernen", "Remove category": "Kategorie entfernen",
"Remove from list": "Aus Liste entfernen", "Remove from list": "Aus Liste entfernen",
"Remove tag": "Tag entfernen", "Remove tag": "Tag entfernen",
"Remove user": "Benutzer entfernen", "Remove user": "Benutzer entfernen",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "SPEICHERN", "SAVE": "SPEICHERN",
"SEARCH": "SUCHE", "SEARCH": "SUCHE",
"SHARE": "TEILEN", "SHARE": "TEILEN",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Alle Medien auswählen", "Select all media": "Alle Medien auswählen",
"Select publish state:": "Veröffentlichungsstatus auswählen:", "Select publish state:": "Veröffentlichungsstatus auswählen:",
"Selected": "Ausgewählt", "Selected": "Ausgewählt",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Von mir geteilt", "Shared by me": "Von mir geteilt",
"Shared with me": "Mit mir geteilt", "Shared with me": "Mit mir geteilt",
"Sharing": "",
"Sign in": "Anmelden", "Sign in": "Anmelden",
"Sign out": "Abmelden", "Sign out": "Abmelden",
"Sort By": "Sortieren nach", "Sort By": "Sortieren nach",
"Start Recording": "Aufnahme starten", "Start Recording": "Aufnahme starten",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Beginnen Sie mit dem Hochladen von Medien und dem Teilen Ihrer Arbeit. Hochgeladene Medien werden hier angezeigt.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Beginnen Sie mit dem Hochladen von Medien und dem Teilen Ihrer Arbeit. Hochgeladene Medien werden hier angezeigt.",
"Stop Recording": "Aufnahme stoppen", "Stop Recording": "Aufnahme stoppen",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Absenden", "Submit": "Absenden",
"Subtitle was added": "Untertitel wurde hinzugefügt", "Subtitle was added": "Untertitel wurde hinzugefügt",
"Subtitles": "Untertitel", "Subtitles": "Untertitel",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Kommentare erfolgreich aktiviert", "Successfully Enabled comments": "Kommentare erfolgreich aktiviert",
"Successfully changed owner": "Eigentümer erfolgreich geändert", "Successfully changed owner": "Eigentümer erfolgreich geändert",
"Successfully deleted": "Erfolgreich gelöscht", "Successfully deleted": "Erfolgreich gelöscht",
"Successfully deleted comments": "",
"Successfully updated": "Erfolgreich aktualisiert", "Successfully updated": "Erfolgreich aktualisiert",
"Successfully updated categories": "Kategorien erfolgreich aktualisiert", "Successfully updated categories": "Kategorien erfolgreich aktualisiert",
"Successfully updated playlist membership": "Playlist-Mitgliedschaft erfolgreich aktualisiert", "Successfully updated playlist membership": "Playlist-Mitgliedschaft erfolgreich aktualisiert",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Medien hochladen", "Upload media": "Medien hochladen",
"Uploads": "Uploads", "Uploads": "Uploads",
"Users": "Benutzer", "Users": "Benutzer",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "ALLE ANZEIGEN", "VIEW ALL": "ALLE ANZEIGEN",
"Video": "Video", "Video": "Video",
"View all": "Alle anzeigen", "View all": "Alle anzeigen",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Willkommen", "Welcome": "Willkommen",
"You are going to copy": "Sie werden kopieren", "You are going to copy": "Sie werden kopieren",
"You are going to delete": "Sie werden löschen", "You are going to delete": "Sie werden löschen",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Sie werden Kommentare deaktivieren für", "You are going to disable comments to": "Sie werden Kommentare deaktivieren für",
"You are going to disable download for": "Sie werden Download deaktivieren für", "You are going to disable download for": "Sie werden Download deaktivieren für",
"You are going to enable comments to": "Sie werden Kommentare aktivieren für", "You are going to enable comments to": "Sie werden Kommentare aktivieren für",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "ΔΙΑΓΡΑΦΗ ΑΡΧΕΙΟΥ", "DELETE MEDIA": "ΔΙΑΓΡΑΦΗ ΑΡΧΕΙΟΥ",
"DOWNLOAD": "ΚΑΤΕΒΑΣΜΑ", "DOWNLOAD": "ΚΑΤΕΒΑΣΜΑ",
"DURATION": "ΔΙΑΡΚΕΙΑ", "DURATION": "ΔΙΑΡΚΕΙΑ",
"Delete Comments": "",
"Delete Media": "Διαγραφή Αρχείου", "Delete Media": "Διαγραφή Αρχείου",
"Delete media": "Διαγραφή αρχείου", "Delete media": "Διαγραφή αρχείου",
"Disable Comments": "Απενεργοποίηση Σχολίων", "Disable Comments": "Απενεργοποίηση Σχολίων",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Αποτυχία αλλαγής ιδιοκτήτη. Παρακαλώ δοκιμάστε ξανά.", "Failed to change owner. Please try again.": "Αποτυχία αλλαγής ιδιοκτήτη. Παρακαλώ δοκιμάστε ξανά.",
"Failed to copy media.": "Αποτυχία αντιγραφής αρχείου.", "Failed to copy media.": "Αποτυχία αντιγραφής αρχείου.",
"Failed to create playlist": "Αποτυχία δημιουργίας λίστας", "Failed to create playlist": "Αποτυχία δημιουργίας λίστας",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Αποτυχία διαγραφής αρχείου. Παρακαλώ δοκιμάστε ξανά.", "Failed to delete media. Please try again.": "Αποτυχία διαγραφής αρχείου. Παρακαλώ δοκιμάστε ξανά.",
"Failed to disable comments.": "Αποτυχία απενεργοποίησης σχολίων.", "Failed to disable comments.": "Αποτυχία απενεργοποίησης σχολίων.",
"Failed to disable download.": "Αποτυχία απενεργοποίησης λήψης.", "Failed to disable download.": "Αποτυχία απενεργοποίησης λήψης.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Φιλτράρισμα υπαρχόντων χρηστών...", "Filter existing users...": "Φιλτράρισμα υπαρχόντων χρηστών...",
"Filter playlists...": "Φιλτράρισμα λιστών...", "Filter playlists...": "Φιλτράρισμα λιστών...",
"Filters": "Φίλτρα", "Filters": "Φίλτρα",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Μετάβαση", "Go": "Μετάβαση",
"History": "Ιστορικό", "History": "Ιστορικό",
"Home": "Αρχική", "Home": "Αρχική",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Διαχείριση σχολίων", "Manage comments": "Διαχείριση σχολίων",
"Manage media": "Διαχείριση αρχείων", "Manage media": "Διαχείριση αρχείων",
"Manage users": "Διαχείριση χρηστών", "Manage users": "Διαχείριση χρηστών",
"Management": "",
"Media": "Αρχεία", "Media": "Αρχεία",
"Media I own": "Δικά μου αρχεία", "Media I own": "Δικά μου αρχεία",
"Media was edited": "Το αρχείο επεξεργάστηκε", "Media was edited": "Το αρχείο επεξεργάστηκε",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Δεν υπάρχουν αποτελέσματα για", "No results for": "Δεν υπάρχουν αποτελέσματα για",
"No tags": "Δεν υπάρχουν ετικέτες", "No tags": "Δεν υπάρχουν ετικέτες",
"No users to add": "Δεν υπάρχουν χρήστες για προσθήκη", "No users to add": "Δεν υπάρχουν χρήστες για προσθήκη",
"Organization": "",
"PLAYLISTS": "ΛΙΣΤΕΣ", "PLAYLISTS": "ΛΙΣΤΕΣ",
"PUBLISH STATE": "ΚΑΤΑΣΤΑΣΗ ΔΗΜΟΣΙΕΥΣΗΣ", "PUBLISH STATE": "ΚΑΤΑΣΤΑΣΗ ΔΗΜΟΣΙΕΥΣΗΣ",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Δημοσιεύτηκε στις", "Published on": "Δημοσιεύτηκε στις",
"Recent uploads": "Πρόσφατα ανεβάσματα", "Recent uploads": "Πρόσφατα ανεβάσματα",
"Recommended": "Προτεινόμενα", "Recommended": "Προτεινόμενα",
"Record": "",
"Record Screen": "Καταγραφή οθόνης", "Record Screen": "Καταγραφή οθόνης",
"Record Screen with Audio": "",
"Register": "Εγγραφή", "Register": "Εγγραφή",
"Remove category": "Αφαίρεση κατηγορίας", "Remove category": "Αφαίρεση κατηγορίας",
"Remove from list": "Αφαίρεση από λίστα", "Remove from list": "Αφαίρεση από λίστα",
"Remove tag": "Αφαίρεση ετικέτας", "Remove tag": "Αφαίρεση ετικέτας",
"Remove user": "Αφαίρεση χρήστη", "Remove user": "Αφαίρεση χρήστη",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "ΑΠΟΘΗΚΕΥΣΗ", "SAVE": "ΑΠΟΘΗΚΕΥΣΗ",
"SEARCH": "ΑΝΑΖΗΤΗΣΗ", "SEARCH": "ΑΝΑΖΗΤΗΣΗ",
"SHARE": "ΚΟΙΝΟΠΟΙΗΣΗ", "SHARE": "ΚΟΙΝΟΠΟΙΗΣΗ",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Επιλογή όλων των αρχείων", "Select all media": "Επιλογή όλων των αρχείων",
"Select publish state:": "Επιλέξτε κατάσταση δημοσίευσης:", "Select publish state:": "Επιλέξτε κατάσταση δημοσίευσης:",
"Selected": "Επιλεγμένα", "Selected": "Επιλεγμένα",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Κοινοποιήθηκαν από εμένα", "Shared by me": "Κοινοποιήθηκαν από εμένα",
"Shared with me": "Κοινοποιήθηκαν σε εμένα", "Shared with me": "Κοινοποιήθηκαν σε εμένα",
"Sharing": "",
"Sign in": "Σύνδεση", "Sign in": "Σύνδεση",
"Sign out": "Αποσύνδεση", "Sign out": "Αποσύνδεση",
"Sort By": "Ταξινόμηση", "Sort By": "Ταξινόμηση",
"Start Recording": "Έναρξη εγγραφής", "Start Recording": "Έναρξη εγγραφής",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Ξεκινήστε να ανεβάζετε αρχεία και να κοινοποιείτε τη δουλειά σας. Τα αρχεία που ανεβάζετε θα εμφανίζονται εδώ.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Ξεκινήστε να ανεβάζετε αρχεία και να κοινοποιείτε τη δουλειά σας. Τα αρχεία που ανεβάζετε θα εμφανίζονται εδώ.",
"Stop Recording": "Διακοπή εγγραφής", "Stop Recording": "Διακοπή εγγραφής",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Υποβολή", "Submit": "Υποβολή",
"Subtitle was added": "Οι υπότιτλοι προστέθηκαν", "Subtitle was added": "Οι υπότιτλοι προστέθηκαν",
"Subtitles": "Υπότιτλοι", "Subtitles": "Υπότιτλοι",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Τα σχόλια ενεργοποιήθηκαν με επιτυχία", "Successfully Enabled comments": "Τα σχόλια ενεργοποιήθηκαν με επιτυχία",
"Successfully changed owner": "Ο ιδιοκτήτης άλλαξε με επιτυχία", "Successfully changed owner": "Ο ιδιοκτήτης άλλαξε με επιτυχία",
"Successfully deleted": "Διαγράφηκε με επιτυχία", "Successfully deleted": "Διαγράφηκε με επιτυχία",
"Successfully deleted comments": "",
"Successfully updated": "Ενημερώθηκε με επιτυχία", "Successfully updated": "Ενημερώθηκε με επιτυχία",
"Successfully updated categories": "Οι κατηγορίες ενημερώθηκαν με επιτυχία", "Successfully updated categories": "Οι κατηγορίες ενημερώθηκαν με επιτυχία",
"Successfully updated playlist membership": "Η συμμετοχή στη λίστα ενημερώθηκε με επιτυχία", "Successfully updated playlist membership": "Η συμμετοχή στη λίστα ενημερώθηκε με επιτυχία",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Ανέβασμα αρχείων", "Upload media": "Ανέβασμα αρχείων",
"Uploads": "Ανεβάσματα", "Uploads": "Ανεβάσματα",
"Users": "Χρήστες", "Users": "Χρήστες",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "ΔΕΣ ΤΑ ΟΛΑ", "VIEW ALL": "ΔΕΣ ΤΑ ΟΛΑ",
"Video": "Βίντεο", "Video": "Βίντεο",
"View all": "Δες τα όλα", "View all": "Δες τα όλα",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Καλώς ήρθατε", "Welcome": "Καλώς ήρθατε",
"You are going to copy": "Πρόκειται να αντιγράψετε", "You are going to copy": "Πρόκειται να αντιγράψετε",
"You are going to delete": "Πρόκειται να διαγράψετε", "You are going to delete": "Πρόκειται να διαγράψετε",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Πρόκειται να απενεργοποιήσετε τα σχόλια για", "You are going to disable comments to": "Πρόκειται να απενεργοποιήσετε τα σχόλια για",
"You are going to disable download for": "Πρόκειται να απενεργοποιήσετε τη λήψη για", "You are going to disable download for": "Πρόκειται να απενεργοποιήσετε τη λήψη για",
"You are going to enable comments to": "Πρόκειται να ενεργοποιήσετε τα σχόλια για", "You are going to enable comments to": "Πρόκειται να ενεργοποιήσετε τα σχόλια για",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE": "", "DELETE": "",
"DELETE MEDIA": "", "DELETE MEDIA": "",
"Delete media": "", "Delete media": "",
"Delete Comments": "",
"Delete Media": "", "Delete Media": "",
"Disable Comments": "", "Disable Comments": "",
"Disable Download": "", "Disable Download": "",
@@ -72,7 +71,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "", "Failed to change owner. Please try again.": "",
"Failed to copy media.": "", "Failed to copy media.": "",
"Failed to create playlist": "", "Failed to create playlist": "",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "", "Failed to delete media. Please try again.": "",
"Failed to disable comments.": "", "Failed to disable comments.": "",
"Failed to disable download.": "", "Failed to disable download.": "",
@@ -104,9 +102,6 @@ translation_strings = {
"Filter existing users...": "", "Filter existing users...": "",
"Filter playlists...": "", "Filter playlists...": "",
"Filters": "", "Filters": "",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "", "Go": "",
"History": "", "History": "",
"Home": "", "Home": "",
@@ -122,7 +117,6 @@ translation_strings = {
"Loading existing users...": "", "Loading existing users...": "",
"Loading playlists...": "", "Loading playlists...": "",
"Loading tags...": "", "Loading tags...": "",
"Management": "",
"Manage": "", "Manage": "",
"Manage comments": "", "Manage comments": "",
"Manage media": "", "Manage media": "",
@@ -149,7 +143,6 @@ translation_strings = {
"No results for": "", "No results for": "",
"No tags": "", "No tags": "",
"No users to add": "", "No users to add": "",
"Organization": "",
"or": "", "or": "",
"Pdf": "", "Pdf": "",
"PLAYLISTS": "", "PLAYLISTS": "",
@@ -169,21 +162,14 @@ translation_strings = {
"Published": "", "Published": "",
"Published on": "", "Published on": "",
"Recent uploads": "", "Recent uploads": "",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Recommended": "", "Recommended": "",
"Record": "",
"Record Screen": "", "Record Screen": "",
"Record Screen with Audio": "",
"Register": "", "Register": "",
"Replace": "",
"Remove category": "", "Remove category": "",
"Remove from list": "", "Remove from list": "",
"Remove tag": "", "Remove tag": "",
"Remove user": "", "Remove user": "",
"results for": "", "results for": "",
"Settings": "",
"SAVE": "", "SAVE": "",
"SEARCH": "", "SEARCH": "",
"Search": "", "Search": "",
@@ -197,12 +183,6 @@ translation_strings = {
"Selected": "", "Selected": "",
"selected": "", "selected": "",
"SHARE": "", "SHARE": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Sharing": "",
"Share with": "",
"Shared by me": "", "Shared by me": "",
"Shared with me": "", "Shared with me": "",
"SHOW MORE": "", "SHOW MORE": "",
@@ -213,7 +193,6 @@ translation_strings = {
"Start Recording": "", "Start Recording": "",
"Start uploading media and sharing your work. Media that you upload will show up here.": "", "Start uploading media and sharing your work. Media that you upload will show up here.": "",
"Stop Recording": "", "Stop Recording": "",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"SUBMIT": "", "SUBMIT": "",
"Submit": "", "Submit": "",
"Subtitle was added": "", "Subtitle was added": "",
@@ -221,7 +200,6 @@ translation_strings = {
"Successfully changed owner": "", "Successfully changed owner": "",
"Successfully Copied": "", "Successfully Copied": "",
"Successfully deleted": "", "Successfully deleted": "",
"Successfully deleted comments": "",
"Successfully Disabled comments": "", "Successfully Disabled comments": "",
"Successfully Disabled Download": "", "Successfully Disabled Download": "",
"Successfully Enabled comments": "", "Successfully Enabled comments": "",
@@ -261,9 +239,6 @@ translation_strings = {
"UPLOAD MEDIA": "", "UPLOAD MEDIA": "",
"Upload media": "", "Upload media": "",
"Uploads": "", "Uploads": "",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"Users": "", "Users": "",
"Video": "", "Video": "",
"view": "", "view": "",
@@ -276,7 +251,6 @@ translation_strings = {
"yet": "", "yet": "",
"You are going to copy": "", "You are going to copy": "",
"You are going to delete": "", "You are going to delete": "",
"You are going to delete all comments from": "",
"You are going to disable comments to": "", "You are going to disable comments to": "",
"You are going to disable download for": "", "You are going to disable download for": "",
"You are going to enable comments to": "", "You are going to enable comments to": "",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "ELIMINAR MEDIOS", "DELETE MEDIA": "ELIMINAR MEDIOS",
"DOWNLOAD": "DESCARGAR", "DOWNLOAD": "DESCARGAR",
"DURATION": "DURACIÓN", "DURATION": "DURACIÓN",
"Delete Comments": "",
"Delete Media": "Eliminar Medio", "Delete Media": "Eliminar Medio",
"Delete media": "Eliminar medios", "Delete media": "Eliminar medios",
"Disable Comments": "Deshabilitar Comentarios", "Disable Comments": "Deshabilitar Comentarios",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Error al cambiar propietario. Por favor, inténtelo de nuevo.", "Failed to change owner. Please try again.": "Error al cambiar propietario. Por favor, inténtelo de nuevo.",
"Failed to copy media.": "Error al copiar medios.", "Failed to copy media.": "Error al copiar medios.",
"Failed to create playlist": "Error al crear lista de reproducción", "Failed to create playlist": "Error al crear lista de reproducción",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Error al eliminar medios. Por favor, inténtelo de nuevo.", "Failed to delete media. Please try again.": "Error al eliminar medios. Por favor, inténtelo de nuevo.",
"Failed to disable comments.": "Error al deshabilitar comentarios.", "Failed to disable comments.": "Error al deshabilitar comentarios.",
"Failed to disable download.": "Error al deshabilitar descarga.", "Failed to disable download.": "Error al deshabilitar descarga.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Filtrar usuarios existentes...", "Filter existing users...": "Filtrar usuarios existentes...",
"Filter playlists...": "Filtrar listas de reproducción...", "Filter playlists...": "Filtrar listas de reproducción...",
"Filters": "Filtros", "Filters": "Filtros",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Ir", "Go": "Ir",
"History": "Historial", "History": "Historial",
"Home": "Inicio", "Home": "Inicio",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Gestionar comentarios", "Manage comments": "Gestionar comentarios",
"Manage media": "Gestionar medios", "Manage media": "Gestionar medios",
"Manage users": "Gestionar usuarios", "Manage users": "Gestionar usuarios",
"Management": "",
"Media": "Medios", "Media": "Medios",
"Media I own": "Medios que poseo", "Media I own": "Medios que poseo",
"Media was edited": "El medio fue editado", "Media was edited": "El medio fue editado",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "No hay resultados para", "No results for": "No hay resultados para",
"No tags": "Sin etiquetas", "No tags": "Sin etiquetas",
"No users to add": "No hay usuarios para agregar", "No users to add": "No hay usuarios para agregar",
"Organization": "",
"PLAYLISTS": "LISTAS DE REPRODUCCIÓN", "PLAYLISTS": "LISTAS DE REPRODUCCIÓN",
"PUBLISH STATE": "ESTADO DE PUBLICACIÓN", "PUBLISH STATE": "ESTADO DE PUBLICACIÓN",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Publicado en", "Published on": "Publicado en",
"Recent uploads": "Subidas recientes", "Recent uploads": "Subidas recientes",
"Recommended": "Recomendado", "Recommended": "Recomendado",
"Record": "",
"Record Screen": "Grabar pantalla", "Record Screen": "Grabar pantalla",
"Record Screen with Audio": "",
"Register": "Registrarse", "Register": "Registrarse",
"Remove category": "Eliminar categoría", "Remove category": "Eliminar categoría",
"Remove from list": "Eliminar de la lista", "Remove from list": "Eliminar de la lista",
"Remove tag": "Eliminar etiqueta", "Remove tag": "Eliminar etiqueta",
"Remove user": "Eliminar usuario", "Remove user": "Eliminar usuario",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "GUARDAR", "SAVE": "GUARDAR",
"SEARCH": "BUSCAR", "SEARCH": "BUSCAR",
"SHARE": "COMPARTIR", "SHARE": "COMPARTIR",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Seleccionar todos los medios", "Select all media": "Seleccionar todos los medios",
"Select publish state:": "Seleccionar estado de publicación:", "Select publish state:": "Seleccionar estado de publicación:",
"Selected": "Seleccionado", "Selected": "Seleccionado",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Compartido por mí", "Shared by me": "Compartido por mí",
"Shared with me": "Compartido conmigo", "Shared with me": "Compartido conmigo",
"Sharing": "",
"Sign in": "Iniciar sesión", "Sign in": "Iniciar sesión",
"Sign out": "Cerrar sesión", "Sign out": "Cerrar sesión",
"Sort By": "Ordenar por", "Sort By": "Ordenar por",
"Start Recording": "Iniciar grabación", "Start Recording": "Iniciar grabación",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Comience a subir medios y compartir su trabajo. Los medios que suba aparecerán aquí.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Comience a subir medios y compartir su trabajo. Los medios que suba aparecerán aquí.",
"Stop Recording": "Detener grabación", "Stop Recording": "Detener grabación",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Enviar", "Submit": "Enviar",
"Subtitle was added": "El subtítulo fue agregado", "Subtitle was added": "El subtítulo fue agregado",
"Subtitles": "Subtítulos", "Subtitles": "Subtítulos",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Comentarios habilitados exitosamente", "Successfully Enabled comments": "Comentarios habilitados exitosamente",
"Successfully changed owner": "Propietario cambiado exitosamente", "Successfully changed owner": "Propietario cambiado exitosamente",
"Successfully deleted": "Eliminado exitosamente", "Successfully deleted": "Eliminado exitosamente",
"Successfully deleted comments": "",
"Successfully updated": "Actualizado exitosamente", "Successfully updated": "Actualizado exitosamente",
"Successfully updated categories": "Categorías actualizadas exitosamente", "Successfully updated categories": "Categorías actualizadas exitosamente",
"Successfully updated playlist membership": "Membresía de lista de reproducción actualizada exitosamente", "Successfully updated playlist membership": "Membresía de lista de reproducción actualizada exitosamente",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Subir medios", "Upload media": "Subir medios",
"Uploads": "Subidas", "Uploads": "Subidas",
"Users": "Usuarios", "Users": "Usuarios",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "VER TODO", "VIEW ALL": "VER TODO",
"Video": "Video", "Video": "Video",
"View all": "Ver todo", "View all": "Ver todo",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Bienvenido", "Welcome": "Bienvenido",
"You are going to copy": "Vas a copiar", "You are going to copy": "Vas a copiar",
"You are going to delete": "Vas a eliminar", "You are going to delete": "Vas a eliminar",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Vas a deshabilitar comentarios de", "You are going to disable comments to": "Vas a deshabilitar comentarios de",
"You are going to disable download for": "Vas a deshabilitar descarga de", "You are going to disable download for": "Vas a deshabilitar descarga de",
"You are going to enable comments to": "Vas a habilitar comentarios de", "You are going to enable comments to": "Vas a habilitar comentarios de",
-26
View File
@@ -49,7 +49,6 @@ translation_strings = {
"DELETE MEDIA": "SUPPRIMER LE MÉDIA", "DELETE MEDIA": "SUPPRIMER LE MÉDIA",
"DOWNLOAD": "TÉLÉCHARGER", "DOWNLOAD": "TÉLÉCHARGER",
"DURATION": "DURÉE", "DURATION": "DURÉE",
"Delete Comments": "",
"Delete Media": "Supprimer le média", "Delete Media": "Supprimer le média",
"Delete media": "Supprimer le média", "Delete media": "Supprimer le média",
"Disable Comments": "Désactiver les commentaires", "Disable Comments": "Désactiver les commentaires",
@@ -72,7 +71,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Échec du changement de propriétaire. Veuillez réessayer.", "Failed to change owner. Please try again.": "Échec du changement de propriétaire. Veuillez réessayer.",
"Failed to copy media.": "Échec de la copie du média.", "Failed to copy media.": "Échec de la copie du média.",
"Failed to create playlist": "Échec de la création de la playlist", "Failed to create playlist": "Échec de la création de la playlist",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Échec de la suppression du média. Veuillez réessayer.", "Failed to delete media. Please try again.": "Échec de la suppression du média. Veuillez réessayer.",
"Failed to disable comments.": "Échec de la désactivation des commentaires.", "Failed to disable comments.": "Échec de la désactivation des commentaires.",
"Failed to disable download.": "Échec de la désactivation du téléchargement.", "Failed to disable download.": "Échec de la désactivation du téléchargement.",
@@ -104,9 +102,6 @@ translation_strings = {
"Filter existing users...": "Filtrer les utilisateurs existants...", "Filter existing users...": "Filtrer les utilisateurs existants...",
"Filter playlists...": "Filtrer les playlists...", "Filter playlists...": "Filtrer les playlists...",
"Filters": "Filtres", "Filters": "Filtres",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Aller", "Go": "Aller",
"History": "Historique", "History": "Historique",
"Home": "Accueil", "Home": "Accueil",
@@ -127,7 +122,6 @@ translation_strings = {
"Manage comments": "Gérer les commentaires", "Manage comments": "Gérer les commentaires",
"Manage media": "Gérer les médias", "Manage media": "Gérer les médias",
"Manage users": "Gérer les utilisateurs", "Manage users": "Gérer les utilisateurs",
"Management": "",
"Media": "Média", "Media": "Média",
"Media I own": "Médias que je possède", "Media I own": "Médias que je possède",
"Media was edited": "Le média a été modifié", "Media was edited": "Le média a été modifié",
@@ -144,7 +138,6 @@ translation_strings = {
"No results for": "Aucun résultat pour", "No results for": "Aucun résultat pour",
"No tags": "Aucun tag", "No tags": "Aucun tag",
"No users to add": "Aucun utilisateur à ajouter", "No users to add": "Aucun utilisateur à ajouter",
"Organization": "",
"PLAYLISTS": "PLAYLISTS", "PLAYLISTS": "PLAYLISTS",
"PUBLISH STATE": "ÉTAT DE PUBLICATION", "PUBLISH STATE": "ÉTAT DE PUBLICATION",
"Pdf": "PDF", "Pdf": "PDF",
@@ -164,18 +157,12 @@ translation_strings = {
"Published on": "Publié le", "Published on": "Publié le",
"Recent uploads": "Téléchargements récents", "Recent uploads": "Téléchargements récents",
"Recommended": "Recommandé", "Recommended": "Recommandé",
"Record": "",
"Record Screen": "Enregistrer l'écran", "Record Screen": "Enregistrer l'écran",
"Record Screen with Audio": "",
"Register": "S'inscrire", "Register": "S'inscrire",
"Remove category": "Supprimer la catégorie", "Remove category": "Supprimer la catégorie",
"Remove from list": "Supprimer de la liste", "Remove from list": "Supprimer de la liste",
"Remove tag": "Supprimer le tag", "Remove tag": "Supprimer le tag",
"Remove user": "Supprimer l'utilisateur", "Remove user": "Supprimer l'utilisateur",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "ENREGISTRER", "SAVE": "ENREGISTRER",
"SEARCH": "RECHERCHER", "SEARCH": "RECHERCHER",
"SHARE": "PARTAGER", "SHARE": "PARTAGER",
@@ -191,22 +178,14 @@ translation_strings = {
"Select all media": "Sélectionner tous les médias", "Select all media": "Sélectionner tous les médias",
"Select publish state:": "Sélectionner l'état de publication:", "Select publish state:": "Sélectionner l'état de publication:",
"Selected": "Sélectionné", "Selected": "Sélectionné",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Partagé par moi", "Shared by me": "Partagé par moi",
"Shared with me": "Partagé avec moi", "Shared with me": "Partagé avec moi",
"Sharing": "",
"Sign in": "Se connecter", "Sign in": "Se connecter",
"Sign out": "Se déconnecter", "Sign out": "Se déconnecter",
"Sort By": "Trier par", "Sort By": "Trier par",
"Start Recording": "Commencer l'enregistrement", "Start Recording": "Commencer l'enregistrement",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Commencez à télécharger des médias et à partager votre travail. Les médias que vous téléchargez apparaîtront ici.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Commencez à télécharger des médias et à partager votre travail. Les médias que vous téléchargez apparaîtront ici.",
"Stop Recording": "Arrêter l'enregistrement", "Stop Recording": "Arrêter l'enregistrement",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Soumettre", "Submit": "Soumettre",
"Subtitle was added": "Le sous-titre a été ajouté", "Subtitle was added": "Le sous-titre a été ajouté",
"Subtitles": "Sous-titres", "Subtitles": "Sous-titres",
@@ -217,7 +196,6 @@ translation_strings = {
"Successfully Enabled comments": "Commentaires activés avec succès", "Successfully Enabled comments": "Commentaires activés avec succès",
"Successfully changed owner": "Propriétaire changé avec succès", "Successfully changed owner": "Propriétaire changé avec succès",
"Successfully deleted": "Supprimé avec succès", "Successfully deleted": "Supprimé avec succès",
"Successfully deleted comments": "",
"Successfully updated": "Mis à jour avec succès", "Successfully updated": "Mis à jour avec succès",
"Successfully updated categories": "Catégories mises à jour avec succès", "Successfully updated categories": "Catégories mises à jour avec succès",
"Successfully updated playlist membership": "Adhésion à la playlist mise à jour avec succès", "Successfully updated playlist membership": "Adhésion à la playlist mise à jour avec succès",
@@ -254,9 +232,6 @@ translation_strings = {
"Upload media": "Télécharger des médias", "Upload media": "Télécharger des médias",
"Uploads": "Téléchargements", "Uploads": "Téléchargements",
"Users": "Utilisateurs", "Users": "Utilisateurs",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "VOIR TOUT", "VIEW ALL": "VOIR TOUT",
"Video": "Vidéo", "Video": "Vidéo",
"View all": "Voir tout", "View all": "Voir tout",
@@ -265,7 +240,6 @@ translation_strings = {
"Welcome": "Bienvenue", "Welcome": "Bienvenue",
"You are going to copy": "Vous allez copier", "You are going to copy": "Vous allez copier",
"You are going to delete": "Vous allez supprimer", "You are going to delete": "Vous allez supprimer",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Vous allez désactiver les commentaires de", "You are going to disable comments to": "Vous allez désactiver les commentaires de",
"You are going to disable download for": "Vous allez désactiver le téléchargement de", "You are going to disable download for": "Vous allez désactiver le téléchargement de",
"You are going to enable comments to": "Vous allez activer les commentaires de", "You are going to enable comments to": "Vous allez activer les commentaires de",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "מחק מדיה", "DELETE MEDIA": "מחק מדיה",
"DOWNLOAD": "הורד", "DOWNLOAD": "הורד",
"DURATION": "משך", "DURATION": "משך",
"Delete Comments": "",
"Delete Media": "", "Delete Media": "",
"Delete media": "מחק מדיה", "Delete media": "מחק מדיה",
"Disable Comments": "", "Disable Comments": "",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "", "Failed to change owner. Please try again.": "",
"Failed to copy media.": "העתקת המדיה נכשלה.", "Failed to copy media.": "העתקת המדיה נכשלה.",
"Failed to create playlist": "", "Failed to create playlist": "",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "מחיקת המדיה נכשלה. אנא נסה שוב.", "Failed to delete media. Please try again.": "מחיקת המדיה נכשלה. אנא נסה שוב.",
"Failed to disable comments.": "ביטול התגובות נכשל.", "Failed to disable comments.": "ביטול התגובות נכשל.",
"Failed to disable download.": "ביטול ההורדה נכשל.", "Failed to disable download.": "ביטול ההורדה נכשל.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "", "Filter existing users...": "",
"Filter playlists...": "", "Filter playlists...": "",
"Filters": "מסננים", "Filters": "מסננים",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "בצע", "Go": "בצע",
"History": "היסטוריה", "History": "היסטוריה",
"Home": "דף הבית", "Home": "דף הבית",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "ניהול תגובות", "Manage comments": "ניהול תגובות",
"Manage media": "ניהול מדיה", "Manage media": "ניהול מדיה",
"Manage users": "ניהול משתמשים", "Manage users": "ניהול משתמשים",
"Management": "",
"Media": "מדיה", "Media": "מדיה",
"Media I own": "", "Media I own": "",
"Media was edited": "המדיה נערכה", "Media was edited": "המדיה נערכה",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "אין תוצאות עבור", "No results for": "אין תוצאות עבור",
"No tags": "", "No tags": "",
"No users to add": "", "No users to add": "",
"Organization": "",
"PLAYLISTS": "פלייליסטים", "PLAYLISTS": "פלייליסטים",
"PUBLISH STATE": "מצב פרסום", "PUBLISH STATE": "מצב פרסום",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "פורסם בתאריך", "Published on": "פורסם בתאריך",
"Recent uploads": "העלאות אחרונות", "Recent uploads": "העלאות אחרונות",
"Recommended": "מומלץ", "Recommended": "מומלץ",
"Record": "",
"Record Screen": "הקלטת מסך", "Record Screen": "הקלטת מסך",
"Record Screen with Audio": "",
"Register": "הרשמה", "Register": "הרשמה",
"Remove category": "", "Remove category": "",
"Remove from list": "", "Remove from list": "",
"Remove tag": "", "Remove tag": "",
"Remove user": "", "Remove user": "",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "שמור", "SAVE": "שמור",
"SEARCH": "חפש", "SEARCH": "חפש",
"SHARE": "שתף", "SHARE": "שתף",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "", "Select all media": "",
"Select publish state:": "", "Select publish state:": "",
"Selected": "", "Selected": "",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "שותף על ידי", "Shared by me": "שותף על ידי",
"Shared with me": "שותף איתי", "Shared with me": "שותף איתי",
"Sharing": "",
"Sign in": "התחבר", "Sign in": "התחבר",
"Sign out": "התנתק", "Sign out": "התנתק",
"Sort By": "מיין לפי", "Sort By": "מיין לפי",
"Start Recording": "התחל הקלטה", "Start Recording": "התחל הקלטה",
"Start uploading media and sharing your work. Media that you upload will show up here.": "התחל להעלות מדיה ולשתף את עבודתך. המדיה שתעלה תופיע כאן.", "Start uploading media and sharing your work. Media that you upload will show up here.": "התחל להעלות מדיה ולשתף את עבודתך. המדיה שתעלה תופיע כאן.",
"Stop Recording": "עצור הקלטה", "Stop Recording": "עצור הקלטה",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "", "Submit": "",
"Subtitle was added": "הכתובית נוספה", "Subtitle was added": "הכתובית נוספה",
"Subtitles": "כתוביות", "Subtitles": "כתוביות",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "התגובות הופעלו בהצלחה", "Successfully Enabled comments": "התגובות הופעלו בהצלחה",
"Successfully changed owner": "", "Successfully changed owner": "",
"Successfully deleted": "נמחק בהצלחה", "Successfully deleted": "נמחק בהצלחה",
"Successfully deleted comments": "",
"Successfully updated": "", "Successfully updated": "",
"Successfully updated categories": "", "Successfully updated categories": "",
"Successfully updated playlist membership": "", "Successfully updated playlist membership": "",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "העלה מדיה", "Upload media": "העלה מדיה",
"Uploads": "העלאות", "Uploads": "העלאות",
"Users": "", "Users": "",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "הצג הכל", "VIEW ALL": "הצג הכל",
"Video": "וידאו", "Video": "וידאו",
"View all": "הצג הכל", "View all": "הצג הכל",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "ברוך הבא", "Welcome": "ברוך הבא",
"You are going to copy": "אתה עומד להעתיק", "You are going to copy": "אתה עומד להעתיק",
"You are going to delete": "אתה עומד למחוק", "You are going to delete": "אתה עומד למחוק",
"You are going to delete all comments from": "",
"You are going to disable comments to": "אתה עומד לבטל תגובות ל", "You are going to disable comments to": "אתה עומד לבטל תגובות ל",
"You are going to disable download for": "אתה עומד לבטל הורדה עבור", "You are going to disable download for": "אתה עומד לבטל הורדה עבור",
"You are going to enable comments to": "אתה עומד להפעיל תגובות ל", "You are going to enable comments to": "אתה עומד להפעיל תגובות ל",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "मीडिया हटाएं", "DELETE MEDIA": "मीडिया हटाएं",
"DOWNLOAD": "डाउनलोड करें", "DOWNLOAD": "डाउनलोड करें",
"DURATION": "अवधि", "DURATION": "अवधि",
"Delete Comments": "",
"Delete Media": "मीडिया हटाएं", "Delete Media": "मीडिया हटाएं",
"Delete media": "मीडिया हटाएं", "Delete media": "मीडिया हटाएं",
"Disable Comments": "टिप्पणियां अक्षम करें", "Disable Comments": "टिप्पणियां अक्षम करें",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "स्वामी बदलने में विफल। कृपया पुनः प्रयास करें।", "Failed to change owner. Please try again.": "स्वामी बदलने में विफल। कृपया पुनः प्रयास करें।",
"Failed to copy media.": "मीडिया कॉपी करने में विफल।", "Failed to copy media.": "मीडिया कॉपी करने में विफल।",
"Failed to create playlist": "प्लेलिस्ट बनाने में विफल", "Failed to create playlist": "प्लेलिस्ट बनाने में विफल",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "मीडिया हटाने में विफल। कृपया पुनः प्रयास करें।", "Failed to delete media. Please try again.": "मीडिया हटाने में विफल। कृपया पुनः प्रयास करें।",
"Failed to disable comments.": "टिप्पणियों को अक्षम करने में विफल।", "Failed to disable comments.": "टिप्पणियों को अक्षम करने में विफल।",
"Failed to disable download.": "डाउनलोड अक्षम करने में विफल।", "Failed to disable download.": "डाउनलोड अक्षम करने में विफल।",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "मौजूदा उपयोगकर्ताओं को फ़िल्टर करें...", "Filter existing users...": "मौजूदा उपयोगकर्ताओं को फ़िल्टर करें...",
"Filter playlists...": "प्लेलिस्ट फ़िल्टर करें...", "Filter playlists...": "प्लेलिस्ट फ़िल्टर करें...",
"Filters": "फ़िल्टर", "Filters": "फ़िल्टर",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "जाएं", "Go": "जाएं",
"History": "इतिहास", "History": "इतिहास",
"Home": "मुख्य पृष्ठ", "Home": "मुख्य पृष्ठ",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "टिप्पणियाँ प्रबंधित करें", "Manage comments": "टिप्पणियाँ प्रबंधित करें",
"Manage media": "मीडिया प्रबंधित करें", "Manage media": "मीडिया प्रबंधित करें",
"Manage users": "उपयोगकर्ताओं को प्रबंधित करें", "Manage users": "उपयोगकर्ताओं को प्रबंधित करें",
"Management": "",
"Media": "मीडिया", "Media": "मीडिया",
"Media I own": "मेरे स्वामित्व वाली मीडिया", "Media I own": "मेरे स्वामित्व वाली मीडिया",
"Media was edited": "मीडिया संपादित किया गया था", "Media was edited": "मीडिया संपादित किया गया था",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "के लिए कोई परिणाम नहीं", "No results for": "के लिए कोई परिणाम नहीं",
"No tags": "कोई टैग नहीं", "No tags": "कोई टैग नहीं",
"No users to add": "जोड़ने के लिए कोई उपयोगकर्ता नहीं", "No users to add": "जोड़ने के लिए कोई उपयोगकर्ता नहीं",
"Organization": "",
"PLAYLISTS": "प्लेलिस्ट", "PLAYLISTS": "प्लेलिस्ट",
"PUBLISH STATE": "प्रकाशन स्थिति", "PUBLISH STATE": "प्रकाशन स्थिति",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "पर प्रकाशित", "Published on": "पर प्रकाशित",
"Recent uploads": "हाल के अपलोड", "Recent uploads": "हाल के अपलोड",
"Recommended": "अनुशंसित", "Recommended": "अनुशंसित",
"Record": "",
"Record Screen": "स्क्रीन रिकॉर्ड करें", "Record Screen": "स्क्रीन रिकॉर्ड करें",
"Record Screen with Audio": "",
"Register": "पंजीकरण करें", "Register": "पंजीकरण करें",
"Remove category": "श्रेणी हटाएं", "Remove category": "श्रेणी हटाएं",
"Remove from list": "सूची से हटाएं", "Remove from list": "सूची से हटाएं",
"Remove tag": "टैग हटाएं", "Remove tag": "टैग हटाएं",
"Remove user": "उपयोगकर्ता हटाएं", "Remove user": "उपयोगकर्ता हटाएं",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "सहेजें", "SAVE": "सहेजें",
"SEARCH": "खोजें", "SEARCH": "खोजें",
"SHARE": "साझा करें", "SHARE": "साझा करें",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "सभी मीडिया चुनें", "Select all media": "सभी मीडिया चुनें",
"Select publish state:": "प्रकाशन स्थिति चुनें:", "Select publish state:": "प्रकाशन स्थिति चुनें:",
"Selected": "चयनित", "Selected": "चयनित",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "मेरे द्वारा साझा किया गया", "Shared by me": "मेरे द्वारा साझा किया गया",
"Shared with me": "मेरे साथ साझा किया गया", "Shared with me": "मेरे साथ साझा किया गया",
"Sharing": "",
"Sign in": "साइन इन करें", "Sign in": "साइन इन करें",
"Sign out": "साइन आउट करें", "Sign out": "साइन आउट करें",
"Sort By": "इसके अनुसार क्रमबद्ध करें", "Sort By": "इसके अनुसार क्रमबद्ध करें",
"Start Recording": "रिकॉर्डिंग प्रारंभ करें", "Start Recording": "रिकॉर्डिंग प्रारंभ करें",
"Start uploading media and sharing your work. Media that you upload will show up here.": "मीडिया अपलोड करना और अपना काम साझा करना शुरू करें। आपके द्वारा अपलोड किया गया मीडिया यहां दिखाई देगा।", "Start uploading media and sharing your work. Media that you upload will show up here.": "मीडिया अपलोड करना और अपना काम साझा करना शुरू करें। आपके द्वारा अपलोड किया गया मीडिया यहां दिखाई देगा।",
"Stop Recording": "रिकॉर्डिंग रोकें", "Stop Recording": "रिकॉर्डिंग रोकें",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "प्रस्तुत करें", "Submit": "प्रस्तुत करें",
"Subtitle was added": "उपशीर्षक जोड़ा गया", "Subtitle was added": "उपशीर्षक जोड़ा गया",
"Subtitles": "उपशीर्षक", "Subtitles": "उपशीर्षक",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "टिप्पणियां सफलतापूर्वक सक्षम की गईं", "Successfully Enabled comments": "टिप्पणियां सफलतापूर्वक सक्षम की गईं",
"Successfully changed owner": "स्वामी सफलतापूर्वक बदला गया", "Successfully changed owner": "स्वामी सफलतापूर्वक बदला गया",
"Successfully deleted": "सफलतापूर्वक हटाया गया", "Successfully deleted": "सफलतापूर्वक हटाया गया",
"Successfully deleted comments": "",
"Successfully updated": "सफलतापूर्वक अपडेट किया गया", "Successfully updated": "सफलतापूर्वक अपडेट किया गया",
"Successfully updated categories": "श्रेणियां सफलतापूर्वक अपडेट की गईं", "Successfully updated categories": "श्रेणियां सफलतापूर्वक अपडेट की गईं",
"Successfully updated playlist membership": "प्लेलिस्ट सदस्यता सफलतापूर्वक अपडेट की गई", "Successfully updated playlist membership": "प्लेलिस्ट सदस्यता सफलतापूर्वक अपडेट की गई",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "मीडिया अपलोड करें", "Upload media": "मीडिया अपलोड करें",
"Uploads": "अपलोड", "Uploads": "अपलोड",
"Users": "उपयोगकर्ता", "Users": "उपयोगकर्ता",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "सभी देखें", "VIEW ALL": "सभी देखें",
"Video": "वीडियो", "Video": "वीडियो",
"View all": "सभी देखें", "View all": "सभी देखें",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "स्वागत है", "Welcome": "स्वागत है",
"You are going to copy": "आप कॉपी करने जा रहे हैं", "You are going to copy": "आप कॉपी करने जा रहे हैं",
"You are going to delete": "आप हटाने जा रहे हैं", "You are going to delete": "आप हटाने जा रहे हैं",
"You are going to delete all comments from": "",
"You are going to disable comments to": "आप टिप्पणियों को अक्षम करने जा रहे हैं", "You are going to disable comments to": "आप टिप्पणियों को अक्षम करने जा रहे हैं",
"You are going to disable download for": "आप डाउनलोड को अक्षम करने जा रहे हैं", "You are going to disable download for": "आप डाउनलोड को अक्षम करने जा रहे हैं",
"You are going to enable comments to": "आप टिप्पणियों को सक्षम करने जा रहे हैं", "You are going to enable comments to": "आप टिप्पणियों को सक्षम करने जा रहे हैं",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "HAPUS MEDIA", "DELETE MEDIA": "HAPUS MEDIA",
"DOWNLOAD": "UNDUH", "DOWNLOAD": "UNDUH",
"DURATION": "DURASI", "DURATION": "DURASI",
"Delete Comments": "",
"Delete Media": "Hapus Media", "Delete Media": "Hapus Media",
"Delete media": "Hapus media", "Delete media": "Hapus media",
"Disable Comments": "Nonaktifkan Komentar", "Disable Comments": "Nonaktifkan Komentar",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Gagal mengganti pemilik. Silakan coba lagi.", "Failed to change owner. Please try again.": "Gagal mengganti pemilik. Silakan coba lagi.",
"Failed to copy media.": "Gagal menyalin media.", "Failed to copy media.": "Gagal menyalin media.",
"Failed to create playlist": "Gagal membuat daftar putar", "Failed to create playlist": "Gagal membuat daftar putar",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Gagal menghapus media. Silakan coba lagi.", "Failed to delete media. Please try again.": "Gagal menghapus media. Silakan coba lagi.",
"Failed to disable comments.": "Gagal menonaktifkan komentar.", "Failed to disable comments.": "Gagal menonaktifkan komentar.",
"Failed to disable download.": "Gagal menonaktifkan unduhan.", "Failed to disable download.": "Gagal menonaktifkan unduhan.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Filter pengguna yang ada...", "Filter existing users...": "Filter pengguna yang ada...",
"Filter playlists...": "Filter daftar putar...", "Filter playlists...": "Filter daftar putar...",
"Filters": "Filter", "Filters": "Filter",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Pergi", "Go": "Pergi",
"History": "Riwayat", "History": "Riwayat",
"Home": "Beranda", "Home": "Beranda",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Kelola komentar", "Manage comments": "Kelola komentar",
"Manage media": "Kelola media", "Manage media": "Kelola media",
"Manage users": "Kelola pengguna", "Manage users": "Kelola pengguna",
"Management": "",
"Media": "Media", "Media": "Media",
"Media I own": "Media yang saya miliki", "Media I own": "Media yang saya miliki",
"Media was edited": "Media telah diedit", "Media was edited": "Media telah diedit",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Tidak ada hasil untuk", "No results for": "Tidak ada hasil untuk",
"No tags": "Tidak ada tag", "No tags": "Tidak ada tag",
"No users to add": "Tidak ada pengguna untuk ditambahkan", "No users to add": "Tidak ada pengguna untuk ditambahkan",
"Organization": "",
"PLAYLISTS": "DAFTAR PUTAR", "PLAYLISTS": "DAFTAR PUTAR",
"PUBLISH STATE": "STATUS PUBLIKASI", "PUBLISH STATE": "STATUS PUBLIKASI",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Diterbitkan pada", "Published on": "Diterbitkan pada",
"Recent uploads": "Unggahan terbaru", "Recent uploads": "Unggahan terbaru",
"Recommended": "Direkomendasikan", "Recommended": "Direkomendasikan",
"Record": "",
"Record Screen": "Rekam Layar", "Record Screen": "Rekam Layar",
"Record Screen with Audio": "",
"Register": "Daftar", "Register": "Daftar",
"Remove category": "Hapus kategori", "Remove category": "Hapus kategori",
"Remove from list": "Hapus dari daftar", "Remove from list": "Hapus dari daftar",
"Remove tag": "Hapus tag", "Remove tag": "Hapus tag",
"Remove user": "Hapus pengguna", "Remove user": "Hapus pengguna",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "SIMPAN", "SAVE": "SIMPAN",
"SEARCH": "CARI", "SEARCH": "CARI",
"SHARE": "BAGIKAN", "SHARE": "BAGIKAN",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Pilih semua media", "Select all media": "Pilih semua media",
"Select publish state:": "Pilih status publikasi:", "Select publish state:": "Pilih status publikasi:",
"Selected": "Dipilih", "Selected": "Dipilih",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Dibagikan oleh saya", "Shared by me": "Dibagikan oleh saya",
"Shared with me": "Dibagikan dengan saya", "Shared with me": "Dibagikan dengan saya",
"Sharing": "",
"Sign in": "Masuk", "Sign in": "Masuk",
"Sign out": "Keluar", "Sign out": "Keluar",
"Sort By": "Urutkan Berdasarkan", "Sort By": "Urutkan Berdasarkan",
"Start Recording": "Mulai Merekam", "Start Recording": "Mulai Merekam",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Mulai mengunggah media dan berbagi karya Anda. Media yang Anda unggah akan muncul di sini.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Mulai mengunggah media dan berbagi karya Anda. Media yang Anda unggah akan muncul di sini.",
"Stop Recording": "Hentikan Perekaman", "Stop Recording": "Hentikan Perekaman",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Kirim", "Submit": "Kirim",
"Subtitle was added": "Subtitle telah ditambahkan", "Subtitle was added": "Subtitle telah ditambahkan",
"Subtitles": "Subtitel", "Subtitles": "Subtitel",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Komentar berhasil diaktifkan", "Successfully Enabled comments": "Komentar berhasil diaktifkan",
"Successfully changed owner": "Berhasil mengganti pemilik", "Successfully changed owner": "Berhasil mengganti pemilik",
"Successfully deleted": "Berhasil dihapus", "Successfully deleted": "Berhasil dihapus",
"Successfully deleted comments": "",
"Successfully updated": "Berhasil diperbarui", "Successfully updated": "Berhasil diperbarui",
"Successfully updated categories": "Kategori berhasil diperbarui", "Successfully updated categories": "Kategori berhasil diperbarui",
"Successfully updated playlist membership": "Keanggotaan daftar putar berhasil diperbarui", "Successfully updated playlist membership": "Keanggotaan daftar putar berhasil diperbarui",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Unggah media", "Upload media": "Unggah media",
"Uploads": "Unggahan", "Uploads": "Unggahan",
"Users": "Pengguna", "Users": "Pengguna",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "LIHAT SEMUA", "VIEW ALL": "LIHAT SEMUA",
"Video": "Video", "Video": "Video",
"View all": "Lihat semua", "View all": "Lihat semua",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Selamat datang", "Welcome": "Selamat datang",
"You are going to copy": "Anda akan menyalin", "You are going to copy": "Anda akan menyalin",
"You are going to delete": "Anda akan menghapus", "You are going to delete": "Anda akan menghapus",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Anda akan menonaktifkan komentar untuk", "You are going to disable comments to": "Anda akan menonaktifkan komentar untuk",
"You are going to disable download for": "Anda akan menonaktifkan unduhan untuk", "You are going to disable download for": "Anda akan menonaktifkan unduhan untuk",
"You are going to enable comments to": "Anda akan mengaktifkan komentar untuk", "You are going to enable comments to": "Anda akan mengaktifkan komentar untuk",
-26
View File
@@ -49,7 +49,6 @@ translation_strings = {
"DELETE MEDIA": "ELIMINA MEDIA", "DELETE MEDIA": "ELIMINA MEDIA",
"DOWNLOAD": "SCARICA", "DOWNLOAD": "SCARICA",
"DURATION": "DURATA", "DURATION": "DURATA",
"Delete Comments": "",
"Delete Media": "Elimina Media", "Delete Media": "Elimina Media",
"Delete media": "Elimina media", "Delete media": "Elimina media",
"Disable Comments": "Disabilita Commenti", "Disable Comments": "Disabilita Commenti",
@@ -72,7 +71,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Impossibile cambiare proprietario. Riprova.", "Failed to change owner. Please try again.": "Impossibile cambiare proprietario. Riprova.",
"Failed to copy media.": "Impossibile copiare il media.", "Failed to copy media.": "Impossibile copiare il media.",
"Failed to create playlist": "Impossibile creare playlist", "Failed to create playlist": "Impossibile creare playlist",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Impossibile eliminare il media. Riprova.", "Failed to delete media. Please try again.": "Impossibile eliminare il media. Riprova.",
"Failed to disable comments.": "Impossibile disabilitare i commenti.", "Failed to disable comments.": "Impossibile disabilitare i commenti.",
"Failed to disable download.": "Impossibile disabilitare il download.", "Failed to disable download.": "Impossibile disabilitare il download.",
@@ -104,9 +102,6 @@ translation_strings = {
"Filter existing users...": "Filtra utenti esistenti...", "Filter existing users...": "Filtra utenti esistenti...",
"Filter playlists...": "Filtra playlist...", "Filter playlists...": "Filtra playlist...",
"Filters": "Filtri", "Filters": "Filtri",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Vai", "Go": "Vai",
"History": "Cronologia", "History": "Cronologia",
"Home": "Home", "Home": "Home",
@@ -127,7 +122,6 @@ translation_strings = {
"Manage comments": "Gestisci i commenti", "Manage comments": "Gestisci i commenti",
"Manage media": "Gestisci i media", "Manage media": "Gestisci i media",
"Manage users": "Gestisci gli utenti", "Manage users": "Gestisci gli utenti",
"Management": "",
"Media": "Media", "Media": "Media",
"Media I own": "Media di mia proprietà", "Media I own": "Media di mia proprietà",
"Media was edited": "Il media è stato modificato", "Media was edited": "Il media è stato modificato",
@@ -144,7 +138,6 @@ translation_strings = {
"No results for": "Nessun risultato per", "No results for": "Nessun risultato per",
"No tags": "Nessun tag", "No tags": "Nessun tag",
"No users to add": "Nessun utente da aggiungere", "No users to add": "Nessun utente da aggiungere",
"Organization": "",
"PLAYLISTS": "PLAYLIST", "PLAYLISTS": "PLAYLIST",
"PUBLISH STATE": "STATO DI PUBBLICAZIONE", "PUBLISH STATE": "STATO DI PUBBLICAZIONE",
"Pdf": "PDF", "Pdf": "PDF",
@@ -164,18 +157,12 @@ translation_strings = {
"Published on": "Pubblicato il", "Published on": "Pubblicato il",
"Recent uploads": "Caricamenti recenti", "Recent uploads": "Caricamenti recenti",
"Recommended": "Raccomandati", "Recommended": "Raccomandati",
"Record": "",
"Record Screen": "Registra schermo", "Record Screen": "Registra schermo",
"Record Screen with Audio": "",
"Register": "Registrati", "Register": "Registrati",
"Remove category": "Rimuovi categoria", "Remove category": "Rimuovi categoria",
"Remove from list": "Rimuovi dalla lista", "Remove from list": "Rimuovi dalla lista",
"Remove tag": "Rimuovi tag", "Remove tag": "Rimuovi tag",
"Remove user": "Rimuovi utente", "Remove user": "Rimuovi utente",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "SALVA", "SAVE": "SALVA",
"SEARCH": "CERCA", "SEARCH": "CERCA",
"SHARE": "CONDIVIDI", "SHARE": "CONDIVIDI",
@@ -191,22 +178,14 @@ translation_strings = {
"Select all media": "Seleziona tutti i media", "Select all media": "Seleziona tutti i media",
"Select publish state:": "Seleziona stato di pubblicazione:", "Select publish state:": "Seleziona stato di pubblicazione:",
"Selected": "Selezionato", "Selected": "Selezionato",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Condiviso da me", "Shared by me": "Condiviso da me",
"Shared with me": "Condiviso con me", "Shared with me": "Condiviso con me",
"Sharing": "",
"Sign in": "Login", "Sign in": "Login",
"Sign out": "Logout", "Sign out": "Logout",
"Sort By": "Ordina per", "Sort By": "Ordina per",
"Start Recording": "Inizia registrazione", "Start Recording": "Inizia registrazione",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Inizia a caricare media e condividere il tuo lavoro. I media caricati appariranno qui.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Inizia a caricare media e condividere il tuo lavoro. I media caricati appariranno qui.",
"Stop Recording": "Interrompi registrazione", "Stop Recording": "Interrompi registrazione",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Invia", "Submit": "Invia",
"Subtitle was added": "I sottotitoli sono stati aggiunti", "Subtitle was added": "I sottotitoli sono stati aggiunti",
"Subtitles": "Sottotitoli", "Subtitles": "Sottotitoli",
@@ -217,7 +196,6 @@ translation_strings = {
"Successfully Enabled comments": "Commenti abilitati con successo", "Successfully Enabled comments": "Commenti abilitati con successo",
"Successfully changed owner": "Proprietario cambiato con successo", "Successfully changed owner": "Proprietario cambiato con successo",
"Successfully deleted": "Eliminato con successo", "Successfully deleted": "Eliminato con successo",
"Successfully deleted comments": "",
"Successfully updated": "Aggiornato con successo", "Successfully updated": "Aggiornato con successo",
"Successfully updated categories": "Categorie aggiornate con successo", "Successfully updated categories": "Categorie aggiornate con successo",
"Successfully updated playlist membership": "Appartenenza alla playlist aggiornata con successo", "Successfully updated playlist membership": "Appartenenza alla playlist aggiornata con successo",
@@ -254,9 +232,6 @@ translation_strings = {
"Upload media": "Carica i media", "Upload media": "Carica i media",
"Uploads": "Caricamenti", "Uploads": "Caricamenti",
"Users": "Utenti", "Users": "Utenti",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "MOSTRA TUTTI", "VIEW ALL": "MOSTRA TUTTI",
"Video": "Video", "Video": "Video",
"View all": "Mostra tutti", "View all": "Mostra tutti",
@@ -265,7 +240,6 @@ translation_strings = {
"Welcome": "Benvenuto", "Welcome": "Benvenuto",
"You are going to copy": "Stai per copiare", "You are going to copy": "Stai per copiare",
"You are going to delete": "Stai per eliminare", "You are going to delete": "Stai per eliminare",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Stai per disabilitare i commenti di", "You are going to disable comments to": "Stai per disabilitare i commenti di",
"You are going to disable download for": "Stai per disabilitare il download di", "You are going to disable download for": "Stai per disabilitare il download di",
"You are going to enable comments to": "Stai per abilitare i commenti di", "You are going to enable comments to": "Stai per abilitare i commenti di",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "メディアを削除", "DELETE MEDIA": "メディアを削除",
"DOWNLOAD": "ダウンロード", "DOWNLOAD": "ダウンロード",
"DURATION": "期間", "DURATION": "期間",
"Delete Comments": "",
"Delete Media": "メディアを削除", "Delete Media": "メディアを削除",
"Delete media": "メディアを削除", "Delete media": "メディアを削除",
"Disable Comments": "コメントを無効化", "Disable Comments": "コメントを無効化",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "所有者の変更に失敗しました。もう一度お試しください。", "Failed to change owner. Please try again.": "所有者の変更に失敗しました。もう一度お試しください。",
"Failed to copy media.": "メディアのコピーに失敗しました。", "Failed to copy media.": "メディアのコピーに失敗しました。",
"Failed to create playlist": "プレイリストの作成に失敗しました", "Failed to create playlist": "プレイリストの作成に失敗しました",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "メディアの削除に失敗しました。もう一度お試しください。", "Failed to delete media. Please try again.": "メディアの削除に失敗しました。もう一度お試しください。",
"Failed to disable comments.": "コメントの無効化に失敗しました。", "Failed to disable comments.": "コメントの無効化に失敗しました。",
"Failed to disable download.": "ダウンロードの無効化に失敗しました。", "Failed to disable download.": "ダウンロードの無効化に失敗しました。",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "既存ユーザーをフィルター...", "Filter existing users...": "既存ユーザーをフィルター...",
"Filter playlists...": "プレイリストをフィルター...", "Filter playlists...": "プレイリストをフィルター...",
"Filters": "フィルター", "Filters": "フィルター",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "行く", "Go": "行く",
"History": "履歴", "History": "履歴",
"Home": "ホーム", "Home": "ホーム",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "コメントを管理", "Manage comments": "コメントを管理",
"Manage media": "メディアを管理", "Manage media": "メディアを管理",
"Manage users": "ユーザーを管理", "Manage users": "ユーザーを管理",
"Management": "",
"Media": "メディア", "Media": "メディア",
"Media I own": "自分が所有するメディア", "Media I own": "自分が所有するメディア",
"Media was edited": "メディアが編集されました", "Media was edited": "メディアが編集されました",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "の結果はありません", "No results for": "の結果はありません",
"No tags": "タグなし", "No tags": "タグなし",
"No users to add": "追加するユーザーなし", "No users to add": "追加するユーザーなし",
"Organization": "",
"PLAYLISTS": "プレイリスト", "PLAYLISTS": "プレイリスト",
"PUBLISH STATE": "公開状態", "PUBLISH STATE": "公開状態",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "公開日", "Published on": "公開日",
"Recent uploads": "最近のアップロード", "Recent uploads": "最近のアップロード",
"Recommended": "おすすめ", "Recommended": "おすすめ",
"Record": "",
"Record Screen": "画面を録画", "Record Screen": "画面を録画",
"Record Screen with Audio": "",
"Register": "登録", "Register": "登録",
"Remove category": "カテゴリーを削除", "Remove category": "カテゴリーを削除",
"Remove from list": "リストから削除", "Remove from list": "リストから削除",
"Remove tag": "タグを削除", "Remove tag": "タグを削除",
"Remove user": "ユーザーを削除", "Remove user": "ユーザーを削除",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "保存", "SAVE": "保存",
"SEARCH": "検索", "SEARCH": "検索",
"SHARE": "共有", "SHARE": "共有",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "すべてのメディアを選択", "Select all media": "すべてのメディアを選択",
"Select publish state:": "公開状態を選択:", "Select publish state:": "公開状態を選択:",
"Selected": "選択済み", "Selected": "選択済み",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "自分が共有", "Shared by me": "自分が共有",
"Shared with me": "共有されたもの", "Shared with me": "共有されたもの",
"Sharing": "",
"Sign in": "サインイン", "Sign in": "サインイン",
"Sign out": "サインアウト", "Sign out": "サインアウト",
"Sort By": "並び替え", "Sort By": "並び替え",
"Start Recording": "録画開始", "Start Recording": "録画開始",
"Start uploading media and sharing your work. Media that you upload will show up here.": "メディアをアップロードして作品を共有しましょう。アップロードしたメディアはここに表示されます。", "Start uploading media and sharing your work. Media that you upload will show up here.": "メディアをアップロードして作品を共有しましょう。アップロードしたメディアはここに表示されます。",
"Stop Recording": "録画停止", "Stop Recording": "録画停止",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "送信", "Submit": "送信",
"Subtitle was added": "字幕が追加されました", "Subtitle was added": "字幕が追加されました",
"Subtitles": "字幕", "Subtitles": "字幕",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "コメントが正常に有効化されました", "Successfully Enabled comments": "コメントが正常に有効化されました",
"Successfully changed owner": "所有者が正常に変更されました", "Successfully changed owner": "所有者が正常に変更されました",
"Successfully deleted": "正常に削除されました", "Successfully deleted": "正常に削除されました",
"Successfully deleted comments": "",
"Successfully updated": "正常に更新されました", "Successfully updated": "正常に更新されました",
"Successfully updated categories": "カテゴリーが正常に更新されました", "Successfully updated categories": "カテゴリーが正常に更新されました",
"Successfully updated playlist membership": "プレイリストメンバーシップが正常に更新されました", "Successfully updated playlist membership": "プレイリストメンバーシップが正常に更新されました",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "メディアをアップロード", "Upload media": "メディアをアップロード",
"Uploads": "アップロード", "Uploads": "アップロード",
"Users": "ユーザー", "Users": "ユーザー",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "すべて表示", "VIEW ALL": "すべて表示",
"Video": "ビデオ", "Video": "ビデオ",
"View all": "すべて表示", "View all": "すべて表示",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "ようこそ", "Welcome": "ようこそ",
"You are going to copy": "コピーします", "You are going to copy": "コピーします",
"You are going to delete": "削除します", "You are going to delete": "削除します",
"You are going to delete all comments from": "",
"You are going to disable comments to": "コメントを無効化します", "You are going to disable comments to": "コメントを無効化します",
"You are going to disable download for": "ダウンロードを無効化します", "You are going to disable download for": "ダウンロードを無効化します",
"You are going to enable comments to": "コメントを有効化します", "You are going to enable comments to": "コメントを有効化します",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "미디어 삭제", "DELETE MEDIA": "미디어 삭제",
"DOWNLOAD": "다운로드", "DOWNLOAD": "다운로드",
"DURATION": "재생 시간", "DURATION": "재생 시간",
"Delete Comments": "",
"Delete Media": "미디어 삭제", "Delete Media": "미디어 삭제",
"Delete media": "미디어 삭제", "Delete media": "미디어 삭제",
"Disable Comments": "댓글 비활성화", "Disable Comments": "댓글 비활성화",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "소유자 변경에 실패했습니다. 다시 시도해주세요.", "Failed to change owner. Please try again.": "소유자 변경에 실패했습니다. 다시 시도해주세요.",
"Failed to copy media.": "미디어 복사에 실패했습니다.", "Failed to copy media.": "미디어 복사에 실패했습니다.",
"Failed to create playlist": "재생 목록 만들기 실패", "Failed to create playlist": "재생 목록 만들기 실패",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "미디어 삭제에 실패했습니다. 다시 시도해주세요.", "Failed to delete media. Please try again.": "미디어 삭제에 실패했습니다. 다시 시도해주세요.",
"Failed to disable comments.": "댓글 비활성화에 실패했습니다.", "Failed to disable comments.": "댓글 비활성화에 실패했습니다.",
"Failed to disable download.": "다운로드 비활성화에 실패했습니다.", "Failed to disable download.": "다운로드 비활성화에 실패했습니다.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "기존 사용자 필터링...", "Filter existing users...": "기존 사용자 필터링...",
"Filter playlists...": "재생 목록 필터링...", "Filter playlists...": "재생 목록 필터링...",
"Filters": "필터", "Filters": "필터",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "이동", "Go": "이동",
"History": "기록", "History": "기록",
"Home": "", "Home": "",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "댓글 관리", "Manage comments": "댓글 관리",
"Manage media": "미디어 관리", "Manage media": "미디어 관리",
"Manage users": "사용자 관리", "Manage users": "사용자 관리",
"Management": "",
"Media": "미디어", "Media": "미디어",
"Media I own": "내가 소유한 미디어", "Media I own": "내가 소유한 미디어",
"Media was edited": "미디어가 편집되었습니다", "Media was edited": "미디어가 편집되었습니다",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "결과 없음", "No results for": "결과 없음",
"No tags": "태그 없음", "No tags": "태그 없음",
"No users to add": "추가할 사용자 없음", "No users to add": "추가할 사용자 없음",
"Organization": "",
"PLAYLISTS": "재생 목록", "PLAYLISTS": "재생 목록",
"PUBLISH STATE": "게시 상태", "PUBLISH STATE": "게시 상태",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "게시일", "Published on": "게시일",
"Recent uploads": "최근 업로드", "Recent uploads": "최근 업로드",
"Recommended": "추천", "Recommended": "추천",
"Record": "",
"Record Screen": "화면 녹화", "Record Screen": "화면 녹화",
"Record Screen with Audio": "",
"Register": "등록", "Register": "등록",
"Remove category": "카테고리 제거", "Remove category": "카테고리 제거",
"Remove from list": "목록에서 제거", "Remove from list": "목록에서 제거",
"Remove tag": "태그 제거", "Remove tag": "태그 제거",
"Remove user": "사용자 제거", "Remove user": "사용자 제거",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "저장", "SAVE": "저장",
"SEARCH": "검색", "SEARCH": "검색",
"SHARE": "공유", "SHARE": "공유",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "모든 미디어 선택", "Select all media": "모든 미디어 선택",
"Select publish state:": "게시 상태 선택:", "Select publish state:": "게시 상태 선택:",
"Selected": "선택됨", "Selected": "선택됨",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "내가 공유함", "Shared by me": "내가 공유함",
"Shared with me": "나와 공유됨", "Shared with me": "나와 공유됨",
"Sharing": "",
"Sign in": "로그인", "Sign in": "로그인",
"Sign out": "로그아웃", "Sign out": "로그아웃",
"Sort By": "정렬", "Sort By": "정렬",
"Start Recording": "녹화 시작", "Start Recording": "녹화 시작",
"Start uploading media and sharing your work. Media that you upload will show up here.": "미디어를 업로드하고 작업을 공유하세요. 업로드한 미디어가 여기에 표시됩니다.", "Start uploading media and sharing your work. Media that you upload will show up here.": "미디어를 업로드하고 작업을 공유하세요. 업로드한 미디어가 여기에 표시됩니다.",
"Stop Recording": "녹화 중지", "Stop Recording": "녹화 중지",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "제출", "Submit": "제출",
"Subtitle was added": "자막이 추가되었습니다", "Subtitle was added": "자막이 추가되었습니다",
"Subtitles": "자막", "Subtitles": "자막",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "댓글이 활성화되었습니다", "Successfully Enabled comments": "댓글이 활성화되었습니다",
"Successfully changed owner": "소유자가 변경되었습니다", "Successfully changed owner": "소유자가 변경되었습니다",
"Successfully deleted": "삭제 성공", "Successfully deleted": "삭제 성공",
"Successfully deleted comments": "",
"Successfully updated": "업데이트 성공", "Successfully updated": "업데이트 성공",
"Successfully updated categories": "카테고리가 업데이트되었습니다", "Successfully updated categories": "카테고리가 업데이트되었습니다",
"Successfully updated playlist membership": "재생 목록 멤버십이 업데이트되었습니다", "Successfully updated playlist membership": "재생 목록 멤버십이 업데이트되었습니다",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "미디어 업로드", "Upload media": "미디어 업로드",
"Uploads": "업로드", "Uploads": "업로드",
"Users": "사용자", "Users": "사용자",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "모두 보기", "VIEW ALL": "모두 보기",
"Video": "비디오", "Video": "비디오",
"View all": "모두 보기", "View all": "모두 보기",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "환영합니다", "Welcome": "환영합니다",
"You are going to copy": "복사하려고 합니다", "You are going to copy": "복사하려고 합니다",
"You are going to delete": "삭제하려고 합니다", "You are going to delete": "삭제하려고 합니다",
"You are going to delete all comments from": "",
"You are going to disable comments to": "댓글을 비활성화하려고 합니다", "You are going to disable comments to": "댓글을 비활성화하려고 합니다",
"You are going to disable download for": "다운로드를 비활성화하려고 합니다", "You are going to disable download for": "다운로드를 비활성화하려고 합니다",
"You are going to enable comments to": "댓글을 활성화하려고 합니다", "You are going to enable comments to": "댓글을 활성화하려고 합니다",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "MEDIA VERWIJDEREN", "DELETE MEDIA": "MEDIA VERWIJDEREN",
"DOWNLOAD": "DOWNLOADEN", "DOWNLOAD": "DOWNLOADEN",
"DURATION": "DUUR", "DURATION": "DUUR",
"Delete Comments": "",
"Delete Media": "Media verwijderen", "Delete Media": "Media verwijderen",
"Delete media": "Media verwijderen", "Delete media": "Media verwijderen",
"Disable Comments": "Reacties uitschakelen", "Disable Comments": "Reacties uitschakelen",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Eigenaar wijzigen mislukt. Probeer het opnieuw.", "Failed to change owner. Please try again.": "Eigenaar wijzigen mislukt. Probeer het opnieuw.",
"Failed to copy media.": "Media kopiëren mislukt.", "Failed to copy media.": "Media kopiëren mislukt.",
"Failed to create playlist": "Afspeellijst maken mislukt", "Failed to create playlist": "Afspeellijst maken mislukt",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Media verwijderen mislukt. Probeer het opnieuw.", "Failed to delete media. Please try again.": "Media verwijderen mislukt. Probeer het opnieuw.",
"Failed to disable comments.": "Reacties uitschakelen mislukt.", "Failed to disable comments.": "Reacties uitschakelen mislukt.",
"Failed to disable download.": "Download uitschakelen mislukt.", "Failed to disable download.": "Download uitschakelen mislukt.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Filter bestaande gebruikers...", "Filter existing users...": "Filter bestaande gebruikers...",
"Filter playlists...": "Filter afspeellijsten...", "Filter playlists...": "Filter afspeellijsten...",
"Filters": "Filters", "Filters": "Filters",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Ga", "Go": "Ga",
"History": "Geschiedenis", "History": "Geschiedenis",
"Home": "Home", "Home": "Home",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Reacties beheren", "Manage comments": "Reacties beheren",
"Manage media": "Media beheren", "Manage media": "Media beheren",
"Manage users": "Gebruikers beheren", "Manage users": "Gebruikers beheren",
"Management": "",
"Media": "Media", "Media": "Media",
"Media I own": "Media die ik bezit", "Media I own": "Media die ik bezit",
"Media was edited": "Media is bewerkt", "Media was edited": "Media is bewerkt",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Geen resultaten voor", "No results for": "Geen resultaten voor",
"No tags": "Geen tags", "No tags": "Geen tags",
"No users to add": "Geen gebruikers om toe te voegen", "No users to add": "Geen gebruikers om toe te voegen",
"Organization": "",
"PLAYLISTS": "AFSPEELLIJSTEN", "PLAYLISTS": "AFSPEELLIJSTEN",
"PUBLISH STATE": "PUBLICATIESTATUS", "PUBLISH STATE": "PUBLICATIESTATUS",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Gepubliceerd op", "Published on": "Gepubliceerd op",
"Recent uploads": "Recente uploads", "Recent uploads": "Recente uploads",
"Recommended": "Aanbevolen", "Recommended": "Aanbevolen",
"Record": "",
"Record Screen": "Scherm opnemen", "Record Screen": "Scherm opnemen",
"Record Screen with Audio": "",
"Register": "Registreren", "Register": "Registreren",
"Remove category": "Categorie verwijderen", "Remove category": "Categorie verwijderen",
"Remove from list": "Verwijderen uit lijst", "Remove from list": "Verwijderen uit lijst",
"Remove tag": "Tag verwijderen", "Remove tag": "Tag verwijderen",
"Remove user": "Gebruiker verwijderen", "Remove user": "Gebruiker verwijderen",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "OPSLAAN", "SAVE": "OPSLAAN",
"SEARCH": "ZOEKEN", "SEARCH": "ZOEKEN",
"SHARE": "DELEN", "SHARE": "DELEN",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Alle media selecteren", "Select all media": "Alle media selecteren",
"Select publish state:": "Selecteer publicatiestatus:", "Select publish state:": "Selecteer publicatiestatus:",
"Selected": "Geselecteerd", "Selected": "Geselecteerd",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Gedeeld door mij", "Shared by me": "Gedeeld door mij",
"Shared with me": "Gedeeld met mij", "Shared with me": "Gedeeld met mij",
"Sharing": "",
"Sign in": "Inloggen", "Sign in": "Inloggen",
"Sign out": "Uitloggen", "Sign out": "Uitloggen",
"Sort By": "Sorteer op", "Sort By": "Sorteer op",
"Start Recording": "Opname starten", "Start Recording": "Opname starten",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Begin met het uploaden van media en het delen van uw werk. Media die u uploadt, verschijnt hier.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Begin met het uploaden van media en het delen van uw werk. Media die u uploadt, verschijnt hier.",
"Stop Recording": "Opname stoppen", "Stop Recording": "Opname stoppen",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Indienen", "Submit": "Indienen",
"Subtitle was added": "Ondertitel is toegevoegd", "Subtitle was added": "Ondertitel is toegevoegd",
"Subtitles": "Ondertitels", "Subtitles": "Ondertitels",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Reacties succesvol ingeschakeld", "Successfully Enabled comments": "Reacties succesvol ingeschakeld",
"Successfully changed owner": "Eigenaar succesvol gewijzigd", "Successfully changed owner": "Eigenaar succesvol gewijzigd",
"Successfully deleted": "Succesvol verwijderd", "Successfully deleted": "Succesvol verwijderd",
"Successfully deleted comments": "",
"Successfully updated": "Succesvol bijgewerkt", "Successfully updated": "Succesvol bijgewerkt",
"Successfully updated categories": "Categorieën succesvol bijgewerkt", "Successfully updated categories": "Categorieën succesvol bijgewerkt",
"Successfully updated playlist membership": "Afspeellijstlidmaatschap succesvol bijgewerkt", "Successfully updated playlist membership": "Afspeellijstlidmaatschap succesvol bijgewerkt",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Media uploaden", "Upload media": "Media uploaden",
"Uploads": "Uploads", "Uploads": "Uploads",
"Users": "Gebruikers", "Users": "Gebruikers",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "BEKIJK ALLES", "VIEW ALL": "BEKIJK ALLES",
"Video": "Video", "Video": "Video",
"View all": "Bekijk alles", "View all": "Bekijk alles",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Welkom", "Welcome": "Welkom",
"You are going to copy": "Je gaat kopiëren", "You are going to copy": "Je gaat kopiëren",
"You are going to delete": "Je gaat verwijderen", "You are going to delete": "Je gaat verwijderen",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Je gaat reacties uitschakelen voor", "You are going to disable comments to": "Je gaat reacties uitschakelen voor",
"You are going to disable download for": "Je gaat download uitschakelen voor", "You are going to disable download for": "Je gaat download uitschakelen voor",
"You are going to enable comments to": "Je gaat reacties inschakelen voor", "You are going to enable comments to": "Je gaat reacties inschakelen voor",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "EXCLUIR MÍDIA", "DELETE MEDIA": "EXCLUIR MÍDIA",
"DOWNLOAD": "BAIXAR", "DOWNLOAD": "BAIXAR",
"DURATION": "DURAÇÃO", "DURATION": "DURAÇÃO",
"Delete Comments": "",
"Delete Media": "Excluir mídia", "Delete Media": "Excluir mídia",
"Delete media": "Excluir mídia", "Delete media": "Excluir mídia",
"Disable Comments": "Desativar comentários", "Disable Comments": "Desativar comentários",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Falha ao mudar proprietário. Por favor, tente novamente.", "Failed to change owner. Please try again.": "Falha ao mudar proprietário. Por favor, tente novamente.",
"Failed to copy media.": "Falha ao copiar mídia.", "Failed to copy media.": "Falha ao copiar mídia.",
"Failed to create playlist": "Falha ao criar playlist", "Failed to create playlist": "Falha ao criar playlist",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Falha ao excluir mídia. Por favor, tente novamente.", "Failed to delete media. Please try again.": "Falha ao excluir mídia. Por favor, tente novamente.",
"Failed to disable comments.": "Falha ao desativar comentários.", "Failed to disable comments.": "Falha ao desativar comentários.",
"Failed to disable download.": "Falha ao desativar download.", "Failed to disable download.": "Falha ao desativar download.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Filtrar usuários existentes...", "Filter existing users...": "Filtrar usuários existentes...",
"Filter playlists...": "Filtrar playlists...", "Filter playlists...": "Filtrar playlists...",
"Filters": "Filtros", "Filters": "Filtros",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Ir", "Go": "Ir",
"History": "Histórico", "History": "Histórico",
"Home": "Início", "Home": "Início",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Gerenciar comentários", "Manage comments": "Gerenciar comentários",
"Manage media": "Gerenciar mídia", "Manage media": "Gerenciar mídia",
"Manage users": "Gerenciar usuários", "Manage users": "Gerenciar usuários",
"Management": "",
"Media": "Mídia", "Media": "Mídia",
"Media I own": "Mídia que possuo", "Media I own": "Mídia que possuo",
"Media was edited": "Mídia foi editada", "Media was edited": "Mídia foi editada",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Nenhum resultado para", "No results for": "Nenhum resultado para",
"No tags": "Nenhuma tag", "No tags": "Nenhuma tag",
"No users to add": "Nenhum usuário para adicionar", "No users to add": "Nenhum usuário para adicionar",
"Organization": "",
"PLAYLISTS": "PLAYLISTS", "PLAYLISTS": "PLAYLISTS",
"PUBLISH STATE": "ESTADO DE PUBLICAÇÃO", "PUBLISH STATE": "ESTADO DE PUBLICAÇÃO",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Publicado em", "Published on": "Publicado em",
"Recent uploads": "Uploads recentes", "Recent uploads": "Uploads recentes",
"Recommended": "Recomendado", "Recommended": "Recomendado",
"Record": "",
"Record Screen": "Gravar tela", "Record Screen": "Gravar tela",
"Record Screen with Audio": "",
"Register": "Registrar", "Register": "Registrar",
"Remove category": "Remover categoria", "Remove category": "Remover categoria",
"Remove from list": "Remover da lista", "Remove from list": "Remover da lista",
"Remove tag": "Remover tag", "Remove tag": "Remover tag",
"Remove user": "Remover usuário", "Remove user": "Remover usuário",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "SALVAR", "SAVE": "SALVAR",
"SEARCH": "PESQUISAR", "SEARCH": "PESQUISAR",
"SHARE": "COMPARTILHAR", "SHARE": "COMPARTILHAR",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Selecionar todas as mídias", "Select all media": "Selecionar todas as mídias",
"Select publish state:": "Selecionar estado de publicação:", "Select publish state:": "Selecionar estado de publicação:",
"Selected": "Selecionado", "Selected": "Selecionado",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Compartilhado por mim", "Shared by me": "Compartilhado por mim",
"Shared with me": "Compartilhado comigo", "Shared with me": "Compartilhado comigo",
"Sharing": "",
"Sign in": "Entrar", "Sign in": "Entrar",
"Sign out": "Sair", "Sign out": "Sair",
"Sort By": "Ordenar por", "Sort By": "Ordenar por",
"Start Recording": "Iniciar gravação", "Start Recording": "Iniciar gravação",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Comece a fazer upload de mídia e compartilhar seu trabalho. A mídia que você fizer upload aparecerá aqui.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Comece a fazer upload de mídia e compartilhar seu trabalho. A mídia que você fizer upload aparecerá aqui.",
"Stop Recording": "Parar gravação", "Stop Recording": "Parar gravação",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Enviar", "Submit": "Enviar",
"Subtitle was added": "Legenda foi adicionada", "Subtitle was added": "Legenda foi adicionada",
"Subtitles": "Legendas", "Subtitles": "Legendas",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Comentários ativados com sucesso", "Successfully Enabled comments": "Comentários ativados com sucesso",
"Successfully changed owner": "Proprietário alterado com sucesso", "Successfully changed owner": "Proprietário alterado com sucesso",
"Successfully deleted": "Excluído com sucesso", "Successfully deleted": "Excluído com sucesso",
"Successfully deleted comments": "",
"Successfully updated": "Atualizado com sucesso", "Successfully updated": "Atualizado com sucesso",
"Successfully updated categories": "Categorias atualizadas com sucesso", "Successfully updated categories": "Categorias atualizadas com sucesso",
"Successfully updated playlist membership": "Associação da playlist atualizada com sucesso", "Successfully updated playlist membership": "Associação da playlist atualizada com sucesso",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Carregar mídia", "Upload media": "Carregar mídia",
"Uploads": "Uploads", "Uploads": "Uploads",
"Users": "Usuários", "Users": "Usuários",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "VER TODOS", "VIEW ALL": "VER TODOS",
"Video": "Vídeo", "Video": "Vídeo",
"View all": "Ver todos", "View all": "Ver todos",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Bem-vindo", "Welcome": "Bem-vindo",
"You are going to copy": "Você vai copiar", "You are going to copy": "Você vai copiar",
"You are going to delete": "Você vai excluir", "You are going to delete": "Você vai excluir",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Você vai desativar comentários de", "You are going to disable comments to": "Você vai desativar comentários de",
"You are going to disable download for": "Você vai desativar download de", "You are going to disable download for": "Você vai desativar download de",
"You are going to enable comments to": "Você vai ativar comentários de", "You are going to enable comments to": "Você vai ativar comentários de",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "УДАЛИТЬ МЕДИА", "DELETE MEDIA": "УДАЛИТЬ МЕДИА",
"DOWNLOAD": "СКАЧАТЬ", "DOWNLOAD": "СКАЧАТЬ",
"DURATION": "ДЛИТЕЛЬНОСТЬ", "DURATION": "ДЛИТЕЛЬНОСТЬ",
"Delete Comments": "",
"Delete Media": "Удалить медиа", "Delete Media": "Удалить медиа",
"Delete media": "Удалить медиа", "Delete media": "Удалить медиа",
"Disable Comments": "Отключить комментарии", "Disable Comments": "Отключить комментарии",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Не удалось изменить владельца. Пожалуйста, попробуйте снова.", "Failed to change owner. Please try again.": "Не удалось изменить владельца. Пожалуйста, попробуйте снова.",
"Failed to copy media.": "Не удалось скопировать медиа.", "Failed to copy media.": "Не удалось скопировать медиа.",
"Failed to create playlist": "Не удалось создать плейлист", "Failed to create playlist": "Не удалось создать плейлист",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Не удалось удалить медиа. Пожалуйста, попробуйте снова.", "Failed to delete media. Please try again.": "Не удалось удалить медиа. Пожалуйста, попробуйте снова.",
"Failed to disable comments.": "Не удалось отключить комментарии.", "Failed to disable comments.": "Не удалось отключить комментарии.",
"Failed to disable download.": "Не удалось отключить загрузку.", "Failed to disable download.": "Не удалось отключить загрузку.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Фильтровать существующих пользователей...", "Filter existing users...": "Фильтровать существующих пользователей...",
"Filter playlists...": "Фильтровать плейлисты...", "Filter playlists...": "Фильтровать плейлисты...",
"Filters": "Фильтры", "Filters": "Фильтры",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Перейти", "Go": "Перейти",
"History": "История", "History": "История",
"Home": "Главная", "Home": "Главная",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Управление комментариями", "Manage comments": "Управление комментариями",
"Manage media": "Управление медиа", "Manage media": "Управление медиа",
"Manage users": "Управление пользователями", "Manage users": "Управление пользователями",
"Management": "",
"Media": "Медиа", "Media": "Медиа",
"Media I own": "Медиа, которыми я владею", "Media I own": "Медиа, которыми я владею",
"Media was edited": "Медиа было отредактировано", "Media was edited": "Медиа было отредактировано",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Нет результатов для", "No results for": "Нет результатов для",
"No tags": "Нет тегов", "No tags": "Нет тегов",
"No users to add": "Нет пользователей для добавления", "No users to add": "Нет пользователей для добавления",
"Organization": "",
"PLAYLISTS": "ПЛЕЙЛИСТЫ", "PLAYLISTS": "ПЛЕЙЛИСТЫ",
"PUBLISH STATE": "СОСТОЯНИЕ ПУБЛИКАЦИИ", "PUBLISH STATE": "СОСТОЯНИЕ ПУБЛИКАЦИИ",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Опубликовано", "Published on": "Опубликовано",
"Recent uploads": "Недавние загрузки", "Recent uploads": "Недавние загрузки",
"Recommended": "Рекомендуемое", "Recommended": "Рекомендуемое",
"Record": "",
"Record Screen": "Запись экрана", "Record Screen": "Запись экрана",
"Record Screen with Audio": "",
"Register": "Регистрация", "Register": "Регистрация",
"Remove category": "Удалить категорию", "Remove category": "Удалить категорию",
"Remove from list": "Удалить из списка", "Remove from list": "Удалить из списка",
"Remove tag": "Удалить тег", "Remove tag": "Удалить тег",
"Remove user": "Удалить пользователя", "Remove user": "Удалить пользователя",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "СОХРАНИТЬ", "SAVE": "СОХРАНИТЬ",
"SEARCH": "ПОИСК", "SEARCH": "ПОИСК",
"SHARE": "ПОДЕЛИТЬСЯ", "SHARE": "ПОДЕЛИТЬСЯ",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Выбрать все медиа", "Select all media": "Выбрать все медиа",
"Select publish state:": "Выберите состояние публикации:", "Select publish state:": "Выберите состояние публикации:",
"Selected": "Выбрано", "Selected": "Выбрано",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Мной поделено", "Shared by me": "Мной поделено",
"Shared with me": "Поделено со мной", "Shared with me": "Поделено со мной",
"Sharing": "",
"Sign in": "Войти", "Sign in": "Войти",
"Sign out": "Выйти", "Sign out": "Выйти",
"Sort By": "Сортировать по", "Sort By": "Сортировать по",
"Start Recording": "Начать запись", "Start Recording": "Начать запись",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Начните загружать медиа и делиться своей работой. Загруженные медиа появятся здесь.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Начните загружать медиа и делиться своей работой. Загруженные медиа появятся здесь.",
"Stop Recording": "Остановить запись", "Stop Recording": "Остановить запись",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Отправить", "Submit": "Отправить",
"Subtitle was added": "Субтитры были добавлены", "Subtitle was added": "Субтитры были добавлены",
"Subtitles": "Субтитры", "Subtitles": "Субтитры",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Комментарии успешно включены", "Successfully Enabled comments": "Комментарии успешно включены",
"Successfully changed owner": "Владелец успешно изменен", "Successfully changed owner": "Владелец успешно изменен",
"Successfully deleted": "Успешно удалено", "Successfully deleted": "Успешно удалено",
"Successfully deleted comments": "",
"Successfully updated": "Успешно обновлено", "Successfully updated": "Успешно обновлено",
"Successfully updated categories": "Категории успешно обновлены", "Successfully updated categories": "Категории успешно обновлены",
"Successfully updated playlist membership": "Членство в плейлисте успешно обновлено", "Successfully updated playlist membership": "Членство в плейлисте успешно обновлено",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Загрузить медиа", "Upload media": "Загрузить медиа",
"Uploads": "Загрузки", "Uploads": "Загрузки",
"Users": "Пользователи", "Users": "Пользователи",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "ПОКАЗАТЬ ВСЕ", "VIEW ALL": "ПОКАЗАТЬ ВСЕ",
"Video": "Видео", "Video": "Видео",
"View all": "Показать все", "View all": "Показать все",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Добро пожаловать", "Welcome": "Добро пожаловать",
"You are going to copy": "Вы собираетесь скопировать", "You are going to copy": "Вы собираетесь скопировать",
"You are going to delete": "Вы собираетесь удалить", "You are going to delete": "Вы собираетесь удалить",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Вы собираетесь отключить комментарии для", "You are going to disable comments to": "Вы собираетесь отключить комментарии для",
"You are going to disable download for": "Вы собираетесь отключить загрузку для", "You are going to disable download for": "Вы собираетесь отключить загрузку для",
"You are going to enable comments to": "Вы собираетесь включить комментарии для", "You are going to enable comments to": "Вы собираетесь включить комментарии для",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "IZBRIŠI MEDIJ", "DELETE MEDIA": "IZBRIŠI MEDIJ",
"DOWNLOAD": "PRENESI", "DOWNLOAD": "PRENESI",
"DURATION": "TRAJANJE", "DURATION": "TRAJANJE",
"Delete Comments": "",
"Delete Media": "Izbriši Medij", "Delete Media": "Izbriši Medij",
"Delete media": "Izbriši medij", "Delete media": "Izbriši medij",
"Disable Comments": "Onemogoči Komentarje", "Disable Comments": "Onemogoči Komentarje",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Spreminjanje lastnika ni uspelo. Prosim poskusite ponovno.", "Failed to change owner. Please try again.": "Spreminjanje lastnika ni uspelo. Prosim poskusite ponovno.",
"Failed to copy media.": "Kopiranje medija ni uspelo.", "Failed to copy media.": "Kopiranje medija ni uspelo.",
"Failed to create playlist": "Ustvarjanje seznama predvajanja ni uspelo", "Failed to create playlist": "Ustvarjanje seznama predvajanja ni uspelo",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Brisanje medija ni uspelo. Prosim poskusite ponovno.", "Failed to delete media. Please try again.": "Brisanje medija ni uspelo. Prosim poskusite ponovno.",
"Failed to disable comments.": "Onemogočanje komentarjev ni uspelo.", "Failed to disable comments.": "Onemogočanje komentarjev ni uspelo.",
"Failed to disable download.": "Onemogočanje prenosa ni uspelo.", "Failed to disable download.": "Onemogočanje prenosa ni uspelo.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Filtriraj obstoječe uporabnike...", "Filter existing users...": "Filtriraj obstoječe uporabnike...",
"Filter playlists...": "Filtriraj sezname predvajanja...", "Filter playlists...": "Filtriraj sezname predvajanja...",
"Filters": "Filtri", "Filters": "Filtri",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Pojdi", "Go": "Pojdi",
"History": "Zgodovina", "History": "Zgodovina",
"Home": "Domov", "Home": "Domov",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Upravljaj komentarje", "Manage comments": "Upravljaj komentarje",
"Manage media": "Upravljaj medije", "Manage media": "Upravljaj medije",
"Manage users": "Upravljaj uporabnike", "Manage users": "Upravljaj uporabnike",
"Management": "",
"Media": "Mediji", "Media": "Mediji",
"Media I own": "Mediji, ki jih posedujam", "Media I own": "Mediji, ki jih posedujam",
"Media was edited": "Medij je bil urejen", "Media was edited": "Medij je bil urejen",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Ni rezultatov za", "No results for": "Ni rezultatov za",
"No tags": "Brez oznak", "No tags": "Brez oznak",
"No users to add": "Ni uporabnikov za dodajanje", "No users to add": "Ni uporabnikov za dodajanje",
"Organization": "",
"PLAYLISTS": "SEZNAMI PREDVAJANJA", "PLAYLISTS": "SEZNAMI PREDVAJANJA",
"PUBLISH STATE": "STANJE OBJAVE", "PUBLISH STATE": "STANJE OBJAVE",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Objavljeno", "Published on": "Objavljeno",
"Recent uploads": "Nedavne naložitve", "Recent uploads": "Nedavne naložitve",
"Recommended": "Priporočeno", "Recommended": "Priporočeno",
"Record": "",
"Record Screen": "Snemanje zaslona", "Record Screen": "Snemanje zaslona",
"Record Screen with Audio": "",
"Register": "Registracija", "Register": "Registracija",
"Remove category": "Odstrani kategorijo", "Remove category": "Odstrani kategorijo",
"Remove from list": "Odstrani s seznama", "Remove from list": "Odstrani s seznama",
"Remove tag": "Odstrani oznako", "Remove tag": "Odstrani oznako",
"Remove user": "Odstrani uporabnika", "Remove user": "Odstrani uporabnika",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "SHRANI", "SAVE": "SHRANI",
"SEARCH": "ISKANJE", "SEARCH": "ISKANJE",
"SHARE": "DELI", "SHARE": "DELI",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Izberi vse medije", "Select all media": "Izberi vse medije",
"Select publish state:": "Izberi stanje objave:", "Select publish state:": "Izberi stanje objave:",
"Selected": "Izbrano", "Selected": "Izbrano",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Deljeno z moje strani", "Shared by me": "Deljeno z moje strani",
"Shared with me": "Deljeno z mano", "Shared with me": "Deljeno z mano",
"Sharing": "",
"Sign in": "Prijava", "Sign in": "Prijava",
"Sign out": "Odjava", "Sign out": "Odjava",
"Sort By": "Razvrsti po", "Sort By": "Razvrsti po",
"Start Recording": "Začni snemanje", "Start Recording": "Začni snemanje",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Začnite nalagati medije in deliti svoje delo. Mediji, ki jih naložite, bodo prikazani tukaj.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Začnite nalagati medije in deliti svoje delo. Mediji, ki jih naložite, bodo prikazani tukaj.",
"Stop Recording": "Ustavi snemanje", "Stop Recording": "Ustavi snemanje",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Pošlji", "Submit": "Pošlji",
"Subtitle was added": "Podnapisi so bili dodani", "Subtitle was added": "Podnapisi so bili dodani",
"Subtitles": "Podnapisi", "Subtitles": "Podnapisi",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Komentarji uspešno omogočeni", "Successfully Enabled comments": "Komentarji uspešno omogočeni",
"Successfully changed owner": "Lastnik uspešno spremenjen", "Successfully changed owner": "Lastnik uspešno spremenjen",
"Successfully deleted": "Uspešno izbrisano", "Successfully deleted": "Uspešno izbrisano",
"Successfully deleted comments": "",
"Successfully updated": "Uspešno posodobljeno", "Successfully updated": "Uspešno posodobljeno",
"Successfully updated categories": "Kategorije uspešno posodobljene", "Successfully updated categories": "Kategorije uspešno posodobljene",
"Successfully updated playlist membership": "Članstvo seznama predvajanja uspešno posodobljeno", "Successfully updated playlist membership": "Članstvo seznama predvajanja uspešno posodobljeno",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Naloži medij", "Upload media": "Naloži medij",
"Uploads": "Naloženi", "Uploads": "Naloženi",
"Users": "Uporabniki", "Users": "Uporabniki",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "PRIKAŽI VSE", "VIEW ALL": "PRIKAŽI VSE",
"Video": "Video", "Video": "Video",
"View all": "Prikaži vse", "View all": "Prikaži vse",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Dobrodošli", "Welcome": "Dobrodošli",
"You are going to copy": "Kopirate", "You are going to copy": "Kopirate",
"You are going to delete": "Brišete", "You are going to delete": "Brišete",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Onemogočate komentarje za", "You are going to disable comments to": "Onemogočate komentarje za",
"You are going to disable download for": "Onemogočate prenos za", "You are going to disable download for": "Onemogočate prenos za",
"You are going to enable comments to": "Omogočate komentarje za", "You are going to enable comments to": "Omogočate komentarje za",
-26
View File
@@ -48,7 +48,6 @@ translation_strings = {
"DELETE MEDIA": "MEDYAYI SİL", "DELETE MEDIA": "MEDYAYI SİL",
"DOWNLOAD": "İNDİR", "DOWNLOAD": "İNDİR",
"DURATION": "SÜRE", "DURATION": "SÜRE",
"Delete Comments": "",
"Delete Media": "Medyayı Sil", "Delete Media": "Medyayı Sil",
"Delete media": "Medyayı sil", "Delete media": "Medyayı sil",
"Disable Comments": "Yorumları Devre Dışı Bırak", "Disable Comments": "Yorumları Devre Dışı Bırak",
@@ -71,7 +70,6 @@ translation_strings = {
"Failed to change owner. Please try again.": "Sahip değiştirilemedi. Lütfen tekrar deneyin.", "Failed to change owner. Please try again.": "Sahip değiştirilemedi. Lütfen tekrar deneyin.",
"Failed to copy media.": "Medya kopyalanamadı.", "Failed to copy media.": "Medya kopyalanamadı.",
"Failed to create playlist": "Çalma listesi oluşturulamadı", "Failed to create playlist": "Çalma listesi oluşturulamadı",
"Failed to delete comments.": "",
"Failed to delete media. Please try again.": "Medya silinemedi. Lütfen tekrar deneyin.", "Failed to delete media. Please try again.": "Medya silinemedi. Lütfen tekrar deneyin.",
"Failed to disable comments.": "Yorumlar devre dışı bırakılamadı.", "Failed to disable comments.": "Yorumlar devre dışı bırakılamadı.",
"Failed to disable download.": "İndirme devre dışı bırakılamadı.", "Failed to disable download.": "İndirme devre dışı bırakılamadı.",
@@ -103,9 +101,6 @@ translation_strings = {
"Filter existing users...": "Mevcut kullanıcıları filtrele...", "Filter existing users...": "Mevcut kullanıcıları filtrele...",
"Filter playlists...": "Çalma listelerini filtrele...", "Filter playlists...": "Çalma listelerini filtrele...",
"Filters": "Filtreler", "Filters": "Filtreler",
"Give users editor permissions to your media by adding them to the below list.": "",
"Give users owner permissions to your media, except for deleting the media, by adding them to the below list.": "",
"Give users viewer permissions to your media by adding them to the below list.": "",
"Go": "Git", "Go": "Git",
"History": "Geçmiş", "History": "Geçmiş",
"Home": "Ana Sayfa", "Home": "Ana Sayfa",
@@ -126,7 +121,6 @@ translation_strings = {
"Manage comments": "Yorumları yönet", "Manage comments": "Yorumları yönet",
"Manage media": "Medyayı yönet", "Manage media": "Medyayı yönet",
"Manage users": "Kullanıcıları yönet", "Manage users": "Kullanıcıları yönet",
"Management": "",
"Media": "Medya", "Media": "Medya",
"Media I own": "Sahip olduğum medya", "Media I own": "Sahip olduğum medya",
"Media was edited": "Medya düzenlendi", "Media was edited": "Medya düzenlendi",
@@ -143,7 +137,6 @@ translation_strings = {
"No results for": "Sonuç bulunamadı", "No results for": "Sonuç bulunamadı",
"No tags": "Etiket yok", "No tags": "Etiket yok",
"No users to add": "Eklenecek kullanıcı yok", "No users to add": "Eklenecek kullanıcı yok",
"Organization": "",
"PLAYLISTS": "ÇALMA LİSTELERİ", "PLAYLISTS": "ÇALMA LİSTELERİ",
"PUBLISH STATE": "YAYINLANMA DURUMU", "PUBLISH STATE": "YAYINLANMA DURUMU",
"Pdf": "PDF", "Pdf": "PDF",
@@ -163,18 +156,12 @@ translation_strings = {
"Published on": "Yayınlanma tarihi", "Published on": "Yayınlanma tarihi",
"Recent uploads": "Son yüklemeler", "Recent uploads": "Son yüklemeler",
"Recommended": "Önerilen", "Recommended": "Önerilen",
"Record": "",
"Record Screen": "Ekranı Kaydet", "Record Screen": "Ekranı Kaydet",
"Record Screen with Audio": "",
"Register": "Kayıt Ol", "Register": "Kayıt Ol",
"Remove category": "Kategoriyi kaldır", "Remove category": "Kategoriyi kaldır",
"Remove from list": "Listeden kaldır", "Remove from list": "Listeden kaldır",
"Remove tag": "Etiketi kaldır", "Remove tag": "Etiketi kaldır",
"Remove user": "Kullanıcıyı kaldır", "Remove user": "Kullanıcıyı kaldır",
"Remove users from the list to remove editor permissions": "",
"Remove users from the list to remove owner permissions": "",
"Remove users from the list to remove viewer permissions": "",
"Replace": "",
"SAVE": "KAYDET", "SAVE": "KAYDET",
"SEARCH": "ARA", "SEARCH": "ARA",
"SHARE": "PAYLAŞ", "SHARE": "PAYLAŞ",
@@ -190,22 +177,14 @@ translation_strings = {
"Select all media": "Tüm medyayı seç", "Select all media": "Tüm medyayı seç",
"Select publish state:": "Yayınlanma durumunu seç:", "Select publish state:": "Yayınlanma durumunu seç:",
"Selected": "Seçildi", "Selected": "Seçildi",
"Settings": "",
"Share with": "",
"Share with Co-Editors": "",
"Share with Co-Owners": "",
"Share with Co-Viewers": "",
"Share with Course Members": "",
"Shared by me": "Paylaştıklarım", "Shared by me": "Paylaştıklarım",
"Shared with me": "Benimle paylaşılanlar", "Shared with me": "Benimle paylaşılanlar",
"Sharing": "",
"Sign in": "Giriş Yap", "Sign in": "Giriş Yap",
"Sign out": "Çıkış Yap", "Sign out": "Çıkış Yap",
"Sort By": "Sırala", "Sort By": "Sırala",
"Start Recording": "Kaydı Başlat", "Start Recording": "Kaydı Başlat",
"Start uploading media and sharing your work. Media that you upload will show up here.": "Medya yüklemeye ve çalışmanızı paylaşmaya başlayın. Yüklediğiniz medya burada görünecektir.", "Start uploading media and sharing your work. Media that you upload will show up here.": "Medya yüklemeye ve çalışmanızı paylaşmaya başlayın. Yüklediğiniz medya burada görünecektir.",
"Stop Recording": "Kaydı Durdur", "Stop Recording": "Kaydı Durdur",
"Students will get viewer permissions, while lecturers will get co-owner permissions (same as owner, but cannot delete the media)": "",
"Submit": "Gönder", "Submit": "Gönder",
"Subtitle was added": "Alt yazı eklendi", "Subtitle was added": "Alt yazı eklendi",
"Subtitles": "Altyazılar", "Subtitles": "Altyazılar",
@@ -216,7 +195,6 @@ translation_strings = {
"Successfully Enabled comments": "Yorumlar başarıyla etkinleştirildi", "Successfully Enabled comments": "Yorumlar başarıyla etkinleştirildi",
"Successfully changed owner": "Sahip başarıyla değiştirildi", "Successfully changed owner": "Sahip başarıyla değiştirildi",
"Successfully deleted": "Başarıyla silindi", "Successfully deleted": "Başarıyla silindi",
"Successfully deleted comments": "",
"Successfully updated": "Başarıyla güncellendi", "Successfully updated": "Başarıyla güncellendi",
"Successfully updated categories": "Kategoriler başarıyla güncellendi", "Successfully updated categories": "Kategoriler başarıyla güncellendi",
"Successfully updated playlist membership": "Çalma listesi üyeliği başarıyla güncellendi", "Successfully updated playlist membership": "Çalma listesi üyeliği başarıyla güncellendi",
@@ -253,9 +231,6 @@ translation_strings = {
"Upload media": "Medya yükle", "Upload media": "Medya yükle",
"Uploads": "Yüklemeler", "Uploads": "Yüklemeler",
"Users": "Kullanıcılar", "Users": "Kullanıcılar",
"Users can edit your media via: My Media > Shared with Me > particular media > Edit...": "",
"Users can manage your media via: My Media > Shared with Me > particular media > ...": "",
"Users can view your media via: My Media > Shared with Me > particular media > ...": "",
"VIEW ALL": "HEPSİNİ GÖR", "VIEW ALL": "HEPSİNİ GÖR",
"Video": "Video", "Video": "Video",
"View all": "Hepsini gör", "View all": "Hepsini gör",
@@ -264,7 +239,6 @@ translation_strings = {
"Welcome": "Hoş geldiniz", "Welcome": "Hoş geldiniz",
"You are going to copy": "Kopyalayacaksınız", "You are going to copy": "Kopyalayacaksınız",
"You are going to delete": "Sileceksiniz", "You are going to delete": "Sileceksiniz",
"You are going to delete all comments from": "",
"You are going to disable comments to": "Yorumları devre dışı bırakacaksınız", "You are going to disable comments to": "Yorumları devre dışı bırakacaksınız",
"You are going to disable download for": "İndirmeyi devre dışı bırakacaksınız", "You are going to disable download for": "İndirmeyi devre dışı bırakacaksınız",
"You are going to enable comments to": "Yorumları etkinleştireceksiniz", "You are going to enable comments to": "Yorumları etkinleştireceksiniz",

Some files were not shown because too many files have changed in this diff Show More