synacor / preact-i18n

Simple localization for Preact.
BSD 3-Clause "New" or "Revised" License
205 stars 18 forks source link

Can't use <Text/> node as translated string on object #35

Closed acangiani closed 5 years ago

acangiani commented 5 years ago

On the project I'm currently working we needed to support several languages so we ended upusing preact-helmet to inject the title and the corresponding metatags for each of the App views, but I'm unable to make it work with {{fields}} placeholders, so I created this sample project to demonstrate the issue.

How to install and run the sample project

First view

This one works fine and correctly adds the title and the title metatag.

Doing curl http://localhost:3000/, this outputs the following html:

...
<title>Foo - Bar</title>
<meta name="title" content="Foo - Bar" data-preact-helmet="true">
...

Second view

On the other hand on this view I needed to use a {{field}} placeholder, so doing curl http://localhost:3000/test, this outputs the following html:

...
<title>test - Bar</title>
<meta name="title" content="[object Object]" data-preact-helmet="true">
...

Things I tried

  1. Use @withText as decorator on the second view, but I cannot access the props.
  2. Tried to use withText as a functional component wrapper so to obtain the translated text but I couldn't make it work.
  3. Tried to render the component to a string like:
    render(<Text id="second.title" " fields={{ field: props.slug }}>default text</Text>)

    but I only obtained the default text regardless of the i18n definitions loaded on the IntlProvider.

Bottom line what I need it's to obtain the translated text as a string but I'm unable to do so, could you please help with this?

pl12133 commented 5 years ago

@acangiani Thanks for the report. withText is also capable of accepting a function which will receive props, and resolve <Text> components with fields. I gave your App a try and the following changes seemed to make the title render correctly:

@withText((props) => ({
  title: <Text id="second.title" fields={{ field: props.slug }} />
}))
export default class SecondView extends Component {
  render(props, state) {
    return (
      <div>
        <Helmet
          title={props.title}
          meta={[
            {name: "title", content: props.title },
          ]}
        />
      </div>
    );
  }
};

Let me know if that resolves the issue.

acangiani commented 5 years ago

@pl12133 your code resolves the issue!

Thank you for your time and for the quick response!