React
The SejHey React library provides a fully integrated solution for managing translations in React applications. It is fully integrated towards the SejHey platform, allowing for seamless translation management and collaboration. It includes a extensive in-context editing support, making it easy for developers and translators to work together.
✨ Features
- React context provider via
SejHeyProvider - Translation hook
useTranslate - Component-based translation with
<T /> - In-context editing support (Even in production)
- Static or CDN-based file loading
- Lazy language loading
- Custom loader component support
- SSR Support for Next.js
🚀 Installation
npm install @sejhey/react-i18n
🧩 Usage
1. Wrap your app in the SejHeyProvider
Minimal setup with CDN Loader and In Context Editor.
import { SejheyI18n, SejHeyProvider } from '@sejhey/react-i18n'
/* Create the i18n instance */
const i18n = new SejheyI18n({ defaultLanguage: 'en', projectId: 'zbzz-xqjv' })
.useCdnLoader() //Fetch translations from SejHey CDN, always up to date.
.useInContextEditor() //This enables in-context editing by adding ?in_context=true
.useLanguagePicker() //Place a language picker on your site automatically
/* Wrap you app with <SejHeyProvider> */
export default function MyApp() {
return (
<SejHeyProvider i18n={i18n}>
<AnotherComponent />
</SejHeyProvider>
)
}
/* Now use translations like this */
const AnotherComponent = () => {
const { t } = useTranslate()
return (
<>
<h1>{t('welcome_message')}</h1>
{/* Or if you prefer a component */}
<T keyName='welcome_message' />
</>
)
}
You can also use static files as a backup or alternative to the CDN
const en = () => import('../locales/en.json')
const fr = () => import('../locales/fr.json')
const i18n = new SejheyI18n({ defaultLanguage: 'en', projectId: 'zbsz-xqjv' })
.useCdnLoader() //Fetch translations from SejHey CDN, always up to date.
.useStaticLoader({ files: { en: en, fr: fr } }) //Treated as fallback if CdnLoader would fail
.useInContextEditor() //This enables in-context editing by adding ?in_context=true
.useLanguagePicker() //Place a language picker on your site automatically
2. Pluralization and parameters
SejHey supports pluralization and parameters both for useTranslate and the <T /> component.
import { useTranslate } from 'sejhey-i18n'
export function Welcome() {
const { t } = useTranslate()
return (
<>
{/* Will be outputted as Patrik has one new message */}
{t('welcome_message_plural', { count: 1, name: 'Patrik' })}
{/* Same as above, but with T */}
<T keyName='welcome_message_plural' params={{ count: 1, name: 'Patrik' }} />
{/* Will be outputted as Anders has five new messages */}
{t('welcome_message_plural', { count: 5, name: 'Anders' })}
{/* Same as above, but with T */}
<T keyName='welcome_message_plural' params={{ count: 5, name: 'Anders' }} />
</>
)
}
3. Next.js and SSR Support
SejHey provides full support for server-side rendering (SSR) in Next.js applications. This enables translations to be fetched and cached on your server during the initial render. This means that users will see the correct translations immediately, without any flickering or loading states.
SejHey also caches translations locally on your server for concurrent request. This is implemented using a SWR (Stale While Revalidate) approach. This means that translations updates are propagated within a few seconds to your application without compromising any caching performance.
import { SejheyI18n, SejHeyProvider,getSejHeyInitialProps } from '@sejhey/react-i18n'
const i18n = new SejheyI18n({
defaultLanguage: "en",
projectId: 'zbsz-xqjv',
}).useCdnLoader({envName:'production'});
/* Wrap your NextJs app like this, usually in _app.tsx */
export default function MyApp({ Component, pageProps, serialized }: { Component: any, pageProps: any, serialized?: any }) {
return (
<SejHeyProvider i18n={i18n} serialized={serialized}>
<Component {...pageProps} />
</SejHeyProvider>
);
}
/* Enables that SSR works correctly, all translations are fetched and cached on your backend */
MyApp.getInitialProps = async (appContext: (import('next/app').AppContext)) => getSejHeyInitialProps(appContext, i18n);
4. Changing language
You can change language easily by using the hook useTranslate. It can be done like this
const MyComponent= () => {
const { t, changeLanguage,availableLanguages,currentLanguage } = useTranslate();
return(
<div onClick={()=>changeLanguage('fr')}>
Change to french
</div>
)
}
📦 CDN Loader
The CDN Loader allows you to fetch translations from the SejHey CDN dynamically. This ensures that your translations are always up to date without requiring a full redeploy of your application. Translations from the CDN is hosted using Cloudflare edge servers. This means that they always are delivered with low latency and high availability.
You can set which Environment that the application should point towards. This enables you to have different environments for development, staging, and production. This is set by using the envName option in the CDN loader. Note
const i18n = new SejheyI18n({ defaultLanguage: "en",projectId: 'zbsz-xqjv'})
.useCdnLoader({envName:'staging'}) // Specific environment. Defined in SejHey dashboard.
To create a new environment, follow this instruction from within the SejHey dashboard. Note that the format must be i18n-JSON.
✏️ In-Context Editor
You easily enable in the in-context editor by adding the .useInContextEditor() in the configuration. This enables in-context editing by adding ?in_context=true to the URL. The in-context editor allow translations to be edited on the web-page directly.
Note: When In-Context is enabled, the translators must still authenticate themselves towards SejHey and translations can only be edited if the user has the appropriate permissions.
You can customize the query parameter to enable in-context by providing your own parameter name:
.useInContextEditor({ enableByQueryParam: 'my_custom_param' })
This would enable in_context by adding ?my_custom_param=true to the URL.
Creating keys
If the logged in user has the appropriate permissions, they can create new translation keys directly from the in-context editor. This allows for a more streamlined workflow, as translators can add missing keys on the fly without needing to switch back to the main application.
Language detection
By default, language detection is enabled in this plugin. The default order is defined as. "querystring","nextjs", "cookie", "localStorage", "path", "subdomain", "htmlTag", "navigator". This can be customized or disabled, see langageDetectionSettings in the API documentation for reference.
🗂 Static Translations File Format
If you provide static translation files, they must follow flat JSON-i18n format, e.g.:
{
"welcome_message": "Welcome to SejHey!",
//If params are present
"greeting_message": "Hello, {{name}}!",
//If plural use suffix _one, _other etc, and the variable {{count}}
"welcome_message_plural_one": "You have one message",
"welcome_message_plural_other": "You have {{count}} messages"
}
If you are exporting files from SejHey, this option format is called i18n JSON.
📘 API Reference: SejheyI18n
new SejheyI18n(config)
Creates a new SejHey i18n instance.
Parameters:
config: DefaultConfigdefaultLanguage(string, required): The initial language to use (e.g.,"en").projectId(string, required): Your SejHey project ID (found in your SejHey project under Settings & More ->Settings).langageDetectionSettings(LanguageDetectorConfig, optional):detectionOrder?: DetectorAlternative[]— Detection order:"querystring","nextjs","cookie","localStorage","path","subdomain","htmlTag","navigator". You can customize which ways the plugin uses to detect the current language of their choice.queryParamName?: string— Name of query parameter to detect language if querystring is used. Defaults to locale. Eg?locale=de.disable?: boolean— Disable detection entirely.
fallbackSettings(FallbackConfig, optional):show:'key' | 'empty' | 'fallback_language'— What to display if translation is missing.fallbackLanguage?: string— Language to use as fallback.
Chainable Instance Methods
The SejheyI18n instance implements these methods to configure the functionality:
.useCdnLoader(options?: CdnLoaderOptions)
Fetch translations dynamically from SejHey CDN.
options.envName?: string— Environment name (e.g.,"production","staging"). This is defined from the SejHey project underExport & Download -> OTA -> Environments. If not provided, thedefaultenv will be used.
i18n.useCdnLoader({ envName: 'production' });
.useStaticLoader(options: { files: StaticFileLoader })
Define fallback static translations (bundled with your app).
-
files: Object where keys are language codes and values are:- A function returning
Promise<FlatJson>(lazy import) - Or a
Promise<FlatJson>directly.
- A function returning
i18n.useStaticLoader({
files: {
en: () => import('../locales/en.json'),
fr: () => import('../locales/fr.json'),
}
});
.useInContextEditor(options?: InContextEditorSettings)
Enable in-context editing for translators.
Note: By enabling this, you do not increase the bundle size. This part of the bundle is dynamically loaded only when needed.
enableByQueryParam?: string— Query parameter that activates the editor (e.g.,?in_context=true).
i18n.useInContextEditor({ enableByQueryParam: 'in_context' });
.useLanguagePicker(options?: LanguagePickerSettings)
Automatically render a floating language picker on your site.
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'onChangeLanguage?: (lang: string) => voidfixedLocales?: string[]— Restrict available locales.
i18n.useLanguagePicker({ position: 'bottom-right' });
<SejHeyProvider />
React provider to wrap your app.
Props:
i18n(ISejHeyCoreWrapper, required): Instance created vianew SejheyI18n().serialized?: any: Preloaded translations (e.g., from SSR). See more under getSejHeyInitialProps.children: React.ReactNode: Your app components.suspenseComponent?: React.ReactNode: Optional loading fallback (e.g., spinner) that is shown before translations are loaded.
Example:
<SejHeyProvider i18n={i18n}>
<App />
</SejHeyProvider>
useTranslate()
React hook returning translation utilities:
Returns:
t(key: string, params?: OptionsParams, defaultValue?: string, context?: string): string— Translation function.changeLanguage(lang: string): void— Change language dynamically.currentLanguage: string— Active language code.availableLanguages: string[]— All available languages.
Example:
const { t, changeLanguage } = useTranslate();
return <p>{t('welcome_message', { name: 'John' })}</p>;
<T /> Component
JSX component alternative to t() function.
Props:
keyName: string— Translation key.params?: OptionsParams— Dynamic variables{ name: 'John' }.defaultValue?: string— Fallback if missing.
Example:
<T keyName="welcome_message" params={{ name: 'John' }} />
getSejHeyInitialProps(appContext, i18n)
For SSR (Next.js or similar), preloads translations on the server. This is how you can use it using Next.js.
const i18n = ...; //Define the SejHeyi18n object here
export default function MyApp({ Component, pageProps, serialized }: { Component: any, pageProps: any, serialized?: any }) {
return (
<SejHeyProvider i18n={i18n} serialized={serialized}>
<Component {...pageProps} />
</SejHeyProvider>
);
}
MyApp.getInitialProps = async (appContext: (import('next/app').AppContext)) => getSejHeyInitialProps(appContext, i18n);
🔧 Example Usage
import { SejheyI18n, SejHeyProvider, getSejHeyInitialProps } from '../ReactProvider.js';
const en = () => import('../locales/en.json');
const fr = () => import('../locales/fr.json');
const i18n = new SejheyI18n({
defaultLanguage: "en",
projectId: 'zbsz-xqjv',
})
.useCdnLoader({ envName: 'production' })
.useStaticLoader({ files: { en, fr } })
.useInContextEditor()
.useLanguagePicker();
/* If you are using NextJS, this is the recommend way */
export default function MyApp({ Component, pageProps, serialized }: { Component: any, pageProps: any, serialized?: any }) {
return (
<SejHeyProvider i18n={i18n} serialized={serialized}>
<Component {...pageProps} />
</SejHeyProvider>
);
}
/* Enables that SSR works correctly, all translations are fetched and cached on your backend */
MyApp.getInitialProps = async (appContext: (import('next/app').AppContext)) => getSejHeyInitialProps(appContext, i18n);
