Type Safety
koto generates TypeScript type definitions from your translation files, giving you autocompletion and compile-time safety for every translation key.
Why type-safe keys?
Without types, translation key errors are silent runtime bugs:
// Typo -- renders empty string or the raw key in productiont('homePage.hero.subtitel')// ^^^^^ no error, no warningWith koto-generated types, your editor and CI catch this immediately:
// TypeScript error: Property 'subtitel' does not existt('homePage.hero.subtitel')// ^^^^^ TS2339Generating types
-
Enable type generation in your config:
koto.config.ts import { defineConfig } from 'koto'export default defineConfig({sourceLocale: 'en',targetLocales: ['es', 'fr', 'de'],files: ['src/locales/[locale].json'],provider: {name: 'openai',model: 'gpt-4o-mini',},types: {output: 'src/types/i18n.d.ts',framework: 'next-intl',},}) -
Run the types command —
npx koto types -
Include the generated file in your
tsconfig.jsonif needed (most setups pick it up automatically).
Generated output
Given a source locale file like:
{ "common": { "save": "Save", "cancel": "Cancel", "delete": "Delete" }, "homePage": { "hero": { "title": "Welcome to {appName}", "subtitle": "The best way to manage your projects" } }, "auth": { "login": "Log in", "signup": "Sign up", "forgotPassword": "Forgot password?" }}koto generates:
// Auto-generated by koto -- do not edit manually
export interface Messages { common: { save: string cancel: string delete: string } homePage: { hero: { title: string subtitle: string } } auth: { login: string signup: string forgotPassword: string }}Framework integrations
Set framework: 'next-intl'. koto generates a module declaration compatible with next-intl’s useTranslations hook:
types: { output: 'src/types/i18n.d.ts', framework: 'next-intl',}Generated output:
import 'next-intl'
type Messages = { common: { save: string; cancel: string; delete: string } homePage: { hero: { title: string; subtitle: string } } auth: { login: string; signup: string; forgotPassword: string }}
declare module 'next-intl' { interface AppMessages extends Messages {}}Now useTranslations('common') gives you autocompletion for save, cancel, and delete.
Set framework: 'i18next':
types: { output: 'src/@types/i18next.d.ts', framework: 'i18next',}Generated output:
// src/@types/i18next.d.tsimport 'i18next'
declare module 'i18next' { interface CustomTypeOptions { defaultNS: 'translation' resources: { translation: { 'common.save': string 'common.cancel': string 'common.delete': string 'homePage.hero.title': string 'homePage.hero.subtitle': string 'auth.login': string 'auth.signup': string 'auth.forgotPassword': string } } }}Set framework: 'react-intl':
types: { output: 'src/types/intl.d.ts', framework: 'react-intl',}Generated output:
import 'react-intl'
declare module 'react-intl' { interface AppMessageIds { 'common.save': string 'common.cancel': string 'common.delete': string 'homePage.hero.title': string 'homePage.hero.subtitle': string 'auth.login': string 'auth.signup': string 'auth.forgotPassword': string }}Set framework: 'generic' (or omit framework) for a plain interface export:
types: { output: 'src/types/i18n.d.ts', framework: 'generic',}This generates a simple Messages interface you can use however you like.
Watch mode
Regenerate types automatically whenever your source locale files change:
npx koto types --watchPairs well with your dev server for instant feedback on new or renamed keys.
Tips
- Commit the generated type file so all team members and CI have access without running
koto typesfirst. - Add
koto typesto your build script as a pre-build step:{"scripts": {"prebuild": "koto types","build": "next build"}} - Use
koto types --watchalongside your dev server for a seamless workflow.