多语言CMS的URL布局

时间:2012-11-01 00:59:04

标签: url rest content-management-system multilingual

所以我正在尝试为我们的CMS添加一个新的,闪亮的REST Web服务。它应该非常接近REST“roules”,所以它应该使用GET / POST / PUT / DELETE和正确的逻辑URL。我的设计深受Apigee Best Practices的启发。

CMS管理一个类别树,其中每个类别可以包含许多文章。对于多语言项目,每种语言的类别都是重复的(因此任何文章都是其ID和语言ID的唯一标识符)。 结构在所有语言中都是相同的,只有位置可以变化(因此类别X包含每种语言中的类别Y和Z,但Y可以在语言1中的Z之前,反之亦然语言2)。创建新文章或类别始终也会创建所有语言的副本。删除工作方式相同,因此始终会删除所有语言的文章。

仅供参考:语言由其数字ID或其区域设置标识(如en_US)。

(请在所有URI前面对前导/v1进行成像;我已跳过它,因为它不会对此问题添加任何内容。)`

我目前的方法是使用这样的URL方案:

GET    /articles               :(  returns all articles in all languages
GET    /articles/:id-:langid   :)  returns a single article in a given language
POST   /articles               :)  creates a new article
PUT    /articles/:id-:langid   :)  update a single article in a given language
DELETE /articles/:id           :)  delete an article in all languages

但是...

如何识别语言?

目前,每种语言分配的语言环境不需要是唯一的,因此在极少数情况下两种语言可以具有相同的语言环境。保证使用ID是唯一的。

使用区域设置(最有可能强制为小写)会很好,因为URL更具可读性。但这会

  • 可能导致区域设置重叠的项目。
  • 要求客户端首先获取区域设置(但我想客户端无论如何都必须获取语言ID,所以这没关系。)

我想最终得到一个解决方案,并倾向于使用区域设置。但是否值得冒着重叠区域的风险?

(您可以将langid=X映像与以下locale=xx_xx互换。)

语言应该是层次结构元素吗?

在大多数情况下,API的客户端将希望获取给定语言的文章而不是全部。我可以通过允许GET参数并提供GET /articles?langid=42来解决这个问题。但由于这是一个常见的用例,我想避免使用可选参数并使其明确。

这将导致GET /articles/:langid,但这引入了该语言是API内部的层次结构级别的概念。如果我要这样做,我想让其他动词保持一致。新的URL布局如下所示:

GET    /articles/:langid       :)  returns all articles in a given language
GET    /articles/:langid/:id   :)  returns a single article in a given language
POST   /articles               :(  creates a new article in all languages
PUT    /articles/:langid/:id   :)  update a single article in a given language
DELETE /articles/:langid/:id   :(  delete an article in all languages

GET    /:langid/articles       :)  returns all articles in a given language
GET    /:langid/articles/:id   :)  returns a single article in a given language
POST   /articles               :(  creates a new article in all languages
PUT    /:langid/articles/:id   :)  update a single article in a given language
DELETE /:langid/articles/:id   :(  delete an article in all languages

这导致......

如何处理全球行动?

上述布局存在POSTDELETE适用于所有语言的问题,但URL表明它们仅适用于一种语言。所以我可以修改布局:

GET    /articles/:langid       :)  returns all articles in a given language
GET    /articles/:langid/:id   :)  returns a single article in a given language
POST   /articles               :)  creates a new article in all languages
PUT    /articles/:langid/:id   :)  update a single article in a given language
DELETE /articles/:id           :)  delete an article in all languages

这使得布局有点混乱,因为语言级别有时只存在,并且需要对系统的内部有很多了解。从好的方面来说,这与系统非常匹配,与内部工作方式非常相似。

牺牲?

那我在哪里做出牺牲?我是否应该引入别名URL以获得良好的URL布局,但是在背景中可能有意外的东西吗?

2 个答案:

答案 0 :(得分:1)

前段时间我遇到了完全相同的问题,我决定将当地人置于一切之前。在消费内容时,阅读以下网址会更有意义:

  

/en/articles/1/

     

/en/authors/2/

     

/gr/articles/1/

     

/gr/authors/2/

  

/articles/en/1/

     

/authors/en/2/

     

/articles/gr/1/

     

/authors/gr/2/

为了解决“没有特定的语言环境”问题,我会使用一个关键字来引用所有可用的语言环境或默认的语言环境。所以:

  

/global/articles/

  

/all-locales/articles/

  

/all/articles/

说实话,我喜欢全球化,因为他们阅读它们是有意义的。

  

DELETE /global/articles/:id :) delete an article in all languages

希望我能帮助

答案 1 :(得分:0)

我最初的做法是将语言作为URL中的可选前缀,例如/en_us/articles/en_us/articles/:id,但如果您不想使用语言标识符“污染”您的网址,则可以改为使用Accept-language标头,方法与定义内容协商的方式相同RFC 2616。微软的WebAPI正在使用这种方法进行格式协商。