Localization
The SDK comes with a built-in translation service powered internally by the i18next
library. The main focus of the service is to provide support for:
- Switching the language
- Easy addition of custom translations in any language mutation
- Access to underlying i18n instance from i18next library and thus have access to the library's API
Also, the SDK already provides default translations for the available components.
Integration
The service is made available through the StreamVideo
provider. That means that all the child components of this provider can access the StreamI18nContextValue
object by using the useI18n
context consumer.
The StreamI18nContextValue
carries the following properties:
- the translator function
t
- expects to receive a string to translate and returns its translation or the original value, if no translation for the given key and language could be found. - the
StreamI18n
instance - allows for more control over the service
It is also possible to use StreamI18nProvider
without the StreamVideo
provider. Again, all the child components of this provider can access the StreamI18nContextValue
object by using the useI18n
context consumer.
Configuration
What ends up in the StreamI18nContextValue
depends on what configuration parameters we provide to the StreamI18nProvider
. These are:
type StreamI18nProviderProps = {
i18nInstance?: StreamI18n;
language?: string;
translationsOverrides?: TranslationsMap;
};
StreamVideo
internally forwards these parameters to StreamI18nProvider
.
In the following sections, we will look more into these individual configuration parameters.
Custom translations
In case you would like to add to or change the default translations, you can use the translationsOverrides
prop. This should be an object that will match the type TranslationsMap
.
type TranslationsMap = Record<TranslationLanguage, TranslationSheet>;
type TranslationLanguage = keyof typeof defaultTranslations | string;
type TranslationSheet = typeof defaultTranslations.en | Record<string, string>;
The translations are merged with the SDK's defaults. That means that the defaults are overridden or new keys are added to the translation sheets.
const translations = {
en: {
// ...
terminate: 'terminate',
// ...
},
de: {
// ...
terminate: 'beended',
// ...
},
// ...
};
const App = () => {
// ...
return (
<StreamVideo client={client} translationsOverrides={translations}>
// ...
</StreamVideo>
);
};
Provide your own instance of StreamI18n
You may want to initialize the service somewhere else and pass the instance through the prop i18nInstance
. If an instance of StreamI18n
is provided, it will be forwarded to the context without any changes.
type CreateI18nParams = {
language?: string;
translationsOverrides?: TranslationsMap;
};
const useCreateI18n = ({
language,
translationsOverrides,
}: CreateI18nParams) => {
const i18nRef = useRef(
new StreamI18n({ currentLanguage: language, translationsOverrides }),
);
useEffect(() => {
const i18n = i18nRef.current;
if (i18n.isInitialized && language && i18n?.currentLanguage !== language) {
i18n.changeLanguage(language);
} else if (!i18n.isInitialized) {
// sets the default language
if (!language) i18n.changeLanguage();
i18n.init();
}
}, [language, translationsOverrides]);
return i18n;
};
const App = () => {
const i18n = useCreateI18n();
return (
<StreamVideo client={client} i18nInstance={i18n}>
...
</StreamVideo>
);
};
Language
You can set the current language for the translation service with language
prop. This should be a language code (for example en
, de
etc.) that matches a key in translationsOverrides
or is among the SDK's default language mutations which are specified by the type TranslationLanguage
.
const App = () => {
/* a hook that keeps track of the current language in your app */
const { language, setLanguage } = useLanguage();
// ...
return (
<StreamVideo
client={client}
language={language}
translationsOverrides={translations}
>
{/*...*/}
</StreamVideo>
);
};
Translation function
This is the central feature of the service. The function is passed a string we want to translate and returns its translation. If the translated key is not found, then the returned value is the original string. We rely on the translation function provided by the library i18next
. This function is exposed on StreamI18n
object
StreamI18nContextValue
.Accessing the translation function
You can access the translation function in any child component of StreamVideo
resp. StreamI18nProvider
through the context consumer useI18n
:
import { useI18n } from '@stream-io/video-react-sdk';
const CustomButton = () => {
const { t } = useI18n();
return <button>{t('Submit')}</button>;
};
Final recommendations
As the translation service is based on i18next
which i18n
instance is made available through StreamI18n
, we encourage you to consult the library's documentation in order to learn about:
- the use of the translation function
- how to dynamically insert text with interpolation documentation article
- how to format interpolated value i18next's formatting guide
- how to specify different plural forms with the pluralization guide