Download the PHP package ozankurt/laravel-modules-i18n without Composer

On this page you can find all versions of the php package ozankurt/laravel-modules-i18n. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-modules-i18n

laravel-modules-i18n

A self-hosted translation-file manager for Laravel. It ships its own UI (Tailwind 4 + vanilla JS — no build step required in your app) for editing both JSON and PHP array language files on disk, including deeply nested PHP keys like 'foo' => ['bar' => 'baz'].

Part of the KurtModules family. Requires ozankurt/laravel-modules-core.

Features

Requirements

Installation

Publish the config and the prebuilt UI assets:

Access control

Translation management writes files on your server and is treated as an admin surface, so it is safe by default: nothing is registered until you opt in.

Enable the REST API by setting the HTTP mode (Core API-kit convention):

Every REST endpoint (reads and writes alike) runs behind two layers:

  1. config('i18n.http.auth_middleware') (default ['auth']) — the request must be authenticated.
  2. The i18n.manageTranslations gate — granted automatically in any environment listed in config('i18n.enabled_environments') (default ['local']); everywhere else you override it, typically in app/Providers/AppServiceProvider.php:

The API routes use the api middleware group (stateless). To drive the bundled ui-mode UI (whose SPA authenticates with the session cookie), add web to config('i18n.http.middleware') — or point auth_middleware at a guard that reads your session — so the API shares the UI's session context. The UI shell itself keeps the legacy web + environment/viewI18n guard.

Usage

In ui mode, visit /i18n (configurable via config('i18n.route.prefix')). Pick JSON or PHP array; for PHP choose a group (file); then edit in the grid:

By default the manager reads and writes the application's lang_path(). Point it elsewhere with config('i18n.paths.root').

JSON API

Set I18N_HTTP_MODE=api (or ui) to mount the REST API under config('i18n.http.prefix') (default api/i18n). It is built on the Core API kit: successful responses are wrapped in a { "data": …, "meta": … } envelope (meta omitted when empty), and errors are { "message": …, "errors": … }. Every route is authenticated and gated (see Access control) and throttled by the i18n-api limiter (config('i18n.http.rate_limit'), default 60,1). All request and response bodies are JSON.

Method & path Purpose
GET /api/i18n/catalog List locales, JSON files, PHP groups, vendor packages.
GET /api/i18n/groups List every translation group as {type, group} pairs.
GET /api/i18n/locales List the known locales.
GET /api/i18n/json Read the JSON translation grid.
PATCH /api/i18n/json Apply a batch of edits to JSON files.
GET /api/i18n/php/{group} Read a PHP group grid ({group} may be nested, e.g. admin/users, or namespaced, e.g. firewall::notifications).
PATCH /api/i18n/php/{group} Apply a batch of edits to a PHP group.
GET /api/i18n/translations Show one key's value across locales (?type=&group=&key=).
PUT /api/i18n/translations Set a single key for one locale.
DELETE /api/i18n/translations Delete a single key from every loaded locale.
POST /api/i18n/locales Create a new empty locale file.
GET /api/i18n/report/missing Cross-group missing-key report for a reference locale.
GET /api/i18n/export Export a locale (one group or all) to CSV/JSON.
POST /api/i18n/import Import CSV/JSON key,value rows into a group.
POST /api/i18n/translate-missing Fill a locale's missing keys via the configured translator.

Reading a grid

GET /api/i18n/json?locales=en,tr (omit locales to load every known locale) returns:

hashes is a locale => SHA-1 map of each file's current on-disk contents (null when the file does not exist yet). You send these back unchanged as the baseHashes of a later edit; they are how the server detects that a file changed under you.

Applying edits

PATCH /api/i18n/json (or /api/i18n/php/{group}) takes the loaded baseHashes plus an ordered list of ops:

On success (200 OK) the response mirrors a fresh read of the affected files:

changed lists only the locales whose files were actually rewritten (a batch that resolves to the current contents changes nothing and writes nothing). Use the returned hashes as the baseHashes for your next edit.

Single-key writes

For one-cell changes without assembling a batch, PUT /api/i18n/translations sets a key and DELETE /api/i18n/translations removes it — both through the same safe write path (lock + backup + optimistic hash), returning the same { "data": { "changed", "hashes" } } envelope:

GET /api/i18n/translations?type=json&key=greeting reads a single key's value per locale plus the current hashes and an exists flag.

Conflicts (409)

When any file's current hash no longer matches the baseHashes you sent, the whole batch is rejected and nothing is written:

