Multi-Language Integration & Source of Truth
PolyCMS offers a robust, globally available translation architecture that automatically discovers and merges localization files from the Core, Modules, and Themes.
To ensure performance without sacrificing ease of use for administrators, the system uses a Compilation Pipeline architecture. As a developer, it is critical to understand the concept of the Source of Truth to prevent data loss or silent translation failures.
1. The Compilation Pipeline Architecture
PolyCMS separates translation storage into two formats:
.jsonfiles (The Source of Truth): These are human-readable, administrator-editable dictionary files..phpfiles (The Compiled Cache): These are high-performance PHP arrays generated by the system.
How it works at Runtime
When a page loads (Backend or Frontend) and a string needs translation, the core LanguageHelper only reads from the compiled .php cache files. It does not scan or parse .json files at runtime to guarantee maximum rendering speed.
How it works during Editing
When an administrator edits a language via the PolyCMS Admin UI (Settings > Languages), the system reads and writes to the .json files. After saving, the system automatically triggers the compiler to regenerate the .php cache.
2. Developer Workflow: Adding Translations
When developing a Module or Theme, you will often need to add new translatable strings.
File Location
Translations should be placed in the lang/ directory at the root of your extension:
- Module:
modules/Vendor/ModuleName/lang/{locale}.json - Theme:
themes/theme-slug/lang/{locale}.json
The Golden Rule
CRITICAL: The
{locale}.jsonfile is the absolute Source of Truth. You must never manually edit the{locale}.phpfile, as the system compiler will overwrite it.
Step-by-Step Translation Workflow
-
Add to JSON: Open your module or theme's
lang/en.jsonorlang/vi.jsonand add your new key-value pairs.{ "My Custom Setting": "Cài đặt tùy chỉnh của tôi", "Show Blog Header": "Hiển thị Header Blog" } -
Compile to PHP: Because the system only reads from
.php, your new JSON keys will not take effect until they are compiled. You must manually trigger the compiler in your development environment.Using Artisan Tinker:
php artisan tinker --execute="app(\App\Services\LanguageService::class)->compileToPhp('vi');"Alternatively, you can go to the PolyCMS Admin panel: Settings > Languages, and click the Compile button.
-
Verify: Hard reload (
Ctrl + F5) your browser. The new translations should now appear in the UI.
3. Formatting Warnings & Silent Failures
If you run the compilation command but your translations still do not appear, it is almost always due to an invalid JSON file.
If json_decode() fails to parse your .json file, the LanguageService will silently skip it to prevent crashing the application.
Common JSON formatting errors to avoid:
- UTF-8 BOM: Ensure your code editor (or terminal commands like PowerShell's
Set-Content) does not inject a Byte Order Mark (BOM). The file must be pureUTF-8. - Trailing Commas: JSON does not allow trailing commas after the last item.
- Unescaped Quotes: Ensure any double quotes inside your string are properly escaped (e.g.,
\").
4. Using Translations in Code
Once compiled, you can use the translation strings seamlessly across different layers of your module or theme.
In Blade Templates
Always wrap hardcoded text in Laravel's native translator __() or the PolyCMS helper _l():
<button>{{ __('Show Blog Header') }}</button>
In PHP (Controllers, Service Providers)
Use the _l() helper for administrative strings, menu labels, or settings:
$menuRegistry->addChild('content', [
'key' => 'blog_enhancer_tools',
'label' => _l('SEO Tools'), // Translates automatically based on Admin's language
'url' => '/admin/blog-enhancer'
]);
In Vue Components
Import and use the global useTranslation composable:
import { useTranslation } from '@/admin/composables/useTranslation';
const { t } = useTranslation();
// In your Vue template:
// <h2>{{ t('SEO Tools') }}</h2>