Build apps with i18n
lib/i18n.ts wires i18next with expo-localization for automatic locale detection and JSON translation files generated per locale. Goodspeed generates i18n as a standard part of every app, so the output is a working codebase from day one, not a scaffold you have to finish yourself.
WHAT GETS GENERATED
Built into every i18n build
Every app Goodspeed generates with i18n includes these production-ready patterns, wired together from the first build.
| Item | Description | Strength |
|---|---|---|
| lib/i18n.ts with expo-localization | getLocales() reads the device's preferred language. The detected language is matched against gasConfig.features.i18n.locales; unrecognized locales fall back to defaultLocale. | Detection |
| locales/ directory with JSON translation files | The DevAgent generates locales/en.json and one file per declared locale. Each file has the same key set so missing translations surface as runtime warnings. | Translations |
| gasConfig.features.i18n feature flag | When gasConfig.features.i18n.enabled is false, i18next is not initialized and t() returns the key string as a passthrough, keeping single-locale apps lightweight. | Feature Flag |
| t() and changeLanguage() exports | lib/i18n.ts re-exports t from i18next and a typed changeLanguage(locale) helper. Components import from lib/i18n rather than i18next directly for consistent error handling. | API |
| Conditional i18n CI workflow | .github/workflows/i18n.yml runs a translation-completeness check on PRs, failing if any declared locale is missing a key present in en.json. | CI |
Source: gas-template repository · Internationalization
REAL GENERATED CODE
A snippet from a i18n app the studio shipped
This pattern comes directly from the gas-template codebase, the foundation every Goodspeed app is generated on. The studio generates i18n code like this for every app in the pipeline, not just a hello-world scaffold.
Locale detection
// lib/i18n.ts: expo-localization locale detection function getDeviceLocale(): string { try { const locales = getLocales(); const deviceLang = locales[0]?.languageCode ?? i18nConfig.defaultLocale; if (i18nConfig.locales.includes(deviceLang)) { return deviceLang; } return i18nConfig.defaultLocale; } catch { return i18nConfig.defaultLocale; } }
GDaily Allergens
Today's log
Gluten
Tree nuts
Shellfish
Dairy
HomeScanLogProfile