PHPackages                             wazza/dom-translate - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. wazza/dom-translate

ActiveLibrary[Templating &amp; Views](/categories/templating)

wazza/dom-translate
===================

A Laravel Package that will use the build-in Blade Directive to define specific phrases for auto-translation before being rendered to the screen.

v2.5.0(1mo ago)5977↓62.5%1MITPHPPHP ^8.2

Since Jul 26Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/wazzac/laravel-translate)[ Packagist](https://packagist.org/packages/wazza/dom-translate)[ Docs](https://www.wazzac.dev)[ RSS](/packages/wazza-dom-translate/feed)WikiDiscussions main Synced today

READMEChangelog (10)Dependencies (17)Versions (21)Used By (0)

 [![Version](https://camo.githubusercontent.com/e319a0e18594384ccb062ef0f2290b874243b9c001d6792fe856a11591073498/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f77617a7a61632f6c61726176656c2d7472616e736c6174653f6c6162656c3d76657273696f6e26736f72743d73656d766572)](https://github.com/wazzac/laravel-translate/releases) [![Tests](https://camo.githubusercontent.com/d940ad7f0752e2cbe0d63c50dcebf329078807390051c41fe63258f1b5c4e182/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d70617373696e672d627269676874677265656e)](https://github.com/wazzac/laravel-translate/actions) [![Laravel](https://camo.githubusercontent.com/9fd685955dc72c634ae58db0e59befe78a818f5a6065d8caef21376c8cbad11b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322e782d7265643f6c6f676f3d6c61726176656c)](https://camo.githubusercontent.com/9fd685955dc72c634ae58db0e59befe78a818f5a6065d8caef21376c8cbad11b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322e782d7265643f6c6f676f3d6c61726176656c) [![PHP](https://camo.githubusercontent.com/d939ed2787af03e76ef8d8b6cd0ffa17e5da11b7772994ae6ac95f50cb146d5f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d626c75653f6c6f676f3d706870)](https://camo.githubusercontent.com/d939ed2787af03e76ef8d8b6cd0ffa17e5da11b7772994ae6ac95f50cb146d5f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d626c75653f6c6f676f3d706870) [![License](https://camo.githubusercontent.com/dab9c52d31f6b5f9dfadfd9a3e6ed69d5f30de34bdcb5a7106ff0932cd5e1f11/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f77617a7a61632f6c61726176656c2d7472616e736c617465)](https://github.com/wazzac/laravel-translate/blob/main/LICENSE) [![Issues](https://camo.githubusercontent.com/e44246a8036150b6301b6ac36593a69f704a11cdd6277ea2e87de577cf148006/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f77617a7a61632f6c61726176656c2d7472616e736c617465)](https://github.com/wazzac/laravel-translate/issues) [![Buy me a coffee](https://camo.githubusercontent.com/13e63865d501f276dcf7b89a7da0341df09da2403900558af748f40e11655d1b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4275792532306d6525323061253230636f666665652de298952d79656c6c6f773f7374796c653d666c6174266c6f676f3d6275792d6d652d612d636f66666565)](https://coff.ee/wazzac)

Laravel Translate Package
=========================

[](#laravel-translate-package)

A Laravel package that uses Blade directives to provide real-time translations for any phrase in your views — backed by a smart caching layer (session → database → cloud API) to minimise API calls and costs.

*Write your Blade templates in English, serve every visitor in their own language — automatically.*

---

Table of Contents
-----------------

[](#table-of-contents)

- [How it Works](#how-it-works)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Translation Providers](#translation-providers)
    - [Google Cloud Translation](#google-cloud-translation-setup)
    - [Bing / Azure Cognitive Translator](#bing--azure-cognitive-translator-setup)
- [Blade Directives](#blade-directives)
- [Auto-Translation (`@transl8auto`)](#auto-translation-transl8auto)
- [Language Preference API Routes](#language-preference-api-routes)
- [SetLocale Middleware](#setlocale-middleware)
- [Using the Helper Directly](#using-the-helper-directly)
- [Upgrading to v2.5](#upgrading-to-v25)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)

---

How it Works
------------

[](#how-it-works)

Three database tables (`domt_languages`, `domt_phrases`, `domt_translations`) power a three-level cache:

1. **Session** *(fastest)* — if `DOM_TRANSLATE_USE_SESSION=true`, translations are stored in the user's session after the first retrieval.
2. **Database** *(fast)* — if `DOM_TRANSLATE_USE_DATABASE=true` *(default)*, translations are stored and retrieved from the DB. Each phrase is hashed (SHA-256 HMAC) and stored in an indexed column for sub-millisecond lookups.
3. **Cloud API** *(fallback)* — only when no cached translation exists. The result is immediately stored in the DB (and session) to prevent future API calls.

> Laravel caches compiled Blade views, so unchanged pages make zero database or API calls after the first render.

---

Requirements
------------

[](#requirements)

RequirementVersionPHP**^8.2**Laravel**^12.0**GuzzleHTTP`^7.8` (auto-installed)Cloud API keyGoogle *or* Bing (at least one)---

Installation
------------

[](#installation)

```
composer require wazza/dom-translate
```

Publish the config and migrations, then run the migrations:

```
php artisan vendor:publish --tag="dom-translate-config"
php artisan vendor:publish --tag="dom-translate-migrations"
php artisan migrate
```

Add your API key(s) to `.env`:

```
DOM_TRANSLATE_GOOGLE_KEY=your_google_key_here
# or
DOM_TRANSLATE_BING_KEY=your_bing_key_here
DOM_TRANSLATE_PROVIDER=bing
```

Clear config cache:

```
php artisan config:clear
```

> **Auto-discovery:** The service provider is auto-discovered. No manual registration is needed in `bootstrap/providers.php` unless you have disabled package discovery.

---

Configuration
-------------

[](#configuration)

After publishing, the config file is at `config/dom_translate.php`. All settings are also controllable via `.env`:

```
# Caching layers
DOM_TRANSLATE_USE_SESSION=false         # Cache translations in the user's session
DOM_TRANSLATE_USE_DATABASE=true         # Cache translations in the database (recommended)

# Translation provider
DOM_TRANSLATE_PROVIDER=google           # 'google' or 'bing'
DOM_TRANSLATE_GOOGLE_KEY=               # Google Cloud Translation API v2 key
DOM_TRANSLATE_BING_KEY=                 # Azure Cognitive Services subscription key

# Languages
DOM_TRANSLATE_LANG_SRC=en              # Default source language (ISO 639-1)
DOM_TRANSLATE_LANG_DEST=af             # Default destination language (ISO 639-1)

# Phrase hashing
DOM_TRANSLATE_HASH_SALT=DzBQ2DxKhNaF  # Change this — used in HMAC hash
DOM_TRANSLATE_HASH_ALGO=sha256

# Logging (0=off, 1=high, 2=mid, 3=verbose)
DOM_TRANSLATE_LOG_LEVEL=1
DOM_TRANSLATE_LOG_INDICATOR=dom-translate

# Language preference routes
DOM_TRANSLATE_ROUTES_ENABLED=true
DOM_TRANSLATE_ROUTES_PREFIX=api/translate
DOM_TRANSLATE_ROUTES_MIDDLEWARE=web

# Session/cookie key for language preference
DOM_TRANSLATE_SESSION_KEY=app_language_code

# SetLocale middleware
DOM_TRANSLATE_MIDDLEWARE_ENABLED=true
DOM_TRANSLATE_MIDDLEWARE_AUTO_APPLY=true
```

> **Security note:** Change `DOM_TRANSLATE_HASH_SALT` to a unique value per application. Do not reuse the default across projects.

---

Translation Providers
---------------------

[](#translation-providers)

### Google Cloud Translation Setup

[](#google-cloud-translation-setup)

1. Visit [Google Cloud Console](https://console.cloud.google.com/) and create a project.
2. Enable **Cloud Translation API** under *APIs &amp; Services → Library*.
3. Create an API key under *APIs &amp; Services → Credentials*.
4. Restrict the key to **Cloud Translation API** to limit exposure.
5. Add to `.env`: ```
    DOM_TRANSLATE_PROVIDER=google
    DOM_TRANSLATE_GOOGLE_KEY=your_key_here
    ```

**Free tier:** 500,000 characters/month. Billing account required even for free tier.

**Test with curl:**

```
curl -X POST \
  "https://www.googleapis.com/language/translate/v2?key=YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"Hello world","target":"fr","source":"en"}'
```

---

### Bing / Azure Cognitive Translator Setup

[](#bing--azure-cognitive-translator-setup)

1. Sign in to the [Azure Portal](https://portal.azure.com/).
2. Create a **Cognitive Services** resource (or a dedicated **Translator** resource).
3. Copy one of the subscription keys from *Keys and Endpoint*.
4. Add to `.env`: ```
    DOM_TRANSLATE_PROVIDER=bing
    DOM_TRANSLATE_BING_KEY=your_azure_key_here
    ```

**Free tier:** 2,000,000 characters/month (F0 tier).

---

Blade Directives
----------------

[](#blade-directives)

### `@transl8(phrase[, dest[, src]])`

[](#transl8phrase-dest-src)

The primary directive. Translates a phrase to the destination language.

```
{{-- Use config defaults for src/dest languages --}}
@transl8("I like this feature.")

{{-- Specify destination --}}
@transl8("We need to test it in staging.", "de")

{{-- Specify both source and destination --}}
@transl8("Wie weet waar Willem Wouter woon?", "en", "af")
```

### Language-Specific Shortcuts

[](#language-specific-shortcuts)

Pre-registered directives for common languages:

```
@transl8fr("Translated to French")
@transl8de("Translated to German")
@transl8nl("Translated to Dutch")
@transl8es("Translated to Spanish")
@transl8it("Translated to Italian")
@transl8pt("Translated to Portuguese")
@transl8ru("Translated to Russian")
@transl8zhcn("Translated to Chinese Simplified")
@transl8zhtw("Translated to Chinese Traditional")
@transl8af("Translated to Afrikaans")
@transl8ar("Translated to Arabic")
```

**Adding more languages** in your `AppServiceProvider::register()`:

```
use Wazza\DomTranslate\Controllers\TranslateController;

Blade::directive('transl8ja', function ($string) {
    return "";
});
```

### `@transl8auto(phrase)`

[](#transl8autophrase)

Translates to whatever language is stored in the user's session or cookie. See [Auto-Translation](#auto-translation-transl8auto) below.

```
@transl8auto("Welcome to our website!")
@transl8auto("This content adapts to the visitor's preferred language.")
```

---

Auto-Translation (`@transl8auto`)
---------------------------------

[](#auto-translation-transl8auto)

`@transl8auto` is the most powerful directive. It reads the user's language preference (set via a language switcher) and translates accordingly — no per-phrase language specification needed.

### Language priority order

[](#language-priority-order)

1. **Session** — `session('app_language_code')`
2. **Cookie** — `cookie('app_language_code')`
3. **Config default** — `dom_translate.language.dest`
4. **App locale** — `config('app.locale')`
5. **English** — final fallback

### Building a language switcher

[](#building-a-language-switcher)

**1. Add a selector to your layout:**

```

    English
    Français
    Deutsch
    Español
    Nederlands
    Afrikaans

```

**2. Wire it up with JavaScript:**

```
const selector = document.getElementById('languageSelector');

// Restore current preference on load
fetch('/api/translate/get-language')
    .then(r => r.json())
    .then(data => { selector.value = data.language; });

// Persist change and reload
selector.addEventListener('change', async function () {
    await fetch('/api/translate/set-language', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
        },
        body: JSON.stringify({ language: this.value })
    });
    window.location.reload();
});
```

### Vue 3 Component Example

[](#vue-3-component-example)

```

    English
    Français
    Deutsch
    Español

import { ref, onMounted } from 'vue'
import axios from 'axios'

const language = ref('en')

onMounted(async () => {
    const { data } = await axios.get('/api/translate/get-language')
    language.value = data.language
})

async function switchLanguage() {
    await axios.post('/api/translate/set-language', { language: language.value })
    window.location.reload()
}

```

---

Language Preference API Routes
------------------------------

[](#language-preference-api-routes)

Enabled by default. Can be disabled with `DOM_TRANSLATE_ROUTES_ENABLED=false`.

### `POST /api/translate/set-language`

[](#post-apitranslateset-language)

```
POST /api/translate/set-language
Content-Type: application/json

{ "language": "fr" }
```

Response:

```
{
    "message": "Language preference set successfully.",
    "language": "fr"
}
```

Also sets a 1-year, `httpOnly` cookie with the preference.

### `GET /api/translate/get-language`

[](#get-apitranslateget-language)

```
GET /api/translate/get-language
```

Response:

```
{ "language": "fr" }
```

### Disable routes and roll your own

[](#disable-routes-and-roll-your-own)

```
DOM_TRANSLATE_ROUTES_ENABLED=false
```

```
use Wazza\DomTranslate\Helpers\TranslateHelper;

class LanguageController extends Controller
{
    public function set(Request $request)
    {
        $request->validate(['language' => 'required|string|min:2|max:5']);
        return TranslateHelper::setLanguage($request->input('language'));
    }

    public function get()
    {
        return TranslateHelper::getLanguage();
    }
}
```

---

SetLocale Middleware
--------------------

[](#setlocale-middleware)

`SetLocaleMiddleware` automatically syncs Laravel's application locale — and Carbon's locale — to the user's language preference on every request.

This ensures `__()`, `trans()`, `@lang`, validation messages, and Carbon date formatting all use the same language as the translate directives.

**Enabled by default.** To disable:

```
DOM_TRANSLATE_MIDDLEWARE_ENABLED=false
```

To keep the middleware but not auto-apply it to the `web` group:

```
DOM_TRANSLATE_MIDDLEWARE_AUTO_APPLY=false
```

Then apply it manually where needed:

```
// routes/web.php
Route::middleware(['web', 'dom-translate.locale'])->group(function () {
    // your routes
});
```

---

Using the Helper Directly
-------------------------

[](#using-the-helper-directly)

`TranslateHelper` and `PhraseHelper` are also available for use in controllers, jobs, or anywhere outside Blade:

```
use Wazza\DomTranslate\Helpers\TranslateHelper;
use Wazza\DomTranslate\Controllers\TranslateController;

// Translate directly
$translated = app(TranslateController::class)->translate('Hello world', 'fr', 'en');

// Auto-translate using current user's preference
$translated = TranslateHelper::autoTransl8('Hello world');

// Get current user's language code
$lang = TranslateHelper::currentDefinedLanguageCode();

// Set language preference (returns JsonResponse with cookie)
return TranslateHelper::setLanguage('de');
```

---

Upgrading to v2.5
-----------------

[](#upgrading-to-v25)

If you are upgrading from v2.4.x:

1. **Re-publish migrations** — the migration files have been updated to anonymous class syntax (required by Laravel 12). If you have already run the old migrations, no action is needed for existing databases. For fresh installs, re-publish:

    ```
    php artisan vendor:publish --tag="dom-translate-migrations" --force
    php artisan migrate
    ```
2. **No breaking changes** — all Blade directives, config keys, and `.env` variables remain identical.
3. **BingTranslate is now implemented** — if you set `DOM_TRANSLATE_PROVIDER=bing` in your `.env`, it will now work with the Azure Cognitive Translator v3 API.
4. **Cookie security** — the language preference cookie is now `httpOnly=true` (XSS protection). This is transparent to your application.
5. **`DOM_TRANSLATE_HASH_SALT`** — if you are using a custom salt, ensure it remains set in your `.env` to preserve existing hash lookups in the database.

---

Troubleshooting
---------------

[](#troubleshooting)

### `E_STRICT` deprecation warnings during `composer install`

[](#e_strict-deprecation-warnings-during-composer-install)

```
Deprecation Notice: Constant E_STRICT is deprecated in /usr/share/php/Composer/Util/Silencer.php

```

This is **not** caused by this package. It is caused by an outdated system-level Composer installation (typically `/usr/share/php/Composer/`). Update your server's Composer:

```
sudo composer self-update
# or, on Debian/Ubuntu:
sudo apt-get install --only-upgrade composer
```

### Translations not showing / returning original phrase

[](#translations-not-showing--returning-original-phrase)

1. Check your API key is set: `DOM_TRANSLATE_GOOGLE_KEY` or `DOM_TRANSLATE_BING_KEY`.
2. Check `DOM_TRANSLATE_LOG_LEVEL=3` and review Laravel's log for API errors.
3. Ensure the destination language code (`DOM_TRANSLATE_LANG_DEST`) exists in the `domt_languages` table.
4. Clear config and view cache: ```
    php artisan config:clear
    php artisan view:clear
    ```

### `MissingAppKeyException` in tests

[](#missingappkeyexception-in-tests)

Ensure `APP_KEY` is set in `phpunit.xml` or your `.env.testing`. The package's test suite sets a dummy key automatically for its own tests.

### Language not persisting between requests

[](#language-not-persisting-between-requests)

Ensure `DOM_TRANSLATE_USE_SESSION=true` or that cookies are being sent with requests. For AJAX requests, verify the `X-CSRF-TOKEN` header is included in `POST` calls.

---

Contributing
------------

[](#contributing)

Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. For security vulnerabilities, see [SECURITY.md](SECURITY.md).

---

Made with ☕ by [Warren Coetzee](https://www.wazzac.dev)

###  Health Score

54

—

FairBetter than 96% of packages

Maintenance92

Actively maintained with recent releases

Popularity23

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 93.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~98 days

Recently: every ~168 days

Total

19

Last Release

38d ago

Major Versions

v0.7 → v1.0.0-beta2021-08-22

v1.2.0 → v2.0-BETA2023-10-25

PHP version history (5 changes)v0.2PHP ^7.2.5|^8.0

v2.0-BETAPHP ^8.0

v2.0PHP ^8.1

v2.3.0PHP ^8.2 || ^8.3

v2.5.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/92689bb54f2bafcddf15e9566e22ddc326a3c985e6c6b3f1ac23c8241178e3ba?d=identicon)[wazza](/maintainers/wazza)

---

Top Contributors

[![wazzac](https://avatars.githubusercontent.com/u/5511358?v=4)](https://github.com/wazzac "wazzac (108 commits)")[![Warrengit](https://avatars.githubusercontent.com/u/96111698?v=4)](https://github.com/Warrengit "Warrengit (6 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (1 commits)")

---

Tags

auto-translatedom-manipulationdom-translategoogle-translate-apihtml-translateinternationalizationlaravellaravel-bladelaravel-blade-directivelaravel10xlocalizationmanage-translationsmulti-language-supportpage-translationphp8translate-bladetranslate-domtranslate-phrasestranslate-websitetranslationlaravelpackagetranslationbladeblade-translate

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/wazza-dom-translate/health.svg)

```
[![Health](https://phpackages.com/badges/wazza-dom-translate/health.svg)](https://phpackages.com/packages/wazza-dom-translate)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.1k](/packages/craftcms-cms)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M131](/packages/roots-acorn)[hasinhayder/tyro-dashboard

Tyro Dashboard - Beautiful admin dashboard for managing Tyro roles, privileges, users, and settings

5443.8k](/packages/hasinhayder-tyro-dashboard)[technikermathe/blade-lucide-icons

A package to easily make use of Lucide icons in your Laravel Blade views.

18421.4k11](/packages/technikermathe-blade-lucide-icons)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5021.9k](/packages/simplestats-io-laravel-client)[hasinhayder/tyro-login

Tyro Login - Beautiful, customizable authentication views for Laravel 12 &amp; 13

2464.9k6](/packages/hasinhayder-tyro-login)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
