Skip to main content
Version: 4.0 preview

Language Overrides (changing displayed text)

Version
4.0 preview
Updated
View markdown

How to change the wording of CBX's interface text — relabel a field, reword a tooltip, retitle a button — without editing core language files. This is the language_overrides/ mechanism: a single overrides.ini per language whose entries are loaded last, so they win over the shipped strings.

It is a small mechanism, but it comes with one essential distinction: CBX has two text systems, and overrides.ini only touches one of them. §1 sorts that out; get it right and the rest is a one-file edit.

Read com_configbox_customization_overview.md first. All paths are relative to the component root docroot/components/com_configbox/. Source references are point-in-time (component 3.4.1) — verify against the code.


1. Which text system are you changing? (read this first)

If the text is…It comes from…Change it via…
Static UI text — field labels, tooltips, buttons, messages, headings (keyed strings like FIELD_LABEL_COMPONENT_SKU)the INI language files (language/<tag>/frontend.ini / backend.ini), resolved by KText::_()language_overrides/<tag>/overrides.ini — this guide
Admin-authored content — a product's name, a page's description, an option's label, country namesthe EAV #__configbox_strings table, edited per-language in the admin (via the translatable property type)the admin UI (edit the record in that language), not overrides.ini

overrides.ini overrides static UI strings only. Content strings live in the database and are translated by editing the record in each active language — there is no file override for them. (This is the EAV i18n system the project notes refer to; it is separate from the INI files this guide covers.)

Quick test: if the text has an ALL_CAPS key and is the same for every product (a label, a button, an error), it's an INI string → overrides.ini. If it's specific to one product/option/page and an admin typed it, it's a content string → edit it in the admin.


2. How the override is resolved

KText::getLanguageFiles() (external/kenedo/classes/KText.php:173-207) builds the list of INI files to load for the active language, in this order:

language/en-GB/frontend.ini ← en-GB is the built-in fallback (loaded first)
language/<tag>/frontend.ini ← the active language
language/en-GB/backend.ini ┐ (admin pages only)
language/<tag>/backend.ini ┘
data/customization/language_overrides/<tag>/overrides.ini ← YOUR overrides (loaded LAST)

Each file is parsed and merged into one map, later files overwriting earlier keys (load(), :214-234):

foreach ($strings as $key => $string) {
self::$strings[$languageTag][$key] = $string; // last write wins
}

Because overrides.ini is loaded last (:195), any key you set there beats the shipped value — for both frontend and backend strings of that language. Missing files are skipped silently (:199-203), so you only ship the overrides.ini for languages you actually customize.

Per language tag. The override file is keyed by the active language tag (<tag>, e.g. en-US, de-DE). To override the same string in two languages, add an overrides.ini under each tag's folder. The active tag is the platform language if it's an active CB language, else the CB default (determineLanguage(), :151-165).


3. Finding the key to override

Keys are looked up upper-cased (_() does strtoupper($key), :261), so override keys are by convention ALL_CAPS and match case-insensitively. To find the key for a piece of text:

  • Grep the shipped INI files for the visible text: grep -ri "SKU/Code Segment" language/ → gives you the key (e.g. FIELD_LABEL_COMPONENT_SKU).
  • Or grep templates/code for the KText::_('SOME_KEY') call that emits it.

Then copy that key into your overrides.ini with your new value.

Two lookup quirks worth knowing (rarely needed, but they explain odd keys):

  • Trailing colonKText::_('Name:') will match a key NAME and re-append the colon (:258-266). So override NAME, not NAME:.
  • Parentheses in keys are encoded to __POPEN__ / __PCLOSE__ (:255-256). You'll see these in the shipped files; match them if you override such a key.

4. Writing overrides.ini

Standard PHP INI syntax (parse_ini_file, :221): KEY="value", one per line; quote the value and keep it on one line. From the shipped en-US/overrides.ini (real example):

; data/customization/language_overrides/en-US/overrides.ini

FIELD_LABEL_COMPONENT_SKU="SKU/Code Segment"
TOOLTIP_COMPONENT_SKU="This code will be included in the configuration code. Enter (none) if you don't want this answer to add to the code."

FIELD_LABEL_QUESTION_HEADING="Heading (generic for both metric and imperial)"
TOOLTIP_QUESTION_HEADING="Tell what should show in the heading above the question"

Each line replaces the shipped string for that key in that language. INI gotchas:

  • Always quote values (KEY="…"). Unquoted values with spaces/special characters break parsing or get truncated.
  • Escape inner double quotes or use single quotes inside, and avoid raw " mid-value.
  • No multi-line values. Keep each string on one line.
  • A parse error logs and the whole override file is skipped (:223-226) — if your overrides "don't apply", check the INI syntax first.

5. Deployment checklist

data/customization/
language_overrides/
<tag>/ ← one folder per language tag you customize (e.g. en-US, de-DE)
overrides.ini ← KEY="new value" lines; loaded LAST, wins over shipped strings
  1. Confirm it's a UI/INI string, not admin content (§1). Content → edit in the admin instead.
  2. Find the key by grepping language/ for the current text (§3).
  3. Add KEY="new value" to data/customization/language_overrides/<tag>/overrides.ini, quoted, one line (§4).
  4. Repeat per language — one overrides.ini per tag.
  5. Verify manually — reload the screen in that language and confirm the new text (and that you didn't break the INI: a syntax error silently drops all your overrides). CBX has zero automated tests.

6. Conventions & gotchas

  • overrides.ini is for INI/UI strings only. Admin-authored content lives in #__configbox_strings and is translated in the admin, not here (§1).
  • Loaded last → wins. Your keys override shipped frontend and backend strings for that language (:195).
  • Keys are upper-cased on lookup — write ALL_CAPS keys; matching is case-insensitive (§3).
  • Per language tag — add an overrides.ini under each <tag>/ you want to change.
  • Quote values, single line, valid INI — a parse error drops the whole file silently (§4).
  • Find keys by grepping language/ for the visible text, or for the KText::_('KEY') call.
  • Override NAME, not NAME: — trailing colons are handled automatically (§3).

See also

  • com_configbox_customization_overview.md — the extension-point map (this is a merge/append mechanism: your file is combined with the shipped INI files, loaded last).
  • external/kenedo/classes/KText.phpgetLanguageFiles() (:173, the load order), load() (:214, last-write-wins), _() (:241, the lookup + quirks).
  • language/<tag>/ — the shipped INI files to grep for keys and copy from.
  • external/kenedo/properties/translatable.php — the translatable property type that stores admin-authored content strings in #__configbox_strings (the other i18n system, not overridable here).