errors.locales names the files that changed underneath you. Re-read the grid (to get fresh values and hashes), reapply your edits, and retry. Invalid input (bad locale/group, unknown op, out-of-root path) returns 422 with { "message": "…", "errors": … } instead.

Concurrency semantics

Saves are serialized per group with an exclusive file lock, and the optimistic hash check runs inside that lock immediately before writing. Two concurrent PATCHes that started from the same baseHashes can therefore never both succeed: the first wins, and the second sees the file it just changed and gets a 409 — there is no silent last-writer-wins. A multi-locale batch is atomic: all locales are staged and verified first, then swapped in together, and any failure rolls the batch back so the files are never left half-applied.

Extending: the TranslationsChanged event

After a batch actually changes at least one file, the manager dispatches Kurt\Modules\I18n\Events\TranslationsChanged with the file type, the group (or null for JSON), the changedLocales, the applied ops, and the actor (the authenticated user, when resolvable). Listen for it to keep an audit log, fire a webhook, bust a translation cache, or trigger a redeploy. It does not fire for a no-op batch.

Cross-group missing-key report

GET /api/i18n/report/missing?reference=en answers "what still needs translating?" across every group at once — the JSON pseudo-group plus every project and vendor PHP group — instead of one open group at a time. Given a reference locale it lists, per target locale, the keys the reference defines that are absent from that locale's copy of each group.

Only gaps are reported: a locale appears under a group only when it is missing at least one key, and a group is omitted entirely when every target is complete. A group whose file is absent for a locale surfaces as all the reference keys being missing for it. The same report is available in PHP via Kurt\Modules\I18n\Support\MissingKeyReport::generate($reference, $targets = null).

Import / export

Export and import a locale's translations as flat key,value rows (nested PHP keys are dot-paths, e.g. title.icon), in CSV or JSON.

Export

GET /api/i18n/export?locale=en&format=json returns a downloadable file (Content-Disposition: attachment). Being a file download, its body is the raw key,value rows — not the data envelope.

The CSV form is the same rows with a key,value header (RFC 4180 quoting).

Import

POST /api/i18n/import applies rows to one group + locale:

The JSON content accepts either [{ "key": …, "value": … }] rows or a flat { "key": "value" } object of scalars; CSV needs key and value columns in any order (extra columns are ignored). An import is not a raw overwrite: it is turned into a batch of set operations and applied through the same safe write path as edits — the exclusive per-group lock, timestamped backups, and the optimistic-hash conflict check all apply. Send the target locale's current hash as baseHashes (read it from a grid first); a stale hash returns 409, and a malformed payload returns 422 with nothing written. Kurt\Modules\I18n\Support\TranslationExporter and TranslationImporter expose the same behaviour in PHP.

Machine translation

The package ships a seam, not a provider. POST /api/i18n/translate-missing fills a target locale's missing keys in one group by machine-translating the reference values and writing the results through the safe write path:

It responds (inside the data envelope) with the usual changed / hashes plus a translated list of the keys it filled. Only keys the target lacks are translated; existing values are left untouched.

Translation goes through the Kurt\Modules\I18n\Contracts\Translator contract:

The default binding is NullTranslator, which throws (TranslatorNotConfiguredException, surfaced as 501) rather than silently writing the untranslated source. Wire your own DeepL/Google/LLM-backed implementation via config:

Any dependencies your implementation type-hints are resolved from the container.

Configuration

See config/i18n.php — the http block (mode / prefix / middleware / auth_middleware / rate_limit for the REST API), environment allowlist, UI route prefix/middleware, lang root, backups, and an optional explicit locale → label map.

Security

This is a filesystem-writing admin tool. Review SECURITY.md before exposing it. It is headless (nothing registered) until you set I18N_HTTP_MODE, and every endpoint requires authentication plus the i18n.manageTranslations gate. Never serve it publicly without a restrictive gate override in production (and, for the ui shell, the viewI18n gate).

Development

The UI assets are prebuilt and committed under resources/dist/. To rebuild after changing resources/css or resources/js:

License

MIT © Ozan Kurt


All versions of laravel-modules-i18n with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
illuminate/contracts Version ^12.0 || ^13.0
illuminate/filesystem Version ^12.0 || ^13.0
illuminate/support Version ^12.0 || ^13.0
ozankurt/laravel-modules-core Version ^1.0
spatie/laravel-package-tools Version ^1.92
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package ozankurt/laravel-modules-i18n contains the following files

Loading the files please wait ...