How to translate Eshops using DeepL

Verze:

25. 09. 2025

Zodpovědná osoba:

Jakub Silný

Poslední aktualizace:

24. 11. 2025, silny2003@gmail.com

DeepL Translation System Guide

This guide explains the full process of transferring translations to the new e-shop. All translation-related functions are located in the ServerPresenter. It also includes instructions on how to properly check and translate the e-shop using DeepL

Prerequisites

IMPORTANT: If the DeepL model is not in the project, add it via Composer:

composer require deeplcom/deepl-php

1. Pre-Translation Preparation

1.1 Transfer Functions

Transfer all translation-related functions from the original project (e.g., Fencee/Dogtrace) to the new project.

1.2 Database Copying

In Zeroadmin, copy the database to the new language mutation (e.g., DE) using the "Kopirovat Data do jine jazykove mutace" form.

1.3 DeepL API Configuration

Verify that the DeepL API key is correctly configured in your settings_config table.

1.4 RouterFactory Configuration

In RouterFactory.php, you need to add locale parameter to each route where locale is used. This ensures proper URL generation for different language mutations.

// Example route configuration
$frontRoutes[] = new Route('//<domain>/<locale cs|en|de|ru|sk>/p-<product_id [0-9]+>[-<product_name>]', [
    'presenter' => 'Homepage',
    'action' => 'product',
    null => [
        Route::FILTER_IN => function (array $params) {
            $params = $this->checkOwnDomain($params);
            $params = $this->checkProductName($params);
            $this->checkLocale($params);
            return $params;
        },
    ],
]);

Note: Make sure to add all language codes that your website supports (e.g., cs, en, de) to the locale parameter in routes.


2. Configuring Supplements for Translation

Review which supplements exist in the database for the CS mutation and uncomment only those that actually exist. You may need to add some manually.

2.1 MenuItem Supplements

In ServerPresenter.php constructor, define the $menuItemXSupplementArray:

$this->menuItemXSupplementArray = [
    // Uncomment gradually in batches of 3-4 supplements
    // MenuRepository::getSupplements()['Nadpis_h1'] => [],
    // MenuRepository::getSupplements()['Perex'] => [
    //     'options' => [TranslateTextOptions::TAG_HANDLING => 'html']
    // ],
    // ...
];

IMPORTANT: Uncomment supplements gradually in batches of 3-4 to translate in smaller chunks.

2.2 Product Supplements

Similar to MenuItem supplements, define the $productXSupplementArray in ServerPresenter.php constructor:

$this->productXSupplementArray = [
    // Uncomment gradually in batches of 3-4 supplements
    // ProductRepository::getSupplements()['Nadpis_h1'] => [],
    // ProductRepository::getSupplements()['Perex'] => [
    //     'options' => [TranslateTextOptions::TAG_HANDLING => 'html']
    // ],
    // ...
];

IMPORTANT:

  • Uncomment supplements in batches of 3-4
  • You'll need to push changes to production multiple times as you uncomment new supplements and comment out completed ones

2.3 Excluded Supplement IDs

Define excluded IDs in the createComponentConvertValues() method. For example, to exclude all headings:

$excludeIds = [1, 4, 26, 31];

These supplements are automatically skipped during replacing operation (prepsat nejake hodnoty jinymi). Add more IDs to this list as needed.

Recommendation: Before trying to batch replace values, identify which supplements to avoid that shouldn't be replaced and add them to the excluded IDs list.


3. Excluded Property IDs

In ServerPresenter.php within the processDeeplTranslateOption() method, define excluded property IDs:

$excludedProperties = [3];

These properties are automatically skipped when translating property values.

Important: Before transferring to a new website, identify which properties contain certain data that should not be translated and add them to the excluded properties list.


4. Local Testing

  • First, try translating everything without using DeepL, just to verify that the system works. You should see products, menu items, supplements—whatever you’re translating—with the word ‘test’ appended to the end of each value. If you see that, you can proceed to the next steps.
  • when you comment out IsProduction() it starts using DeepL so be careful.

4.1 Testing a Single Product

IMPORTANT: Always test on one product before running batch translations!

  1. In ServerPresenter, use the deeplTranslate form to translate existing content (NEVER create new content during translation)
  2. Enter the ID of one product in the "IDs for translating specific products" field (e.g., 123)
  3. Check only "products"
  4. Select source (always CS) and target language
  5. Run the translation
  6. Verify results in the database and frontend

4.2 Testing a Single MenuItem

Follow the same process as for products, but:

  • Enter the MenuItem ID in the "ids" field (e.g., 456)
  • Check only "menu items"

4.3 Verifying Results

After test translation, verify:

  • ✅ Name translation
  • ✅ Content translation (text)
  • ✅ Text contains elements that shouldn't be translated (anchors, etc.) - verify regex is excluding them

5. Batch Translation in Production

Important: Create a BACKUP after each table translation

