projectfluent / fluent

Fluent — planning, spec and documentation
https://projectfluent.org
Apache License 2.0
1.42k stars 45 forks source link

Referencing to empty messages #236

Open Alserda opened 5 years ago

Alserda commented 5 years ago

Hello,

I'm currently building a template which will be shared across clients so that they can optionally translate an interface on their own. A lot of my id's are dynamically generated on different locations in my (React) application. So for example:

# en-US.ftl

dynamically-generated-id--BicycleBell =
other-generated-id--BicycleBell =
random-other-one--BicycleBell =

For the React side:

<Localized id={`dynamically-generated-id--${variableThatContainsSomeString}`}>
  <span>{variableThatContainsSomeString}</span>
</Localized>

My fallback would print 'BicycleBell' in this case, and that's the expected behaviour that I would want in English so I'd leave that translation blank. But If I would translate this in some other language I would have to format it as the following in my .ftl file.

# nl.ftl

dynamically-generated-id--BicycleBell = Fietsbel
other-generated-id--BicycleBell = Fietsbel
random-other-one--BicycleBell = Fietsbel

In that case it would make more sense to do something as the following to make it easier to translate recurring terms:

# nl.ftl

-bycicleBell = Fietsbel

dynamically-generated-id--BicycleBell = { -bycicleBell }
other-generated-id--BicycleBell = { -bycicleBell }
random-other-one--BicycleBell = { -bycicleBell }

This works fine if the -bycicleBell contains a translation. If I would leave this blank (-bycicleBell =), the output would result in: <span>-bycicleBell</span>. My expected behaviour would be for it to use the fallback, because the referred term is empty. The same way as when id's are empty.

Is this the way it's designed? Or do you have an alternative solution for optionally translating dynamically generated ids?

Pike commented 5 years ago

Let me turn the question around a bit, and talk about localizing your interface.

How are localizers going to know what string to put in for those entries? And which entries they need to create in the first place?

We've designed Fluent to expose an English FTL file to localizers, and that creating a Dutch version of that is what they're asked to do. In what you described, I'm not sure how want that to pan out.

Side note, you might want to have a look at #80, which could be related to what you're trying to do, or maybe not at all? Depends a bit on the dynamic context you have.

stasm commented 5 years ago

Hey @Alserda, thanks for starting the discussion. If I understand correctly, you'd like dynamically-generated-id--BicycleBell = { -bicycleBell } to count as an empty message if -bicycleBell is empty, too?

First, there's #91 which is about allowing empty values as legal syntax. I think part of the behavior that you're seeing right now is due to the fact that dynamically-generated-id--BicycleBell = followed by a newline is not valid syntax right now. As such, it never makes it to the bundle and the fallback mechanism of fluent-react's <Localized> uses the contents of the <span> as a fallback.

Secondly, if I understand the problem statement correctly, I think that's hard to achieve in Fluent. The design of placeables makes them opaque to their surroundings. In dynamically-generated-id--BicycleBell = { -bicycleBell }, there's no inspection of -bicycleBell happening before its value is interpolated. And if it doesn't have any value, Fluent falls back to the identifier as a last resort to give the user something at least remotely useful.

Consider a different example:

dynamically-generated-id--BicycleBell = Hello, { -bicycleBell }

Here, I think it's more clear what's going on: dynamically-generated-id--BicycleBell can never be empty; its value is composed of a TextElement and a Placeable.

In your example, there's only a Placeable, but the principle stays the same: the dynamically-generated-id--BicycleBell message always has a non-empty value.