Skip to main content

OL Open edX Course Translations

An Open edX plugin to manage course translations.

Purpose

Translate course content into multiple languages to enhance accessibility for a global audience.

Setup

For detailed installation instructions, please refer to the plugin installation guide.

Installation required in:

  • Studio (CMS)

  • LMS

Configuration

  • Add the following configuration values to the config file in Open edX. For any release after Juniper, that config file is /edx/etc/lms.yml and /edx/etc/cms.yml. If you’re using private.py, add these values to lms/envs/private.py and cms/envs/private.py. These should be added to the top level. Ask a fellow developer for these values.

    # Output directory for translated courses
    # Default: /openedx/data/course_translations/
    COURSE_TRANSLATIONS_BASE_DIR: "/openedx/data/course_translations/"
    
    # Relative path (within exported course/course/) for course updates JSON
    # where each item's `content` HTML is translated.
    # Default: info/updates.items.json
    COURSE_TRANSLATIONS_UPDATES_ITEMS_JSON_RELATIVE_PATH: "info/updates.items.json"
    
    # Translation providers configuration
    TRANSLATIONS_PROVIDERS: {
        "default_provider": "mistral",  # Default provider to use
        "openai": {
            "api_key": "<YOUR_OPENAI_API_KEY>",
            "default_model": "gpt-5.2",
        },
        "gemini": {
            "api_key": "<YOUR_GEMINI_API_KEY>",
            "default_model": "gemini-3-pro-preview",
        },
        "mistral": {
            "api_key": "<YOUR_MISTRAL_API_KEY>",
            "default_model": "mistral-large-latest",
        },
    }
    LITE_LLM_REQUEST_TIMEOUT: 300  # Timeout for LLM API requests in seconds
  • For Tutor installations, these values can also be managed through a custom Tutor plugin.

Translation Providers

The plugin supports multiple translation providers:

  • OpenAI (GPT models)

  • Gemini (Google)

  • Mistral

Configuration

All providers are configured through the TRANSLATIONS_PROVIDERS dictionary in your settings:

TRANSLATIONS_PROVIDERS = {
    "default_provider": "mistral",  # Optional: default provider for commands
    "openai": {
        "api_key": "<YOUR_OPENAI_API_KEY>",
        "default_model": "gpt-5.2",  # Optional: used when model not specified
    },
    "gemini": {
        "api_key": "<YOUR_GEMINI_API_KEY>",
        "default_model": "gemini-3-pro-preview",
    },
    "mistral": {
        "api_key": "<YOUR_MISTRAL_API_KEY>",
        "default_model": "mistral-large-latest",
    },
}

Important Notes:

  1. Default Models: The default_model in each provider’s configuration is used when you specify a provider without a model (e.g., openai instead of openai/gpt-5.2).

Provider Selection

You can specify providers in two ways:

  1. Provider only (uses default model from settings):

./manage.py cms translate_course \
    --source-course-id course-v1:TestOrg+Source+Run \
    --target-course-id course-v1:TestOrg+Arabic+Run \
    --target-language ar \
    --content-translation-provider openai \
    --srt-translation-provider gemini
  1. Provider with specific model:

./manage.py cms translate_course \
    --source-course-id course-v1:TestOrg+Source+Run \
    --target-course-id course-v1:TestOrg+Arabic+Run \
    --target-language ar \
    --content-translation-provider openai/gpt-5.2 \
    --srt-translation-provider gemini/gemini-3-pro-preview

Note: If you specify a provider without a model (e.g., openai instead of openai/gpt-5.2), the system will use the default_model configured in TRANSLATIONS_PROVIDERS for that provider.

Translating a Course

The command reads the source course directly from the modulestore, translates its content, and imports the result into the target course. No manual export or TAR file handling is required.

  1. Open the CMS shell.

  2. Run the management command:

    ./manage.py cms translate_course \
        --source-course-id course-v1:TestOrg+Source+Run \
        --target-course-id course-v1:TestOrg+Arabic+Run \
        --source-language en \
        --target-language ar \
        --content-translation-provider openai \
        --srt-translation-provider gemini \
        --translation-validation-provider openai/gpt-5.2 \
        --content-glossary /path/to/content/glossary \
        --srt-glossary /path/to/srt/glossary

    The target course is created automatically if it does not already exist.

