Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use optional chaining, nullish coalescing and nullish coalescing assignment #1774

Merged
merged 3 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/Trans.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
27 changes: 12 additions & 15 deletions src/TransWithoutContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand All @@ -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 <br/> ipsum {{ messageCount, format }} dolor <strong>bold</strong> amet
childrenArray.forEach((child, childIndex) => {
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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') {
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
8 changes: 3 additions & 5 deletions src/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@ export class ReportNamespaces {

addUsedNamespaces(namespaces) {
namespaces.forEach((ns) => {
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
this.usedNamespaces[ns] ??= true;
});
}

getUsedNamespaces = () => Object.keys(this.usedNamespaces);
}

export const composeInitialProps = (ForComponent) => async (ctx) => {
const componentsInitialProps = ForComponent.getInitialProps
? await ForComponent.getInitialProps(ctx)
: {};
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};

const i18nInitialProps = getInitialProps();

Expand All @@ -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 = {};
Expand Down
2 changes: 1 addition & 1 deletion src/useSSR.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 6 additions & 6 deletions src/useTranslation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
);
Expand All @@ -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 =
Expand Down Expand Up @@ -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));
};
Expand Down
10 changes: 4 additions & 6 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down