Ensure you've copied the database from CS language to the target language using "Copy data to another language mutation". Always verify you're translating to the correct language.

5.1 Translation Order

It does not really matter but I recommend to follow this sequence:

  1. Translate basic entities first:
    • Properties
    • Options
  2. Then translate content:
    • Messages/mutations (settings_translations) - WARNING: Verify that JS_IS_ESHOP has an empty value in the new mutation
    • Menu items (menuitems)
    • Products
  3. Next translate supplements:
    • Menu supplements (menu_supplements)
    • Product supplements (product_supplements)
  4. Finally translate order_states, form, form_item, all of that is most of the time translated manually

5.2 Batch Translation Process

  1. Copy Database:
    • Use the copyDb form in ServerPresenter
    • Select source and target language
  2. Translate Individual Parts:
    • Use the deeplTranslate form
    • Leave the "ids" field empty to translate everything
    • For tables with high record counts, translate gradually by specifying individual IDs - typically 100-150 records works well
    • For supplements, uncomment usually 3-4 at a time
    • You'll need to push changes to production multiple times as you uncomment supplements and comment out completed ones
  3. Monitor Progress:
    • Check for errors
    • Monitor logs in log/exception.log

6. Translating Properties and Options

6.1 Translating New Properties

  • Check "properties" to translate properties
  • Check "options" to translate options

6.2 Translating Property Values in Products

Property values in products are automatically translated when translating the product using ProductTranslator->translateProductPropertiesValues().

Note: Properties with IDs in $excludedProperties are not translated.


7. Currency Conversion and Pricing

7.1 Exchange Rate Configuration

In settings_translation for the target language, set:

  • EXCHANGE_RATE - base exchange rate
  • EXCHANGE_RATE_DECREASION - rate reduction (optional)

7.2 Automatic Price Conversion

When translating a product, ProductTranslator->convertPriceByCs() is automatically called, which:

  • Loads the exchange rate from configuration
  • Applies rate reduction (if set)
  • Updates product prices in the target language
  • If you dont set it up during translations it does not matter you can change the price of all producrs later

8. Transferring to a New Website

8.1 Pre-Transfer Checklist

  1. Copy Configurations:
    • menuItemXSupplementArray and productXSupplementArray from ServerPresenter constructor
    • Excluded IDs (supplements and properties)
    • Exchange rates
  2. Copy Code:
    • ServerPresenter.php
    • ProductTranslator.php
    • MenuItemTranslator.php
    • PropertyTranslator.php
    • Languages.php
    • ProductSettings.php
    • MenuItemSettings.php
    • All related classes and utilities
  3. Configure Environment:
    • DeepL API key
    • Language mutations in database
    • IsProduction according to environment (comment out for testing)
  4. Test:
    • Translation of one product
    • Translation of one MenuItem
    • Verify results (including regex for anchors, etc.)
  5. Run Batch Translation:
    • Gradually uncomment supplements in batches of 3-4
    • For large tables, translate in batches of 100-150 records

9. Troubleshooting

9.1 Translation Not Executing or adding just test

  • Verify IsProduction is commented out
  • Check DeepL API key and limit
  • Review logs in log/exception.log

9.2 Some Supplements Not Translating

  • Verify supplements are uncommented in menuItemXSupplementArray / productXSupplementArray
  • Verify supplement ID is not in excluded IDs

9.3 Properties Not Translating

  • Verify property ID is not in $excludedProperties

9.4 Prices Not Converting

  • Verify EXCHANGE_RATE and EXCHANGE_RATE_DECREASION settings in settings_translation
  • Verify convertPriceByCs() is called when translating products
  • If not, you can batch convert all product prices afterward

9.5 Anchors and HTML Elements Being Translated

  • Review regex in text filtering methods
  • Ensure TAG_HANDLING => 'html' is correctly set for HTML content

10. Important Notes

10.1 Transactions

All translations occur within database transactions, so changes are rolled back on error.

10.2 Foreign Keys

When copying the database, foreign keys are temporarily disabled (SET FOREIGN_KEY_CHECKS=0) to prevent errors.

10.3 Gradual Translation

IMPORTANT:

  • For large tables (more than 100-150 records), translate gradually by specifying individual IDs
  • Uncomment supplements gradually in batches of 3-4
  • Push changes to production each time you uncomment supplements

10.4 Local Testing

ALWAYS test locally first with IsProduction commented out and one product/MenuItem before running batch translations!


Best Practices Summary

  • ✅ Always create database backups before major operations
  • ✅ Test with a single item before batch processing
  • ✅ Gradually uncomment supplements in small batches
  • ✅ Monitor logs and verify results at each step
  • ✅ Keep excluded IDs lists up to date
  • ✅ Document any project-specific configurations
  • ✅ Verify exchange rates before price conversions
  • ✅ Use transactions for data safety

Kontaktní osoby

PHP, Nette, VueJS, Javascript, HTML, CSS