URL оформление за многоезична CMS

Така че се опитвам да добавя нова, лъскава уеб услуга REST към нашата CMS. Трябва да следва REST "правилата" доста отблизо, така че трябва да използва GET/POST/PUT/DELETE и правилни, логични URL адреси. Моят дизайн е силно вдъхновен от Най-добрите практики на Apigee.

CMS управлява дърво от категории, където всяка категория може да съдържа определен брой статии. За многоезични проекти категориите се дублират за всеки език (така че всяка статия е уникален идентификатор чрез своя ID и езиковия ID). Структурата е една и съща за всички езици, само позициите могат да варират (така че категория X съдържа категориите Y и Z във всеки език, но Y може да бъде преди Z в език 1 и обратното в език 2). Създаването на нова статия или категория винаги създава и копия на всички езици. Изтриването работи по същия начин, така че дадена статия винаги се изтрива на всички езици.

FYI: Езиците се идентифицират чрез техния цифров идентификатор или техния локал (като en_US).

(Моля, изобразете водещо /v1 пред всички URI; пропуснах го, защото не добавя нищо към този въпрос.)`

Настоящият ми подход е да имам 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 адресите са по-четими. Но това би

  • може да доведе до проекти с припокриващи се локали.
  • изискват от клиентите първо да извлекат локалите (но предполагам, че иначе клиентът би трябвало да извлече езиковите идентификатори така или иначе, така че това е добре).

Бих искал да завърша с точно едно решение за това и да съм склонен да използвам локала. Но струва ли си да рискувате припокриващи се локали?

(Можете изображение 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

or

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

Това води до...

Какво да правим с глобалните действия?

Проблемът с горното оформление е, че POST и DELETE работят на всички езици, но 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 адреси, но да правя може би нежелани неща във фоновия план?


person xrstf    schedule 01.11.2012    source източник


Отговори (2)


Имах абсолютно същия проблем преди време и реших да сложа local пред всичко. Докато консумирате съдържание, има много по-смислено да четете URL адреси като:

/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/

or

/all-locales/articles/

or

/all/articles/

честно казано, харесвам глобалните и всичко това, защото има смисъл да ги чета.

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

дано помогнах

person PetrosZ    schedule 08.07.2013

Първоначалният ми подход би бил да има език като незадължителен префикс в URL адреса, напр. /en_us/articles, /en_us/articles/:id, но ако не искате да „замърсявате“ вашите URL адреси с езикови идентификатори, можете вместо това да използвате заглавката Accept-language по същия начин, по който договарянето на съдържанието е дефинирано в RFC 2616. WebAPI на Microsoft използва този подход за договаряне на формат.

person gnz    schedule 02.11.2012