Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable scope differs between messages and terms #372

Open
eemeli opened this issue May 4, 2019 · 4 comments
Open

Variable scope differs between messages and terms #372

eemeli opened this issue May 4, 2019 · 4 comments

Comments

@eemeli
Copy link
Member

eemeli commented May 4, 2019

I find it surprising that this happens (playground link):

const bundle = new FluentBundle('en-US', { useIsolating: false })
bundle.addMessages(ftl`
  msg = { $foo ->
    [foo] FOO
   *[other] BAR
  }
  -term = { $foo ->
    [foo] FOO
   *[other] BAR
  }
  test = {msg} {-term}
`)
const test = bundle.getMessage('test')
bundle.format(test, { foo: 'foo' }) // 'FOO BAR'

Essentially, it looks like the argument scope is handled differently by {msg} and {-term} references, with the former getting access to the parent scope, and the latter not. Is this a part of the spec, or a bug in the JS implementation? In either case, it might be better if both of these worked the same way -- preferably as messages currently do.

@Pike
Copy link
Contributor

Pike commented May 5, 2019

This is how it's designed to work. See also https://projectfluent.org/fluent/guide/terms.html.

The reasoning is that the variations of Terms are something internal to the localization, and thus shouldn't be visible to the program, or have to be chosen such that the program doesn't conflict.

We've been pondering extending the valid values for named arguments in projectfluent/fluent/issues/230, but haven't done so yet. Most use cases we came up with smell like "over-programming". By which I mean that software developers try to use one terms for 20 things instead of using 20 terms.

The latter being not accessible to programmatic APIs, which is projectfluent/fluent/issues/80

@eemeli
Copy link
Member Author

eemeli commented May 5, 2019

Okay, I can see now that the docs clearly do spell out this difference. I'd read them earlier, but that detail had not registered. Honestly, it does seem like an unnecessary extra difference between terms and messages.

Here's the specific example where I managed to stumble across this, while working on a JS-to-Fluent compiler:

person = { $gender ->
   [male] He
   [female] She
  *[other] They
}
results = { $count ->
   [0] no results
   [one] 1 result
  *[other] {$count} results
}
resultSummary = {person} found {results}

At the moment, that only works if person and (in particular) results are messages, even if they're only used in resultSummary. The idea with the above construct is to make the resulting FTL file simpler to understand, as I at least find that messages with multiple selectors tend to get difficult to read.

As a flipside of this difference, I didn't realise until now that e.g. {person(gender: "female")} would be invalid, i.e. that a message could not be given additional or different variables.

@Pike
Copy link
Contributor

Pike commented May 14, 2019

For technical-minded people, it's common to think about refactors and coding patterns.

For translators, in our experience, that mindset is far fetched, and they're much better off with a sequence of sentences, with a complex expression around it.

This is also enforced by the common tool paradigms of localization tools, which rarely reflect a file structure in their forms. If you'd, say, search for found on a tool like Pontoon, you'd get resultSummary, but it wouldn't show the person nor the results message.

@eemeli
Copy link
Member Author

eemeli commented May 14, 2019

Mostly I'm trying to consider this from the point of view of a translator, in a situation where they want to add a parameterized term to an FTL file. I'm presuming here that this may be a relatively common way that parameterized terms are expected to be used, as they're explicitly under the control of the localizer. In that situation, the FTL available to the translator may well contain examples of how messages work with variables, as well as examples of how one message may refer to another message, but it might not include any prior parameterized terms.

My claim here is that in that situation, it's needlessly cumbersome for the translator to need to know that a parameterized term doesn't work like a parameterized message, and that they need to pass the parameters as -term(foo: "bar"), and that e.g. foo can't be assigned the value of $var. Furthermore, the way that using just -term allows these parameters to take empty values (and not throw errors) makes it highly possible that such a mistake wouldn't be immediately caught, and that spotting it later in the FTL code would take time.

The change I'm asking for (and I suppose this is the wrong repo for it) is that the default values for variables in terms should be taken from the message scope, rather than be left empty. Separately I think that message variables ought to be usable as parameter values, but for that there's projectfluent/fluent#230.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants