Search by

chevere / translate

rodolfo

A chevere translate component.

Package info

github.com/chevere/translate

Homepage

pkg:composer/chevere/translate

Statistics

Installs: 14

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-10-20 21:27 UTC

This package is auto-updated.

Last update: 2026-10-20 21:33:00 UTC


README

Chevere

Build Code size Apache-2.0 PHPStan Mutation testing badge

Quality Gate Status Maintainability Rating Reliability Rating Security Rating Coverage Technical Debt CodeFactor

Summary

Translator is built on top of gettext and it provides a set of tools to manage translations in PHP applications.

Installing

Translate is available through Packagist and the repository source is at chevere/translate.

composer require chevere/translate

Quick Start

Mark translatable strings in your code using the translation functions.

// /app/src/hello.php
use function Chevere\Translate\__;

echo __('Hello, world!');

Extract the strings into a .po file, translate it, compile it to PHP and load it at runtime.

use Chevere\Translate\PoMaker;
use Chevere\Translate\TranslatorBuilder;
use Chevere\Translate\TranslatorInstance;
use Chevere\Translate\TranslatorLoader;
use function Chevere\Filesystem\directoryForPath;

$source = directoryForPath('/app/src/');
$locales = directoryForPath('/app/locales/');
$compiled = directoryForPath('/app/compiled/');

// 1. Scan source and create /app/locales/es-CL/messages.po
(new PoMaker('es-CL', 'messages'))
    ->withScanFor($source)
    ->make($locales);

// 2. Translate messages.po using any PO editor

// 3. Compile to /app/compiled/es-CL/messages.php
(new TranslatorBuilder($locales, $compiled))
    ->withBuild('es-CL', 'messages');

// 4. Load the translator and register it
$translator = (new TranslatorLoader())
    ->withLoad($compiled, 'es-CL', 'messages')
    ->translator();
new TranslatorInstance($translator);

echo __('Hello, world!');
// ¡Hola, mundo!

Steps 1 to 3 are build-time tasks, only step 4 is needed at runtime.

When using a domain files are stored at {directory}/{locale}/{domain}. Pass an empty domain to store files at {directory}/{locale} instead.

Domain PO file PHP file
'messages' /app/locales/es-CL/messages.po /app/compiled/es-CL/messages.php
'' /app/locales/es-CL.po /app/compiled/es-CL.php

PoMaker

PoMaker scans .php and .js files for translatable strings and generates a PO file for a given locale.

Create PoMaker

Pass the locale and optionally the domain. Use writer to log the scan progress (defaults to NullWriter).

use Chevere\Translate\PoMaker;
use Chevere\Writer\StreamWriter;
use function Chevere\Writer\streamFor;

$poMaker = new PoMaker(
    locale: 'es-CL',
    domain: 'messages',
    writer: new StreamWriter(streamFor('php://stdout', 'w')),
);

Scan directory

Use withScanFor to recursively scan a directory. It returns a new instance.

use function Chevere\Filesystem\directoryForPath;

$poMaker = $poMaker->withScanFor(
    directoryForPath('/app/src/')
);

By default it scans for __ and __n calls. Use functions to map additional function names to its gettext handler. For example, to also extract strings with context and domain, or calls to your own helpers:

$poMaker = $poMaker->withScanFor(
    directory: directoryForPath('/app/src/'),
    functions: [
        '__p' => 'pgettext',
        '__np' => 'npgettext',
        '__d' => 'dgettext',
        '__dn' => 'dngettext',
        '__dp' => 'dpgettext',
        '__dnp' => 'dnpgettext',
        'myTranslate' => 'gettext',
    ],
);

Available handlers are gettext, ngettext, pgettext, npgettext, dgettext, dngettext, dpgettext and dnpgettext.

Strings passed to domain functions are only extracted when their domain matches the PoMaker domain. For example, __d('admin', 'Dashboard') is extracted by new PoMaker('es-CL', 'admin') but not by new PoMaker('es-CL', 'messages').

Make PO file

Use make to generate the .po file at the target directory, which is created if it doesn't exist.

$poMaker->make(
    directoryForPath('/app/locales/')
);

make overwrites any existing .po file at the target path, including translations already in it. Generate into a separate directory and merge the result with your translated files (for example, using msgmerge).

Calling make before withScanFor throws BadMethodCallException.

TranslatorBuilder

