PHPackages                             corbinjurgens/qtrans - 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. corbinjurgens/qtrans

ActiveLibrary

corbinjurgens/qtrans
====================

Improved key translations and chainable html manipulations

v1.0.0-rc1(5y ago)00MITPHP

Since May 1Pushed 5y ago1 watchersCompare

[ Source](https://github.com/corbinjurgens/qtrans)[ Packagist](https://packagist.org/packages/corbinjurgens/qtrans)[ RSS](/packages/corbinjurgens-qtrans/feed)WikiDiscussions master Synced 5d ago

READMEChangelog (2)Dependencies (1)Versions (3)Used By (0)

Introduction
============

[](#introduction)

This package helps you access your key translations (json translations not supported) with some handy features, and allows you to modify how the translation is displayed by chaining 'processors'

Before
------

[](#before)

In cases where your translations in a certain area are all pointing to the same place, its not very DRY to do this

```
{{ __('columns.users.name') }}
{!! nl2br( e( __('columns.users.notes') ) ) !!}
{!! __('columns.users.description') !!}
```

After
-----

[](#after)

Instead of \_\_() or trans(), use \_\_\_() or qtrans() Use "shift" function to declare that all following translations should look in a certain area

You can use qtrans($key) or qtrans()-&gt;get($key), the latter useful for when you want to call other functions before getting the translation.

If in your config 'qtrans.processor' array 'escape' is active, then by default all translations will be escaped unless you manually apply processors by chaining off the translation, or chain clear(). In the below example, the config will be as shipped in the package, with escape processor active

There is no longer any need to switch between {{ }} and {!! !!} blade functions. Always use {{ }} and whether or not the text is escaped will depend on your html processor defaults, or on what processors you manually chain

**Inline shift**

```
{{ qtrans()->shift('columns.users')->get('name') }}
{{ qtrans('notes')->escape()->br() }}
{{ qtrans('description')->clear() }}
```

**Pre-shift**

```
@php(qtrans()->shift('columns.users'))

{{ qtrans('name') }}
{{ qtrans('notes')->escape()->br() }}
{{ qtrans('description')->clear() }}
```

Warning
-------

[](#warning)

QTrans by default escapes translation strings. You can edit this in config qtrans.processor. The intention is that you will not escape translations as generally they should be safe, so I recommend turning off escape default. However if you manually apply HTML processors to a translation and forget escape(), it will not be escaped, even if escape is in the defaults.

Installation
============

[](#installation)

Composer
--------

[](#composer)

`composer require corbinjurgens/qtrans`

Config
------

[](#config)

`php artisan vendor:publish --tag="qtrans-config"`

Manual Installation
-------------------

[](#manual-installation)

Copy the following to main composer.(in the case that the package is added to packages/corbinjurgens/qroute)

```
 "autoload": {
	"psr-4": {
		"Corbinjurgens\\QTrans\\": "packages/corbinjurgens/qtrans/src"
	},
	"files": {
		"packages/corbinjurgens/qtrans/src/helpers.php"
	}
},

```

and run

```
composer dump-autoload

```

Add the following to config/app.php providers

```
Corbinjurgens\QTrans\ServiceProvider::class,

```

Add alias to config/app.php alias

```
"QTrans" => Corbinjurgens\Trans\Facade::class,

```

Usage
=====

[](#usage)

See introduction for basic usage

Multiple Options
----------------

[](#multiple-options)

When shifting, you can pass an array to declare that the translation key can be found in one of muliple places

In the following example, each key eg. 'name' will look to 'forms.signup.name', then if not found 'columns.users.name' to find the translation.

This is my preference for arranging table column translations, have general translations in one area, then translations specific to the current page in another area with only translations given that differ from the general.

```
@php(qtrans()->shift(['forms.signup', 'columns.users']))

{{ qtrans('name') }}
{{ qtrans('email') }}
{{ qtrans('description') }}
```

Give a preference dynamically
-----------------------------

[](#give-a-preference-dynamically)

Your translations may have a set list of places to be found, and the number 1 preference may depend on a variable. In such case use priority function. The given variable should be one that exisst in the given shift array, but it can also be one not in the array.

```
$get_page = request()->query('page', 'columns.users');
$shifts = [
	'signup' => 'forms.signup',
	'manage' => 'columns.users',
];
$page = $shifts[$get_page] ?? 'columns.users';
```

```
@php(qtrans()->shift(['forms.signup', 'columns.users'])->priority($page))

{{ qtrans('name') }}
{{ qtrans('email') }}
{{ qtrans('description') }}
```

Shifting elsewhere, then back
-----------------------------

[](#shifting-elsewhere-then-back)

When shifting a second, third or futher times, the history of you shifts is kept, and you can back out to the previous shift with back()

```
@php(qtrans()->shift(['forms.signup', 'columns.users']))

{{ qtrans('name') }} {{-- forms.signup.name, columns.users.name --}}
{{ qtrans('email') }} {{-- forms.signup.email, columns.users.email --}}
{{ qtrans('description') }} {{-- forms.signup.description, columns.users.description --}}

@php(qtrans()->shift('common'))

{{ qtrans('header') }} {{-- common.header --}}
{{ qtrans('url') }} {{-- common.url --}}

@php(qtrans()->back())

{{ qtrans('address') }} {{-- forms.signup.address, columns.users.address --}}
```

Deeper and deeper
-----------------

[](#deeper-and-deeper)

When shifting, if you pass true as a second variable, the given shift value or values will be an extension of the previous shift. Only possible after the 1st shift

```
@php(qtrans()->shift(['forms.signup', 'columns.users']))

{{ qtrans('name') }} {{-- forms.signup.name, columns.users.name --}}
{{ qtrans('email') }} {{-- forms.signup.email, columns.users.email --}}
{{ qtrans('description') }} {{-- forms.signup.description, columns.users.description --}}

@php(qtrans()->shift('common', true))

{{ qtrans('header') }} {{-- forms.signup.common.header, columns.users.common.header --}}
{{ qtrans('url') }} {{-- forms.signup.common.url, columns.users.common.header --}}

@php(qtrans()->back())

{{ qtrans('address') }} {{-- forms.signup.address, columns.users.address --}}
```

Of course you can give array each shift and it'll follow the following pattern when searching for translation. Actual use cases for this seem rare though.

```
@php(qtrans()->shift(['forms.signup', 'columns.users']))
@php(qtrans()->shift(['common', 'address'], true))
@php(qtrans()->shift(['contact', 'private_contact'], true))

{{ qtrans('cell') }}
```

The key "cell" will be searched for in

```
[
  0 => "forms.signup.common.contact"
  1 => "forms.signup.common.private_contact"
  2 => "forms.signup.address.contact"
  3 => "forms.signup.address.private_contact"
  4 => "columns.users.common.contact"
  5 => "columns.users.common.private_contact"
  6 => "columns.users.address.contact"
  7 => "columns.users.address.private_contact"
]

```

Use current() function to get an array like above showing the current shift levels bases

Reset
-----

[](#reset)

To clear shift history and start a new base, or start an empty base use base()

Temporary pause shift
---------------------

[](#temporary-pause-shift)

Use pause() then later resume() to turn off shift features temporary and look for key raw as with normal translations

```
@php(qtrans()->shift(['forms.signup', 'columns.users']))

@php(qtrans()->pause())
{{ qtrans('user.cell') }} {{ user.cell }}

@php(qtrans()->resume())
{{ qtrans('user.cell') }} {{ forms.signup.user.cell, columns.users.user.cell }}
```

Or use skip() to pause shift feature for the next translation. You can pass a numer to skip if you want to skip a certain numer of times

```
@php(qtrans()->shift(['forms.signup', 'columns.users']))

@php(qtrans()->skip())
{{ qtrans('user.cell') }} {{ user.cell }}

{{ qtrans('user.cell') }} {{ forms.signup.user.cell, columns.users.user.cell }}
```

Html processors
---------------

[](#html-processors)

If the current instance $basic\_setting property is set to false (determined by config 'qtrans.basic'), all returned translation values will be an 'Htmlable' instance. This allows you to chain processors.

**Before**

If you wanted to use the nl2br function and escape, you needed to do something like

```
{!! nl2br( e( __('translation.key') ) ) !!}
```

Which is very messy.

**After**

```
{{ ___('translation.key')->escape()->br() }}
```

Note the order of processors matters. Running br()-&gt;escape() will cause html
 tags to show as plain text

**Available Processors**

- escape(): apply e() to string
- br(): apply nl2br() to string
- markdown(): apply Illuminate\\Mail\\Markdown::parse() to string, which is laravel's built in mail markdown, also useful for html markdown

### Html processor defaults

[](#html-processor-defaults)

To apply a set of default processors to all your translations, modify and add to the config qtrans.processor array.

For example, by default processors is set as

```
'processor' => [
	['escape', [] ],
]
```

This means for the situation `{{ ___('users.name') }}`, the escape processor is applied. BUT if you manually call a processor such as `{{ ___('users.name')->br() }}` escape, or any other processors declared in default wont be used. This is for situations where you want to reorder the processors.

If you dont want to use the default processors for a specific translation but don't have any processors to replace it with call clear() for example `{{ ___('users.name')->clear() }}`. You may also modify the default processors by editing $processor\_setting array property eg `qtrans()->processor_setting = []`

### Custom Processor

[](#custom-processor)

Create a custom processor by calling Corbinjurgens\\QTrans\\Html::custom()

For example, in your AppServiceProvider register function

```
Corbinjurgens\QTrans\Html::custom('upper', function($string){
	return \Str::upper($string)
});
```

```
{{ ___('users.name')->escape()->upper() }}
```

###  Health Score

17

—

LowBetter than 6% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

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 ~0 days

Total

2

Last Release

1840d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/171ca92c9485e447aa4e83d138a01ccd433e377faf2c005fc74fbf036499a2b8?d=identicon)[corbinjurgens](/maintainers/corbinjurgens)

### Embed Badge

![Health badge](/badges/corbinjurgens-qtrans/health.svg)

```
[![Health](https://phpackages.com/badges/corbinjurgens-qtrans/health.svg)](https://phpackages.com/packages/corbinjurgens-qtrans)
```

PHPackages © 2026

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