36

In our company we had a discussion whether formatting data in a certain locale is the responsibility of the frontend application or of the API that provides data to it.

Which of the following scenarios would be best practice?

Scenario 1

  • The API returns data (DateTimes, decimals, etc.) in their original data type (i.e. as DateTime, decimal, etc.)
  • The frontend application is responsible for formatting the data that's been provided by the API in the required locale.

Scenario 2

  • The API is responsible for formatting DateTimes, decimals, etc. in a specific locale and returning them as formatted strings to the frontend.
  • The frontend displays the data (formatted strings) as they are, and doesn't need to take care about the formatting.
8
  • 6
    Sharing your research helps everyone. Tell us what you've tried and why it didn't meet your needs. This demonstrates that you've taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer. Also see How to Ask
    – gnat
    Feb 7 at 10:17
  • 24
    by "culture" do you mean "locale"?
    – njzk2
    Feb 7 at 22:08
  • @njzk2 I mean the BCP 47 codes mentioned on docs.microsoft.com/en-us/openspecs/office_standards/ms-oe376/… e.g. en-US for US-English
    – Dario
    Feb 8 at 7:11
  • All the below answers are usually good for timezone calculations as well. Dat ashould be stored and transmitted in a set timezone (almost always UTC), and the fronetend display should convert to the user's timezone (or provide a choice of timezone - some log viewers do this).
    – Jonathan
    Feb 8 at 12:15
  • 3
    @Jonathan That advice comes up quite often, but it definitely isn't a silver bullet and can be a horrible choice (I should know, I did exactly this once and ran into a similar problem that Jon describes). Jon Skeet has a nice blog post about why you have to consider the semantics to choose the right format. (Another classic counter example is that of an alarm clock - you probably want to store the next alarm in local time)
    – Voo
    Feb 8 at 15:04

6 Answers 6

70

Approach 1 – handling formatting in the frontend – is usually the best answer, as once something has been formatted it is less suitable for further processing. If there are multiple consumers in different cultures it is more natural to handle that closer to the point of use. It also saves you having to pass the culture back up to the API, and consequently simplifies the test coverage.

However, in some cases you are obliged to use the other approach (localization in the backend). For example, sorting and pagination - what constitutes "alphabetical order" is culture-dependent, which would appear is, say, the selection of sort order in an SQL query so that the cursor is in the user's culture-appropriate sort order (so that results can be incrementally returned by the cursor, instead of all results returned to the front end, then have the front end reorder all results).

13
  • 1
    @ShmuelNewmark If the client-side code needs the ability to sort a table/list locally, and returned dates have already been localised as dd/mm/yyyy or mm/dd/yyyy then it's less convenient to sort them than if they were returned as yyyy-mm-dd or seconds (or whatever) since some epoch.
    – TripeHound
    Feb 8 at 15:24
  • 9
    @ShmuelNewmark date/time ordering should not be locale dependent, although in that case you have far worse worries about timezones. I was talking about alphabetical order; things like the Turkish i and letter Ø sort differently depending on your locale.
    – pjc50
    Feb 8 at 16:04
  • 10
    For timezones, you should generally store UTC* and display local, if possible. Think hard about where "local" is. Airline reservation websites tend to display each leg as local to the airport where the arrival/departure is.
    – pjc50
    Feb 8 at 16:07
  • 4
    @IMSoP: "Nonetheless, I agree that back-end systems should store and return UTC, converting to local time only when displaying to a human; it would save a lot of pain!" Would it? If I schedule a meeting at 9am in 3 months, and my country decides to stop doing DST, I still want the meeting at 9am regardless, because at 8:00am I'm dropping the kids to school! One reason that airlines always talk in local time, is that many things are done in local times: opening hours of the various businesses, curfew (thanks COVID), etc.. are all in local times (cont.) Feb 9 at 14:50
  • 3
    @IMSoP: (cont.) So, how to store the time? Well, it depends on the usecase. If the user wants a meeting at 10 AM in Rabbat (Morocco) that's what they want, and storing in UTC will put you in for a world of pain should Rabbat switch timezone quickly -- like, because the King of Morocco decided to scrap Winter Time, less than 2 days before it was due in 2018 (BBC). Feb 9 at 14:56
11

When you think about having one frontend application and one backend, the decision seems to be very arbitrary and both can work.
But the more you have different frontends and backends the clearer it will be that you want to do close to the frontend.

Let look at the example of DateTime:
Imagine you have a train booking website and a backend that gives you the schedule and you decide to put the formatting on the backend in either German, Dutch or English.
Now you add another service that deals with vouchers that have an expiry time. Now you have to duplicate the date formatting functionality on two services and need to make sure that they are in sync, since otherwise your formats will be inconsistent (if your care about such things).
Then you decide to integrate your schedule service with another product which also supports French, now you have to go back to both of your services and have to make them support French as well. Finally you decide to make an iOS, now you provide the schedule through an API as strings, but since iOS has native date formatting your app looks inconsistent if you mix it with other date information that you format locally on the phone.

If you instead choose to return data instead of formatted strings, you don't have to worry about any of that.
Just add new backend services that return times and whenever you want to add a language all you need to change is the frontend application.
You also can have different formats and language support on different apps. Note that when I say frontend application it doesn't necessarily be on the client side. For a website you might want to do the formatting as one of last steps when rendering the server-side HTML.

