-
Notifications
You must be signed in to change notification settings - Fork 26
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
Fixed regression with variant expressions involving missing terms #104
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is a regression, sorry.
Looking back into the pre-pre-eval code
python-fluent/fluent.runtime/fluent/runtime/resolver.py
Lines 348 to 361 in 59292d6
@handle.register(VariantExpression) | |
def handle_variant_expression(expression, env): | |
message = lookup_reference(expression.ref, env) | |
if isinstance(message, FluentNone): | |
return message | |
# TODO What to do if message is not a VariantList? | |
# Need test at least. | |
assert isinstance(message.value, VariantList) | |
variant_name = expression.key.name | |
return select_from_variant_list(message.value, | |
env, | |
variant_name) |
there was a explicit not-found handler, and an assert for VariantList
.
In my patch, there was a period where I was heavily confused between FluentNone
and FluentNoneResolver
, and I probably removed that and didn't add it back.
What do you think about
if isinstance(message, FluentNoneResolver):
return message(env)
# ....
assert isinstance(message, ...
Thanks for the check @Pike - I finally realized that we do need to handle the case of neither |
@Pike - did you get chance to look at this? My latest addition addresses your last suggestion I think. Cheers! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the lag, the spec was on PTO. And I needed to talk to the spec about the error here.
So, a term variant reference on a term w/out variants isn't actually an error in general. At least not in the same sense that other runtime errors are. In particular, we should allow for language fallback on runtime errors, but not in this case.
A warning-level thing is in order, though, and chatting with stas, we had the idea to add reporter APIs for errors and warnings to the bundle or the context, which could then act accordingly. But that's probably way out of scope.
What do you think about adding the message to logging.info
instead? It's a bit overboarding right now, given that we're remove Term Variants in Fluent 0.9, but we'll have the same scenario with parameterized terms in 0.8+, where you can do {-term(1,2,not-having:"this")}
. We'll add checks for that to c-l, too, but doesn't hurt to have runtime reporting?
The idea is that applications could observe the logger, and for example fail the test suite if such a term reference is executed.
FYI, you can see the filed and fixed bugs we have on those checks on https://bugzilla.mozilla.org/showdependencytree.cgi?id=1280893&maxdepth=1&hide_resolved=0
I agree that runtime warning/error reporting is helpful, as well as pre-deployment/release checks like compare-locales - runtime reporting can give you an idea of the size of the problem for specific strings under actual usage conditions, so you can prioritize fixes that you decided to ignore at release time. Two questions:
On the other hand, I don't like to report warnings unless those warnings both can and should be fixed (otherwise people drown in warnings and ignore them all). I'm guessing in this case the FTL should be fixed, right? If a message says I imagine there could be unusual cases where normally the translator would specify these variants, so for consistency always does so when using terms in messages, but certain terms are exceptions and therefore never decline according to case (for example) and therefore don't specify variants. This could be fixed by having a dummy select expression i.e. instead of
you'd have to write this to silence the warning:
Does that sound reasonable for exceptional cases?
In other words, whose job is it to use I presume we don't want to gain a Putting error/warning reporting into Maybe for now using |
(I was away last week and I'm catching up with the discussions here.) Thanks for the good comment, @spookylukey. I have a few thoughts on how to handle errors/warnings for missing variables in terms. However, I'd like to prefix them by saying that this issue seems to be specifically about
There are valid scenarios where the term shouldn't be fixed. The use-case for terms is to factor out common translations out of messages so that they are consistent across all of the UI. As a secondary goal, terms can be swapped in and out without having to touch other messages. For instance, the
Yes, that could be a work-around. Or even the following if there are more variables to ignore: -my-term = { "always" ->
[ignore] {$case} {$capitalization} {$some-other-variable}
*[always] My Term
} However, I think this is against the simple things should be simple principle. At a higher level it would also hurt the localization. The alternative terms (in forks of the app, for example) would need to keep track of all possible variables names in the upstream term, and make sure they implement the upstream term's interface, so to speak.
Good point. Again, this highlights the lack of the reference resolver. Thanks for having these conversations with us :) @Pike suggested to me yesterday that perhaps what we really need is a reference test suite for the resolver rather than the actual implementation. I think both could be useful, but I like the idea of focusing on the test suite. It would specify which errors and warnings should be reported, but doesn't have to specify how they are reported. This could be left for the implementation to decide, matching the idioms of the programming language. In functional languages, the errors can be returned in a
I like this solution a lot, especially given that we already have the code which collects and returns the |
@Pike - are you happy with the idea of adding a |
Yeah regarding And sorry for the continuous radio silence here, I paged |
I agree No worries about the silence. I have no pressing need for fast progress with fluent.runtime - I'm now happily using my branches in production, that's fine for now. |
I'm not sure what exact code re-organisation caused this, but it is a regression as far as I can tell.
Interestingly, I caught this when re-basing my compiler branch onto master (with the re-worked resolver implementation). In the compiler branch I added a test purely to handle a corner case in the compiler implementation - the resolver already passed that test and didn't need to be changed. With the changed resolver implementation, that test caught a new corner case. This is an illustration of how the two implementations can help each other (tests added only for one end up catching bugs in the other), and an argument in favour of keeping the two implementations in one code base, so they can share a test suite (@stasm we talked about this).