bitrix-localization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Localization

本地化

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:
    .../lang/<lang>/<...>
    mirrors the structure of the main code.
/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
Content:
php
<?php
$MESS['VENDOR_MODULE_POST_PUBLISHED'] = 'Post #NAME# published';
$MESS['VENDOR_MODULE_POST_EMPTY_TITLE'] = 'Post title is empty';
Prefix rules:
<VENDOR>_<MODULE>_<CONTEXT>_<CODE>
— a short unique key. Without a prefix, conflicts with other modules are likely.
  • 编码格式为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::getMessage
与短语加载

php
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
    #PLACEHOLDER#
    templates (historical convention). Keys in
    $replace
    — with hash marks.
  • $language
    — language ID (
    ru
    ,
    en
    ). If not passed — current site language.
Loc::loadMessages(__FILE__)
resolves the neighboring
lang/<lang>/<same_file>.php
from the caller path.
Loc::loadLanguageFile($path)
loads phrases for an arbitrary PHP file path (when the mapping is not “same name next to
__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
    数组中的键需带有哈希标记。
  • $language
    ——语言ID(如
    ru
    en
    )。若未传入,则使用当前站点的语言。
Loc::loadMessages(__FILE__)
会从调用者路径中解析相邻的
lang/<lang>/<same_file>.php
文件。
Loc::loadLanguageFile($path)
则可加载任意PHP文件路径对应的短语(当映射关系不是“与__FILE__同名相邻”时使用)。

When Explicit Loading is Needed

何时需要显式加载

For components, component templates, site templates, and Bitrix admin files, the kernel will automatically include neighboring
lang/<lang>/<same_file>.php
. Manually call
Loc::loadMessages(__FILE__)
if:
  • 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>.php
文件。若出现以下情况,需手动调用
Loc::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 (
ua
,
kz
→ "fall back" to
ru
).
php
$lang = Loc::getDefaultLang(LANGUAGE_ID); // 根据语言设置回退:'ru' → 'ru', 'ua' → 'ru'
当项目支持的语言范围超出模块所支持的语言时(如
ua
kz
),可使用此方法回退到模块的基础语言(如
ru
),用于生成语言包名称。

Lazy Loading and
BX_MESS_LOG

懒加载与
BX_MESS_LOG

The kernel loads a language file only upon the first
getMessage(...)
call from it — the "PHP file ↔ language file" mapping must be strict. If a
getMessage('FOO_BAR')
call comes from one file while the phrase is defined in another, the kernel will start scanning all files — this slows things down.
Diagnostics: enable in
/local/php_interface/init.php
:
php
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
    getMessage
    call originates.
  • 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.
系统仅在首次调用
getMessage(...)
时才会加载对应的语言文件——“PHP文件 ↔ 语言文件”的映射关系必须严格对应。如果在某个文件中调用
getMessage('FOO_BAR')
,但该短语定义在另一个文件中,系统会开始扫描所有文件,导致性能下降。
诊断方法:在
/local/php_interface/init.php
中启用日志:
php
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

Date/time/name formats are retrieved from
Bitrix\Main\Context\Culture
:
php
$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\Culture
获取:
php
$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.php
:
php
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>'
);
或者更符合规范的方式——通过
config.php
中的JS扩展:
php
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:index
命令

bash
php bitrix/bitrix.php translate:index
Indexes 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/
    ,
    lang/de/
    — in the root of the PHP file that uses them.
  • In the module's
    install/index.php
    , include translations:
    Loc::loadMessages(__FILE__)
    .
  • Use
    Loc::getDefaultLang(LANGUAGE_ID)
    to "fall back" to the module's base language (
    ru
    ) if
    kz
    /
    ua
    is missing.
  • Publish language names in the system via the Interface Languages form — it cannot be set from
    .settings.php
    .
  • 短语需存储在
    lang/ru/
    lang/en/
    lang/de/
    目录下,且与使用该短语的PHP文件位于同一根目录。
  • 在模块的
    install/index.php
    中引入翻译文件:
    Loc::loadMessages(__FILE__)
  • kz
    /
    ua
    等语言未提供,使用
    Loc::getDefaultLang(LANGUAGE_ID)
    回退到模块的基础语言(如
    ru
    )。
  • 通过界面语言表单在系统中发布语言名称——无法通过
    .settings.php
    设置。

Antipatterns

反模式

  • Hardcoding strings in services/controllers.
    Error
    message texts should be via
    Loc::getMessage
    .
  • getMessage('CODE')
    in one file when the phrase is defined in another → scanning all files, slowdown.
  • Copying phrases between modules via
    BX_MESS_LOG
    without analysis — risk of duplication and confusion.
  • Outputting dates via
    date('d.m.Y')
    instead of
    Culture::getDateFormat()
    — breaks multilingual projects.
  • Mixing UTF-8 and CP1251 in
    lang/
    — Bitrix will "re-convert" and you'll get garbled text.
  • JS phrases written as strings from PHP without
    htmlspecialcharsbx
    for headers going into attributes.
Set
default_language
in
.settings.php
for kernel default. BitrixVue 3 localization: skill
bitrix-vue
.
  • 在服务/控制器中硬编码字符串。错误提示文本应通过
    Loc::getMessage
    获取。
  • 在一个文件中调用
    getMessage('CODE')
    ,但短语定义在另一个文件中→系统会扫描所有文件,导致性能下降。
  • 未经分析就通过
    BX_MESS_LOG
    复制短语到其他模块——存在短语重复和混淆的风险。
  • 使用
    date('d.m.Y')
    输出日期而非
    Culture::getDateFormat()
    ——会破坏多语言项目的兼容性。
  • lang/
    目录中混合使用UTF-8和CP1251编码——Bitrix会自动重新转换,导致文本乱码。
  • PHP直接输出字符串作为JS短语,未对进入属性的内容使用
    htmlspecialcharsbx
    处理。
可在
.settings.php
中设置
default_language
作为系统默认语言。BitrixVue 3本地化相关技能:
bitrix-vue