Examples

React Native

A complete React Native integration with a useSyncExternalStore hook, AsyncStorage caching, and offline bundled fallback seeded via Metro require.

A minimal but complete React Native setup using the AirStrings React Native SDK. One module-level instance, one hook, one component. For every configuration field in detail, see the React Native SDK reference.

Strings used in this example

KeyFormatValue
home.welcome_titletextWelcome!
home.items_counticu{count, plural, one {# item} other {# items}}

Install

npm install @airstrings/react-native @react-native-async-storage/async-storage

Create a module-level instance

One instance per app. It caches verified bundles in AsyncStorage and refreshes when the app returns to the foreground. Seeding a committed bundle serves real strings on a cold offline start.

import { AirStrings } from '@airstrings/react-native'

export const airstrings = new AirStrings({
  organizationId: 'org_...',
  projectId: 'proj_...',
  environmentId: 'env_...',
  publicKeys: ['pk_...'],
  locale: 'en',
  seed: [require('./airstrings/bundles/en.json')],
})

Subscribe with a hook

The SDK exposes data and events, not UI bindings. useSyncExternalStore turns the strings:updated event into React re-renders; on() returns the unsubscribe function React needs.

import { useSyncExternalStore } from 'react'
import { airstrings } from './airstrings'

export function useStrings() {
  return useSyncExternalStore(
    (cb) => airstrings.on('strings:updated', cb),
    () => airstrings.strings,
  )
}

Render

t() returns the raw string (or the key as fallback), format() formats ICU patterns. Calling useStrings() is what re-renders the component when a new bundle lands.

import { View, Text } from 'react-native'
import { airstrings } from './airstrings'
import { useStrings } from './useStrings'

export function Welcome() {
  useStrings()

  return (
    <View>
      <Text>{airstrings.t('home.welcome_title')}</Text>
      <Text>{airstrings.format('home.items_count', { count: 3 })}</Text>
    </View>
  )
}

Offline cold start

Seed committed bundles so the first launch with no cache and no network serves real strings instead of key names. Pull the published bundles, commit them, and pass each locale through the seed option with Metro's require:

airstrings bundles pull
export const airstrings = new AirStrings({
  organizationId: 'org_...',
  projectId: 'proj_...',
  environmentId: 'env_...',
  publicKeys: ['pk_...'],
  locale: 'en',
  seed: [
    require('./airstrings/bundles/en.json'),
    require('./airstrings/bundles/ja.json'),
  ],
})

Every seed candidate runs the full Ed25519 verification pipeline before use. The highest verified revision across cache, seed, and network wins, and a tampered or mismatched seed is rejected and never served. See Offline & fallback for the full model.

On this page