> For the complete documentation index, see [llms.txt](https://quantumphp.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantumphp.gitbook.io/docs/packages/lang/architecture.md).

# Architecture

The Lang package uses a small factory-plus-translator model.

## Shared instance lifecycle

`LangFactory::get()` is the main entry point.

On first use it:

1. registers `LangFactory` in the DI container if needed
2. resolves the factory from DI
3. memoizes one `Lang` instance inside the factory

Repeated calls return the same `Lang` object until the container or factory state is reset.

## Config loading

The factory lazily imports `config/lang.php` when the `lang` config key is not already present.

It expects these settings:

* `enabled`
* `supported`
* `default`
* `url_segment`

If no usable language can be detected and `default` is empty, the factory throws `LangException::misconfiguredDefaultConfig()`.

The `default` value is used as-is. It does not need to appear in `supported`, because the supported list is only applied to request-derived values.

## Detection details

### Query parameter

`?lang=<value>` has highest priority.

### URL segment

The URL strategy reads `request()->getSegment((int) config()->get('lang.url_segment'))`.

There is one routing-specific adjustment: when the current route has a prefix and `lang.url_segment` is `1`, the factory increments the segment index to `2`. That keeps the language lookup aligned with prefixed routes.

### Header fallback

Header-based detection accepts only the primary language from the first `Accept-Language` entry, normalized to a two-letter code.

Example: `es-ES, en;q=0.8` resolves to `es`.

## Translation loading model

Translation files are loaded once per language instance and reused until you explicitly call `flush()`.

The `enabled` flag stored on `Lang` is informational at this layer. The factory still creates the service either way; the web bootstrap decides whether `load()` is called automatically.

Loading order is:

1. shared translation files
2. current module translation files

Both locations are scanned with `*.php` globbing. Each file is required and imported under its basename.

That means this structure:

* `shared/resources/lang/en/messages.php`
* `modules/Blog/resources/lang/en/messages.php`

loads both files into the `messages` namespace. Because module files are imported after shared files, later imports can replace or extend earlier values for the same file/key paths.

## Translation lookup contract

`t($key, $params)` behaves like this:

* if the key exists, return the translated string
* if params are passed, apply placeholder substitution
* if the key does not exist, return the original key

Missing keys fall back to the key string (not `null`) in normal lookup flow.

## Stateful caveat: reported lang vs translator lang

`Lang` stores the current language string and the `Translator` as separate state.

* `setLang()` updates only `Lang::$currentLang`
* the existing `Translator` keeps the language string it was constructed with

So this is not a full language switch:

```php
$lang = LangFactory::get();
$lang->setLang('es');
```

After that, `current_lang()` reports `es`, but already-wired translation loading still points at the translator's original language unless you rebuild the Lang instance.

The same caveat applies to `flush()` followed by `load()`: that reload cycle clears cached translations, but it still reloads the translator's original language.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://quantumphp.gitbook.io/docs/packages/lang/architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
