Blog

i18next Translations Not Loading? Fix 404s, CORS Issues & Misconfigurations Fast

i18next Translations Not Loading? Fix 404s, CORS Issues & Misconfigurations Fast

May 5, 2025
If your app is showing raw translation keys instead of real text, this guide will walk you through the most common reasons — and how to fix them quickly.

Modern JavaScript applications rely heavily on internationalization (i18n) to reach a global audience. i18next, combined with the i18next‑http‑backend, makes it easy to load translation files over HTTP. Yet, one of the most common developer frustrations is watching their translation keys (like welcome_message) appear instead of the translated text. In this article, you’ll learn:

  1. Why translation files sometimes fail to load
  2. How to diagnose file‑loading errors quickly
  3. What you need to configure — step by step
  4. An alternative backend that sidesteps these issues entirely

Let’s dive in!

Why translation files aren’t loading

No matter how carefully you write your translation JSON, if the browser can’t fetch it, i18next.t() will return the raw key. Here are the top culprits:

loadPath misconfiguration

By default, i18next‑http‑backend tries to fetch /locales/{{lng}}/{{ns}}.json. If your files live under /public/i18n or on a CDN, that path probably won’t exist — resulting in 404s.

Server setup doesn’t serve JSON

Whether you’re on Next.js, Express, or static hosting, you must explicitly serve translation files from the correct directory.

CORS & Cross‑Origin requests

If translation files are hosted on another domain (a CDN or API), missing CORS headers will block the request.

Wrong language or namespace

Requesting a missing namespace or an unsupported language code will also 404.

Diagnosing translation file errors

Before guessing at solutions, inspect the network and enable debug logs:

i18next.init({
  debug: true, // set the debug option to true
  // ...
  backend: { loadPath: '/i18n/{{lng}}/{{ns}}.json' },
  fallbackLng: 'en'
})

Browser DevTools → Network Tab → Filter “.json”: Look for failed requests (status 404, 403, or CORS errors).

Console logs: You’ll see messages like i18next::backendConnector: loading namespace translation for language en failed

Step‑by‑step: Fixing your configuration

1. Put your files in the correct public folder

i.e.

Next.js Place /public/i18n/en/common.json and /public/i18n/de/common.json. Next.js auto‑serves /public.

Express app.use('/i18n', express.static(path.join(__dirname, 'public/i18n')));

Static Hosts (Netlify, Vercel, S3) Ensure your build output includes the i18n directory with JSON files.

2. Configure loadPath to match

// i18n.js
import i18next from 'i18next'
import Backend  from 'i18next-http-backend'
import LanguageDetector from 'i18next-browser-languagedetector'

i18next
  .use(Backend)
  .use(LanguageDetector)
  .init({
    debug: true,
    fallbackLng: 'en',
    ns: ['common', 'errors'],
    defaultNS: 'common',
    backend: {
      loadPath: '/i18n/{{lng}}/{{ns}}.json' // => adapt the loadPath to match the url your translations are served/hosted
    }
  })

3. Handle CORS (if needed)

If you host JSON on cdn.example.com:

backend: {
  loadPath: 'https://cdn.example.com/i18n/{{lng}}/{{ns}}.json'
}
// On cdn server: add response header
// Access-Control-Allow-Origin: *

4. Verify your namespaces & languages

  • JSON files must match both {{lng}} and {{ns}}.
  • example for multiple namespaces on init: i18next.init({ ns: ['common','validation'], defaultNS: 'common' }) or depending on your integration, for example with react-i18next check the useTranslation('my-ns') calls

Alternative: i18next‑locize‑backend

If configuring static files or dealing with CORS feels brittle, consider using our i18next‑locize‑backend. It seamlessly integrates with locize (our translation management service), auto‑handles file loading, versioning, and CDN delivery — so you never worry about 404s or stale JSON again.

// i18n.js with locize backend
import i18next from 'i18next'
import LocizeBackend from 'i18next-locize-backend'
import LanguageDetector from 'i18next-browser-languagedetector'

i18next
  .use(LocizeBackend)
  .use(LanguageDetector)
  .init({
    debug: true,
    ns: ['common','errors'],
    defaultNS: 'common',
    backend: {
      projectId: 'YOUR_LOCIZE_PROJECT_ID'
    }
  })

Benefits:

  • Versioning & CDN: Locize hosts your JSON, delivers it via a fast CDN.
  • No Server Config Required: Simply drop your keys into Locize; your web or mobile app picks them up.
  • Context & In‑Context Editing: Collaborate with translators, manage revisions, and keep your app always in sync.

Check out this demo video or sign up and try the 14 days free trial to learn more about it.

Conclusion

By carefully configuring your loadPath, ensuring your server serves JSON correctly, and handling CORS, you can eliminate the dreaded "raw key" problem in i18next‑http‑backend. And if you prefer a managed approach, give i18next‑locize‑backend a try — it solves all these issues out of the box and adds powerful collaboration features.

Happy translating! 🎉