bitrix-localization
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLocalization
本地化
Baseline: main 23.0+.
基线版本:main 23.0+。
Language File
语言文件
- Encoding UTF-8 without BOM.
- Translation file name matches the name of the PHP file it accompanies.
- Folder: mirrors the structure of the main code.
.../lang/<lang>/<...>
/local/modules/vendor.module/lib/Application/Service/PostService.php
/local/modules/vendor.module/lib/Application/Service/lang/ru/PostService.php
/local/modules/vendor.module/lib/Application/Service/lang/en/PostService.phpContent:
php
<?php
$MESS['VENDOR_MODULE_POST_PUBLISHED'] = 'Post #NAME# published';
$MESS['VENDOR_MODULE_POST_EMPTY_TITLE'] = 'Post title is empty';Prefix rules: — a short unique key. Without a prefix, conflicts with other modules are likely.
<VENDOR>_<MODULE>_<CONTEXT>_<CODE>- 编码格式为UTF-8 without BOM。
- 翻译文件名需与对应的PHP文件名完全匹配。
- 目录结构:与主代码的结构保持一致。
.../lang/<lang>/<...>
/local/modules/vendor.module/lib/Application/Service/PostService.php
/local/modules/vendor.module/lib/Application/Service/lang/ru/PostService.php
/local/modules/vendor.module/lib/Application/Service/lang/en/PostService.php内容示例:
php
<?php
$MESS['VENDOR_MODULE_POST_PUBLISHED'] = 'Post #NAME# published';
$MESS['VENDOR_MODULE_POST_EMPTY_TITLE'] = 'Post title is empty';前缀规则: —— 简短且唯一的键名。若不使用前缀,很可能与其他模块产生冲突。
<VENDOR>_<MODULE>_<CONTEXT>_<CODE>Loc::getMessage
and Loading Phrases
Loc::getMessageLoc::getMessage
与短语加载
Loc::getMessagephp
use Bitrix\Main\Localization\Loc;
Loc::loadMessages(__FILE__); // knowing where we are — the kernel will find the translation file
echo Loc::getMessage('VENDOR_MODULE_POST_PUBLISHED', ['#NAME#' => $post->getTitle()]);
echo Loc::getMessage('VENDOR_MODULE_POST_PUBLISHED', ['#NAME#' => 'x'], 'en');- Signature: .
Loc::getMessage(string $code, ?array $replace = null, ?string $language = null) - Substitutions — via templates (historical convention). Keys in
#PLACEHOLDER#— with hash marks.$replace - — language ID (
$language,ru). If not passed — current site language.en
Loc::loadMessages(__FILE__)lang/<lang>/<same_file>.phpLoc::loadLanguageFile($path)__FILE__php
use Bitrix\Main\Localization\Loc;
Loc::loadMessages(__FILE__); // 系统会根据当前文件路径自动查找对应的翻译文件
echo Loc::getMessage('VENDOR_MODULE_POST_PUBLISHED', ['#NAME#' => $post->getTitle()]);
echo Loc::getMessage('VENDOR_MODULE_POST_PUBLISHED', ['#NAME#' => 'x'], 'en');- 方法签名:。
Loc::getMessage(string $code, ?array $replace = null, ?string $language = null) - 占位符替换——通过模板实现(历史约定)。
#PLACEHOLDER#数组中的键需带有哈希标记。$replace - ——语言ID(如
$language、ru)。若未传入,则使用当前站点的语言。en
Loc::loadMessages(__FILE__)lang/<lang>/<same_file>.phpLoc::loadLanguageFile($path)When Explicit Loading is Needed
何时需要显式加载
For components, component templates, site templates, and Bitrix admin files, the kernel will automatically include neighboring . Manually call if:
lang/<lang>/<same_file>.phpLoc::loadMessages(__FILE__)- The file is outside the standard structure (e.g., ).
/local/php_interface/ - You have your own loader/class — each file must itself include its translations, otherwise lazy loading will break.
对于组件、组件模板、站点模板以及Bitrix后台文件,系统会自动引入相邻的文件。若出现以下情况,需手动调用:
lang/<lang>/<same_file>.phpLoc::loadMessages(__FILE__)- 文件位于标准结构之外(例如目录下)。
/local/php_interface/ - 自定义了加载器/类——每个文件必须自行引入其翻译文件,否则懒加载机制会失效。
Arbitrary File
加载任意文件
php
Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/custom.php');php
Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/custom.php');Module Default Language
模块默认语言
php
$lang = Loc::getDefaultLang(LANGUAGE_ID); // fallback from language settings: 'ru' → 'ru', 'ua' → 'ru'Use this when forming language package names if the project language is broader than those supported in the module (, → "fall back" to ).
uakzruphp
$lang = Loc::getDefaultLang(LANGUAGE_ID); // 根据语言设置回退:'ru' → 'ru', 'ua' → 'ru'当项目支持的语言范围超出模块所支持的语言时(如、),可使用此方法回退到模块的基础语言(如),用于生成语言包名称。
uakzruLazy Loading and BX_MESS_LOG
BX_MESS_LOG懒加载与 BX_MESS_LOG
BX_MESS_LOGThe kernel loads a language file only upon the first call from it — the "PHP file ↔ language file" mapping must be strict. If a call comes from one file while the phrase is defined in another, the kernel will start scanning all files — this slows things down.
getMessage(...)getMessage('FOO_BAR')Diagnostics: enable in :
/local/php_interface/init.phpphp
define('BX_MESS_LOG', $_SERVER['DOCUMENT_ROOT'] . '/var/log/bitrix/mess.log');The log will contain entries like:
[ru]SOME_MESSAGE: not found for /path/to/file.php
CTranslateUtils::CopyMessage('DEMO_CODE', '/path/a.php', '/path/b.php');How to fix:
- Copy the phrase to the language file of the module/code where the call originates.
getMessage - Rename the code to something unique if it conflicts with the kernel.
- Move the code to the correct file if it physically ended up in the wrong place.
Do not copy automatically — you might duplicate phrases; investigate the cause.
系统仅在首次调用时才会加载对应的语言文件——“PHP文件 ↔ 语言文件”的映射关系必须严格对应。如果在某个文件中调用,但该短语定义在另一个文件中,系统会开始扫描所有文件,导致性能下降。
getMessage(...)getMessage('FOO_BAR')诊断方法:在中启用日志:
/local/php_interface/init.phpphp
define('BX_MESS_LOG', $_SERVER['DOCUMENT_ROOT'] . '/var/log/bitrix/mess.log');日志中会包含类似如下的条目:
[ru]SOME_MESSAGE: not found for /path/to/file.php
CTranslateUtils::CopyMessage('DEMO_CODE', '/path/a.php', '/path/b.php');修复方案:
- 复制短语到调用的模块/代码对应的语言文件中。
getMessage - 若与系统内核冲突,重命名短语键为唯一名称。
- 若短语位置错误,移动代码到正确的文件中。
请勿自动复制短语——这可能导致短语重复,需先排查原因。
Regional Settings (Culture
)
Culture区域设置(Culture
)
CultureDate/time/name formats are retrieved from :
Bitrix\Main\Context\Culturephp
$culture = \Bitrix\Main\Context::getCurrent()->getCulture();
$culture->getDateTimeFormat(); // 'DD.MM.YYYY HH:MI:SS'
$culture->getDateFormat(); // 'DD.MM.YYYY'
$culture->getShortTimeFormat(); // 'HH:MI'
$culture->getNameFormat(); // '#LAST_NAME# #NAME# #SECOND_NAME#'
$culture->getNumberDecimals();
$culture->getNumberDecSeparator();
$culture->getNumberThousandsSeparator();Formatting:
php
use Bitrix\Main\Type\DateTime;
$date = new DateTime();
echo $date->format($culture->getDateTimeFormat());
// Via classic helpers:
echo \FormatDate($culture->getDateFormat(), $date->getTimestamp());
echo \CurrencyFormat(1234.5, 'RUB');Language setup: Settings → Product Settings → Language Parameters (date/time/name formats are set per site language). If a component is configured for its own format — it will take precedence.
日期/时间/姓名格式可通过获取:
Bitrix\Main\Context\Culturephp
$culture = \Bitrix\Main\Context::getCurrent()->getCulture();
$culture->getDateTimeFormat(); // 'DD.MM.YYYY HH:MI:SS'
$culture->getDateFormat(); // 'DD.MM.YYYY'
$culture->getShortTimeFormat(); // 'HH:MI'
$culture->getNameFormat(); // '#LAST_NAME# #NAME# #SECOND_NAME#'
$culture->getNumberDecimals();
$culture->getNumberDecSeparator();
$culture->getNumberThousandsSeparator();格式化示例:
php
use Bitrix\Main\Type\DateTime;
$date = new DateTime();
echo $date->format($culture->getDateTimeFormat());
// 通过经典助手函数:
echo \FormatDate($culture->getDateFormat(), $date->getTimestamp());
echo \CurrencyFormat(1234.5, 'RUB');语言设置路径:设置 → 产品设置 → 语言参数(日期/时间/姓名格式按站点语言分别设置)。若组件配置了自定义格式,则组件格式优先级更高。
Setting Phrases in JavaScript
在JavaScript中设置短语
PHP code publishes phrases in :
BX.message(...)php
\Bitrix\Main\Page\Asset::getInstance()->addString(
'<script>' . \Bitrix\Main\Web\Json::encode([
'VENDOR_POST_SAVE' => Loc::getMessage('VENDOR_POST_SAVE'),
'VENDOR_POST_CANCEL' => Loc::getMessage('VENDOR_POST_CANCEL'),
]) . '</script>'
);Or — more idiomatically — via a JS extension in :
config.phpphp
return [
'js' => 'script.js',
'css' => 'style.css',
'rel' => ['main.core'],
'lang_additional' => [
'VENDOR_POST_SAVE', 'VENDOR_POST_CANCEL',
],
];js
BX.message('VENDOR_POST_SAVE');
BX.message({ VENDOR_POST_DYNAMIC: 'Loaded asynchronously' });
const welcome = BX.message('WELCOME_TEXT').replace('#NAME#', userName);PHP代码可通过发布短语:
BX.message(...)php
\Bitrix\Main\Page\Asset::getInstance()->addString(
'<script>' . \Bitrix\Main\Web\Json::encode([
'VENDOR_POST_SAVE' => Loc::getMessage('VENDOR_POST_SAVE'),
'VENDOR_POST_CANCEL' => Loc::getMessage('VENDOR_POST_CANCEL'),
]) . '</script>'
);或者更符合规范的方式——通过中的JS扩展:
config.phpphp
return [
'js' => 'script.js',
'css' => 'style.css',
'rel' => ['main.core'],
'lang_additional' => [
'VENDOR_POST_SAVE', 'VENDOR_POST_CANCEL',
],
];js
BX.message('VENDOR_POST_SAVE');
BX.message({ VENDOR_POST_DYNAMIC: 'Loaded asynchronously' });
const welcome = BX.message('WELCOME_TEXT').replace('#NAME#', userName);BitrixVue 3
BitrixVue 3
js
// template
<button>{{ $Bitrix.Loc.getMessage('UI_BUTTON_SAVE') }}</button>
// with replacement + reactivity
{{ $Bitrix.Loc.getMessage('DEMO_COUNTER', { '#COUNTER#': this.counter }) }}
// programmatically
this.$Bitrix.Loc.setMessage({ DEMO_COUNTER: 'Counter: #COUNTER#' });
// optimization for heavy templates — (vueInstance, phrasePrefix, phrases?)
import { BitrixVue } from 'ui.vue3';
computed: {
localize() { return BitrixVue.getFilteredPhrases(this, 'MYCOMP_'); }
}js
// 模板
<button>{{ $Bitrix.Loc.getMessage('UI_BUTTON_SAVE') }}</button>
// 带替换+响应式
{{ $Bitrix.Loc.getMessage('DEMO_COUNTER', { '#COUNTER#': this.counter }) }}
// 程序化设置
this.$Bitrix.Loc.setMessage({ DEMO_COUNTER: 'Counter: #COUNTER#' });
// 重型模板优化 —— (vueInstance, phrasePrefix, phrases?)
import { BitrixVue } from 'ui.vue3';
computed: {
localize() { return BitrixVue.getFilteredPhrases(this, 'MYCOMP_'); }
}translate:index
Command
translate:indextranslate:index
命令
translate:indexbash
php bitrix/bitrix.php translate:indexIndexes language files so that the Settings → Localization → View Files page works (CSV export/import, package building). Run this after bulk adding new phrases to a module.
bash
php bitrix/bitrix.php translate:index该命令用于索引语言文件,使设置 → 本地化 → 查看文件页面正常工作(支持CSV导出/导入、语言包构建)。批量向模块添加新短语后需运行此命令。
Multilingual Modules
多语言模块开发
- Store phrases in ,
lang/ru/,lang/en/— in the root of the PHP file that uses them.lang/de/ - In the module's , include translations:
install/index.php.Loc::loadMessages(__FILE__) - Use to "fall back" to the module's base language (
Loc::getDefaultLang(LANGUAGE_ID)) ifru/kzis missing.ua - Publish language names in the system via the Interface Languages form — it cannot be set from .
.settings.php
- 短语需存储在、
lang/ru/、lang/en/目录下,且与使用该短语的PHP文件位于同一根目录。lang/de/ - 在模块的中引入翻译文件:
install/index.php。Loc::loadMessages(__FILE__) - 若/
kz等语言未提供,使用ua回退到模块的基础语言(如Loc::getDefaultLang(LANGUAGE_ID))。ru - 通过界面语言表单在系统中发布语言名称——无法通过设置。
.settings.php
Antipatterns
反模式
- Hardcoding strings in services/controllers. message texts should be via
Error.Loc::getMessage - in one file when the phrase is defined in another → scanning all files, slowdown.
getMessage('CODE') - Copying phrases between modules via without analysis — risk of duplication and confusion.
BX_MESS_LOG - Outputting dates via instead of
date('d.m.Y')— breaks multilingual projects.Culture::getDateFormat() - Mixing UTF-8 and CP1251 in — Bitrix will "re-convert" and you'll get garbled text.
lang/ - JS phrases written as strings from PHP without for headers going into attributes.
htmlspecialcharsbx
Set in for kernel default. BitrixVue 3 localization: skill .
default_language.settings.phpbitrix-vue- 在服务/控制器中硬编码字符串。错误提示文本应通过获取。
Loc::getMessage - 在一个文件中调用,但短语定义在另一个文件中→系统会扫描所有文件,导致性能下降。
getMessage('CODE') - 未经分析就通过复制短语到其他模块——存在短语重复和混淆的风险。
BX_MESS_LOG - 使用输出日期而非
date('d.m.Y')——会破坏多语言项目的兼容性。Culture::getDateFormat() - 在目录中混合使用UTF-8和CP1251编码——Bitrix会自动重新转换,导致文本乱码。
lang/ - PHP直接输出字符串作为JS短语,未对进入属性的内容使用处理。
htmlspecialcharsbx
可在中设置作为系统默认语言。BitrixVue 3本地化相关技能:。
.settings.phpdefault_languagebitrix-vue