PHPackages                             zpmlabs/laravel-i18n-audit - 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. zpmlabs/laravel-i18n-audit

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

zpmlabs/laravel-i18n-audit
==========================

Laravel package to audit translation usage, missing keys, and unused keys.

v1.0.3(2mo ago)41231↓75%2MITPHPPHP ^8.2

Since Feb 23Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/i18n-audit/i18n-audit-laravel)[ Packagist](https://packagist.org/packages/zpmlabs/laravel-i18n-audit)[ RSS](/packages/zpmlabs-laravel-i18n-audit/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (4)Versions (4)Used By (0)

[![image](https://private-user-images.githubusercontent.com/100382372/554059076-979aaced-50ee-474c-a6a8-905145abdd69.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzcyMzMsIm5iZiI6MTc3MjIzNjkzMywicGF0aCI6Ii8xMDAzODIzNzIvNTU0MDU5MDc2LTk3OWFhY2VkLTUwZWUtNDc0Yy1hNmE4LTkwNTE0NWFiZGQ2OS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwMjI4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDIyOFQwMDAyMTNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04YTUzYmIwYjMxNWJkOWUwNDZmYjY0ZDViOTNlOTg2ZmNlNGQzMWFiZWQ4ZTJkZWE0MmNkZGMyMWRiN2QzZGNkJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.WGPYetaNAaiMHroxTEX0Z5bhXKBbVDdBNuRt7-EATCM)](https://private-user-images.githubusercontent.com/100382372/554059076-979aaced-50ee-474c-a6a8-905145abdd69.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzcyMzMsIm5iZiI6MTc3MjIzNjkzMywicGF0aCI6Ii8xMDAzODIzNzIvNTU0MDU5MDc2LTk3OWFhY2VkLTUwZWUtNDc0Yy1hNmE4LTkwNTE0NWFiZGQ2OS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwMjI4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDIyOFQwMDAyMTNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04YTUzYmIwYjMxNWJkOWUwNDZmYjY0ZDViOTNlOTg2ZmNlNGQzMWFiZWQ4ZTJkZWE0MmNkZGMyMWRiN2QzZGNkJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.WGPYetaNAaiMHroxTEX0Z5bhXKBbVDdBNuRt7-EATCM)[![image](https://private-user-images.githubusercontent.com/100382372/554059625-a6b1f3bc-2a82-4875-89bb-77e9fea55e97.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzcyMzMsIm5iZiI6MTc3MjIzNjkzMywicGF0aCI6Ii8xMDAzODIzNzIvNTU0MDU5NjI1LWE2YjFmM2JjLTJhODItNDg3NS04OWJiLTc3ZTlmZWE1NWU5Ny5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwMjI4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDIyOFQwMDAyMTNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mNmNhODhkM2ExMjExNGVkMjVkNWM4ZTEzZGMyNGYwZmFiNDVkMzA5M2IxMWMzMGJlNmNlNjgyYWE2NzllOTBiJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.luPMZjtpLtBQITtYRAmqTek1imJ3EYgeo8C2kzvFqCU)](https://private-user-images.githubusercontent.com/100382372/554059625-a6b1f3bc-2a82-4875-89bb-77e9fea55e97.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzcyMzMsIm5iZiI6MTc3MjIzNjkzMywicGF0aCI6Ii8xMDAzODIzNzIvNTU0MDU5NjI1LWE2YjFmM2JjLTJhODItNDg3NS04OWJiLTc3ZTlmZWE1NWU5Ny5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwMjI4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDIyOFQwMDAyMTNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mNmNhODhkM2ExMjExNGVkMjVkNWM4ZTEzZGMyNGYwZmFiNDVkMzA5M2IxMWMzMGJlNmNlNjgyYWE2NzllOTBiJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.luPMZjtpLtBQITtYRAmqTek1imJ3EYgeo8C2kzvFqCU)Laravel I18n Audit
==================

[](#laravel-i18n-audit)

Cross-platform Laravel package for scanning translation usage in source code and comparing it against available keys in `lang/` files.

Features
--------

[](#features)

- Scans source usage for:
    - `__()`
    - `trans()`
    - `trans_choice()`
    - `Lang::get()`
    - `Lang::choice()`
    - Blade `@lang()`
    - Blade output calls such as `{{ __('...') }}`
- Loads translation repositories from:
    - `lang/{locale}/*.php` (flattened to dot notation)
    - `lang/{locale}.json` (JSON keys)
- Reports:
    - Missing keys per locale
    - Unused keys per locale
    - Dynamic translation key warnings (non-literal arguments)
    - Missing key locations with file, line, column, and char position
- No external binaries; uses native PHP iterators for Linux, Windows, and macOS.

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

[](#installation)

```
composer require zpmlabs/laravel-i18n-audit
```

Publish config:

```
php artisan vendor:publish --tag=i18n-audit-config
```

Usage
-----

[](#usage)

Basic table output:

```
php artisan i18n:audit
```

The table output is intentionally compact (per-locale totals). Detailed entries are appended to `storage/logs/i18n-audit.log` by default.

JSON output:

```
php artisan i18n:audit --format=json
```

Custom locales and paths:

```
php artisan i18n:audit --locales=sr,en,de --paths=app,resources/views,routes,config,database
```

Write JSON report to file:

```
php artisan i18n:audit --format=json --output=storage/app/i18n-audit.json
```

In local/dev environments, the package auto-registers a route to view the latest audit dashboard (Blade page loaded from latest JSON payload in audit log):

`/i18n-audit/latest`

The dashboard includes:

- locale summary table (used/missing/unused/total)
- tabs per locale for focused inspection
- missing key locations with copy buttons (`path:line:column`)
- dynamic warning table
- full raw JSON payload section (complete data visibility)
- action buttons:
    - auto populate missing translations
    - remove currently unused translations

Both dashboard actions automatically rerun `i18n:audit` so data refreshes immediately after changes.

Auto-populate missing translations using default template:

```
php artisan i18n:audit --fill-missing
```

Generate standalone HTML file report (optional):

```
php artisan i18n:audit --html --html-output=storage/app/i18n-audit-latest.html
```

Use a custom default fill template:

```
php artisan i18n:audit --fill-missing --fill-template="Miissing Translation for {$locale}"
```

Fail CI if missing or unused keys exist:

```
php artisan i18n:audit --fail-on-missing --fail-on-unused
```

Command Options
---------------

[](#command-options)

- `--locales=sr,en,de` Comma-separated locales. If omitted, locales are auto-detected from `lang/`.
- `--paths=app,resources/views,routes,config,database` Comma-separated scan roots.
- `--exclude=vendor,node_modules,storage,bootstrap/cache` Comma-separated path fragments to exclude.
- `--format=table|json` Output format (`table` default).
- `--output=storage/app/i18n-audit.json` Optional path to write JSON report.
- `--only-missing` Show only missing keys in table output.
- `--only-unused` Show only unused keys in table output.
- `--html` Generate an HTML report file.
- `--html-output=storage/app/i18n-audit-latest.html` Custom HTML output path.
- `--fill-missing` Automatically create missing translation entries in locale files.
- `--fill-template="Miissing Translation for {$locale}"` Template for auto-filled values.
- `--fail-on-missing` Exit with code `1` if missing keys are found.
- `--fail-on-unused` Exit with code `1` if unused keys are found.

JSON Output Shape
-----------------

[](#json-output-shape)

```
{
  "usedKeys": ["auth.failed", "Reset Password"],
  "usedKeyLocations": {
    "auth.failed": [
      {
        "file": "app/Http/Controllers/AuthController.php",
        "line": 34,
        "column": 17,
        "char": 1024,
        "source": "__()"
      }
    ]
  },
  "dynamicKeys": [
    {
      "file": "resources/views/home.blade.php",
      "line": 12,
      "expression": "$prefix . $name",
      "source": "blade-call"
    }
  ],
  "missingByLocale": {
    "en": ["messages.missing"]
  },
  "missingKeyLocationsByLocale": {
    "en": {
      "messages.missing": [
        {
          "file": "resources/views/home.blade.php",
          "line": 12,
          "column": 9,
          "char": 421,
          "source": "@lang()"
        }
      ]
    }
  },
  "unusedByLocale": {
    "en": ["messages.unused"]
  },
  "stats": {
    "usedKeysTotal": 2,
    "dynamicKeysTotal": 1,
    "missingTotal": 1,
    "unusedTotal": 1,
    "perLocale": {
      "en": {
        "used": 2,
        "missing": 1,
        "unused": 1,
        "totalTranslations": 3
      }
    }
  },
  "meta": {
    "timestamp": "2026-02-23T10:00:00+00:00",
    "paths": ["app", "resources/views"],
    "exclude": ["vendor"],
    "locales": ["en"],
    "langPath": "lang",
    "warnings": [],
    "detailedLogPath": "storage/logs/i18n-audit.log",
    "dashboardUrl": "http://localhost/i18n-audit/latest"
  }
}
```

Dynamic Key Limitations
-----------------------

[](#dynamic-key-limitations)

Dynamic calls such as `__('messages.' . $name)` cannot be resolved to a concrete key statically. They are listed in `dynamicKeys` as warnings with file and line information.

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

[](#configuration)

Config file is publishable as `config/i18n-audit.php`.

Defaults include scan paths, excludes, language path, file extension filters, symlink behavior, and detailed logging options:

- `include_tests` (default: `false`)
- `include_vendor` (default: `false`)
- `follow_symlinks` (default: `false`)
- `log_detailed_report` (default: `true`)
- `log_path` (default: `storage/logs/i18n-audit.log`)
- `html_output_path` (default: `storage/app/i18n-audit-latest.html`)
- `fill_template` (default: `Miissing Translation for {$locale}`)
- `register_dev_route` (default: `true`)
- `dev_route_path` (default: `i18n-audit/latest`)
- `dev_route_middleware` (default: `['web']`)

Cross-platform Notes
--------------------

[](#cross-platform-notes)

- Uses `RecursiveDirectoryIterator` and `RecursiveIteratorIterator`
- Uses path normalization for stable output across separators
- Does not rely on `grep`, `find`, `awk`, or `sed`

Testing
-------

[](#testing)

```
composer install
composer test
```

License
-------

[](#license)

MIT

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance84

Actively maintained with recent releases

Popularity28

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity48

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

3

Last Release

84d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/211412089?v=4)[ZPM Labs](/maintainers/zpmlabs)[@ZPMLabs](https://github.com/ZPMLabs)

---

Top Contributors

[![sasaorasanin](https://avatars.githubusercontent.com/u/100382372?v=4)](https://github.com/sasaorasanin "sasaorasanin (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/zpmlabs-laravel-i18n-audit/health.svg)

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

###  Alternatives

[barryvdh/laravel-translation-manager

Manage Laravel Translations

1.7k3.6M17](/packages/barryvdh-laravel-translation-manager)[php-translation/extractor

Extract translations form the source code

1294.4M8](/packages/php-translation-extractor)[vluzrmos/language-detector

Detect the language for your application using browser preferences, subdomains or route prefixes.

109554.8k3](/packages/vluzrmos-language-detector)[elegantly/laravel-translator

All on one translations management for Laravel

6216.9k](/packages/elegantly-laravel-translator)[kerigard/laravel-lang-ru

Ru lang for Laravel

2116.8k](/packages/kerigard-laravel-lang-ru)[highsolutions/laravel-translation-manager

Manage Laravel Translations

1518.8k](/packages/highsolutions-laravel-translation-manager)

PHPackages © 2026

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