Shall REST API error messages be internationalized?

7,036 views
Skip to first unread message

Rafael B.C.

unread,
Mar 25, 2015, 8:34:32 AM3/25/15
to api-...@googlegroups.com

When designing the errors of a REST API seems to be a good practice to follow standard HTTP codes (4XX and 5XX) and to include a body (XML/JSON) with:

  • brief message
  • description
  • code

My question is ... shall these messages be internationalized?

I tend to think that showing a message to the client is client side responsability, and those API errors should be considered as an agreement (format, and code field) between the client app and the API but shall not be considered by default as perfectly suited to be exposed to the client directly, so formatting the final message "Ooops ... something was wrong, dude" shall be done at client side since words like "Ooops" and "Dude" makes no sense in the API. In other case i can see API deployments because P.O. needs to change "Oops" to "Uups" and things like that, that seems totally like something related to the look and feel of the client app IMHO.

Further if i include final specific messages in the API we can fail to be able to serve heterogeneous client systems since some of them may want "Ooops ... we screwed it up, dude" while others may want "We are sorry something was wrong, Mr. Client".


Do you agree with this? ... or i am missing something?

Jørn Wildt

unread,
Mar 25, 2015, 8:42:58 AM3/25/15
to api-...@googlegroups.com
Basically I believe the server should do the translation - otherwise you will run into problems when translating a message like "The amount of 1234 items is too big" (where "1234" varies).

/Jørn

--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft.
For more options, visit https://groups.google.com/d/optout.

Kijana Woodard

unread,
Mar 25, 2015, 12:32:50 PM3/25/15
to api-...@googlegroups.com
You can always use the code to override the error message. But it will be tricky to add contextual information unless the "error template" is well documented/understood.

Pedro Santos

unread,
Mar 25, 2015, 2:43:39 PM3/25/15
to api-...@googlegroups.com
I think both options are valid, but each one has tradeoffs. One of the first questions you should ask yourself is whether you intend the API to be user oriented (targeting the end user) or more of a "machine" API (to be consumed by other automated systems). If the latter definitely leave i18n to clients, otherwise there are pros and cons...

Client concern
+ Clients can customize their own error messages (different clients, different messages)
+ API doesn't have to deal with i18n (which can be tricky, for example when creating resources should locale be considered? how about when mapping i18n enums? lots of stuff to be considered)
- More difficult to enable dynamic data in error messages (though not impossible)
- Clients have to create their own messages


Server Concern
+ Clients can still customize their own error messages assuming a code is still sent (different clients, different messages)
+ Clients can let the server handle i18n but they must somehow signal the server which locale they want in every request (assuming statelessness)
+ Easier to place dynamic error data in messages
- API has to deal with i18n (more complexity)
-/+ If message customization is required (one for mobile another for desktop for example) either the server must do it or the clients have to do their own customization

There are certainly other considerations (consistency and maintainability of the localization, etc.) but honestly I don't think there is a "best" way, depends on the situation.

Kijana Woodard

unread,
Mar 25, 2015, 3:44:46 PM3/25/15
to api-...@googlegroups.com
It occurs to me that you could also have the error messages live at a separate resource:

--

Rafael B.C.

unread,
Mar 25, 2015, 3:59:46 PM3/25/15
to api-...@googlegroups.com
Hi Jørn,

Thanks for your suggestions, i've read your article and it's very helpful.

However in the same article you state, about Localization, that:

Error messages for end users should be localized (translated into other languages) if your service is already a multi language service. Personally I don't think developer messages should be localized: it is difficult to translate technical terms correct and it will make it more difficult to search online for more information.

So what i see is that you are considering two kind of messages ... is this correct?

You refer to some APIs in the article (twitter, google, ...) ... do you know if these ones has error message translation?


At this moment i do not see the need of dynamic content in error messages: "The amount of 1234 items is too big" share the same information that "Too many items" ... and i've thought in other possibilities with same result. Maybe i'm wrong.

In other hand what i see more clear now is that, even with internationalization, it should be allowed (encouraged?) that client apps customize their error messages in order to fit them with the rest of the psicology of the client interface. I think this enforces the point about the client side responsability of the error messages.