TranslatorBuilder compiles .po files to .php files, which is the format used at runtime by TranslatorLoader.

Create TranslatorBuilder

Pass the sourceDirectory containing the .po files and the targetDirectory for the generated .php files. Use writer to log the generated files (defaults to NullWriter).

use Chevere\Translate\TranslatorBuilder;
use function Chevere\Filesystem\directoryForPath;

$builder = new TranslatorBuilder(
    sourceDirectory: directoryForPath('/app/locales/'),
    targetDirectory: directoryForPath('/app/compiled/'),
);

The source directory must exist or DirectoryNotExistsException is thrown.

Build translations

Use withBuild to compile the .po file for a locale and domain. It returns a new instance, so calls can be chained.

$builder = $builder
    ->withBuild(locale: 'es-CL', domain: 'messages')
    ->withBuild(locale: 'es-CL', domain: 'admin')
    ->withBuild(locale: 'pt-BR', domain: 'messages');

It throws DirectoryNotExistsException if the locale directory doesn't exist and FileNotExistsException if the .po file doesn't exist.

TranslatorLoader

TranslatorLoader loads compiled .php translation files into a Translator.

Load translations

Use withLoad to load the translation file for a locale and domain from a directory. It returns a new instance, so calls can be chained to load multiple domains.

use Chevere\Translate\TranslatorLoader;
use function Chevere\Filesystem\directoryForPath;

$compiled = directoryForPath('/app/compiled/');
$loader = (new TranslatorLoader())
    ->withLoad($compiled, 'es-CL', 'messages')
    ->withLoad($compiled, 'es-CL', 'admin');

The first loaded domain becomes the default domain, used by functions that don't take a domain argument.

It throws DirectoryNotExistsException if the locale directory doesn't exist and FileNotExistsException if the .php file doesn't exist.

Get Translator

Use translator to get the Translator.

$translator = $loader->translator();

Translator

Translator extends gettext/translator, so it provides all gettext methods such as gettext, ngettext, pgettext and dgettext.

$translator->gettext('Hello, world!');
// ¡Hola, mundo!

Use withAdd to add or override messages at runtime. Messages are indexed by context, with '' for no context. Plural translations are passed as a list of forms.

$translator = $translator->withAdd(
    messages: [
        '' => [
            'Hello, world!' => '¡Hola, mundo!',
            '%d file' => ['%d archivo', '%d archivos'],
        ],
        'menu' => [
            'Open' => 'Abrir',
        ],
    ],
    pluralForms: 'nplurals=2; plural=(n != 1);',
    domain: 'messages',
);

Use withLoad to load compiled translation files directly.

use function Chevere\Filesystem\filePhpReturnForPath;

$translator = $translator->withLoad(
    filePhpReturnForPath('/app/compiled/es-CL/messages.php')
);

Use domain, dictionary, pluralForms and toArray to read the translator state.

Functions

Translation functions are provided at the Chevere\Translate namespace.

Register Translator

Functions use the Translator registered with TranslatorInstance.

use Chevere\Translate\TranslatorInstance;

new TranslatorInstance($translator);

If no Translator is registered, functions return the original string. Plural functions return $singular when $count is 1 and $plural otherwise.

Use translator to get the registered Translator.

use function Chevere\Translate\translator;

$translator = translator();

Available functions

Function Description
__($message) Translate a string
__n($singular, $plural, $count) Translate a plural string
__p($context, $message) Translate a string with context
__np($context, $singular, $plural, $count) Translate a plural with context
__d($domain, $message) Translate a string in a domain
__dn($domain, $singular, $plural, $count) Translate a plural in a domain
__dp($domain, $context, $message) Translate a string in a domain with context
__dnp($domain, $context, $singular, $plural, $count) Translate a plural in a domain with context
use function Chevere\Translate\__;
use function Chevere\Translate\__d;
use function Chevere\Translate\__p;

__('Open');
// Abierto
__p('menu', 'Open');
// Abrir
__d('admin', 'Dashboard');
// Panel

Functions return the translated string as-is, use sprintf or strtr to replace placeholders.

use function Chevere\Translate\__n;

$count = 3;
sprintf(__n('%d file', '%d files', $count), $count);
// 3 archivos

Remember to pass __p, __np and domain functions to PoMaker so their strings are extracted.

Documentation

Documentation is available at chevere.org/packages/translate.

License

Copyright Rodolfo Berrios A.

Chevere is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.