功能

CDN Delivery: Edge-Cached Translations Worldwide

CDN Delivery: Edge-Cached Translations Worldwide

Every translation you publish in better-i18n is deployed to Cloudflare's global edge network. Your application fetches translations from the nearest edge node — no origin server round-trip, no app redeployment needed for translation updates.


CDN URL Structure

Translations follow a predictable URL pattern built around your organization, project, locale, and namespace:

https://cdn.better-i18n.com/{org}/{project}/{locale}/{namespace}.json

Examples:

# English common namespace
https://cdn.better-i18n.com/acme/web-app/en/common.json

# Turkish auth namespace
https://cdn.better-i18n.com/acme/web-app/tr/auth.json

# French navigation namespace
https://cdn.better-i18n.com/acme/web-app/fr/nav.json

Each namespace-locale combination is a separate JSON file, so your app only loads the translations it needs. This URL structure is stable and cacheable — CDN edge nodes, browser caches, and service workers can all leverage it.

Project Manifest

The CDN also serves a manifest file with your project's language configuration:

https://cdn.better-i18n.com/{org}/{project}/manifest.json

Returns the languages array with every locale in your project. The Expo SDK uses this to auto-discover available languages at runtime.


CDN Operations

better-i18n provides a complete set of CDN management operations through the CLI, REST API, and MCP tools.

Setup and Teardown

OperationDescription
cdn.setupInitialize CDN delivery for your project. Creates the R2 bucket structure and configures edge routing.
cdn.uninstallRemove CDN delivery. Cleans up R2 storage and edge configuration.

Upload Operations

Single Upload (cdn.upload)

Upload a single namespace-locale file to the CDN:

# Upload English common translations
better-i18n cdn upload --locale en --namespace common

This writes the file to R2 and invalidates the edge cache for that specific path. Changes propagate to all 300+ edge nodes within seconds.

Batch Upload (cdn.uploadBatch)

Upload multiple namespace-locale combinations in a single operation:

# Upload all namespaces for English and Turkish
better-i18n cdn upload-batch --locales en,tr --namespaces common,auth,dashboard

Batch upload is significantly faster than individual uploads when publishing multiple files. It batches R2 writes and cache invalidations, reducing total propagation time.

Merge Operations

Merge lets you update specific keys within an existing CDN file without replacing the entire file. This is critical for incremental translation updates.

Merge (cdn.merge)

# Merge updated keys into the English common namespace
better-i18n cdn merge --locale en --namespace common --keys "welcome,nav.home"

Merge reads the existing file from R2, applies the key-level changes, and writes the result back. Keys not included in the merge remain unchanged. This prevents accidental overwrites when multiple team members or automation pipelines publish concurrently.

Merge Preview (cdn.mergePreview)

Preview what a merge operation would produce before executing it:

# Preview the merge result without applying it
better-i18n cdn merge-preview --locale en --namespace common --keys "welcome"

Returns a diff showing added, updated, and unchanged keys. Use this in CI pipelines or review workflows to verify changes before they go live.

File Management

OperationDescription
cdn.listFilesList all files currently deployed to CDN for your project. Returns locale, namespace, size, and last-modified timestamp for each file.
cdn.deleteFileRemove a specific namespace-locale file from CDN. Use when deprecating a namespace or removing a locale.

Duplicate Detection and Cleanup

Translation projects accumulate duplicates over time — especially when namespaces are reorganized or keys are moved between namespaces.

Detect Duplicates (cdn.detectDuplicates)

Scans all CDN files in your project and identifies duplicate translation values across namespaces:

better-i18n cdn detect-duplicates

Returns a report showing which keys share identical values across different namespaces. This helps you consolidate translations into shared namespaces and reduce total CDN payload size.

Cleanup Duplicates (cdn.cleanupDuplicates)

Automatically resolve detected duplicates based on your consolidation preferences:

# Move duplicates to the common namespace
better-i18n cdn cleanup-duplicates --target-namespace common

This is a destructive operation — always run cdn.detectDuplicates first to review what will change, and use cdn.mergePreview to verify the target namespace result.


