RESTful API和i18n:如何设计响应?


15

我们正在设计一个RESTful API,主要用于满足单个客户端的需求。由于其非常特殊的情况,此客户端必须发出尽可能少的请求。

API通过请求中的Accept-Language标头处理i18n。这适用于客户端需要做的所有事情,除了一项功能外,在该功能中,客户端需要在所有可用的语言环境中存储对单个端点的请求响应。

我们是否可以以某种方式设计API,使客户端可以在单个请求中获取所有这些信息,而又不会破坏一致的,结构良好的RESTful API设计?

到目前为止,我们已经考虑的选项:

  • 允许在Accept-Language标头中包含多个语言环境,并在响应中为所有请求的语言环境添加本地化版本,每个语言环境均以其ISO 639-1语言代码标识为密钥。
  • 为该端点创建类似“?all_languages = true”的参数,并在响应中返回所有可用语言环境的本地化版本(如果存在该参数的话)。
  • (如果以上方法对我们都不起作用),将发出多个请求以从客户端获取所有本地化版本。

哪一个是最好的选择?

Answers:


22

您已经描述了两种要求多种语言的有效方法。两者都应该工作正常。我将为自己的代码选择显式语言请求参数。

TL; DR背景故事

有一个Accept-Language标头。请注意,Accept不是Accepted。这是HTTP内容协商的标准部分。响应通常会将Content-Language标头放回原处。

Accept-Language是开标价,提供一组选项;Content-Language分辨率,说明选择了哪种语言。大多数Content-Language答案都返回一种语言,但是可以选择提供一个用逗号分隔的响应语言列表。通常,这是混合内容,但是没有理由不能表示多个不相交的替代方案。如果您希望客户端请求所有可用的语言,则已经有一个通配符请求选项*

因此,已经有了可以使用的HTTP标头机制。但是,请注意,您会背负谈判过程,而谈判过程通常会显示一系列可能的选项,并且会获得单个选项。您将把感觉转移到“这里有一个选项列表,请全部给我!” 如果您对此表示满意,那么您将找到解决方案。

但是,关于在HTTP标头中用信号发送REST API参数的适用性存在很多争论。这有点像进入餐厅,然后将详细的订单显示给房东或房东,而不是等待侍应生出现。它可以工作,也可以很好地工作,例如,如果针对主机的订单与饮料或开胃菜有关—主机可以快速查看或与您的服务器通信的事物。但这也可以看作是违反协议,以错误的级别/层或错误的参与者来解决。

第二种选择是显式请求参数。你建议?all_languages=true。这似乎过于具体。诸如lang=en,fr,es(允许多种列出的语言)或lang=*lang=all(指定每种可用的语言)之类的东西看起来比较笼统。可以在URL或请求正文中表示。

无论哪种方式,您的多语言响应都可以轻松地编码为返回的JSON有效负载:

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

最后,这两种方法都应该对您有效。任何一种都可以被视为“一致的,结构良好的RESTful API设计”。确定哪种更好的方法主要取决于您对HTTP内容协商标头的piggy带(并略有改变的典型含义)是否适当。

我自己的偏好是不要将标头和其他参数混合在一起作为API请求的相同部分。对我来说,显式langlanguage参数似乎更干净。但是,由于HTTP动词(如GETPUTPOSTPATCH,...)是头部的一部分,也是至关重要的/与请求的解释混杂,我承认信封与内容的区别有点人为的和模糊的。与大多数设计决策一样,真正的专家对YMMV的回答也不同。


他们的反应非常有教育意义和信息量。谢谢。也感谢您注意到“接受不接受”的内容。这在我们的代码中是正确的,但是后来我在写帖子时没有使用正确的术语。我将对其进行修改以供进一步参考。
AMM
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.