@sanvika/lang
v0.8.1
Published
Sanvika ecosystem Lang platform SDK — consumer i18n + server/admin Cloud clients. Indian-12 + Global-60, contentHash-aware runtime cache, segment lazy loading, RTL, voice codes.
Downloads
509
Maintainers
Readme
@sanvika/lang
Version: 0.8.1
Centralized Lang platform SDK for the Sanvika ecosystem. Consumer i18n (Indian-12 / Global-60), contentHash-aware runtime cache, plus additive server/admin Cloud clients.
Rules:docs/sanvika-eco-system/Lang/very-strict-rules.md
Table of Contents
- Kya hai
- Install
- Quick Start (Indian 12)
- Quick Start (Global 60)
- API
- Server Translations
- Platform clients (0.8.0)
- Migration
- Migration from raw i18next setup
Kya hai
Har Sanvika project mein i18n ka same boilerplate (200-700 lines, 192-560+ JSON imports) repeat ho raha tha. Yeh SDK us boilerplate ko single config call mein collapse karta hai. JSON files project mein hi rehti hain (project-owned), engine yahan se aata hai.
Install
pnpm add @sanvika/lang i18next react-i18nextQuick Start (Indian 12)
// src/utils/language/i18n.js
import { createSanvikaI18n, LANGUAGE_PRESETS } from "@sanvika/lang";
import enNavigation from "./translations/segments/en/navigation.json";
import hiNavigation from "./translations/segments/hi/navigation.json";
// ... other core segment imports
import enDashboard from "./translations/segments/en/dashboard.json";
import hiDashboard from "./translations/segments/hi/dashboard.json";
// ... other lazy segment imports
const { i18n, ensureTranslationSegment } = createSanvikaI18n({
languages: LANGUAGE_PRESETS.INDIAN_12,
defaultLanguage: "en",
fallbackLanguage: "en",
storageKey: "language",
coreSegments: {
en: { ...enNavigation /* , ...enUiCommon, ... */ },
hi: { ...hiNavigation /* , ...hiUiCommon, ... */ },
},
lazySegments: {
dashboard: { en: enDashboard, hi: hiDashboard },
},
});
export default i18n;
export { ensureTranslationSegment };Quick Start (Global 60)
import { createSanvikaI18n, LANGUAGE_PRESETS } from "@sanvika/lang";
const { i18n, ensureTranslationSegment } = createSanvikaI18n({
languages: LANGUAGE_PRESETS.GLOBAL_60,
defaultLanguage: "hi",
fallbackLanguage: "en",
coreSegments: { /* ... */ },
lazySegments: { /* ... */ },
});API
createSanvikaI18n(options)
Returns { i18n, ensureTranslationSegment, getCurrentLanguage }.
| Option | Type | Required | Default |
|---|---|---|---|
| languages | Array | yes | — |
| coreSegments | Object | yes | — |
| lazySegments | Object | no | {} |
| defaultLanguage | string | no | "en" |
| fallbackLanguage | string | no | "en" |
| storageKey | string | no | "language" |
| i18nextOptions | Object | no | {} |
<LanguageProvider validLanguages={[...]}>
Wraps your app, exposes useLanguage() hook with { currentLanguage, changeLanguage }. Auto-applies dir="rtl" for Urdu/Arabic.
Voice / Flag helpers
import {
getVoiceLanguageCode, // "hi" → "hi-IN"
getFlagEmoji, // "hi" → "🇮🇳"
getNativeName, // "ta" → "தமிழ்"
isRTLLanguage, // "ur" → true
applyLanguageDirection,
getSupportedLanguages,
} from "@sanvika/lang";normalizeTranslationArray(value)
Coerces JSON list-like values (object → array, single → array, etc.) into proper arrays.
Server Translations
// src/utils/language/getTranslations.js
import { createServerTranslations } from "@sanvika/lang";
import enNavigation from "./translations/segments/en/navigation.json";
import hiNavigation from "./translations/segments/hi/navigation.json";
const { getTranslations, getServerLocale } = createServerTranslations({
segmentDataMap: {
navigation: { en: enNavigation, hi: hiNavigation },
},
validLocales: ["en", "hi", "ta", "te", "kn", "ml", "bn", "mr", "gu", "pa", "or", "ur"],
fallbackLocale: "en",
});
export { getTranslations, getServerLocale };Runtime cache (0.8.1)
createFetcherBackend compares manifest contentHash to the local cache entry before each namespace GET.
| Case | Behaviour |
|---|---|
| Hash identical | Skip network — return cached data |
| Hash different / missing | GET namespace → replace cache { contentHash, data } |
| Network failure | Fall back to last cached data (offline) |
Cache key unchanged: sanvika-lang:{clientId}:{namespace}:{locale} (localStorage by default).
Optional durable storage (React Native):
import AsyncStorage from "@react-native-async-storage/async-storage";
import { createFetcherBackend } from "@sanvika/lang/client";
createFetcherBackend({
apiUrl, clientId, namespaces,
storage: {
getItem: (k) => AsyncStorage.getItem(k),
setItem: (k, v) => AsyncStorage.setItem(k, v),
},
});ETag / If-None-Match: not implemented in the SDK (intentional). Cloud already supports ETag/304; after contentHash skip the hot path does not hit the network. Adding If-None-Match would duplicate the skip decision and add 304→cache handling with little benefit.
Platform clients (0.8.0+)
Additive only. Existing imports are unchanged.
@sanvika/lang/server — LangServerClient (S2S)
import { LangServerClient, createServerTranslations } from "@sanvika/lang/server";
const lang = LangServerClient.fromProcessEnv();
await lang.bulkUpsert({ namespace: "legal", locale: "en", data });
await lang.getManifest();
await lang.getNamespace("navigation", { locale: "hi", fallback: "en" });@sanvika/lang/admin — LangAdminClient (Bearer SuperAdmin JWT)
import { LangAdminClient } from "@sanvika/lang/admin";
const admin = new LangAdminClient({
baseUrl: process.env.LANG_URL,
accessToken: jwt, // from @sanvika/auth
});
await admin.importNamespace(clientId, "legal", { locale: "en", data });
await admin.listClients();@sanvika/lang/client — side-effect-free fetcher
import { createFetcherBackend, clearLocalFetcherCache } from "@sanvika/lang/client";
// Does not auto-init projectI18n (unlike importing @sanvika/lang main entry)Other additive paths
| Path | Exports |
|---|---|
| @sanvika/lang/react | LanguageProvider, useLanguage |
| @sanvika/lang/contracts | LangError, DEFAULT_LANG_URL, ENDPOINTS, validators |
Migration
No migration required.
Upgrade to @sanvika/[email protected]. All existing imports continue to work without code changes. Runtime cache is transparent (same keys; hash compare is additive). Server/admin/client paths from 0.8.0 remain available.
Migration from raw i18next setup
| Before (per project) | After |
|---|---|
| 700-line i18n.js with 192/560+ static imports + manual resources, segmentLoaders, loadedSegments, ensureTranslationSegment | 1 createSanvikaI18n(...) call |
| Hand-written voiceCodeMapper.js per project | Built-in (getVoiceLanguageCode, getFlagEmoji, etc.) |
| Hand-written LanguageProvider/useLanguage per project | Built-in |
| Hand-written getTranslations SSR helper per project | createServerTranslations(...) |
