【问题标题】:How to map through objects and arrays in translations如何在翻译中映射对象和数组
【发布时间】:2023-08-04 18:55:01
【问题描述】:

我的翻译数据有 2 个 JSON 文件 -> EN 文件和 FR 文件。

我正在使用 react-i18next 以这种方式处理我的翻译,效果很好,但由于我有可重复的组件,我需要映射/循环翻译以获得正确的输出

示例

zh:

export const EN = {
    page1: {
      section1 {
         titles: {
            title1: "title1_name",
            title2: "title2_name",
            title3: "title3_name"
          },
          buttons: {
             button1 : "button1_name",
             button2 : "button2_name",
             button3 : "button3_name",
          }
       }
       section2 { THE SAME AS SECTION 1 }
       section3 { THE SAME AS SECTION 1 }

    page2 { SAME AS PAGE 1 } 

同样的事情也适用于 FR 文件(用法语翻译代替)

如何实现从 section1 和 page1 映射所有例如标题。使用map() 是否正确?

现在我的解决方案是使用{t page1.section1.0.titles.title1},它当然会在任何地方打印相同的标题 - 在本例中为 title1_name

使用电流输出 {t page1.section1.0.titles.title1} :

slider1:title1_name

slider2:title1_name

滑块3:title1_name

滑块4:title1_name 以此类推……

预期输出:

slider1:title1_name,button1_name

滑块2:title2_name,button2_name

slider3:title4_name,button3_name

slider4: title4_name, button4_name

【问题讨论】:

  • 嘿艾略特,你需要EN.page2EN.page1 相同吗?
  • @jburtondev 不,这只是使其更短的示例-解释我的 json 文件结构。我需要打印出 page1 和 section1 中的所有标题 - 你可以看到我正在使用 useTranslation 中的 { t } 所以我现在正在打印它{t page1.section1.0.titles.title1}但这只是到处打印 title1_name
  • 好的,请在您的问题中添加预期的输出对象,然后我就可以添加答案了。
  • 我更新了我的帖子,如果没有意义请告诉我
  • 好的,现在看看。

标签: reactjs typescript next.js react-i18next


【解决方案1】:

这可行,您需要进行翻译,但这使您可以访问每个页面和部分中的标题对象:

    Object.entries(EN).map(([key,object]) => {

      Object.entries(object).map(([token, value]) => {
          console.log(`${token} : ${value}`);
          Object.keys(value).map((key, index) => {
            console.log(value[key]); // titles access here
        });
      });
    });

【讨论】:

  • 感谢您的回答。它确实在我的控制台中打印了我需要的所有内容,虽然是的,但我需要弄清楚语言的事情。
  • 没有问题艾略特。
【解决方案2】:

当你迭代一个对象时,你会想要使用一个函数来从数组中的对象中获取数据。传统上是Object.keys(),但较新版本的Javascript 引入了Object.values()Object.entries(),根据具体情况可能会非常有用。您可以从其键中访问值,例如 myObject[myKey],因此 Object.keys() 可以在任何情况下工作。

您的 JSON 文件的当前结构并不理想,因为 titlesbuttons 具有完全独立的对象,因此您无法确保标题文本与按钮文本的数量相同。我稍后会解决这个问题,但首先这里是您可以使用当前结构的一种方式。

const MySlider = () => {
  const currentlang = ... // get the EN or FR object based on your current language

  // an array of all the title texts
  const titles = Object.values(currentlang.page1.section1.titles);

  // an array of all the button texts
  const buttons = Object.values(currentlang.page1.section1.buttons);

  return (
    <Slider>
      {titles.map((title, i) => ( // map through the titles
        <Slide
          title={title}
          buttonText={buttons[i]} // get the button text with the same index -- how do we know this is valid?
          key={i} // i as a key is not great
        />
      ))}
    </Slider>
  );
};

使用一些虚拟组件,以便您可以渲染它:

const Slider: React.FC = ({ children }) => <div>{children}</div>;

interface SliderProps {
  title: string;
  buttonText: string;
}

const Slide: React.FC<SliderProps> = ({ title, buttonText }) => {
  return (
    <div>
      <h2>{title}</h2>
      <button>{buttonText}</button>
    </div>
  );
};

我建议按幻灯片而不是按titlesbuttons 对标签进行分组。这样可以确保标题和按钮匹配,如果您想自定义顺序,可以通过滑动键轻松访问,并为我们的组件提供独特的 key 属性。

export const EN = {
  page1: {
    section1: {
      slides: {
        sale: {
          title: "title1_name",
          button: "button1_name"
        },
        featured: {
          title: "title2_name",
          button: "button2_name"
        },
        promo: {
          title: "title3_name",
          button: "button3_name"
        },
      }
    }
  }
};
const MySlider = () => {
  const currentlang = ... // get the EN or FR object based on your current language

  // keyed object of slides
  const slides = currentlang.page1.section1.slides;

  return (
    <Slider>
      {Object.entries(slides).map(
        // Object.entries gives us an array with elements key and value
        ([key, value]) => (
          <Slide
            title={value.title}
            buttonText={value.button}
            key={key}
          />
        )
      )}
    </Slider>
  );
};

允许自定义排序的基于键的方法:

const MySlider = () => {
  const currentlang = ... // get the EN or FR object based on your current language

  // keyed object of slides
  const slides = currentlang.page1.section1.slides;

  // helper function renders the slide for a given key
  const renderSlide = (key: keyof typeof slides) => {
    const {title, button} = slides[key];
    return (
      <Slide 
        title={title}
        buttonText={button}
      />
    )
  }

  return (
    <Slider>
      {renderSlide("promo")}
      {renderSlide("sale")}
      {renderSlide("featured")}
    </Slider>
  );
};

【讨论】:

  • 很好的解释,我会尽力跟进。不过,我的翻译来自 i18next useTranslation = 所以我使用的是{t 一些`}`,我应该只创建函数 currentLang 而不是那个?
  • currentLang 只是一个带有语言对象的变量。我正在设置 const currentLang = EN 来玩它。
【解决方案3】:

对象上的 .map 函数没有选项,但您可以使用 Object.keys 选项。:

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

Object.keys(myObject).map(function(key, index) {
  myObject[key] *= 2;
});

console.log(myObject);
// => { 'a': 2, 'b': 4, 'c': 6 }

map function for objects (instead of arrays)

Medium MultiLanguage Website

【讨论】:

  • 但是 myObject 是什么?因为我有 2 个(翻译 EN 和 FR)我需要使用。你能根据我的例子指定它吗?
  • 在讲座和文档中投入一些精力,添加了一篇关于如何使用 i18next 制作多语言网站的中篇文章。
  • 这与此无关,我的翻译工作正常。
  • {Object.values(currentLang.page1.section1.titles).map(title => ())} ?在代码的更高层(外部渲染),您将根据您当前的翻译语言获得 currentLang 对象。
最近更新 更多