Internacionalizar e Localizar Respostas de Componentes Personalizados

Se você tiver componentes personalizados que retornem conteúdo em conversas, também será necessário garantir que eles retornem esse conteúdo no idioma de destino do usuário.

Há várias maneiras de fazer isso:
  • Crie entradas do pacote de recursos na habilidade e faça referência a elas diretamente no componente personalizado. Essa abordagem permite que você trate traduções de mensagens de componentes personalizados no mesmo local que você para outras mensagens da habilidade.
  • Use um componente do sistema e entradas do pacote de recursos para montar as strings traduzíveis que incorporam a saída de dados do componente personalizado. Essa abordagem permite que você trate traduções de mensagens de componentes personalizados no mesmo lugar que para outras mensagens da habilidade, promovendo um acoplamento mais fraco entre o componente personalizado e essa habilidade específica.
  • Se quiser usar o serviço de tradução da habilidade para traduzir as respostas do componente, defina a propriedade translate do componente personalizado como true.
  • Se o seu componente recuperar e retornar dados de backend que precisam ser incorporados a uma mensagem e você quiser usar o serviço de tradução da habilidade para traduzir as respostas do componente, armazene esses dados retornados em uma variável no fluxo de caixas de diálogo. Em seguida, você pode fazer referência a essa variável em um componente do sistema.

Fazer Referência a Pacotes de Recursos do Componente Personalizado

Assim como você pode usar pacotes de recursos para mensagens em componentes integrados, intenções de resposta etc., você também pode usar pacotes de recursos para seus componentes personalizados. Para isso, é necessário:

  1. Defina entradas do pacote de recursos na habilidade para sua mensagem. Consulte Criar Chaves de Pacote de Recursos.
  2. Usando o método context.translate() do Bots Node SDK, faça referência às chaves de pacotes de recursos do código do componente personalizado.

    O context.translate() usa um nome de chave do pacote de recursos especificado (e qualquer parâmetro especificado na entrada do pacote de recursos) e gera o modelo FreeMarker apropriado necessário para carregar a string de idioma do pacote de recursos nomeado quando a conversa é enviada de volta ao usuário por meio do método context.reply().

  3. Use o método auxiliar context.reply para imprimir a resposta traduzida. Por exemplo :
    context.reply(translate('date.message', dateToday, dayOfWeek ));
  4. Documente todas as chaves de pacotes de recursos às quais o componente personalizado faz referência, bem como as strings padrão esperadas. (Como o componente personalizado faz referência diretamente à chave do pacote de recursos dentro da habilidade, é necessário haver um alto grau de coordenação entre o desenvolvedor do componente personalizado e aqueles que criam a habilidade para garantir que as chaves referenciadas sejam válidas dentro da habilidade).

Neste exemplo, date.message é uma chave de pacote de recursos, dateToday e dayOfWeek são variáveis e uma expressão FreeMarker como a seguinte é retornada:

${rb('date.message', 'Monday', 'July 12, 2021')}

Observação

O método context.translate() só suporta valores de pacotes de recursos que não têm parâmetros ou que usam parâmetros posicionais (numerados). Por exemplo, no caso do exemplo de chave date.message, seu valor pode ser algo como “Today is {0}, {1}”. Não há suporte para parâmetros nomeados e formatos de mensagem complexos.

Usar um Componente de Sistema para Fazer Referência a um Pacote de Recursos

Você pode usar um componente do sistema para montar mensagens usando entradas do pacote de recursos e dados que foram retornados de um componente personalizado. Você define as strings de mensagem base nas entradas do pacote de recursos. As entradas do pacote podem incluir parâmetros para dados (como números e datas) que são gerados do componente personalizado. Como as strings de mensagem base são definidas no fluxo de caixas de diálogo, essa abordagem garante que os componentes personalizados não dependam do código de implementação específico e permaneçam reutilizáveis.

Estas são as etapas gerais:

  1. Para o componente personalizado, inclua um parâmetro de entrada obrigatório para o nome da variável de contexto na qual armazenar os dados retornados.
  2. Como o desenvolvedor do componente personalizado e o desenvolvedor do fluxo de caixas de diálogo podem não ser a mesma pessoa ou até mesmo na mesma equipe, documente cuidadosamente quais dados o componente personalizado retorna nessa variável e disponibilize as informações a qualquer consumidor do componente personalizado para que ele entenda como apresentar os dados retornados ao usuário em uma mensagem.
  3. No fluxo de caixas de diálogo, crie uma variável para armazenar os dados retornados do componente personalizado e informe seu nome no parâmetro de entrada necessário.
  4. Defina entradas do pacote de recursos na habilidade para sua mensagem. Consulte Criar Chaves de Pacote de Recursos.
  5. No fluxo de caixas de diálogo, faça referência à entrada do pacote de recursos e preencha todos os parâmetros necessários.

A amostra a seguir de uma habilidade desenvolvida no modo de caixa de diálogo YAML faz referência a um componente personalizado no estado initializeReceipt e informa o nome da variável (receipt) que contém a resposta do componente e purchaseId como parâmetros de entrada. O estado printProduct então incorpora o valor receipt como parâmetro em uma referência à entrada do pacote de recursos chamada receiptMessage.

  initializeReceipt:
    component: "sample.receipt.dataresponse"
    properties:
      dataVariable: "receipt"
      purchaseId: "${purchaseId.value}"
 ...
  printProduct:
    component: "System.CommonResponse"
    properties:
      keepTurn: true
      metadata:
        responseItems:        
        - type: "text" 
          text: "${rb('receiptMessage','${receipt.value}')}"

