How Supersplat Implements Localization and Multi-Language Support
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. 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 (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 (lines 11-12), the detection order follows this priority:
- URL query string parameters
- Browser
navigator.languagesettings - 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, 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 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 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 optionalellipsisflag that automatically appends "..." to the output (lines 28-34).formatInteger(value)– Formats numeric values according to the active locale usingIntl.NumberFormat(lines 40-44).
Practical Usage Examples
Initialize the localization system when bootstrapping the application:
import { localizeInit } from './ui/localization';
localizeInit();
Retrieve translated UI strings with optional formatting:
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:
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. The service worker automatically includes new locale files in its cache manifest on the next build cycle.
Summary
- i18next Foundation: Supersplat uses
i18nextwith HTTP backend and browser language detection configured insrc/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.tspre-caches translation JSON files to ensure functionality without network access. - Simple API: Three exported functions—
localizeInit(),localize(), andformatInteger()—handle all translation needs. - Zero-Code Extensions: New languages require only JSON file creation and registration in the
supportedLngsarray.
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 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 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. 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →