1. Core Architecture
OwnPay uses a hybrid Database-and-Filesystem storage pattern for language translation files to ensure high performance during checkout hot-paths while allowing dynamic run-time adjustments from the Admin Panel.1.1 Translation Storage
- Database Table (
op_languages): Stores language profiles and translation catalogs. Contains the following columns:code(VARCHAR): The ISO 639-1 language code (e.g.,en,bn,es).name(VARCHAR): The human-readable name of the language (e.g.,English,Bengali,Spanish).status(ENUM): The state of the language (active,inactive). Only active languages can be resolved by the system.is_default(TINYINT): Indicator for the system-wide fallback default language.translations(JSON): The catalog of flat translation key-value mappings.
- Filesystem Compilation (
storage/languages/): To prevent database query overhead on high-throughput payment checkouts, translations are compiled tostorage/languages/{code}.jsonon-the-fly when a language is created, uploaded, or saved in the admin panel. - Base English Fallback (
config/languages/): English (en) acts as the base default locale and fallback. The master file is maintained atconfig/languages/en.json. If the compiled filesystem cachestorage/languages/en.jsonis missing or deleted, the system automatically recovers it by copying the contents fromconfig/languages/en.json.
2. Locale Resolution Pipeline
Locale resolution is managed in the HTTP request lifecycle by LanguageMiddleware:- Global Default Check: Resolves the default system language by querying the database for the active default language (fallback to
enif not specified). - Staff User Preference: If an administrative staff user is logged in, the middleware queries the
languagecolumn of theop_merchant_userstable for their explicit user preference. - Context Binding: The resolved locale is bound to the
TranslationServiceviasetLocale(), clearing any stale in-memory translations cache.
3. Translation Key Formatting
OwnPay enforces a flat, dot-notation format for translation keys.3.1 Dot-Notation
Language arrays uploaded via nested JSON structures are automatically flattened into a single-level key-value map using dot-notation. For example, the following nested JSON:3.2 Placeholders & Replacements
Dynamic parameters within translation strings are identified by a leading colon (:).
4. Usage in PHP Code
To use translations within PHP classes (Controllers, Services, Repositories), retrieve TranslationService from the PSR-11 dependency container:4.1 Fallback Rules
When$translationService->trans($key) is called:
- It searches the cached translations for the active locale (e.g.
bn). - If the key is missing or empty, it falls back to the baseline English (
en) catalog. - If the key is missing in English, the literal
$keystring is returned.
5. Usage in Templates & Checkout Themes
5.1 Admin Templates
Admin views utilize the base translations loaded during runtime. You can bind translated strings directly in Twig templates.5.2 Checkout Templates
Checkout views (e.g.templates/checkout/checkout.twig) represent white-labeled interfaces where merchants can customize standard messaging.
- The customer-facing templates access translation and branding strings through the
langview variable: - These variables are populated from the active brand profile, metadata overrides, or system-wide default settings by the BrandThemeService.
6. Translation Administration
Super-administrators can manage localization settings under System → Settings → Language in the Admin Sidebar:- Select Default Language: Sets the default fallback language for all sessions that do not carry a specific staff locale override.
- Manually Add Language: Registers a new language profile. The system initializes the translation catalog for this language by cloning the default English (
en) strings. - Upload Translation File: Imports a JSON file containing translation strings (supports flat or nested dictionaries).
- Translate Strings (Inline Editor): An interactive key-value form to edit translations line-by-line.
- Delete Language: Permitted for all languages except the base English (
en) configuration. Deleting a language deletes the corresponding records from the database and removes its filesystem cache file.
7. Contributing Translations
When submitting a pull request to add or update language translations:Step 1: Create the Translation Catalog
Create a translation JSON file using dot-notation. Placeholders (prefixed with:) must remain unchanged (e.g., :name, :amount must keep their colons).
Example es.json (Spanish):
Step 2: Test the Catalog
- Upload your JSON file via the Upload Translation File panel in settings.
- Verify that strings display correctly across the admin interface.
- Switch your staff user language to the newly uploaded language under Account → My Account to verify the user-specific middleware resolution.
Step 3: Update Default Config (For core languages)
If you are contributing a translation that should ship natively with OwnPay, place the file in theconfig/languages/ directory of your branch (e.g., config/languages/es.json) and submit a pull request on GitHub.