i18n Translations Management System Development

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815

Translation Management System (i18n) Development

A translation management system is essential for multilingual sites where translation text needs to be regularly added and updated across multiple languages without editing code or JSON files manually. Translators work in a convenient interface, developers add new keys through code.

Translation Storage Options

File-based approach (Laravel lang, i18next) — translations in PHP/JSON files. Drawbacks: editing requires file system access, no change history, difficult for non-technical translators.

Database approach — translations in DB. Editors work through UI, change history available, ability to translate without deploy. This is the recommended approach for teams with translators.

Hybrid — translations in files as fallback, override via DB.

Data Model

translation_keys (
  id, key,          -- 'checkout.button.pay', 'nav.home'
  namespace,        -- 'frontend', 'emails', 'admin'
  description,      -- hint for translator
  created_at
)

translations (
  id, key_id, locale,
  value,            -- translated text
  status: pending | approved | needs_review,
  translated_by, approved_by,
  created_at, updated_at
)

translation_change_log (
  id, translation_id, old_value, new_value, changed_by, changed_at
)

Collection of Untranslated Keys

Code uses keys via __() or t(). Artisan command scans code and adds new keys to DB:

class ScanTranslationKeys extends Command
{
    public function handle(): void
    {
        $files = File::allFiles(resource_path('views'))
            ->merge(File::allFiles(resource_path('js')));

        $keys = [];
        foreach ($files as $file) {
            $content = File::get($file);
            preg_match_all("/__\('([^']+)'\)/", $content, $matches);
            preg_match_all("/t\('([^']+)'\)/", $content, $jsMatches);
            $keys = array_merge($keys, $matches[1], $jsMatches[1]);
        }

        $unique = array_unique($keys);
        $existing = TranslationKey::pluck('key')->toArray();
        $new = array_diff($unique, $existing);

        foreach ($new as $key) {
            TranslationKey::create(['key' => $key, 'namespace' => $this->guessNamespace($key)]);
        }

        $this->info("Found new keys: " . count($new));
    }
}

Translator Interface

Main screen — table with filters:

Filters Columns
Namespace Key
Language Original (ru)
Status Current translation
Search by key/text Action: edit

Edit form — inline in table or side panel. Next to translation field — original text in base language. "Machine Translation" button makes request to DeepL or Google Translate API for draft.

Machine Translation API

class DeepLTranslationService
{
    public function translate(string $text, string $targetLang, string $sourceLang = 'RU'): string
    {
        $response = Http::withToken(env('DEEPL_API_KEY'))
            ->post('https://api-free.deepl.com/v2/translate', [
                'text'        => [$text],
                'target_lang' => strtoupper($targetLang),
                'source_lang' => $sourceLang
            ]);

        return $response->json('translations.0.text');
    }
}

Translation Caching

Translations from DB cached in Redis. On change — invalidate only affected namespace:

class Translation extends Model
{
    protected static function booted(): void
    {
        static::saved(fn($t) => Cache::forget("translations:{$t->locale}:{$t->key->namespace}"));
    }
}

Export/Import for Translation Agencies

For working with agencies — export to XLIFF (standard format for CAT tools) or Excel:

// Export untranslated keys to Excel
$untranslated = TranslationKey::whereDoesntHave('translations', fn($q) =>
    $q->where('locale', $targetLocale)
)->get();

$export = $untranslated->map(fn($key) => [
    'key'      => $key->key,
    'source'   => $key->translations->where('locale', 'ru')->first()?->value,
    'target'   => ''
]);

return Excel::download(new TranslationsExport($export), 'translations.xlsx');

Adding New Language Process

  1. Add locale to config/app.php and run php artisan translations:scan
  2. In translator interface select new language — all untranslated keys shown
  3. Translate manually or via machine translation → review → approve
  4. Enable language in site's language switcher

Development timeline: 4–6 weeks for full system with translator interface, machine translation, change history, and export/import.