diff --git a/src/Trans.js b/src/Trans.js
index b14cfd599..7f10ebe81 100644
--- a/src/Trans.js
+++ b/src/Trans.js
@@ -23,7 +23,7 @@ export function Trans({
const { i18n: i18nFromContext, defaultNS: defaultNSFromContext } = useContext(I18nContext) || {};
const i18n = i18nFromProps || i18nFromContext || getI18n();
- const t = tFromProps || (i18n && i18n.t.bind(i18n));
+ const t = tFromProps || i18n?.t.bind(i18n);
return TransWithoutContext({
children,
@@ -36,8 +36,7 @@ export function Trans({
defaults,
components,
// prepare having a namespace
- ns:
- ns || (t && t.ns) || defaultNSFromContext || (i18n && i18n.options && i18n.options.defaultNS),
+ ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
i18n,
t: tFromProps,
shouldUnescape,
diff --git a/src/TransWithoutContext.js b/src/TransWithoutContext.js
index a2858aeba..c10b57443 100644
--- a/src/TransWithoutContext.js
+++ b/src/TransWithoutContext.js
@@ -6,15 +6,15 @@ import { getI18n } from './i18nInstance.js';
const hasChildren = (node, checkLength) => {
if (!node) return false;
- const base = node.props ? node.props.children : node.children;
+ const base = node.props?.children ?? node.children;
if (checkLength) return base.length > 0;
return !!base;
};
const getChildren = (node) => {
if (!node) return [];
- const children = node.props ? node.props.children : node.children;
- return node.props && node.props.i18nIsDynamicList ? getAsArray(children) : children;
+ const children = node.props?.children ?? node.children;
+ return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
};
const hasValidReactChildren = (children) =>
@@ -35,10 +35,9 @@ export const nodesToString = (children, i18nOptions) => {
// do not use `React.Children.toArray`, will fail at object children
const childrenArray = getAsArray(children);
- const keepArray =
- i18nOptions.transSupportBasicHtmlNodes && i18nOptions.transKeepBasicHtmlNodesFor
- ? i18nOptions.transKeepBasicHtmlNodesFor
- : [];
+ const keepArray = i18nOptions?.transSupportBasicHtmlNodes
+ ? (i18nOptions.transKeepBasicHtmlNodesFor ?? [])
+ : [];
// e.g. lorem
ipsum {{ messageCount, format }} dolor bold amet
childrenArray.forEach((child, childIndex) => {
@@ -141,7 +140,7 @@ const renderNodes = (children, targetString, i18n, i18nOptions, combinedTOpts, s
// `mappedChildren` will always be empty if using the `i18nIsDynamicList` prop,
// but the children might not necessarily be react components
return (hasValidReactChildren(childs) && mappedChildren.length === 0) ||
- (child.props && child.props.i18nIsDynamicList)
+ child.props?.i18nIsDynamicList
? childs
: mappedChildren;
};
@@ -179,9 +178,7 @@ const renderNodes = (children, targetString, i18n, i18nOptions, combinedTOpts, s
return astNodes.reduce((mem, node, i) => {
const translationContent =
- node.children &&
- node.children[0] &&
- node.children[0].content &&
+ node.children?.[0]?.content &&
i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
if (node.type === 'tag') {
@@ -326,10 +323,10 @@ export function Trans({
const t = tFromProps || i18n.t.bind(i18n) || ((k) => k);
- const reactI18nextOptions = { ...getDefaults(), ...(i18n.options && i18n.options.react) };
+ const reactI18nextOptions = { ...getDefaults(), ...i18n.options?.react };
// prepare having a namespace
- let namespaces = ns || t.ns || (i18n.options && i18n.options.defaultNS);
+ let namespaces = ns || t.ns || i18n.options?.defaultNS;
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
const nodeAsString = nodesToString(children, reactI18nextOptions);
@@ -339,7 +336,7 @@ export function Trans({
const key =
i18nKey ||
(hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
- if (i18n.options && i18n.options.interpolation && i18n.options.interpolation.defaultVariables) {
+ if (i18n.options?.interpolation?.defaultVariables) {
// eslint-disable-next-line no-param-reassign
values =
values && Object.keys(values).length > 0
@@ -393,7 +390,7 @@ export function Trans({
// allows user to pass `null` to `parent`
// and override `defaultTransParent` if is present
- const useAsParent = parent !== undefined ? parent : reactI18nextOptions.defaultTransParent;
+ const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
return useAsParent ? createElement(useAsParent, additionalProps, content) : content;
}
diff --git a/src/context.js b/src/context.js
index 3b00a459f..8434992e0 100644
--- a/src/context.js
+++ b/src/context.js
@@ -14,7 +14,7 @@ export class ReportNamespaces {
addUsedNamespaces(namespaces) {
namespaces.forEach((ns) => {
- if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
+ this.usedNamespaces[ns] ??= true;
});
}
@@ -22,9 +22,7 @@ export class ReportNamespaces {
}
export const composeInitialProps = (ForComponent) => async (ctx) => {
- const componentsInitialProps = ForComponent.getInitialProps
- ? await ForComponent.getInitialProps(ctx)
- : {};
+ const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
const i18nInitialProps = getInitialProps();
@@ -36,7 +34,7 @@ export const composeInitialProps = (ForComponent) => async (ctx) => {
export const getInitialProps = () => {
const i18n = getI18n();
- const namespaces = i18n.reportNamespaces ? i18n.reportNamespaces.getUsedNamespaces() : [];
+ const namespaces = i18n.reportNamespaces?.getUsedNamespaces() ?? [];
const ret = {};
const initialI18nStore = {};
diff --git a/src/useSSR.js b/src/useSSR.js
index b3da6f82f..a1d44a83e 100644
--- a/src/useSSR.js
+++ b/src/useSSR.js
@@ -8,7 +8,7 @@ export const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
// opt out if is a cloned instance, eg. created by i18next-http-middleware on request
// -> do not set initial stuff on server side
- if (i18n.options && i18n.options.isClone) return;
+ if (i18n.options?.isClone) return;
// nextjs / SSR: getting data from next.js or other ssr stack
if (initialI18nStore && !i18n.initializedStoreOnce) {
diff --git a/src/useTranslation.js b/src/useTranslation.js
index e28581dd3..7b9b4426d 100644
--- a/src/useTranslation.js
+++ b/src/useTranslation.js
@@ -49,7 +49,7 @@ export const useTranslation = (ns, props = {}) => {
return retNotReady;
}
- if (i18n.options.react && i18n.options.react.wait !== undefined)
+ if (i18n.options.react?.wait)
warnOnce(
'It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.',
);
@@ -58,11 +58,11 @@ export const useTranslation = (ns, props = {}) => {
const { useSuspense, keyPrefix } = i18nOptions;
// prepare having a namespace
- let namespaces = ns || defaultNSFromContext || (i18n.options && i18n.options.defaultNS);
+ let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
// report namespaces as used
- if (i18n.reportNamespaces.addUsedNamespaces) i18n.reportNamespaces.addUsedNamespaces(namespaces);
+ i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
// are we ready? yes if all namespaces in first language are loaded already (either with data or empty object on failed load)
const ready =
@@ -120,13 +120,13 @@ export const useTranslation = (ns, props = {}) => {
};
// bind events to trigger change, like languageChanged
- if (bindI18n && i18n) i18n.on(bindI18n, boundReset);
- if (bindI18nStore && i18n) i18n.store.on(bindI18nStore, boundReset);
+ if (bindI18n) i18n?.on(bindI18n, boundReset);
+ if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
// unbinding on unmount
return () => {
isMounted.current = false;
- if (bindI18n && i18n) bindI18n.split(' ').forEach((e) => i18n.off(e, boundReset));
+ if (i18n) bindI18n?.split(' ').forEach((e) => i18n.off(e, boundReset));
if (bindI18nStore && i18n)
bindI18nStore.split(' ').forEach((e) => i18n.store.off(e, boundReset));
};
diff --git a/src/utils.js b/src/utils.js
index 8c10aa5e5..26b3155bc 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,5 +1,5 @@
export const warn = (...args) => {
- if (console && console.warn) {
+ if (console?.warn) {
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
console.warn(...args);
}
@@ -54,7 +54,7 @@ export const loadLanguages = (i18n, lng, ns, cb) => {
// WAIT A LITTLE FOR I18NEXT BEING UPDATED IN THE WILD, before removing this old i18next version support
const oldI18nextHasLoadedNamespace = (ns, i18n, options = {}) => {
const lng = i18n.languages[0];
- const fallbackLng = i18n.options ? i18n.options.fallbackLng : false;
+ const fallbackLng = i18n.options?.fallbackLng ?? false;
const lastLng = i18n.languages[i18n.languages.length - 1];
// we're in cimode so this shall pass
@@ -69,8 +69,7 @@ const oldI18nextHasLoadedNamespace = (ns, i18n, options = {}) => {
// so set ready to false while we are changing the language
// and namespace pending (depends on having a backend)
if (
- options.bindI18n &&
- options.bindI18n.indexOf('languageChanging') > -1 &&
+ options.bindI18n?.indexOf('languageChanging') > -1 &&
i18n.services.backendConnector.backend &&
i18n.isLanguageChangingTo &&
!loadNotPending(i18n.isLanguageChangingTo, ns)
@@ -111,8 +110,7 @@ export const hasLoadedNamespace = (ns, i18n, options = {}) => {
lng: options.lng,
precheck: (i18nInstance, loadNotPending) => {
if (
- options.bindI18n &&
- options.bindI18n.indexOf('languageChanging') > -1 &&
+ options.bindI18n?.indexOf('languageChanging') > -1 &&
i18nInstance.services.backendConnector.backend &&
i18nInstance.isLanguageChangingTo &&
!loadNotPending(i18nInstance.isLanguageChangingTo, ns)