Jack Repenning

unread,
Mar 25, 2015, 4:10:53 PM3/25/15
to api-...@googlegroups.com
On Mar 25, 2015, at 5:34 AM, Rafael B.C. <bcr...@gmail.com> wrote:

My question is ... shall these messages be internationalized?

If you use HTTP Problems draft standard (https://tools.ietf.org/html/draft-ietf-appsawg-http-problem-00 or update), then you have three response fields to play with:

* "type": an absolute URI that identifies the problem type. Not required to be dereferencable, but in this case it would be
* "title": a human-readable, non-internationalized one-line string
* "detail": a human-readable, non-internationalized longer string

Then, make "title" and "detail" non-internationalized (they're intended for machine consumption), while "type" can be a URL to an actual web page, subject to standard internationalization procedures, offered to the human assumed to be lurking somewhere.

-- 
Jack Repenning
Repenni...@gmail.com

signature.asc

Jørn Wildt

unread,
Mar 25, 2015, 5:42:03 PM3/25/15
to api-...@googlegroups.com
> So what i see is that you are considering two kind of messages ... is this correct?

Yes.


> You refer to some APIs in the article (twitter, google, ...) ... do you know if these ones has error message translation?

No, I don't know.


> At this moment i do not see the need of dynamic content in error messages: "The amount of 1234 items is too big" share the same information that "Too many items" ... and i've thought in other possibilities with same result. Maybe i'm wrong.

Then turn it around: "Too many items - you are allowed a maximum of 1000 items" - where "1000" depends on some business rule.

But I do consider it good practice to include what the client send as this will help debugging. So it should be more like "1234 is too many items. You are only allowed a maximum of 1000 items".

/Jørn

--

Jack Repenning

unread,
Mar 25, 2015, 5:57:49 PM3/25/15
to api-...@googlegroups.com
On Mar 25, 2015, at 2:41 PM, Jørn Wildt <j...@fjeldgruppen.dk> wrote:

But I do consider it good practice to include what the client send as this will help debugging. So it should be more like "1234 is too many items. You are only allowed a maximum of 1000 items".

Another useful case of dynamic content in errors is including some unique string (say, a GUID) that's also logged at server side, so the client can contact server support and say, "What went wrong when Error:7f3675a7-c979-4df7-8aa5-a299970c3a79 happened?" This does not entail internationalization, but it might complicate it (by forcing you i nto dynamic strings).

-- 
Jack Repenning
Repenni...@gmail.com

signature.asc

Chris Mullins

unread,
Mar 25, 2015, 6:52:33 PM3/25/15
to api-...@googlegroups.com
In the work I've done recently, we decided NOT to localize textual error messages. 

We have an error code, which is not necessary numeric ("BadArgument"), a message, and details. While we're allowing quite a bit of detail in the error responses, we also have the following key bits of internal guidance:
  • For nonsuccess conditions, developers SHOULD be able to write one piece of code that handles errors consistently. This allows building of simple and reliable infrastructure to handle exceptions as a separate flow from successful responses.
  • This object MUST contain name/value pairs with the names “code” and “message,” and it MAY contain name/value pairs with the names “target,” “details” and “innererror.”
  • The value for the “code” name/value pair is a language-independent string. Its value is a service-defined error code that SHOULD be human-readable. This code serves as a more specific indicator of the error than the HTTP error code specified in the response. Services SHOULD have a relatively small number (about 20) of possible values for “code,” and all clients MUST be capable of handling all of them. Most services will require a much larger number of more specific error codes, which are not interesting to all clients. These error codes SHOULD be exposed in the “innererror” name/value pair as described below. Introducing a new value for “code” that is visible to existing clients is a breaking change and requires a version increase. Services can avoid breaking changes by adding new error codes to “innererror” instead.
For those of you playing along at home, this is derivative of (and semantically compatible with) the OData V4 guidance around error handling, although simplified in many respects.

An example error then looks like:

{
"error" : {
"code" : "BadArgument",
"message" : "Previous passwords may not be reused",
"target" : "password",
"innererror" : {
"code" : "PasswordError",
"innererror" : {
"code" : "PasswordDoesNotMeetPolicy",
"minLength" : "6",
"maxLength" : "64",
"characterTypes" : ["lowerCase", "upperCase", "number", "symbol"],
"minDistinctCharacterTypes" : "2",
"innererror" : {
"code" : "PasswordReuseNotAllowed"
}
}
}
}
}

A compound example, handy for many scenarios, looks like:

{
"error" : {
"code" : "BadArgument",
"message" : "Multiple errors in ContactInfo data",
"target" : "ContactInfo",
"details" : [{
"code" : "NullValue",
"target" : "PhoneNumber",
"message" : "Phone number must not be null"
}, {
"code" : "NullValue",
"target" : "LastName",
"message" : "Last name must not be null"
}, {
"code" : "MalformedValue",
"target" : "Address",
"message" : "Address is not valid"
}
]
}
}

Cheers,
Chris

Chris Mullins

unread,
Mar 25, 2015, 6:54:51 PM3/25/15
to api-...@googlegroups.com
Replying to myself is a sure sign I need more sleep. 

I forgot the most relevant bit to this thread:

  • The value for the “message” name/value pair MUST be a human-readable representation of the error. It is intended as an aid to developers and is not suitable for exposure to end users. Services wanting to expose a suitable message for end users MUST do so through an annotation or custom property. Services SHOULD NOT localize “message” for the end user, because doing so MAY make the value unreadable to the app developer who may be logging the value, as well as make the value less searchable on the Internet.

Cheers,
Chris

Rafael B.C.

unread,
Mar 26, 2015, 4:52:54 AM3/26/15
to api-...@googlegroups.com

Sure ... that kind of identification can be indeed useful but, even when it is related dynamic error messages, i think is not related internationalization since we can stablish an agreement in the error format that will be same for all languages.

sune jakobsson

unread,
Mar 26, 2015, 4:56:54 AM3/26/15
to api-...@googlegroups.com
In OMA we defined: http://technical.openmobilealliance.org/Technical/Release_Program/docs/REST_NetAPI_Common/V1_0-20120417-C/OMA-TS-REST_NetAPI_Common-V1_0-20120417-C.pdf

Example from C.1.1.2 
SVC0002: Invalid input value 

Name         Description 
MessageId SVC0002 
Text            Invalid input value for message part %1 
Variables    %1 - message part 
HTTP status code(s) 400 Bad request 

And we have encourage developers to add a link in the textual part to further explain the error that occurred.

Sune

--

Jørn Wildt

unread,
Mar 26, 2015, 5:56:43 AM3/26/15
to api-...@googlegroups.com
I don't disagree with all the good inputs here - I just want to add an observation ...

If you depend on clients knowing *all* the dynamic message formats, like for instance "Invalid input value for message part %1" then you couple clients and servers more tightly together than you would do by expecting the server to respond with a complete, localized, error message.

This means you cannot add parameters to, or change, the error message formats without breaking clients that depends on these details.

/Jørn

Rafael B.C.

unread,
Mar 26, 2015, 6:20:03 AM3/26/15
to api-...@googlegroups.com

The problem i see is that the definition of what is "a complete error message" is something only  the client knows. Since final message formats shown to the user may change between one client app and another.

Figure the situation where you have a public api open to be consumen for different client apps that targets different user profiles.

Then defining a error message format where some fields are mandatory and (maybe) others are optional seems to me like the usual contracts we are used to agree on.
You are not coupled to the server ... you are coupled with the specification, which is good.

Chris Mullins

unread,
Mar 26, 2015, 12:57:04 PM3/26/15
to api-...@googlegroups.com
I'll echo what others have already said. 

> Invalid input value for message part %1 

In the case of a deeply layered system, this approach causes a unmanageable coupling between layers. 

I've personally built, and worked in, large complex systems with error infrastructure defined exactly this way. The degree of difficulty in making changes, edits, or adding new things was overwhelming and forced that style to be abandoned. 

Cheers,
Chris
Reply all
Reply to author
Forward
0 new messages