【问题标题】:Does the symfony translation system support an arbitrary-length list of elements to be concatenated?symfony 翻译系统是否支持连接任意长度的元素列表?
【发布时间】:2020-06-27 03:59:54
【问题描述】:

我需要在 Symfony 3.4 中翻译可变长度的句子。

示例句:“包括:4 份早餐、1 份早午餐和 3 份晚餐。”

例如,假设以下约束:

  1. 我必须表示一次旅行在完整行程中可能包含的早餐、早午餐、午餐和晚餐的数量
  2. 要枚举的“事物”列表是已知且有限的。每个关键词都有单数和复数翻译。
  3. 并非所有这些都必须出现。如果有 0 个单元,则将省略整个块。
  4. 列表以逗号分隔。
  5. 除了最后一个添加了“and”连接器的块。
  6. 如果只有 1 个块,则没有逗号,也没有“and”连接符。
  7. 每个都可以是单数/复数。
  8. 有多种语言,在本例中我将使用英语和西班牙语,但实际上也有加泰罗尼亚语。

English-singular / english-plural / spanish-singular / spanish-plural 中的关键字如下:

breakfast / breakfasts / desayuno / desayunos
brunch / brunches / alumerzo-desayuno / almuerzo-desayunos
lunch / lunches / almuerzo / almuerzos
dinner / dinners / cena / cenas

所以...我可以想象以下测试用例:

[
    'language' => 'en-US',
    'parameters' => [
        'breakfast' => 4,
        'dinner' => 1,
    ],
    'expectedOutput' => 'Included: 4 breakfasts and 1 dinner.'
],
[
    'language' => 'es-ES',
    'parameters' => [
        'breakfast' => 2,
        'brunch' => 1,
        'lunch' => 5,
        'dinner' => 2,
    ],
    'expectedOutput' => 'Incluido: 2 desayunos, 1 desayuno-almuerzo, 5 almuerzos y 2 cenas.'
],
[
    'language' => 'en-US',
    'parameters' => [
        'breakfast' => 1,
    ],
    'expectedOutput' => 'Included: 1 breakfast.'
],
[
    'language' => 'es-ES',
    'parameters' => [
        'dinner' => 4,
        'lunch' => 3,
    ],
    'expectedOutput' => 'Incluido: 3 almuerzos y 4 cenas.'
],

问题

  • Symfony 3.4 中的本地翻译引擎是否支持此功能?
  • 如果不支持,Symfony 4 或 5 的本地翻译引擎是否支持?
  • 否则,是否有任何已知的模式或策略适合这种情况?

【问题讨论】:

    标签: symfony translation symfony-3.4 variable-length-array


    【解决方案1】:

    翻译引擎在某种程度上可以做的是使用一个数字在不同的情况之间切换(单数/复数)。查看transChoice 的 symfony 3.4(显然是 4.1.x)。从 symfony 4.2 开始,ICU message format(也可以点击链接)可以用来处理复数。

    但是,(有条件的)字符串构建根本不是翻译引擎的任务(即使对于简单的情况,transChoice 或 ICU 消息格式可能工作得很好)。因此,您最终可能会从零碎中构建字符串。

    在php中构建字符串

    // fetch translations for the itemss
    $items = [];
    foreach($parameters as $key => $count) {
        if($count <= 0) {
            continue;
        } 
    
        $items[] = $translator->transChoice($key, $count);
    }
    
    // handle 2+ items differently from 1 item
    if(count($items) > 1) {
        // get last item
        $last = array_pop($items);
        // comma-separate all other items, add last item with "and"
        $itemstring = implode(', ', $items)
            . $translator->trans('included_and') 
            . $last; 
    } else {
        $itemstring = $items[0] ?? ''; // if no items or something like 
                                       // $translator->trans('included_none')
    }
    
    return $translator->trans('included', ['%items%' => $itemstring]);
    

    并在翻译文件中(英文):

    'included' => 'Included: %items%.',
    'included_and' => ' and ',
    'breakfast' => '%count% breakfast|%count% breakfasts', // etc. for all other stuff
    

    请注意,transChoice应该自动将 %count% 占位符设置为作为 transChoice 的第二个参数提供的计数。

    替代方法

    如果您想避免使用transChoice,您可以轻松地将可翻译的字符串拆分为breakfast_singularbreakfast_plural,则必须替换

    transChoice($key, $count)
    

    trans($key.($count > 1 ? '_plural' : '_singular'), ['%count%' => $count])
    

    您还可以使用适当的参数和条件将included 字符串扩展为included_singleincluded_multiple,其中后者被翻译为'Included: %items% and %last%'

    但最终,字符串生成或更具体的语言生成对于简单的翻译引擎来说并不是真正的工作。

    【讨论】:

      猜你喜欢
      • 2012-01-17
      • 2014-03-29
      • 2018-04-02
      • 2011-07-30
      • 2011-04-12
      • 2012-04-14
      • 2012-04-01
      • 1970-01-01
      • 2022-01-15
      相关资源
      最近更新 更多