自定义 BotFramework 消息对齐方式

问题描述 投票:0回答:1

我正在使用 BotFramework,并且正在寻求自定义聊天界面中呈现的消息的对齐方式。具体来说,我想确保阿拉伯语消息右对齐,而英语消息保持左对齐。目前,我正在使用 C# SDK 和 WebChat 来渲染聊天界面。但是,我找不到一种直接的方法来根据消息的语言动态调整对齐方式。谁能指导我如何实现这种定制?任何见解、代码片段或相关文档的指针将不胜感激! Chat example

我尝试过使用 Activity.TextFormat xml、markdown,但没有任何效果。

c# botframework direct-line-botframework
1个回答
0
投票

虽然网络聊天确实支持文本的“rtl”格式,但它适用于整个客户端。不幸的是,没有一种机制允许在逐条消息的基础上执行此操作。但这是可以通过一点工作实现的。

首先,我们需要设置机器人,以便它知道何时使用特定语言发送活动。例如,您可以使用本地化库(如 I18N)来检测语言并发送适当的响应。然而,为了简单起见,我通过检测“发送阿拉伯语”命令来发送活动来进行作弊。

请注意,我使用 JS SDK 执行此操作(因为它是我所知道的语言),但逻辑很简单易于理解。另外,请接受有关翻译文本的任何歉意。我只是从页面上抓取一些文本,使用翻译器,然后将其放入。

至于代码,您会注意到我已注释掉

locale
属性,并将其包含在
channelData
属性中。这是因为
locale
属性无法在活动中被覆盖。区域设置由 Azure Bot 服务确定,并且只能在例如生成 DirectLine 客户端(例如 Web 聊天)并连接到服务时进行更改。但是,由于我们正在逐条消息地工作,因此在这种情况下为整个客户端设置区域设置并不能为我们服务,这就是为什么我在
channelData
属性中指定区域设置。

在您的机器人中:

if (activity.text === 'send arabic') {
  await context.sendActivity(
    {
      text: 'هل أنت بصدد إنشاء واجهة مستخدم رسومية أمامية لبرنامج PowerShell النصي الخاص بك؟ هل اصطدمت بجدار مع تجميد واجهة المستخدم الرسومية Winforms؟ هل تواجه مشكلة في التخلص من تجمعات Runspace وجداول التجزئة وجلسات الولاية وتنظيف القمامة؟ \r\n أو ربما تريد ببساطة نقل لعبة البرمجة النصية إلى المستوى التالي ، وإنشاء أكثر من مجرد أمر cmdlet قديم عادي يعمل في نافذة وحدة التحكم. اقتحم مشهد مطور AAA هذا باستخدام تطبيق مرن ... حسنا ، ليس تماما ، لكننا نصل إلى هناك! \r\n ثم هذا بلوق وظيفة الحق في زقاقك...',
      type: 'message',
      // locale: 'ar',
      channelData: { locale: 'ar' },
    },
  );
}

接下来,我们需要设置网络聊天来检测来自机器人的传入活动,以便它知道何时使用“rtl”格式显示文本。为此,我们使用网络聊天的

store
。在商店中,我们监视包含文本以及
channelData
属性的活动,该属性还包含值为“ar”的
locale
属性。

一旦检测到,我们就会搜索正在呈现的关联 HTML 元素。我们通过查找渲染文本时使用的类来做到这一点。我们使用

.querySelectorAll()
创建找到的元素的数组。由于我们没有任何东西可以用来指定确切的文本元素,因此我们只需使用生成的数组并选择其中的最后一个元素。然后,我们找到包含
webchat__bubble
类的最近元素,因为这是控制文本方向的元素,并添加
webchat__bubble--rtl
类和值为“rtl”的
dir
属性。

最后,我们需要将所有这些包装在

setTimeout()
中。为什么?因为网络聊天的功能。所有传入的活动都通过其
store
传递,在渲染之前对其进行处理。如果没有
setTimeout()
,我们尝试对 DOM 施加的任何更改都将在 Web Chat 呈现元素之前发生。因此我们将超时设置为 100 - 400 毫秒之间。少于100,我们就会遇到上述问题。如果我们使用大于 400 的值,我们就会面临任何更改在用户面前可见呈现的风险。

在您的网络聊天脚本中:

const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => async action => {
  if ( action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' ) {
    const { activity } = action.payload;

    if ( activity.text && activity.channelData && activity.channelData.locale === 'ar' ) {
      setTimeout(() => {
        const textElements = document.querySelectorAll('.webchat__bubble__content .webchat__text-content');
        const elementIndex = textElements.length - 1;
        // textElements[elementIndex].style.direction = 'rtl';
        const bubbleFromUser = textElements[elementIndex].closest('.webchat__bubble');
        bubbleFromUser.classList.add('webchat__bubble--rtl');
        bubbleFromUser.setAttribute( 'dir', 'rtl' );
      }, 300);
    }
  }
  next( action );
} );

window.ReactDOM.render(
  <ReactWebChat
    directLine={ directLine }
    store={ store }
    activityMiddleware={ activityMiddleware }
  />,
  document.getElementById( 'webchat' )
);

enter image description here

现在,有几点需要注意。您应该认为这是一种解决方法,而且是一个不完美的方法。但我已经使用了好几年了,并且也向许多其他人推荐过它。我还没有听到投诉。但请记住:

  • 我们正在对 DOM 进行更改。而且,由于 Web Chat 是使用 React 构建的,因此 Web Chat 不会知道我们进行了任何更改。因此,如果您使用 local/sessionStorage 来保存对话,并且用户刷新或导航离开并返回,则所做的任何 UI 更改都将丢失。
  • 我们正在根据类名称和元素进行更改,这些名称和元素可能会在未来版本的 Web Chat 中发生更改。如果发生更改,它将破坏您的网络聊天实例,直到您可以自己进行更新。
  • 超时并非万无一失。再说一遍,我没有听说或经历过任何问题,但网络延迟或其他某个点可能会影响其工作效果。

希望有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.