Command Options:

  • --source-course-id: Course key of the source course to translate (required). Example: course-v1:Org+Course+Run

  • --target-course-id: Course key of the target course to import translated content into (required). The course is created automatically if it does not exist.

  • --source-language: Source language code (default: en)

  • --target-language: Target language code (required)

  • --content-translation-provider: Translation provider for content (XML/HTML and text) (required).

    Format:

    • PROVIDER - uses provider with default model from settings (e.g., openai, gemini, mistral)

    • PROVIDER/MODEL - uses provider with specific model (e.g., openai/gpt-5.2, gemini/gemini-3-pro-preview, mistral/mistral-large-latest)

  • --srt-translation-provider: Translation provider for SRT subtitles (required). Same format as --content-translation-provider

  • --translation-validation-provider: Optional provider to validate/fix XML/HTML translations after translation.

  • --content-glossary: Path to glossary directory for content (XML/HTML and text) translation (optional)

  • --srt-glossary: Path to glossary directory for SRT subtitle translation (optional)

  • --batch-size: Number of translation tasks to run concurrently per batch (optional, default: 20). SRT tasks are still forced to a batch size of 1 when using the Mistral provider, regardless of this setting.

The command also translates course/info/updates.items.json (or the path configured in COURSE_TRANSLATIONS_UPDATES_ITEMS_JSON_RELATIVE_PATH) by translating each update item’s content field as HTML.

Examples:

# Use OpenAI and Gemini with default models from settings
./manage.py cms translate_course \
    --source-course-id course-v1:MyOrg+EnglishCourse+2024 \
    --target-course-id course-v1:MyOrg+FrenchCourse+2024 \
    --target-language fr \
    --content-translation-provider openai \
    --srt-translation-provider gemini

# Use OpenAI with specific model for content, Gemini with default for subtitles
./manage.py cms translate_course \
    --source-course-id course-v1:MyOrg+EnglishCourse+2024 \
    --target-course-id course-v1:MyOrg+FrenchCourse+2024 \
    --target-language fr \
    --content-translation-provider openai/gpt-5.2 \
    --srt-translation-provider gemini

# Use Mistral with specific model and separate glossaries for content and SRT
./manage.py cms translate_course \
    --source-course-id course-v1:MyOrg+EnglishCourse+2024 \
    --target-course-id course-v1:MyOrg+SpanishCourse+2024 \
    --target-language es \
    --content-translation-provider mistral/mistral-large-latest \
    --srt-translation-provider mistral/mistral-large-latest \
    --content-glossary /path/to/content/glossary \
    --srt-glossary /path/to/srt/glossary

# Use different glossaries for content vs subtitles
./manage.py cms translate_course \
    --source-course-id course-v1:MyOrg+EnglishCourse+2024 \
    --target-course-id course-v1:MyOrg+SpanishCourse+2024 \
    --target-language es \
    --content-translation-provider openai \
    --srt-translation-provider gemini \
    --content-glossary /path/to/technical/glossary \
    --srt-glossary /path/to/conversational/glossary

Glossary Support:

You can use separate glossaries for content and subtitle translation. This allows you to apply different terminology choices based on context:

  • Content glossary (--content-glossary): Used for XML/HTML content, policy files, info/updates.items.json HTML content, and text-based course materials. Typically contains more formal or technical terminology.

  • SRT glossary (--srt-glossary): Used for subtitle translation. Can contain more conversational or context-specific terms appropriate for spoken content.

Create language-specific glossary files in each glossary directory:

# Content glossary structure
glossaries/technical/
├── ar.txt  # Arabic glossary
├── fr.txt  # French glossary
└── es.txt  # Spanish glossary

# SRT glossary structure
glossaries/conversational/
├── ar.txt  # Arabic glossary
├── fr.txt  # French glossary
└── es.txt  # Spanish glossary

