# How Supersplat Implements Localization and Multi-Language Support

> Learn how Supersplat implements localization and multi-language support using i18next. Discover how translation bundles are loaded from static files and cached offline.

- Repository: [PlayCanvas/supersplat](https://github.com/playcanvas/supersplat)
- Tags: how-to-guide
- Published: 2026-05-10

---

**Supersplat handles localization and multi-language support through the i18next library, loading JSON translation bundles from static files and caching them offline via a service worker.**

The open-source Gaussian Splat editor **Supersplat** (maintained by **playcanvas/supersplat**) provides a fully internationalized user interface supporting nine languages out of the box. Its approach leverages standard JavaScript internationalization libraries combined with aggressive offline caching to ensure translations remain accessible even without network connectivity.

## i18next Integration and Configuration

The localization architecture centers on **i18next** configured in [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts). This file initializes the internationalization framework, defines supported languages, and exports utility functions for the rest of the application.

### Backend Loading Strategy

Translation resources are loaded dynamically using `i18next-http-backend`. According to the source code in [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts) (lines 14-16), the backend fetches language files from the relative path `./static/locales/{{lng}}.json`. This design keeps translation data separate from application logic, allowing non-developers to modify text without touching TypeScript code.

### Language Detection Hierarchy

The application determines the user's preferred language through `i18next-browser-languagedetector`. As implemented in [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts) (lines 11-12), the detection order follows this priority:

1. URL query string parameters
2. Browser `navigator.language` settings
3. HTML `<html>` tag language attributes

This hierarchy allows users to override their browser settings via URL parameters while maintaining sensible defaults.

## Supported Languages and Fallback Configuration

The `supportedLngs` array explicitly defines nine shipping locales: German (`de`), English (`en`), Spanish (`es`), French (`fr`), Japanese (`ja`), Korean (`ko`), Brazilian Portuguese (`pt-BR`), Russian (`ru`), and Chinese Simplified (`zh`) (see [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts), lines 16-17).

If detection fails or the requested language is unavailable, the system defaults to English via the `fallbackLng: 'en'` configuration. This ensures the interface remains functional regardless of the user's locale.

## Offline Support via Service Worker

Supersplat treats localization as a critical offline asset. The service worker defined in [`src/sw.ts`](https://github.com/playcanvas/supersplat/blob/main/src/sw.ts) pre-caches all language JSON files during the install phase (lines 23-28). By including the `static/locales/` directory in the `cacheUrls` array, the application guarantees that translation data is available even when users lack internet connectivity.

## Utility Functions and API

The [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts) module abstracts i18next complexity behind three primary exports:

- **`localizeInit()`** – Initializes the i18next instance; called once during application startup.
- **`localize(key, options?)`** – Retrieves translated strings by key. Accepts an optional `ellipsis` flag that automatically appends "..." to the output (lines 28-34).
- **`formatInteger(value)`** – Formats numeric values according to the active locale using `Intl.NumberFormat` (lines 40-44).

### Practical Usage Examples

Initialize the localization system when bootstrapping the application:

```typescript
import { localizeInit } from './ui/localization';
localizeInit();

```

Retrieve translated UI strings with optional formatting:

```typescript
import { localize } from './ui/localization';

const title = localize('ui.title');                    // Returns "Super Splat" or translation
const saveButton = localize('ui.save', { ellipsis: true }); // Returns "Save..." in active language

```

Format integers according to locale conventions:

```typescript
import { formatInteger } from './ui/localization';

const formatted = formatInteger(1234567);
// Returns "1 234 567" in French, "1,234,567" in English, etc.

```

## Extending Language Support

Adding a new language requires zero code changes to the TypeScript source. Contributors simply create a new `<lang>.json` file in `static/locales/` following the existing key structure, then append the language code to the `supportedLngs` array in [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts). The service worker automatically includes new locale files in its cache manifest on the next build cycle.

## Summary

- **i18next Foundation**: Supersplat uses `i18next` with HTTP backend and browser language detection configured in [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts).
- **Nine Supported Locales**: German, English, Spanish, French, Japanese, Korean, Brazilian Portuguese, Russian, and Chinese (Simplified), with English as the fallback.
- **Offline-First Caching**: The service worker in [`src/sw.ts`](https://github.com/playcanvas/supersplat/blob/main/src/sw.ts) pre-caches translation JSON files to ensure functionality without network access.
- **Simple API**: Three exported functions—`localizeInit()`, `localize()`, and `formatInteger()`—handle all translation needs.
- **Zero-Code Extensions**: New languages require only JSON file creation and registration in the `supportedLngs` array.

## Frequently Asked Questions

### How does Supersplat detect which language to display?

According to the playcanvas/supersplat source code, the application uses `i18next-browser-languagedetector` to inspect three sources in order: URL query parameters, the browser's `navigator.language` property, and the HTML document's language tag. If none match the supported list, it falls back to English.

### Can Supersplat display translations when offline?

Yes. The service worker defined in [`src/sw.ts`](https://github.com/playcanvas/supersplat/blob/main/src/sw.ts) pre-caches all JSON translation files from `static/locales/` during installation. This ensures that localization and multi-language support remain fully functional even when users have no internet connection.

### How do I add a new language to Supersplat?

Create a new JSON file in `static/locales/` named with the language code (e.g., [`it.json`](https://github.com/playcanvas/supersplat/blob/main/it.json) for Italian), populate it with the translation keys used in other locale files, and add the language code to the `supportedLngs` array in [`src/ui/localization.ts`](https://github.com/playcanvas/supersplat/blob/main/src/ui/localization.ts). The build system automatically includes the new file in the offline cache.

### What is the purpose of the `formatInteger` function?

The `formatInteger` utility in [`localization.ts`](https://github.com/playcanvas/supersplat/blob/main/localization.ts) wraps the browser's `Intl.NumberFormat` API to ensure numbers display according to the active locale's conventions—such as using spaces as thousands separators in French or commas in English—maintaining consistency with the translated interface.