API RESTful e i18n: como projetar a resposta?

15

Estamos projetando uma API RESTful que se destina principalmente a atender às necessidades de um único cliente. Por causa de suas circunstâncias muito particulares, esse cliente precisa fazer o menor número possível de solicitações.

A API manipula o i18n por meio de um cabeçalho Accept-Language nas solicitações. Isso funciona para todas as coisas que o cliente precisa fazer, exceto um recurso, no qual o cliente precisa armazenar as respostas de uma solicitação em um único terminal em todos os códigos de idioma disponíveis.

De alguma forma, podemos projetar a API de uma maneira que permita ao cliente capturar todas essas informações com uma única solicitação e sem interromper um design de API RESTful consistente e bem estruturado?

Opções que consideramos até agora:

  • Permitindo a inclusão de vários códigos de idioma no cabeçalho Accept-Language e adicionando versões localizadas para todos os códigos de idioma solicitados na resposta, cada um identificado pelo código de idioma ISO 639-1 como a chave.
  • Criando algo como um parâmetro "? All_languages ​​= true" para esse terminal e retornando versões localizadas para todos os códigos de idioma disponíveis na resposta, se esse parâmetro estiver presente.
  • (Se nenhuma das opções acima funcionar para nós) fazendo várias solicitações para obter todas as versões localizadas do cliente.

Qual é a melhor alternativa?

AMM
fonte

Respostas:

22

Você descreveu duas maneiras eficazes de solicitar vários idiomas. Ou deve funcionar bem. Eu escolheria o parâmetro de solicitação de idioma explícito para o meu próprio código.

TL; DR Histórico

Há um cabeçalho Accept-Language . Note que Acceptnão Accepted. É uma parte padrão da negociação de conteúdo HTTP. A resposta geralmente define um idioma de conteúdo retorna um cabeçalho de .

Accept-Languageé o lance inicial, oferecendo um conjunto de opções; Content-Languageé a resolução, indicando qual idioma foi escolhido. A maioria das Content-Languagerespostas retorna um único idioma, mas há uma opção para fornecer uma lista separada por vírgula de idiomas de resposta. Normalmente, isso seria um conteúdo misto, mas não há razão para que ele não possa sinalizar várias alternativas disjuntas. Se você deseja que o cliente solicite todos os idiomas disponíveis, já existe uma opção de solicitação curinga *.

Portanto, já existe um mecanismo de cabeçalho HTTP que você pode usar. No entanto, lembre-se de que você poderia pegar carona em um processo de negociação que mais frequentemente apresenta uma variedade de opções possíveis e recebe de volta uma única opção. Você mudaria o sentido para "aqui está uma lista de opções, me dê todas elas!" Se você está bem com isso, você tem uma solução.

Há, no entanto, um debate considerável sobre a adequação da sinalização dos parâmetros da API REST nos cabeçalhos HTTP. É como entrar em um restaurante e soltar seu pedido detalhado para o anfitrião ou o maître d ', em vez de esperar o garçom ou garçonete aparecer. Pode funcionar e pode funcionar bem, por exemplo, se o pedido direcionado ao host estiver relacionado a bebidas ou aperitivos - coisas que o host pode ver rapidamente ou se comunicar rapidamente com o servidor. Mas também pode ser visto como uma violação do protocolo, endereçada no nível / camada errado ou para o jogador errado.

Uma segunda alternativa seria um parâmetro de solicitação explícita. Você sugere ?all_languages=true. Isso parece excessivamente específico. Algo como lang=en,fr,es(permitir vários idiomas listados) ou lang=*oulang=all (especificar todos os idiomas disponíveis) parece mais geral. Isso pode ser expresso no URL ou no corpo da solicitação.

De qualquer maneira, sua resposta multilíngue pode ser facilmente codificada na carga JSON retornada:

[ { "lang": "en", "content": "As Gregor Samsa awoke one morning..." },
  { "lang": "de", "content": "Als Gregor Samsa eines Morgens..." },
  ...
]

No final, qualquer uma dessas abordagens deve funcionar bem para você. Qualquer um deles pode ser visto como um "design de API RESTful consistente e bem estruturado". A determinação de qual é o melhor baseia-se principalmente na sua atitude em relação à adequação de pegar carona (e alterar ligeiramente o senso típico de) cabeçalhos de negociação de conteúdo HTTP.

Minha preferência é não misturar cabeçalhos e outros parâmetros como partes iguais de uma solicitação de API. O explícito langou languageparâmetro parece mais limpo para mim. Mas desde que o verbo HTTP (por exemplo GET, PUT, POST, PATCH, ...) é parte do cabeçalho, e também crítico para / misturados com a interpretação do pedido, eu admito o envelope contra conteúdos distinção é artificial pouco e difusa. Como na maioria das decisões de design, especialistas genuínos respondem de maneira diferente e ao YMMV.

Jonathan Eunice
fonte
Sua resposta foi muito educativa e informativa. Obrigado. Obrigado também por perceber a coisa Aceitar não aceito. Está correto em nosso código, mas não usei o termo adequado ao escrever a postagem. Vou modificá-lo para outras referências.
AMM