EN
Getting started

Languages and translation

This page explains how the interface language is chosen, the language switcher, and how to translate texts.

Acun UI comes with Turkish and English interfaces. The components appear in whatever language the application uses. Numbers (1.234,5 / 1,234.5) and short dates (05.10.2026 / 10/05/2026) follow the language too.

Quick example

// bootstrap/app.php
use Acun\Ui\Http\Middleware\SetLocale;

->withMiddleware(function (Middleware $middleware): void {
    $middleware->web(append: SetLocale::class);
})
{{-- resources/views/layouts/admin/sections/navbar.blade.php --}}
<acun:slot:actions><acun:locale-switcher /></acun:slot:actions>

Both are already set up in the theme. The middleware picks the language of each request, and the visitor changes it with the switcher in the top bar. Livewire updates also go through the web group, so they use the same language.

The visitor's language

SetLocale picks the language in this order:

  1. Saved choice: The field on the signed-in user's account, otherwise the switcher's cookie.
  2. Browser language: The first of the browser's languages that is offered. A value such as en-US counts as en.
  3. Country: A country in the countries list gets its own language, for example Turkey gets Turkish. Any other known country gets the fallback.
  4. Fallback: If nothing else decides, fallback, English by default.

Where the country comes from is described at the end of the page, in the Advanced section.

Common options

The language settings are in the locale block of config/acun-ui.php. Keys you leave out use the package default:

'locale' => [
    'supported' => ['tr', 'en'],
    'fallback' => 'en',
    'countries' => ['TR' => 'tr'],
    'user_attribute' => 'preferred_locale',   // null: cookie only
],
Option What it does Default
supported The languages offered; the switcher lists them. ['tr', 'en']
fallback The language used when no rule decides. 'en'
countries Country code → language. ['TR' => 'tr']
user_attribute The users table column that stores the choice. null (cookie only)
cookie The name of the cookie that stores the choice. 'acun_locale'
names The names in the switcher, each in its own language. Türkçe, English
flags Each language's flag, as a country code. tr → tr, en → gb
country_headers The request headers that carry the country code. Cloudflare, CloudFront, Vercel

Language switcher

<acun:locale-switcher /> goes in the top bar. It lists the offered languages by their own names, with flags: Türkçe, English.

  • The choice is sent to the acun-ui.locale route and stored in a cookie that lasts 400 days. The page reopens in the new language.
  • If user_attribute names a column, the choice is also saved on the signed-in user's account. That column takes precedence over the cookie, so the preference follows the user across devices.
  • Flags are country codes: tr, gb, us, de, fr, es, it, nl, ru. For the US flag on English, write 'flags' => ['en' => 'us']. A language without a flag shows none.
  • If only one language is offered, the switcher isn't shown. align="start" aligns the list to the left; the default is end.

Changing the package's texts

Components have two kinds of text:

Text type Example How to change it
Translation key "Clear selection", "Close", "Change theme" The application's lang/*.json file
Prop title, label, placeholder, cancel-text Pass your own text when you use the component

The package's key is the English text; the Turkish is in the package's lang/tr.json file. If you write the same key in your application's lang/tr.json file, yours is used. To change the English, use lang/en.json:

// lang/tr.json
{ "Clear selection": "Seçimi kaldır" }

// lang/en.json
{ "Could not copy": "Copy failed" }

All the package's keys are in the vendor/acunsoft/acun-ui-free/lang/tr.json and vendor/acunsoft/acun-ui-pro/lang/tr.json files. To add another language, translate the keys into that language's file and add the language to the supported list.

The application's own texts

Titles, labels, descriptions and empty-state texts are values you pass to the component. In a multilingual application, pass them through __(). If your application is written in Turkish, the key can be Turkish, and its English goes in the lang/en.json file:

<acun:confirmation-dialog name="user-delete" :title="__('Kullanıcıyı sil')">
    <acun:button variant="danger" wire:click="delete">{{ __('Sil') }}</acun:button>
</acun:confirmation-dialog>
// lang/en.json
{ "Kullanıcıyı sil": "Delete user", "Sil": "Delete" }

Titles and section names in the JSON menu are translation keys too. The layout translates a Livewire page's #[Title] value. A text without a translation is shown as is.

Plural texts

trans_choice() looks a text up in the current language only if the key exists in that language's JSON file. Otherwise it switches to the fallback language. If a Turkish key is missing from lang/tr.json, a Turkish page shows the English text.

Warning

In an application with Turkish keys, add every key you use with trans_choice() to lang/tr.json, mapped to itself.

{{ trans_choice(':count ürün|:count ürün', $count, ['count' => $count]) }}
// lang/tr.json
{ ":count ürün|:count ürün": ":count ürün|:count ürün" }

// lang/en.json
{ ":count ürün|:count ürün": ":count product|:count products" }

__() doesn't behave this way: when the key isn't found, it shows the key itself.

Number and date format

{{ \Acun\Ui\Support\Localization::number(1234.5, 1) }}   {{-- 1.234,5 · 1,234.5 --}}
{{ \Acun\Ui\Support\Localization::date($order->created_at) }}   {{-- 05.10.2026 · 10/05/2026 --}}

number() takes the number of decimal places as its second value. Both use the page's current language.

Advanced

The country

The country code is read from these request headers: CF-IPCountry (Cloudflare), CloudFront-Viewer-Country (CloudFront), X-Vercel-IP-Country (Vercel) and X-Country-Code (your own proxy). Change the list with country_headers. Cloudflare's XX (unknown) and T1 (Tor) values count as unknown.

On a server without these headers, you can plug in your own GeoIP lookup. The function returns a two-letter country code or null:

// AppServiceProvider::boot()
use Acun\Ui\Support\Localization;

Localization::countryUsing(fn (Request $request) => GeoIp::country($request->ip()));

The package never sends the visitor's IP address to an external service.

Caching

Because the page varies by language, the middleware adds Vary: Accept-Language, Cookie to the response. A cache then keeps a separate copy for each language.

Search and Turkish characters

The DataTable and WithListing search (->searchable(), applySearch()) ignores case and Turkish characters. ı, İ, I and i count as the same letter, and ş/s, ç/c, ğ/g, ö/o and ü/u match. Even if the user types "ayse", "Ayşe" is found. This matching happens in the database, in a generated search column; see the Search page for details.

The in-browser search of acun:combobox follows the same rule. The command palette applies the case rules of the page's language: on a Turkish page, "İSTANBUL" matches "istanbul".

Learn more

  • Menu: translating menu titles.
  • Search: search that ignores Turkish characters.
  • Configuration: every key of the locale block.
Acun UIDesigned for people.