i18next#i18n TypeScript Examples

The following examples show how to use i18next#i18n. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: err.tsx    From tobira with Apache License 2.0 6 votes vote down vote up
ErrorDisplay: React.FC<ErrorDisplayProps> = ({ failedAction, ...props }) => {
    const { t, i18n } = useTranslation();
    const info = "info" in props ? props.info : errorDisplayInfo(props.error, i18n);
    const causes = Array.from(info.causes);

    return <>
        <p>
            {failedAction && failedAction + " "}
            {causes.length === 1
                ? causes[0] + " "
                : <ul>{causes.map(cause => <li key={cause}>{cause}</li>)}</ul>
            }
            {info.potentiallyInternetProblem && t("errors.are-you-connected-to-internet")}
        </p>
        {info.probablyOurFault && <p css={{ marginTop: 16, fontSize: 14 }}>
            {t("errors.not-your-fault")}
        </p>}
    </>;
}
Example #2
Source File: index.ts    From tobira with Apache License 2.0 5 votes vote down vote up
useTranslatedConfig = (s: TranslatedString): string => {
    const { i18n } = useTranslation();
    return translatedConfig(s, i18n);
}
Example #3
Source File: index.ts    From tobira with Apache License 2.0 5 votes vote down vote up
translatedConfig = (s: TranslatedString, i18n: i18n): string => {
    const lang = i18n.resolvedLanguage;
    return (lang in s ? s[lang as keyof TranslatedString] : undefined) ?? s.en;
}
Example #4
Source File: renderer.ts    From clearflask with Apache License 2.0 4 votes vote down vote up
export default function render(): Handler {
  return async (req, res, next) => {
    try {
      const staticRouterContext: StaticRouterContext = {};
      const storesState: StoresState = {};
      const port = req.app.settings.port;
      const requestedUrl = `${req.protocol}://${req.hostname}${(!port || port == 80 || port == 443) ? '' : (':' + port)}${req.path}`;
      const awaitPromises: Array<Promise<any>> = [];

      // From i18next-http-middleware
      const i18n = req.i18n as i18n;
      const lng = i18n.language;

      var renderResult: RenderResult | undefined;
      var isFinished = false;
      var renderCounter = 0;
      const renderPromise = new Promise<void>(async (resolve, reject) => {
        try {
          do {
            if (++renderCounter > 10) {
              console.warn(`Render give up after too many passes ${renderCounter} on ${requestedUrl}`);
              resolve();
              return;
            }
            // console.debug(`Rendering ${requestedUrl} pass #${renderCounter} with ${awaitPromises.length} promises`);
            const renderPassResult: RenderResult = {
              title: 'ClearFlask',
              extractor: renderResult?.extractor || new ChunkExtractor({
                statsFile: path.resolve(connectConfig.publicPath, 'loadable-stats.json'),
                entrypoints: ['main'],
                // SSR public path, for CSR see index.tsx
                outputPath: path.resolve(__dirname, '..', '..', 'build'),
                publicPath: (connectConfig.parentDomain !== 'clearflask.com')
                  ? '/' : undefined,
              }),
              muiSheets: new ServerStyleSheets(),
              renderedScreen: '',
            };
            try {
              await Promise.allSettled(awaitPromises);
            } catch (e) { }
            awaitPromises.length = 0;
            if (isFinished) return; // Request timed out

            resetServerContext(); // For react-beautiful-dnd library

            renderPassResult.renderedScreen = renderIndexSsr({
              i18n,
              url: req.url,
              staticRouterContext,
              storesState,
              awaitPromises,
              renderResult: renderPassResult,
              requestedUrl: requestedUrl,
            });

            if (isFinished) return; // Request timed out
            renderResult = renderPassResult;
          } while (awaitPromises.length > 0);
          console.info(`Rendered ${requestedUrl} in ${renderCounter} pass(es)`);
          resolve();
        } catch (e) {
          reject(e);
        }
      });
      const timeoutPromise = new Promise<void>(resolve => setTimeout(() => {
        !isFinished && console.warn(`Render timeout on ${requestedUrl} after ${renderCounter} pass(es)`);
        resolve();
      }, 10000));
      await Promise.race([timeoutPromise, renderPromise]);
      isFinished = true;

      if (!renderResult) {
        // Timeout with no render finished, fallback to client-side rendering
        res.status(500);
        res.sendFile(path.join(__dirname, '..', '..', "build", "index.html"));
        return;
      }

      var html = await indexHtmlPromise;

      if (process.env.ENV !== 'production') {
        html = html.replace(PH_ENV, `<script>window.ENV='${process.env.ENV}'</script>`);
      } else {
        html = html.replace(PH_ENV, '');
      }

      if (connectConfig.parentDomain !== 'clearflask.com') {
        html = html.replace(PH_PARENT_DOMAIN, `<script>window.parentDomain='${connectConfig.parentDomain}'</script>`);
      } else {
        html = html.replace(PH_PARENT_DOMAIN, '');
      }

      // Favicon
      html = html.replace(PH_FAVICON_URL, renderResult.faviconUrl || `${getParentDomainUrl()}/favicon.ico`);

      // Page title
      html = html.replace(PH_PAGE_TITLE, renderResult.title);

      // JS, CSS
      html = html.replace(PH_LINK_TAGS, renderResult.extractor.getLinkTags());
      html = html.replace(PH_STYLE_TAGS, renderResult.extractor.getStyleTags());
      html = html.replace(PH_SCRIPT_TAGS, renderResult.extractor.getScriptTags());
      html = html.replace(PH_MUI_STYLE_TAGS, renderResult.muiSheets.toString());

      // Add rendered html
      html = html.replace(PH_MAIN_SCREEN, renderResult.renderedScreen);

      // Add populated stores
      if (storesState.serverAdminStore !== undefined || storesState.serverStores !== undefined) {
        const storesStateSerializable: StoresStateSerializable = {
          serverAdminStore: storesState.serverAdminStore?.getState(),
          serverStores: {},
        };
        !!storesState.serverStores && Object.entries(storesState.serverStores)
          .forEach(([id, store]) => storesStateSerializable.serverStores![id] = store.getState());
        html = html.replace(PH_STORE_CONTENT, htmlDataCreate('__SSR_STORE_INITIAL_STATE__', storesStateSerializable));
      } else {
        html = html.replace(PH_STORE_CONTENT, '');
      }

      // I18N initial language and in-memory store
      html = html.replace(PH_I18N_INIT_LNG, htmlDataCreate('__SSR_I18N_INIT_LNG__', lng));
      const i18nStore: Resource = { [lng]: {} };
      (lng === 'en' ? ['en'] : ['en', lng]).forEach(l => {
        i18nStore[l] = {};
        i18n.reportNamespaces.getUsedNamespaces().forEach(ns => {
          i18nStore[l][ns] = i18n.services.resourceStore.data[l][ns];
        });
      });
      html = html.replace(PH_I18N_INIT_STORE, htmlDataCreate('__SSR_I18N_INIT_STORE__', i18nStore));

      res.writeHead(staticRouterContext.statusCode || 200, {
        'Content-Type': 'text/html',
        ...(renderResult.maxAge !== undefined && { 'Cache-Control': 'public, max-age=' + renderResult.maxAge }),
        ...(staticRouterContext.url && { Location: staticRouterContext.url }),
      });
      res.end(html);
    } catch (e) {
      console.error('Failed to get page', e);
      res.header('Cache-Control', 'public, max-age=10');
      res.status(500);
      if (process.env.ENV === 'production') {
        // fallback to client-side rendering (still throwing 500)
        // This is not exactly necessary for CloudFront as it is configured to get index.html on http 500
        // It is necessary for custom domains bypassing CloudFront
        res.sendFile(path.join(__dirname, 'public', 'index.html'));
      } else {
        res.end();
      }
    }
  };
}
Example #5
Source File: err.tsx    From tobira with Apache License 2.0 4 votes vote down vote up
errorDisplayInfo = (error: unknown, i18n: i18n): ErrorDisplayInfo => {
    const t = i18n.t.bind(i18n);

    if (error instanceof NetworkError) {
        return {
            causes: new Set([t("errors.network-error")]),
            probablyOurFault: false,
            potentiallyInternetProblem: true,
        };
    } else if (error instanceof ServerError) {
        const cause = error.response.status >= 500 && error.response.status < 600
            ? t("errors.internal-server-error")
            : t("errors.unexpected-server-error");

        return {
            causes: new Set([cause]),
            probablyOurFault: true,
            potentiallyInternetProblem: false,
        };
    } else if (error instanceof NotJson) {
        return {
            causes: new Set([t("errors.unexpected-response")]),
            probablyOurFault: true,
            potentiallyInternetProblem: false,
        };
    } else if (error instanceof APIError) {
        // OK response, but it contained GraphQL errors.
        const kinds = new Set();
        const causes = new Set<string>();
        let notOurFault = true;
        for (const err of error.errors) {
            // Use a message fitting to the exact error key, if it is present.
            const translationKey = err.key ? `api-remote-errors.${err.key}` : null;
            if (translationKey && i18n.exists(translationKey)) {
                causes.add(t(translationKey));
            } else {
                // Otherwise, derive an error message from the error kind. We
                // use a set to make sure we only emit each kind-derived error
                // message once.
                if (kinds.has(err.kind)) {
                    continue;
                }

                kinds.add(err.kind);

                // The error kind should always be here. But since we are in an
                // error handler, and something is already wrong, we are
                // careful and handle this case, too.
                if (!err.kind) {
                    notOurFault = false;
                    causes.add(t("errors.unexpected-server-error"));
                } else {
                    const msg = match(err.kind, {
                        INTERNAL_SERVER_ERROR: () => {
                            notOurFault = false;
                            return t("errors.internal-server-error");
                        },
                        INVALID_INPUT: () => t("errors.invalid-input"),
                        NOT_AUTHORIZED: () => t("errors.not-authorized"),
                    });
                    causes.add(msg);
                }
            }
        }


        if (causes.size === 0) {
            // This should never happen?
            return {
                causes: new Set([t("errors.unexpected-server-error")]),
                probablyOurFault: true,
                potentiallyInternetProblem: false,
            };
        } else {
            return {
                causes,
                probablyOurFault: !notOurFault,
                potentiallyInternetProblem: false,
            };
        }
    } else {
        return {
            causes: new Set([t("errors.unknown")]),
            probablyOurFault: true,
            potentiallyInternetProblem: false,
        };
    }
}
Example #6
Source File: Fallback.tsx    From viewer with MIT License 4 votes vote down vote up
Fallback: <T>(props: FallbackProps<T>) => JSX.Element = ({
  translate = true,
  message,
  className,
  eventTracker: trackEvent,
  eventTitle,
  withHelmet,
  alternateI18n,
}) => {
  const { t } = useTranslation(undefined, { i18n: iTwinErrorI18n });
  const { t: alternateT } = useTranslation(undefined, { i18n: alternateI18n });
  useEffect(() => {
    if ((trackEvent && !eventTitle) || (!trackEvent && eventTitle)) {
      console.warn(
        "itwin-error-handling-react Fallback: Both trackEvent and eventTitle must be provided for tracking to occur, remove both if no tracking is wanted."
      );
    }
  }, [trackEvent, eventTitle]);
  let src = svgGen;
  let alt = "Generic Error SVG";
  let title = "An Error Has Occurred";
  let text = "";

  if (message) {
    if (translate && iTwinErrorI18n.exists(message)) {
      title = t("fallbackTitleGen");
      alt = t("fallbackAltGen");
      text = t(message);

      switch (message) {
        case "error401":
          title = t("fallbackTitle401");
          alt = t("fallbackAlt401");
          src = svg401;
          break;
        case "error403":
        case "ErrorNoEntitlement":
          title = t("fallbackTitle403");
          alt = t("fallbackAlt403");
          src = svg403;
          break;
        case "error404":
          title = t("fallbackTitle404");
          alt = t("fallbackAlt404");
          src = svg404;
          break;
        case "error500":
          title = t("fallbackTitle500");
          alt = t("fallbackAlt500");
          src = svg500;
          break;
        case "error503":
        case "ConnectFailed":
          title = t("fallbackTitle503");
          alt = t("fallbackAlt503");
          src = svg503;
          break;
        case "MaintenanceMode":
          title = t("fallbackTitle503");
          alt = t("fallbackAlt503");
          src = svg503;
          break;
        case "errorUnsupportedBrowser":
          title = t("fallbackTitleUnsupportedBrowser");
          alt = t("fallbackAltUnsupportedBrowser");
          break;
        case "errorLoginFailed":
          title = t("errorLoginFailed");
          text = t("loginValidationFailed");
          break;
        default:
          title = t("fallbackTitleDefault");
          alt = t("fallbackAltDefault");
          src = svg404;
          text = t("errorDefault");
          message = "errorDefault";
          break;
      }
    } else if (translate && alternateI18n?.exists(message)) {
      title = t("fallbackTitleGen");
      alt = t("fallbackAltGen");
      text = alternateT(message);
    } else {
      text = message;
    }
    if (trackEvent && eventTitle) {
      trackEvent(eventTitle, { error: message });
    }
  }

  return (
    <FallbackComponent
      text={text}
      title={title}
      imageSource={src}
      imageAlt={alt}
      className={className}
      withHelmet={withHelmet}
    />
  );
}