Localize backend responses
This page explains how to use translations if your app's content depends on responses from an API.
Preferred: Frontend localization
To keep your app compatible with various languages, the backend should return status codes or identifiers instead of translated strings. The frontend can then use these to display the correct translated messages, using the FormattedMessage component.
In this example, the backend response contains an error code which the frontend maps to a FormattedMessage to render a localized message:
// component.tsximport { ComponentMessages as Messages } from "./component.messages";type GenerateImageResponse =| { status: "SUCCESS"; data: Image }| { status: "ERROR"; errorCode: ErrorCode };type ErrorCode = "INAPPROPRIATE_CONTENT" | "RATE_LIMIT_EXCEEDED"; // Add more error codes as neededasync function generateImageResponse(): Promise<GenerateImageResponse> {// ... call to your backend}export const Component = () => {// ... call generateImageResponse, data fetching logic, state, etc.if (response.status === "ERROR") {return (<Text><FormattedMessage {...getErrorMessage(response.errorCode)} /></Text>);}// ... handle other cases};const getErrorMessage = (errorCode: ErrorCode) => {switch (errorCode) {case "INAPPROPRIATE_CONTENT":return Messages.inappropriateContent;case "RATE_LIMIT_EXCEEDED":return Messages.rateLimitExceeded;default:return Messages.unknownError;}};
// component.messages.tsximport { defineMessages } from "react-intl";export const ComponentMessages = defineMessages({inappropriateContent: {defaultMessage:"The content you submitted has been flagged as inappropriate. Please review and modify your request.",description:"Error message shown in red text below the input field when the user inputs inappropriate content that we don't want to generate images for.",},rateLimitExceeded: {defaultMessage:"You've made too many requests in the last hour. Please try again later.",description:"Error message shown in red text below the input field when the user has made too many image generation requests.",},unknownError: {defaultMessage: "An unknown error occurred. Please try again later.",description:"Error message shown in red text below the input field when the request fails for an unknown reason.",},});
Backend response depends on user locale
This section explains what to do when the backend uses dynamic content that can't be mapped to static frontend messages. For example, when a backend returns locale-specific data.
- The backend should deliver content tailored to the user's locale, along with any extra context or identifiers to guide the frontend on how to present it.
- To help ensure compatibility with localization tools, keep strings and static content on the frontend, where possible.
To inform the backend of the user's locale, we send a query parameter containing intl.locale:
// frontend/app.tsximport type { Video } from "./api";import { findVideos } from "./api";export const App = () => {// ... stateconst intl = useIntl();const onSearch = useCallback(async (query: string) => {const result = await findVideos(query, intl.locale);if (result) {setVideos(result);}// ...},[intl.locale],);return <div>{/* ... components, use onSearch */}</div>;};// frontend/api.tsxexport const findVideos = async (query: string,locale: string,): Promise<Video[]> => {// Best practice: Send locale information to your server as a query param.// Your server can then be modified to return localized content.const params = new URLSearchParams({ query, locale });const url = `${BACKEND_HOST}/videos/find?${params.toString()}`;const res = await fetch(url, { /* ... headers, e.g. Authorization */ });if (res.ok) {return res.json();}// ... error handling};
In the backend, we use the following query parameter to return localized videos:
Your backend must handle all locale values listed in Supported locales.
// backend/routers/videos.tsconst router = express.Router();router.get("/videos/find", async (req, res) => {const { locale } = req.query; // Extract locale value, e.g. "en", "ja-JP", "es-ES" etc.// ... fetch videos for localeres.send({/* localized video response */});});
More information
- Overview of the localization process: Localization overview
- Localization outside React components: Localize outside React components
- How to use the recommended workflow: Recommended workflow