PHPackages                             preflow/i18n - 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. [Localization &amp; i18n](/categories/localization)
4. /
5. preflow/i18n

ActiveLibrary[Localization &amp; i18n](/categories/localization)

preflow/i18n
============

Preflow i18n — translations, locale detection, pluralization

v0.13.1(1mo ago)0322MITPHPPHP &gt;=8.4

Since Apr 10Pushed 1mo agoCompare

[ Source](https://github.com/getpreflow/i18n)[ Packagist](https://packagist.org/packages/preflow/i18n)[ RSS](/packages/preflow-i18n/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (3)Versions (32)Used By (2)

Preflow I18n
============

[](#preflow-i18n)

Translations, locale detection, and pluralization for Preflow applications.

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

[](#installation)

```
composer require preflow/i18n
```

What it does
------------

[](#what-it-does)

- Loads PHP translation files from `lang/{locale}/{group}.php`
- Resolves dot-notation keys with `:param` replacement and locale fallback
- ICU-style pluralization with exact, range, and simple two-form rules
- PSR-15 middleware for locale detection (URL prefix → cookie → Accept-Language)
- Twig functions for global and component-scoped translations

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

[](#configuration)

`config/i18n.php`:

```
return [
    'default'      => 'en',
    'available'    => ['en', 'de'],
    'fallback'     => 'en',
    'url_strategy' => 'prefix', // 'prefix' | 'none'
];
```

Translation files
-----------------

[](#translation-files)

`lang/en/blog.php`:

```
return [
    'title'      => 'My Blog',
    'published'  => 'Published on :date',
    'post_count' => '{0} No posts|{1} One post|[2,*] :count posts',
];
```

API
---

[](#api)

### Translator

[](#translator)

```
$translator = new Translator(
    langPath: __DIR__ . '/lang',
    locale: 'en',
    fallbackLocale: 'en',
);

$translator->get('blog.title');                          // "My Blog"
$translator->get('blog.published', ['date' => '2026-01-01']); // "Published on 2026-01-01"
$translator->choice('blog.post_count', 5);              // "5 posts"
$translator->setLocale('de');
$translator->getLocale();                               // "de"
```

### PluralResolver

[](#pluralresolver)

Supports three formats:

```
{0} No posts|{1} One post|[2,*] :count posts   // exact + range
[2,10] Some|[11,*] Many                         // range only
One post|:count posts                           // simple two-form (1 = first, else second)

```

### LocaleMiddleware

[](#localemiddleware)

PSR-15 middleware. Detects locale in priority order: URL prefix → cookie → `Accept-Language` header → configured default. Strips the locale prefix from the request path and sets a `locale` cookie on the response.

```
$middleware = new LocaleMiddleware(
    translator: $translator,
    availableLocales: ['en', 'de'],
    defaultLocale: 'en',
    urlStrategy: 'prefix', // request to /de/blog strips /de, sets locale to "de"
);
```

### TranslationExtension (Twig)

[](#translationextension-twig)

Register with your Twig environment:

```
$twig->addExtension(new TranslationExtension($translator));
```

```
{# Simple key #}
{{ t('blog.title') }}

{# With parameters #}
{{ t('blog.published', { date: '2026-01-01' }) }}

{# Pluralization — third arg is the count #}
{{ t('blog.post_count', { count: 5 }, 5) }}

{# Component-scoped — resolves "my-component.label" #}
{{ tc('label', 'MyComponent') }}
```

`tc()` converts the component name from PascalCase to kebab-case and uses it as the translation group.

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance88

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~0 days

Total

31

Last Release

59d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6d8b54efbc79683c32645e3fa8d3590037fa003963a16e0ed989104c6f4a2723?d=identicon)[smyr](/maintainers/smyr)

---

Top Contributors

[![smeyerme](https://avatars.githubusercontent.com/u/1925560?v=4)](https://github.com/smeyerme "smeyerme (7 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/preflow-i18n/health.svg)

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

###  Alternatives

[php-translation/translator

Translator services

25224.8k5](/packages/php-translation-translator)[longman/laravel-multilang

Package to integrate multi language (multi locale) functionality in Laravel 5.x

5514.5k1](/packages/longman-laravel-multilang)[smmoosavi/php-gettext

Wrapper for php-gettext by danilo segan. This library provides PHP functions to read MO files even when gettext is not compiled in or when appropriate locale is not present on the system.

1926.6k1](/packages/smmoosavi-php-gettext)[amendozaaguiar/laraveles-spanish-for-jetstream

Archivos de traducción al español latinoamericano para Laravel con Jetstream (auth, pagination, passwords, validation + todas las cadenas de Jetstream).

1512.6k](/packages/amendozaaguiar-laraveles-spanish-for-jetstream)[laradevs/spanish

labels translated to spanish

166.7k](/packages/laradevs-spanish)

PHPackages © 2026

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