Symfony Translation 复数处理详解
基本配置
Symfony 使用 ICU MessageFormat 来处理复数规则,支持多种语言的复杂复数形式。

消息格式
YAML 格式:
# translations/messages.en.yaml
apples: '{count} apple|{count} apples'
# translations/messages.pl.yaml (波兰语有3种复数形式)
apples: '{count} jabłko|{count} jabłka|{count} jabłek'
# translations/messages.ar.yaml (阿拉伯语有6种复数形式)
apples: '{count} تفاحة|{count} تفاحتين|{count} تفاحات|{count} تفاحة|{count} تفاحة|{count} تفاحة'
使用方式
在模板中:
{# 直接使用 #}
{{ 'apples'|trans({'count': 5}) }}
{# 带参数 #}
{% set count = 3 %}
{{ '{count} item|{count} items'|transchoice(count) }}
在控制器中:
// 使用 TranslatorInterface
use Symfony\Contracts\Translation\TranslatorInterface;
class ProductController extends AbstractController
{
public function index(TranslatorInterface $translator)
{
$translated = $translator->trans(
'{count} item|{count} items',
['count' => 5],
'messages'
);
// 或使用 transChoice (已废弃,但旧项目可能使用)
$translated = $translator->transChoice(
'{0} No items|{1} One item|]1,Inf[ %count% items',
5,
['%count%' => 5]
);
}
}
ICU 消息格式高级用法
# translations/messages.en.yaml
order:
status: |
{status, select,
pending {Order is pending}
confirmed {Order confirmed}
shipped {Order shipped}
delivered {Order delivered}
other {Unknown status}
}
product:
count: |
{count, plural,
=0 {No products}
=1 {One product}
one {# product}
few {# products}
many {# products}
other {# products}
}
# 组合使用
summary: |
{gender, select,
male {{count, plural, =0{He has no items} one{He has # item} other{He has # items}}}
female {{count, plural, =0{She has no items} one{She has # item} other{She has # items}}}
other {{count, plural, =0{They have no items} one{They have # item} other{They have # items}}}
}
XLIFF 格式
<!-- translations/messages.en.xlf -->
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="en" datatype="plaintext">
<body>
<trans-unit id="1">
<source>apples</source>
<target>{count} apple|{count} apples</target>
<note>Apple count</note>
</trans-unit>
</body>
</file>
</xliff>
自定义复数规则
创建自定义复数解析器:
// src/Translation/PluralizationRules.php
namespace App\Translation;
use Symfony\Component\Translation\PluralizationRules;
class CustomPluralizationRules
{
public static function getRule($number, $locale)
{
// 为特定语言自定义复数规则
if ('zh' === $locale) {
// 中文通常没有复数变化
return 0;
}
return PluralizationRules::get($number, $locale);
}
}
在配置中注册:
# config/packages/translation.yaml
framework:
translator:
paths:
- '%kernel.project_dir%/translations'
# 自定义复数规则
pluralization:
rules: 'App\Translation\CustomPluralizationRules::getRule'
最佳实践
# translations/messages.en.yaml
# ✅ 好的做法:明确指定所有可能的值
items: |
{count, plural,
=0 {No items}
=1 {One item}
=2 {Two items}
other {# items}
}
# ✅ 使用数字范围
age: |
{age, select,
child {You are a child}
teen {You are a teenager}
adult {You are an adult}
senior {You are a senior}
other {You are {age} years old}
}
# ❌ 避免:依赖默认值
items: '{count} items|{count} items' # 同一字符串两次
# ✅ 正确:使用 plural 而不是 manual pipe
items: |
{count, plural,
one {# item}
other {# items}
}
测试复数翻译
// tests/Translation/PluralTranslationTest.php
namespace App\Tests\Translation;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class PluralTranslationTest extends KernelTestCase
{
public function testPluralTranslations()
{
self::bootKernel();
$translator = self::$container->get('translator');
$testCases = [
['count' => 0, 'expected' => 'No items'],
['count' => 1, 'expected' => 'One item'],
['count' => 2, 'expected' => '2 items'],
['count' => 5, 'expected' => '5 items'],
];
foreach ($testCases as $testCase) {
$translated = $translator->trans(
'{count, plural, =0{No items} =1{One item} other{# items}}',
['count' => $testCase['count']]
);
$this->assertEquals(
$testCase['expected'],
$translated,
sprintf('Translation for count %d failed', $testCase['count'])
);
}
}
}
注意事项
-
复数规则差异:不同语言复数规则不同
- 英语:2种 (singular/plural)
- 中文:1种
- 俄语:3种
- 阿拉伯语:6种
-
性能考虑:频繁的复数翻译可能影响性能,考虑缓存
-
向后兼容:
transChoice()在 Symfony 5+ 中被标记为废弃 -
格式选择:推荐使用 ICU 格式而不是 pipe 分隔格式
调试工具
# 查看所有可用的翻译 php bin/console debug:translation en # 检查特定翻译 php bin/console translation:extract en --prefix="messages"
这样你就能在 Symfony 项目中正确处理各种语言的复数形式了!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播