Skip to content

Languages & translations.

Manage supported languages, translations, and default locales.

Jul 21, 2026

Reward Loyalty runs in many languages. It detects a visitor's preferred language from their browser settings. You can manage active languages, add new translations, and set text direction.

Available languages

The app includes 12 pre-built translations:

Code Language Direction Status
en_US English (United States) LTR Active by default
de_DE German (Germany) LTR Inactive by default
es_ES Spanish (Spain) LTR Inactive by default
fr_FR French (France) LTR Inactive by default
id_ID Indonesian (Indonesia) LTR Inactive by default
it_IT Italian (Italy) LTR Inactive by default
ja_JP Japanese (Japan) LTR Inactive by default
nl_NL Dutch (Netherlands) LTR Inactive by default
pl_PL Polish (Poland) LTR Inactive by default
pt_BR Portuguese (Brazil) LTR Inactive by default
tr_TR Turkish (Turkey) LTR Inactive by default
ar_SA Arabic (Saudi Arabia) RTL Inactive by default

RTL Support: Arabic includes full right-to-left support. All interface elements adjust for RTL languages.


How it works

The app uses a folder-based structure for languages. Each language lives in its own directory within lang/ (e.g., lang/en_US/, lang/pt_BR/).

When a user visits your site:

  1. The system checks their browser language
  2. If that language is active, it's shown
  3. If not, the system falls back to your default language (usually en_US)

Managing languages

There are two ways to control which languages are active, that is, visible in the language selector and reachable by URL. The recommended way is a single .env setting. The per-folder flag is the fallback.

Set APP_ACTIVE_LOCALES in your .env file to a comma-separated allow-list. Only the listed locales are active, regardless of each folder's own config.php flag:

APP_ACTIVE_LOCALES="en_US,nl_NL"

To pick from everything that ships, copy the full list and remove the ones you don't want:

APP_ACTIVE_LOCALES="ar_SA,de_DE,en_US,es_ES,fr_FR,id_ID,it_IT,ja_JP,nl_NL,pl_PL,pt_BR,tr_TR"

This approach is recommended because:

  • It lives in one place. All active languages sit on a single line instead of across twelve config.php files.
  • It survives updates. Updates always preserve your .env, so your choice is never overwritten. They do not preserve edits to config.php files unless you also protect them (see below).
  • Matching is forgiving. The app treats en-us, EN_us, and en_US as the same locale.

Use full locale codes (en_US), not bare language codes (en). Include your default APP_LOCALE in the list, and make sure every entry is an installed locale (a folder under lang/).

Activating a language with config.php (fallback)

When APP_ACTIVE_LOCALES is empty, each language's own folder decides whether it is active:

  1. Navigate to the language's directory: lang/<locale>/
  2. Open the config.php file
  3. Set 'active' => true
return [
    'active' => true,
    'dir' => 'ltr', // 'ltr' for Left-to-Right, 'rtl' for Right-to-Left
];

Precedence: When APP_ACTIVE_LOCALES is set, it overrides every config.php active flag. When it is empty, the per-folder flag applies. In demo mode, all installed languages are active regardless of either setting.

Deactivating a language

To hide a language, remove it from APP_ACTIVE_LOCALES. If you use the fallback method instead, set 'active' => false in its config.php. You can also delete the language folder entirely if you're sure you won't need it.

Note: If only one language is active, the language selector hides itself.


Adding a new language

To add a language that isn't included:

  1. Copy the Base: Duplicate the lang/en_US/ folder
  2. Rename: Rename the new folder to your target locale (e.g., nl_NL for Dutch)
    • Format: language_COUNTRY (ISO 639-1 language code + ISO 3166-1 country code)
  3. Translate: Open the files inside the new folder and translate the values
  4. Activate: Add the new locale to APP_ACTIVE_LOCALES in .env (or, using the fallback method, set 'active' => true in its config.php)

Language file structure

Each language folder contains:

lang/en_US/
├── config.php          # Active status and text direction
├── common.php          # Main interface strings
├── validation.php      # Form validation messages
├── otp.php             # Login and verification messages
├── faq.php             # FAQ questions and answers (the qa array)
├── install.php         # Installer text
├── javascript.php      # Strings used by front-end scripts
├── agent.php           # Agent API and agent key strings
├── business-page.php   # Public business page strings
├── card-studio.php     # Card studio designer strings
├── member-cards.php    # Member cards feature strings
├── pwa.php             # PWA offline page strings
├── qr-studio.php       # QR studio strings
└── md/                 # Markdown content pages
    ├── about.md        # About page
    ├── contact.md      # Contact page
    ├── privacy.md      # Privacy policy
    └── terms.md        # Terms of service

Note: Copy from en_US when you create a new language. It is the one folder guaranteed to be complete: install.php is absent in ar_SA and pt_BR.


Editing content pages

The About, Contact, Privacy Policy, and Terms pages are stored as Markdown files.

To edit one of these pages:

  1. Go to lang/<locale>/md/
  2. Open the relevant .md file (for example, privacy.md)
  3. Edit the text using Markdown syntax. The title, description, and icon at the top of the file (the frontmatter) set the page's heading and hero.

The FAQ is different. It is not a Markdown page. Its questions and answers live in lang/<locale>/faq.php, inside the qa array, each entry has a q (question) and an a (answer), and answers may include light HTML. Edit that file to change, add, or remove questions.


Setting the default language

If your application should default to a language other than English, add these variables to your .env file:

APP_LOCALE=pt_BR
APP_FALLBACK_LOCALE=pt_BR
Variable Purpose
APP_LOCALE The primary language shown to visitors
APP_FALLBACK_LOCALE Used when a translation key is missing in the current language

Protecting custom translations during updates

⚠️ Important: When you add or modify translations, you must protect them from being overwritten during automatic updates.

Activation vs. preservation: two different settings. APP_ACTIVE_LOCALES controls which languages are visible. PROTECTED_TRANSLATIONS controls which language folders survive updates. They are independent: activating a language does not protect its files, and protecting a folder does not make it active. If you translate or customize a language, set both: add the locale to APP_ACTIVE_LOCALES so people see it, and to PROTECTED_TRANSLATIONS so your edits aren't overwritten on the next update.

Add your custom translation directories to your .env file:

# Protect custom German and French translations
PROTECTED_TRANSLATIONS="de_DE,fr_FR"

Multiple directories are separated by commas. These paths are relative to the lang/ folder.

Why this matters

When you update Reward Loyalty:

  • The updater replaces core language files with new versions
  • Any customizations you made would be lost
  • The updater backs up and restores protected paths

What to protect

Protect any language folder where you have:

  • Translated content for a new language
  • Modified existing translations
  • Added custom Markdown content (privacy policy, terms, etc.)

Protecting other custom files

For custom files or directories outside of translations:

# Protect additional custom paths
PROTECTED_PATHS="custom/branding/,my-config.php"

Learn more: See Updating for complete documentation on how updates work and file preservation.


Cookies on this site.

Google Analytics runs only if you allow it. Cookie policy