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

List formatting #79

Open
vladkolotvin opened this issue Jan 8, 2018 · 7 comments
Open

List formatting #79

vladkolotvin opened this issue Jan 8, 2018 · 7 comments
Labels
FUTURE Ideas and requests to consider after Fluent 1.0 syntax

Comments

@vladkolotvin
Copy link

vladkolotvin commented Jan 8, 2018

Support for list formatting would be extremely useful. I have noticed that you had dropped support for it with reason that it is too complex.

529600f

But complexity can't be a reason to drop it entirely. Now we haven't any alternative.
There is some proposal for list formatting API in ecma402.

https://github.com/tc39/proposal-intl-list-format

It can be an argument to think about reimplementing this functionality.

@vladkolotvin vladkolotvin changed the title Lists formatting List formatting Jan 8, 2018
@stasm
Copy link
Contributor

stasm commented Jan 8, 2018

Thanks for filing this issue!

I removed the list data type because we didn't have clear use-cases for it, it was under-spec'ed and made the JS implementation more complex. The increased complexity stemmed from the fact that the elements of lists should also be valid types in Fluent which made lists monadic in nature.

It's helpful to see interest in bringing it back :) Can you describe your use-case in a little bit more detail?

Some of the recent changes in the implementation of MessageContext (like projectfluent/fluent.js@8c419b1) should make it easier to implement list types at some point in the future. It hasn't been a priority for us for now.

Some open questions remain:

  • Can lists be used as selectors?
  • If so, we probably need to solve Allow selectors to be lists #4 first.
  • If a list is passed in to a Function, should we toString its elements first?
  • Can lists be used as values of named arguments to Functions?

The author of the TC39 proposal you linked is @zbraniecki, Fluent's core contributor :) I'm positive he will be interested in this issue now or when the proposal advances to Stage 3 or 4.

@vladkolotvin
Copy link
Author

vladkolotvin commented Jan 9, 2018

Besides basic example for social networks

"Ann, Peter and other 5 other people liked your photo"

as a game developer I'm stuck with localising complex quests descriptions. Example:

"Collect meat from cows, pigs and sheep."

or

"New dungeons are unlocked on 10, 20 and 30 levels."

It is really hard to maintain such descriptions manually. Parameters are defined in config files or calculated at runtime and can be changed at any moment.

Concerning open questions:
Can lists be used as selectors? - At first glance this isn't a blocker for list formatting feature and can be or not implemented in the future.
If a list is passed in to a Function, should we toString its elements first? - Why not?
Can lists be used as values of named arguments to Functions? - I didn't find named arguments in documentation. Could you give some details?

@stasm
Copy link
Contributor

stasm commented Jan 15, 2018

Thanks for the real-life examples!

In your use-cases, does the number of elements in a list vary? In other words, is it "cows, pigs and sheep" for some users and "cows and pigs" or just "cows" for others? If so, the names of animals would likely come in form of a single external argument, like the following:

# The placeable could also be written as LIST($sources).
quest-desc = Collect meat from { $sources }.

This would require two additions to Fluent:

  1. External arguments (like $sources) would need to accept list-typed data. As I mentioned before, we'd need to specify what happens if someone tries to use an argument like this as a selector. We could start by not supporting list-typed selectors and always choosing the default variant if they're used as selectors none the less.

  2. The values in $sources should be localized. Ideally, we'd have a way to resolve them to other messages in the same MessageContext. I think this is doable without any changes to the Fluent Syntax. I'll open an issue in the fluent.js repo with a proposed solution.

@stasm
Copy link
Contributor

stasm commented Jan 15, 2018

Here's another example from Firefox (source). Thanks to @flodolo for helping me find it.

# %S is the website origin (e.g. www.mozilla.org)
getUserMedia.sharingMenuCamera = %S (camera)
getUserMedia.sharingMenuMicrophone = %S (microphone)
getUserMedia.sharingMenuAudioCapture = %S (tab audio)
getUserMedia.sharingMenuApplication = %S (application)
getUserMedia.sharingMenuScreen = %S (screen)
getUserMedia.sharingMenuWindow = %S (window)
getUserMedia.sharingMenuBrowser = %S (tab)
getUserMedia.sharingMenuCameraMicrophone = %S (camera and microphone)
getUserMedia.sharingMenuCameraMicrophoneApplication = %S (camera, microphone and application)
getUserMedia.sharingMenuCameraMicrophoneScreen = %S (camera, microphone and screen)
getUserMedia.sharingMenuCameraMicrophoneWindow = %S (camera, microphone and window)
getUserMedia.sharingMenuCameraMicrophoneBrowser = %S (camera, microphone and tab)
getUserMedia.sharingMenuCameraAudioCapture = %S (camera and tab audio)
getUserMedia.sharingMenuCameraAudioCaptureApplication = %S (camera, tab audio and application)
getUserMedia.sharingMenuCameraAudioCaptureScreen = %S (camera, tab audio and screen)
getUserMedia.sharingMenuCameraAudioCaptureWindow = %S (camera, tab audio and window)
getUserMedia.sharingMenuCameraAudioCaptureBrowser = %S (camera, tab audio and tab)
getUserMedia.sharingMenuCameraApplication = %S (camera and application)
getUserMedia.sharingMenuCameraScreen = %S (camera and screen)
getUserMedia.sharingMenuCameraWindow = %S (camera and window)
getUserMedia.sharingMenuCameraBrowser = %S (camera and tab)
getUserMedia.sharingMenuMicrophoneApplication = %S (microphone and application)
getUserMedia.sharingMenuMicrophoneScreen = %S (microphone and screen)
getUserMedia.sharingMenuMicrophoneWindow = %S (microphone and window)
getUserMedia.sharingMenuMicrophoneBrowser = %S (microphone and tab)
getUserMedia.sharingMenuAudioCaptureApplication = %S (tab audio and application)
getUserMedia.sharingMenuAudioCaptureScreen = %S (tab audio and screen)
getUserMedia.sharingMenuAudioCaptureWindow = %S (tab audio and window)
getUserMedia.sharingMenuAudioCaptureBrowser = %S (tab audio and tab)

@vladkolotvin
Copy link
Author

vladkolotvin commented Jan 15, 2018

Does the number of elements in a list vary? In other words, is it "cows, pigs and sheep" for some users and "cows and pigs" or just "cows" for others?

By phrase "calculated at runtime" I meant exactly that. Elements themselves and their number can be changed.

I'll open an issue in the fluent.js repo with a proposed solution.

👍

@stasm stasm mentioned this issue Jan 15, 2018
9 tasks
@stasm
Copy link
Contributor

stasm commented Jan 15, 2018

I ended up opening an issue in this repo, since it's more of a Fluent Design question. See #80.

@stasm stasm added this to the Syntax 2.0 milestone Jan 30, 2018
@stasm stasm added the syntax label May 16, 2018
@stasm stasm added the FUTURE Ideas and requests to consider after Fluent 1.0 label May 23, 2018
@stasm stasm removed this from the Syntax FUTURE milestone May 23, 2018
@Manishearth
Copy link

Rust is also finding a need for this. At the moment we pre-format lists using ICU4X, but it gets tricky if you want to sometimes format lists as a, b, c, d, and 5 more, since ideally we'd be able to do something like:

val = list(
{count($mylist) -> {
  [1] $mylist,
  [2] $mylist,
  [3] $mylist
  *[other] concat($mylist, {{count($mylist)} more})
}

})

(pardon my half-remembered fluent syntax)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FUTURE Ideas and requests to consider after Fluent 1.0 syntax
Projects
None yet
Development

No branches or pull requests

3 participants