# Language and Translation Management

Quaeriva keeps **interface language** separate from **question/content language**. Changing the interface never creates a second content URL and never translates user-generated content automatically.

## Where translations live

Bundled source dictionaries are stored in:

```text
resources/lang/ar.php
resources/lang/en.php
```

These files are the shipped base packs. They are safe to version in Git and are used as the source language packs for a release.

Runtime translation edits made in the administration panel are stored separately in the `translation_overrides` database table. This prevents a package upgrade from overwriting local wording changes.

Translation resolution order is:

```text
DB override for selected locale
→ bundled file for selected locale
→ DB override for configured fallback locale
→ bundled file for configured fallback locale
→ translation key itself
```

## Advanced language manager

After migration `012_create_language_management.sql` is applied, open:

```text
/admin?page=languages
```

At the default web-root development mount the local path is `/admin?page=languages`. Under a configured subdirectory such as `APP_BASE_URL=/community`, the same page becomes `/community/admin?page=languages`; no folder name is hard-coded.

The page controls:

- public default language;
- administration default language;
- visibility of the public language switcher;
- optional first-visit browser-language detection;
- installed/enabled languages;
- language code and native display name;
- RTL or LTR direction;
- fallback language;
- sort order;
- per-key translation overrides.

The administration interface has its **own locale preference**. An administrator can change the dashboard language without changing the public site's default language.

## Adding another language

Quaeriva is not limited to Arabic and English after migration 012. Add a language from **Administration → Languages** using a normalized language code such as:

```text
de
fr
tr
ur
pt-br
zh-cn
```

Choose `rtl` or `ltr`, select an enabled fallback, and save it.

Adding a language does **not** machine-translate the interface. Supply translations in either of these ways:

1. Add a versioned source pack such as `resources/lang/de.php`; or
2. Keep the language database-only and translate keys in the administration translation editor.

A database-only language can immediately use its configured fallback for untranslated keys, then receive local overrides gradually.

## Public switching policy

Public URLs stay language-neutral. For example, the question URL remains:

```text
/q/example-question
```

The application does not create `/ar/...`, `/en/...`, or persistent `?lang=` variants for interface language.

The current visitor choice is stored in `quaeriva_locale`. For signed-in users it is also stored in `users.preferred_locale`. The choice survives refresh, navigation, search query strings, anchors, and normal browser back/forward navigation.

Locale precedence while the public switcher is enabled is:

```text
visitor cookie
→ signed-in account preference
→ browser language when detection is enabled
→ public default language
```

When the public switcher is disabled, the configured public default language is enforced.

## Admin language policy

Admin language is independent from public language:

```text
user_preferences.admin_locale
→ quaeriva_admin_locale cookie
→ admin.default_locale
```

Old `&lang=...` dashboard query parameters are cleaned from admin URLs. New admin navigation does not propagate them.

## Direction

Each registered language owns its direction. The runtime writes the resolved values to the root HTML element:

```html
<html lang="ar" dir="rtl">
<html lang="en" dir="ltr">
```

CSS should continue to use logical properties such as `margin-inline-start`, `padding-inline`, and `inset-inline-start` rather than assuming a fixed left/right direction.

## Translation JSON import/export

The Languages page can export an AI/translator-friendly JSON pack for a selected locale and import the translated result back as database overrides.

The exported document uses stable dot-notation keys rather than embedding translated PHP code. Its metadata tells a translator to:

- keep every translation key unchanged;
- translate only string values;
- preserve placeholders such as `:name`, `:count`, and `:language` exactly;
- preserve URLs, code fragments, and product names when instructed by the source value;
- return valid UTF-8 JSON.

This is the preferred exchange format when giving the interface to a human translator or an AI model. It avoids asking the translator to edit `resources/lang/*.php` directly and keeps local translations upgrade-safe in `translation_overrides`.

Before import, Quaeriva validates the locale, JSON structure, known keys, and placeholders. A translated value that loses or changes required placeholders is rejected rather than silently corrupting runtime copy.

---

Quaeriva supports multiple locales and per-locale direction. Arabic should render with `dir=rtl`; templates and styles should use logical CSS properties. Translation packs must preserve keys and placeholders exactly.