Format: One term per line as “source_term : translated_term”

# es HINTS
## TERM MAPPINGS
These are preferred terminology choices for this language. Use them whenever they sound natural; adapt freely if context requires.

- 'accuracy' : 'exactitud'
- 'activation function' : 'función de activación'
- 'artificial intelligence' : 'inteligencia artificial'
- 'AUC' : 'AUC'

Note: Both glossary arguments are optional. If not provided, translation will proceed without glossary terms. You can provide one, both, or neither glossary as needed.

Subtitle Translation and Validation

The course translation system includes robust subtitle (SRT) translation with automatic validation and retry mechanisms to ensure high-quality translations with preserved timing information.

Translation Process

The subtitle translation follows a multi-stage process with built-in quality checks:

  1. Initial Translation: Subtitles are translated using your configured provider

  2. Validation: Timestamps, subtitle count, and content are validated to ensure integrity

  3. Automatic Retry: If validation fails, the system automatically retries translation (up to 1 additional attempt)

  4. Task Failure: If all retries fail validation, the translation task fails to prevent corrupted subtitle files

Validation Rules

The system validates subtitle translations against these criteria:

  • Subtitle Count: Translated file must have the same number of subtitle blocks as the original

  • Index Matching: Each subtitle block index must match the original (e.g., if original has blocks 1-100, translation must have blocks 1-100 in the same order)

  • Timestamp Preservation: Start and end times for each subtitle block must remain unchanged

  • Content Validation: Non-empty original subtitles must have non-empty translations (blank translations are flagged as errors)

Example Validation Process:

1. Initial Translation (using OpenAI):
   ✓ 150 subtitle blocks translated
   ✗ Validation failed: 3 blocks have mismatched timestamps

2. Retry Attempt:
   ✓ 150 subtitle blocks translated
   ✗ Validation failed: 2 blocks still have issues

3. Task Failure:
   ❌ Translation failed after all retries
   ❌ Task aborted to prevent corrupted subtitle files

Failure Handling

If subtitle translation fails after all attempts:

  • The translation task will fail with a ValueError

  • The entire course translation will be aborted to prevent incomplete translations

  • The translated course directory will be automatically cleaned up

  • An error message will indicate which subtitle file caused the failure

  • No partial or corrupted translation files will be left behind

License

The code in this repository is licensed under the AGPL 3.0 unless otherwise noted.

Please see LICENSE.txt for details.

Metadata

Release files for ol-openedx-course-translations 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ol-openedx-course-translations 0.9.0
File Size Uploaded
ol_openedx_course_translations-0.9.0.tar.gz 41.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ol-openedx-course-translations 0.9.0
File Interpreter ABI Platform
ol_openedx_course_translations-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 91.4 kB

Release files / ol_openedx_course_translations-0.9.0.tar.gz

Download URL ol_openedx_course_translations-0.9.0.tar.gz
Size 41.8 kB
Tags Source
SHA-256 checksum
How to use checksums
aa611ef8ee1561945e66132006c5ec915e3ab5807add1015a1fdeed268ee41c8
BLAKE2b-256 checksum
How to use checksums
704c3318c30279e373bd4312d9afdefe5c8481d1be6719e15be15d7e64744838
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / ol_openedx_course_translations-0.9.0-py3-none-any.whl

Download URL ol_openedx_course_translations-0.9.0-py3-none-any.whl
Size 49.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b271958649d9cc300b7dd6f72942cb4633b9467a5bdf044227dae20b7d437cfe
BLAKE2b-256 checksum
How to use checksums
f0128b28574924120df2c1f97cf2f54d99cdbc96804eca34414e1b33dbb59ee3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

0.12.1

2 release files

0.9.1

2 release files

This release

0.9.0 This release

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.21

2 release files

0.3.17

2 release files

0.3.16

2 release files

0.3.15

2 release files

0.3.14

2 release files

0.3.13

2 release files

0.3.12

2 release files

0.3.11

2 release files

0.3.10

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page