O código personalizado para acessar esses parâmetros de entrada pode ter a aparência do seguinte código:

module.exports = {
  metadata: () => ({
    name: 'myComponent',   
    properties: {
       dataVariable: { required: true, type: 'string' },    
       purchaseId: { required: true, type: 'string' },
    },
...
    // Retrieve the value of the 'dataVariable' component property.
    const { dataVariable } = context.properties();
    if (!dataVariable) {
      context.transition();
      done(new Error('The state is missing the dataVariable property.'));
    }
...
    // Retrieve the value of the 'purchaseId' component property.
    const { purchaseId } = context.properties();
    if (!purchaseId) {
      context.transition();
      done(new Error('The state is missing the purchaseId property.'));
    }
...
    context.setVariable(dataVariable, data);      
    context.transition();
    done();
  }
}

Enviar Respostas Diretamente ao Serviço de Tradução

Se você não tiver uma maneira de saber qual será o texto de resposta do componente (por exemplo, se ele for consultado em um backend remoto), poderá usar o serviço de tradução da habilidade para traduzir as respostas. Para fazer isso:

  1. Certifique-se de que o componente esteja configurado para que sua saída seja enviada ao serviço de tradução, definindo a propriedade translate no componente e definindo-a como true.
  2. No componente personalizado, use o método auxiliar context.reply para retornar a resposta.

Essa abordagem só funciona com habilidades configuradas no modo de idioma do Serviço de Tradução.

Usar um Componente de Sistema para Passar a Mensagem para o Serviço de Tradução

Componentes personalizados que os serviços de backend de consulta podem retornar dados em um formato complexo, como um objeto ou um array de objetos. Se você estiver usando um serviço de tradução, esses objetos de dados não poderão ser enviados para o serviço de tradução como estão. Em vez disso, você precisa formar uma mensagem que faça referência a quaisquer atributos necessários do objeto de dados individualmente.

  1. Para o componente personalizado, inclua um parâmetro de entrada obrigatório para o nome da variável de fluxo de caixas de diálogo na qual armazenar os dados retornados.
  2. Como o desenvolvedor do componente personalizado e o desenvolvedor do fluxo de caixas de diálogo podem não ser a mesma pessoa ou até mesmo na mesma equipe, documente cuidadosamente quais dados o componente personalizado retorna nessa variável e disponibilize as informações a qualquer consumidor do componente personalizado para que ele entenda como apresentar os dados retornados ao usuário em uma mensagem.
  3. No fluxo de caixas de diálogo, crie uma variável para armazenar os dados retornados do componente personalizado e informe seu nome no parâmetro de entrada necessário.
  4. Usando as informações na variável, monte a resposta em um componente do sistema, como Resposta comum.
  5. Certifique-se de que a habilidade esteja configurada para tradução automática.
    • Para habilidades desenvolvidas no modo de caixa de diálogo Visual, defina a propriedade Traduzir Mensagem de Resposta do Bot na página Definições da habilidade como true.
    • Para habilidades desenvolvidas no modo de caixa de diálogo YAML, você pode tratar isso globalmente na habilidade definindo a variável de contexto autoTranslate. Por exemplo :
        setAutoTranslate:
          component: "System.SetVariable"   
          properties:
            variable: "autoTranslate"     
            value:
             input: true
             output: true
No exemplo a seguir da propriedade Metadados de um componente de Resposta Comum, a variável é dialogVar. O objeto dos dados que foi passado do componente personalizado para essa variável é {product: "an apple", type: "fruit", origin: "Spain" }.

responseItems:        
- type: "text" 
  text: "The product in your cart is a ${dialogVar.value.type}. It is
   ${dialogVar.value.product} from ${dialogVar.value.origin}"

O código personalizado para acessar esse parâmetro de entrada pode se parecer com o seguinte código:

module.exports = {
  metadata: () => ({
    name: 'myComponent',   
    properties: {
       dialogVar: { required: true, type: 'string' },    
    },
...
    // Retrieve the value of the 'dialogVar' component property.
    const { dialogVar } = context.properties();
    if (!dialogVar) {
      context.transition();
      done(new Error('The state is missing the dialogVar property.'));
    }
...
    context.setVariable(dialogVar, data);    
    context.transition();
    done();
  }
}

Detectar o Idioma do Usuário em um Componente Personalizado

Se o componente personalizado precisar do idioma do usuário para fazer coisas como fornecer formatos de data corretos, você poderá fornecê-lo ao componente de uma destas maneiras:

  • Acesse as variáveis profile.locale e profile.languageTag no código do componente personalizado, conforme mostrado no seguinte exemplo:
    //detect user locale. If not set, define a default
    const locale = context.getVariable('profile.locale') ?
                   context.getVariable('profile.locale') : 'en-AU';
    //Make sure locale is returned with hyphen, not underscore. JavaScript requires a hyphen.
    const jsLocale = locale.replace('_','-'); 
    //when profile languageTag is set, use it. If not, use profile.locale
    const languageTag = context.getVariable('profile.languageTag')?
                        context.getVariable('profile.languageTag') : jslocale;
  • Informe os valores de profile.locale e/ou profile.languageTag como parâmetros de entrada para o componente.
Observação

Se ambas as variáveis forem definidas, o profile.languageTag terá precedência na habilidade.