如何使用 React Suspense 进行部分翻译(例如使用 Trans 组件)

问题描述 投票:0回答:1

参见https://codesandbox.io/p/devbox/i18n-trans-component-with-suspense-p4jt2t?workspaceId=3104452f-3c7c-4688-a065-c2cdc2657c24

使用 Trans 组件(或替代方案)来实现我的目标以便异步加载翻译句子的一部分的正确方法是什么?

我认为这可能有用:

"use client";

import { Suspense } from "react";
import { Trans } from "react-i18next"; // https://react.i18next.com/latest/trans-component

const mockedFetch = (delay: number) => {
  return new Promise<string>((resolve) => {
    setTimeout(() => {
      const last4DigitsOfCard = "3423";
      resolve(last4DigitsOfCard);
    }, delay);
  });
};

function PersonalizedNumber() {
  // TODO: Delete all the mocking. Replace with real backend calls.
  const delay = 2_000;

  // We are throwing a promise here so that Suspense can catch it and show the loader:
  const sentencePromise = mockedFetch(delay);

  // `Suspense` will handle this as a loading state automatically:
  return sentencePromise;
}

function Loading() {
  return <div>Loading...</div>;
}

function Last4DigitsOfCard() {
  return (
    <Suspense fallback={<Loading />}>
      <PersonalizedNumber />
    </Suspense>
  );
}

export function YourPrepaidCardEndingInLastFour({
  locale,
}: {
  locale: string;
}) {
  return (
    <Trans
      locale={locale}
      i18nKey="yourPrepaidCardIsReady"
      components={{
        last4DigitsOfCard: <Last4DigitsOfCard />,
      }}
    />
  );
}

翻译键:

"yourPrepaidCardIsReady": "Your prepaid card ending in <last4DigitsOfCard/> is active and ready to use."

但我明白:

Unhandled Runtime Error
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
reactjs internationalization i18next react-i18next react-suspense
1个回答
0
投票

这似乎有效。

https://codesandbox.io/p/devbox/i18n-trans-component-with-suspense-forked-l325zh?workspaceId=3104452f-3c7c-4688-a065-c2cdc2657c24

"use client";

import { useEffect, useState } from "react";
import { Trans } from "react-i18next"; // https://react.i18next.com/latest/trans-component

// TODO: Delete all the mocking. Replace with real backend calls.
const delay = 2_000;
const sampleLast4DigitsOfCard = "3423";

const mockedFetch = (delayMs: number) => {
  return new Promise<string>((resolve) => {
    setTimeout(() => {
      resolve(sampleLast4DigitsOfCard);
    }, delayMs);
  });
};

function Loading() {
  return (
    <span style={{ border: "1px solid black", padding: "2px" }}>
      Loading...
    </span>
  );
}

function Last4DigitsOfCardSimple() {
  return sampleLast4DigitsOfCard;
}

function Last4DigitsOfCardAsync() {
  const [value, setValue] = useState<string | null>(null);

  useEffect(() => {
    async function main() {
      const lastFourDigits = await mockedFetch(delay);
      setValue(lastFourDigits);
    }

    main();
  }, []);

  return value ?? <Loading />;
}

export function YourPrepaidCardEndingInLastFour({
  locale,
}: {
  locale: string;
}) {
  return (
    <div>
      <div>
        Async:{" "}
        <Trans
          locale={locale}
          i18nKey="yourPrepaidCardIsReady"
          components={{
            last4DigitsOfCard: <Last4DigitsOfCardAsync />,
          }}
        />
      </div>
      <br />
      <br />
      <div>
        Simple (sync):{" "}
        <Trans
          locale={locale}
          i18nKey="yourPrepaidCardIsReady"
          components={{
            last4DigitsOfCard: <Last4DigitsOfCardSimple />,
          }}
        />
      </div>
    </div>
  );
}

但它使用

useEffect
而不是
Suspense

我很想知道如何使用

Suspense
来做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.