8
  • 6
    For extra fun: You often see a date using "yesterday", "today" or "tomorrow". Which one to use depends not only on the local time of the user, but on their actual clock. If my clock is ten minutes fast, then a display should change from "today" to "yesterday" when my clock reaches midnight. Which might be ten minutes before actual midnight.
    – gnasher729
    Feb 7 at 23:55
  • 2
    > For a website you might want to do the formatting as one of last steps when rendering the server-side HTML. A great point - we have some excel exports which also need the appropriate translation applied and so there's a little frontend in our backend api there to allow for this.
    – sommmen
    Feb 8 at 9:21
  • 4
    @gnasher729 Or you could just not do that, because it's extremely irritating to be told that something that happened 5 minutes ago or (as is currently the case with your comment) 38 hours ago was "yesterday", and much more useful to trust that the user knows how clocks work. I appear to be in the minority in this belief, though, because that kind of nonsense seems to be extremely fashionable.
    – IMSoP
    Feb 9 at 13:55
  • 1
    @IMSoP There is some debate over how much consistent presentation matters to users that aren't web designers, but if you start mixing European date format "09/02/2022" with with American "02/09/2022" on the same page it starts getting tricky.
    – Helena
    Feb 9 at 19:24
  • @IMSoP By sending data instead of formatted values the decision when to use what format is left to the iOS designer, rather the developer of the Java backend that serves mobile apps as well as desktop websites.
    – Helena
    Feb 9 at 19:48
4

Rather than getting hung up on frontend vs backend, it would be worth considering what the architecture for your UI looks like.

There are a number of common paradigms for user interface architecture. Model-View-Controller is probably the best known (although the name is often mis-applied to other architectures), with other related paradigms like Model-View-Presenter, Model-View-ViewModel, and the loosely related Flux paradigm.

What most of these paradigms have in common is that they separate business logic (model) from presentation logic (view). They differ in how these components are connected, and what supporting infrastructure assists with this, but that is a key characteristic that they all share.

Assuming you're following a paradigm like this, probably the most important thing to recognise is that culture isn't part of the business logic, so doesn't belong in the model. Depending on your exact paradigm, it might make sense for it to live in the view, or in one of the supporting components (localisation is not an unreasonable thing to handle in a ViewModel, for example), but you probably don't want it in the model.

In terms of web application architectures, there's been a shift in recent years, where the model used to live purely in the backend, but nowadays is more likely to live in the frontend, or at least span the two (and paradigms like Flux attempt to make this more concrete). So depending on your application, it may make sense to put the localisation logic on either side of that divide. But the guiding factor should probably be the architecture. Where is your model, where is your view, what connects them, and what is responsible for what?

1

While I completely agree with pcj50's answer, there's something else that needs to be taken into consideration and hasn't been mentioned in the other answers:

  • Data in its original data type is for processing
  • Data in formatted strings is for displaying

If the sole purpose of your API function is to visually present information to an end user, then you can handle formatting on the back-end. But if the same function (let's say a request for a filtered list of information) is used by a tabled view, and a chart view, and on another function that further processes it to generate a summarized report, and also can possibly be consumed from a future application which you don't know what will it do with that data, then formatting has to be handled by those "consumers" that require it formatted.

0

Both can be suitable for different circumstances.

If you're making a frontend-agnostic API, generally you want to return a machine-readable version of the data and leave formatting to the frontend. When returning dates, you use ISO8601 in UTC, when returning numbers you use regular JSON numbers, etc. For server-to-server APIs and APIs that are going to be consumed by other parties that you don't control, you almost always want to do this. Without any other context on how the API going to be used, this is usually the preferred practice.

However, there are some contexts where returning a pre-formatted data in the API is appropriate. One problem caused by requiring frontend to format the data is that they make the frontend more complex, and for frontend, additional complexity means additional i8n libraries and locale data that needs to be downloaded by the user, bloating the frontend application.

For multi-platform applications, keeping localization in the server means you have consistency on how data is formatted across all platforms, you reduce the size of the frontend, and you only need to write localization logic once.

The alternative that's available for mobile platforms is relying on the platform's Localization API, but these would normally be limited to just simple localizations, like formatting numbers and dates and it may not be available if one of your target frontend is a browser. This can be a a good option if your localization requirement is simple and sufficiently met by the platform's Localization APIs. For more complex localization requirements, like for example, translating error messages and interpolating the values into the error messages, it can be quite complicated to need to build and prepare platform-specific translation files.

2
  • If you want to do things very nicely, send the date in UTC, plus the time zone where it was generated. So if you are in New York, see 5pm on your wristwatch, and send an email to me in London, you would send the 5pm converted to UTC, plus the time zone of New York, so I know correctly that you sent the email late in your afternoon, and not a bit after midnight.
    – gnasher729
    Feb 9 at 13:04
  • @gnasher729 At that point, why convert to UTC? Represent the time and its timezone in a standard format like ISO 8601, knowing that any code consuming it will be able to parse that to a neutral representation like a Unix epoch (which is inherently timezoneless, not UTC) if it needs to.
    – IMSoP
    Feb 9 at 14:02
-3

Geez. It's nice that so many people are eager to have their voices heard and want to help out with an answer. What's not so great is how long-winded the responses are while almost side-stepping the answer in some cases.

Here's the succinct answer:

  1. Your front-end code should handle all your locale and culture-related data formatting. There's many JavaScript libraries for this exact reason. Moment.JS is one such library for handling local datetime formatting.

  2. Your backend data should be agnostic meaning it should be as basic, atomic, and generic (non-biased) as possible so that localization may happen easily anywhere. But, more important, data analytics, warehousing, and machine learning (among other platforms) will also be able to use this data more efficiently (than formatted data from an API or DB).

NOTE: Datetime is seeing an overhaul in the JavaScript language to support formatting much easier for locales. Before jumping into moment.js, please refer to MDN for the current state of the JavaScript Date object as well as your browser's console to verify support.

Not the answer you're looking for? Browse other questions tagged or ask your own question.