How Updates Work

  1. Edit translations in the dashboard, via REST API, or through MCP tools
  2. Publish using publishTranslations — this triggers a cdn_upload sync job
  3. CDN updates within seconds — Cloudflare propagates the change to all edge nodes
  4. Your app picks up changes on the next translation fetch — no redeployment needed

For granular control, use cdn.merge instead of full upload to update only the keys that changed. Combine with cdn.mergePreview in your CI pipeline to gate CDN deployments behind a review step.


Framework Integration

Web: Next.js, TanStack Start, Vite

The web SDKs (@better-i18n/next, @better-i18n/use-intl) handle CDN fetching automatically based on your i18n.config.ts:

// i18n.config.ts
export const project = "acme/web-app";
export const defaultLocale = "en";

The SDK resolves the CDN URL from your project identifier and fetches the right namespace-locale files at runtime.

Mobile: Expo / React Native

@better-i18n/expo adds offline-first caching on top of CDN delivery:

import { initBetterI18n, storageAdapter } from '@better-i18n/expo';
import { MMKV } from 'react-native-mmkv';

const mmkv = new MMKV({ id: 'translations' });

await initBetterI18n({
  project: 'acme/mobile-app',
  i18n,
  defaultLocale: 'en',
  storage: storageAdapter(mmkv),
});

Network-first strategy:

  1. Fetch from CDN (get latest translations)
  2. Fall back to persistent cache (MMKV or AsyncStorage)
  3. Fall back to bundled static data (optional)

Once a user opens the app with network connectivity, translations are cached locally. The app works fully offline from that point.

Any HTTP Client

The CDN is a plain HTTPS endpoint — no SDK required:

curl https://cdn.better-i18n.com/acme/web-app/en/common.json
{
  "welcome": "Welcome to our app",
  "nav.home": "Home",
  "nav.settings": "Settings"
}

Use it from any language or platform: Swift, Kotlin, Go, Python, Ruby — anything that can make an HTTP request.


Infrastructure

  • Cloudflare Workers — Edge computing across 300+ locations worldwide
  • Cloudflare R2 — Object storage with zero egress fees for translation files
  • Automatic propagation — Changes reach all edge nodes within seconds
  • DDoS protection — Built into Cloudflare's network
  • TLS 1.3 — All CDN requests are encrypted
  • Zero egress costs — R2 eliminates bandwidth fees regardless of traffic volume

Namespace Organization

Organize translations into namespaces to control what gets loaded:

acme/web-app/
├── en/
│   ├── common.json      → Shared UI strings
│   ├── auth.json        → Login, signup, password reset
│   ├── dashboard.json   → Dashboard-specific strings
│   └── marketing.json   → Landing page copy
├── tr/
│   ├── common.json
│   ├── auth.json
│   └── ...
└── manifest.json        → Project language configuration

Your app loads only the namespaces it needs for the current page or feature. A login page loads auth.json; the dashboard loads dashboard.json. This keeps bundle sizes small and page loads fast.

Use cdn.detectDuplicates periodically to identify keys that appear in multiple namespaces with identical values — then consolidate them into common.json using cdn.cleanupDuplicates.


Publishing Controls

The CDN only serves published translations. Use the publish pipeline to control what goes live:

  1. getPendingChanges — Preview what will deploy to CDN
  2. publishTranslations — Deploy changes (all or specific translations)
  3. cdn.mergePreview — Preview key-level merge results before applying
  4. cdn.merge — Apply incremental key updates without full file replacement
  5. getSyncs / getSync — Track deployment status

This gives you a staged workflow: preview pending changes, verify merge results, publish, and monitor deployment — all without touching application code.


Getting Started

  1. Create your project at dash.better-i18n.com
  2. Initialize CDN with cdn.setup to configure R2 storage and edge routing
  3. Add translations via dashboard, REST API, or MCP tools
  4. Publish to deploy to CDN
  5. Integrate using @better-i18n/next, @better-i18n/use-intl, @better-i18n/expo, or direct HTTP

Translations are served from the CDN on all plans, including the free tier.