← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Translation Management

i18n PHP 5.0+ Intermediate
debt(d7/e7/b7/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints note automated=no, and while tools like php-translation, symfony-translation, crowdin, and poeditor exist, they catch workflow gaps (missing translations, out-of-sync strings) rather than the structural mistakes like string concatenation or missing plural forms — those require code review or QA with native speakers. The problems are often invisible in development (English works fine) and only surface when actual translated content is displayed.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix describes adopting ICU message format, migrating to PHP arrays/YAML, and integrating external translation platforms. Fixing string concatenation patterns (__('You have') . $count . __('messages')) requires touching every such instance throughout the codebase, updating translation files, adding proper plural forms, and establishing a new workflow — this spans multiple files and components, trending toward cross-cutting.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). Translation management applies to web and CLI contexts across the entire application. Once strings are hardcoded or concatenated incorrectly, every new feature must follow the same broken pattern or risk inconsistency. The choice of i18n strategy shapes how all user-facing strings are written, how translators are engaged, and how plural/gender/register logic is handled — every future maintainer is affected by the established pattern.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field directly states the trap: developers treat translation as mere string replacement, missing that languages have different word orders, up to 6 plural forms (Arabic), grammatical gender, and formal/informal registers. The common mistakes confirm this — the 'obvious' approach of concatenating translated fragments feels correct to an English-speaking developer but produces grammatically wrong output in many languages. This contradicts the intuitive mental model of 'just replace words.'

About DEBT scoring →

Also Known As

gettext Weblate i18n workflow translation strings po files

TL;DR

Organising, extracting, and synchronising translatable strings — gettext .po/.mo files, ICU MessageFormat, and tools like Weblate or Crowdin for translator workflows.

Explanation

Translation management involves: string extraction (identifying all translatable strings in code), storage format (gettext .po files, JSON, XLIFF, ICU), translator workflow (tools like Weblate, Crowdin, Lokalise), and deployment (compiling .po to .mo, importing JSON). PHP implementations: gettext() + ngettext() with .po/.mo files (compiled binary), symfony/translation component (multiple formats), Laravel's __() helper with JSON or PHP array files. Key principles: use ICU MessageFormat for pluralisation and complex messages, never concatenate translated strings (word order differs between languages), and extract strings with context to help translators.

Common Misconception

Translation is just string replacement — languages have different word orders, plural forms (Arabic has 6), grammatical gender, and formal/informal registers; correct translation requires context and ICU MessageFormat for dynamic content.

Why It Matters

Concatenating translated fragments ('You have' . $count . 'messages') produces grammatically wrong sentences in many languages where adjectives, verbs, and nouns change based on count and gender.

Common Mistakes

  • String concatenation: __('You have') . $count . __('messages') — word order breaks in many languages.
  • No context for translators — 'Open' can mean open door, open file, or business status.
  • Not using plural forms — ngettext() or ICU plural rules; hardcoded English plurals break other languages.
  • Translating without a process — strings get out of sync between code and translation files.

Code Examples

✗ Vulnerable
// Concatenation breaks word order:
echo __('Hello') . ' ' . $userName . ', ' . __('you have') . ' ' . $count . ' ' . __('messages');
// German: 'Hallo Alice, Sie haben 5 Nachrichten' — word order different
// Cannot be correctly translated by substituting individual words
✓ Fixed
// ICU MessageFormat — full sentence with placeholders:
$message = $formatter->format(
    '{greeting}, {name}! {count, plural, one {You have # message} other {You have # messages}}.',
    ['greeting' => __('Hello'), 'name' => $userName, 'count' => $count]
);
// Translator gets the full sentence with context
// Each language provides its own plural rules

// gettext with context:
$msg = pgettext('button label', 'Open'); // Different from pgettext('status', 'Open')

Added 16 Mar 2026
Edited 12 Jun 2026
Views 74
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 3 pings F 1 ping S 2 pings S 0 pings M 0 pings T 2 pings W 1 ping T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F
Applebot 1
Brave Search 1
Amazonbot 9 Perplexity 7 ChatGPT 7 Google 6 Ahrefs 5 Unknown AI 4 SEMrush 4 Bing 3 PetalBot 3 Brave Search 3 Scrapy 2 Twitter/X 2 Claude 1 Meta AI 1 Applebot 1
crawler 54 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Store translations in PHP arrays or YAML, use the ICU message format for pluralisation and variables, and integrate Crowdin or POEditor for non-developer translators
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
Translations hardcoded in PHP files; no plural forms support; string concatenation with translated parts (breaks right-to-left languages)
Auto-detectable: ✗ No php-translation symfony-translation crowdin poeditor
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant