You may have been tasked with localizing an API. This is often the case with APIs more near to end-customers or users. Offloading the responsibility for localization to an API provider in some ways can be seen as optimal. Why have N integrations repeat the translation of simpler touch-points to an API? Alas, the only absolute truth of software localization is that we underestimate the complexity of doing it well absolutely.
That difficulty is a challenge, not a dismissal, of the pursuit of localizing an API. Even if it is not perfect in implementation, localization can be a huge value add.
As the "Internationalization guy" at Stripe, I've been asked on numerous occasions about whether and how Stripe should localize its API. These are my thoughts on the broader space of localizing any API which will get you the most bang for your localization buck.
The first thing one might consider localizing is the API error messages. They are the most textual and fit into existing string translation pipelines with only a bit of work. One of those pipelines looks like these steps:
HashMap<MessageID: string, ErrorMessage:
string>
)
Something you'll want to hammer out and quickly is the intended audience of the error messages. Are they for developers to aid them in debugging integration issues, or are they intended to be surfaced directly to users, perhaps in a user interface?
I recommend separating the considerations for the two audiences. The API error messages should be developer facing exclusively. If the API errors are intended to be resurfaced to users, I would suggest a more human-oriented API.
A more human API looks like (1) for validation errors returning all of the validation errors in a batch as opposed to returning early on any single validation like a computer would be okay with. It also means (2) understanding the user interface as most likely some kind of form and allowing certain errors to be attributable easily back to certain form fields. Lastly, (3) humans provide data sparingly and out of order so have API resources which model partial submissions or drafted objects. These considerations make for a larger, different API.
That's a lot of work and not applicable to some integrators' use cases anyways. Human oriented APIs I think work best when offered as a layered approach atop the low-level.
A common scenario API integrators find themselves in: the error is generic and the error message is more specific. If the integrator cares to model that more specific information they must resort to string parsing on the error message.
An example would be:
// US
{
type: 'error',
kind: 'tax_id_invalid',
message: "Taxpayer identification numbers (TIN) is required"
}
// Canada
{
type: 'error',
kind: 'tax_id_invalid',
message: "Individual Tax Number (ITN) is required"
}
We've embedded context only available in the error message so the integrator must either do string parsing or present this error to the user to provide a decent user experience.
This isn't a localization only concern but is something that a lot of providers of APIs force on their users inadvertently by providing great error messages without great error data.
Localization is no different than other cases. If you're going to offer more context in the error message, you'll also want to offer the same information as machine readable data.
In the above example, we'd want to offer data to match:
// US
{
type: 'error',
kind: 'tax_id_invalid',
message: "Taxpayer identification numbers (TIN) is required",
data: {
type_id_type: 'us_tin'
}
}
// Canada
{
type: 'error',
kind: 'tax_id_invalid',
message: "Individual Tax Number (ITN) is required",
data: {
type_id_type: 'ca_itn'
}
}
We don't need to give the pretty, human readable names as data fields. We only need to convey the information in a distinguishable way.
For localization, this error data becomes essential to allowing integrators to localize their interfaces either with proper tone of voice for their businesses and target markets (some markets like a calm voice, some like a strictly professional voice) and expand beyond the supported set of locales that your API offers.
It is easy to get really excited about localizing APIs. After all, programming is so overwhelmingly English-centric it's hard not to have sympathy for everyone else.
However we need to balance our pure vision with the realities of programming. The vast majority of API integrators, upon hitting an error or unexpected state, ask a computer. Search engines, help forums, and LLMs work best on a common text or source language. If we provide a localized error and they can't get to the reference material and external information about the error with ease, that's also a bad development experience.
Having extensive error catalogs are great and more APIs should have them alongside their API reference documentation, but these resources often can't tell the whole story of how to handle these cases. We need richer examples, peer discussion, and lessons already learned the hard way.
Giving access to the canonical / source error message is essential. Make it easy to get it! Some ways you might do so:
message
and
localized_message
together always. This is
simplest, allowing the developer to use both without any
configuration flipping. The edges are:
localized_message
when the two errors differ?
Probably the latter.
Developer localization is an area which still after so long is ripe for experimentation on the right way to do it. Good luck!