-
Notifications
You must be signed in to change notification settings - Fork 7.9k
MessageFormatter parse error improvements #6306
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
Conversation
oh crap - you've just cut the PHP-8 branch. If you think this could go into PHP 8.0, I'll rebase and re-target the PR |
Test failure is unrelated and has been marked as XFAIL on master. |
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.
This looks good to me, and I think it should go into PHP 7.4 (unless it's conflict-y). Doesn't change any behavior, just improves diagnostics.
ext/intl/msgformat/msgformat.c
Outdated
smart_str_free( &parse_error_str ); | ||
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( mfo ) ); | ||
|
||
if( msg != NULL ) |
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.
This null check is unnecessary, spprintf always produces a non-NULL string.
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.
I'll add a fixup (and rebase on top of 7.4), but FYI, this code is somewhat "heavily inspired" by
php-src/ext/intl/transliterator/transliterator_methods.c
Lines 171 to 179 in c3365bb
parse_error_str = intl_parse_error_to_string( &parse_error ); | |
spprintf( &msg, 0, "transliterator_create_from_rules: unable to " | |
"create ICU transliterator from rules (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "" ); | |
smart_str_free( &parse_error_str ); | |
if( msg != NULL ) | |
{ | |
intl_errors_set_custom_msg( INTL_DATA_ERROR_P( to ), msg, 1 ); | |
efree( msg ); | |
} |
I'll make a followup PR to get rid of the null check there too 😝
smart_str_free( &parse_error_str ); | ||
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( mfo ) ); | ||
|
||
if( msg != NULL ) |
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.
Again, this check is not needed.
the message patterns can be pretty complex, so reporting a generic U_PARSE_ERROR without any additional information makes it needlessly hard to fix erroneous patterns. This commit makes use of the additional UParseError* parameter to umsg_open to retrieve more details about the parse error to report that to the user via intl_get_error_message()
All possible failures when calling IntlMessage::__construct() would be masked away with a generic "Constructor failed" message. This would include invalid patterns. This commit makes sure that the underlying error that caused the constructor failure is reported as part of the IntlException error message. Additionally, similar to the previous commit, this also uses this improved error reporting facility to also report details on parsing errors while trying to parse the message pattern
2d792ce
to
6aac147
Compare
there will be a few conflicts on PHP-7.4 (mostly due to format string changes in tests). I'll make a second PR targeting 7.4 - then you can pick which one you'd be willing to merge. |
Closing this as I merged #6325. |
Looking into
MessageFormatter
and the underlying ICU pattern documentation, I was blown away by the functionality offered by the patterns thatMessageFormatter
understands. This is incredibly useful and I was totally going to look into making use of this in our main product which already relies onintl
for number and date formatting, but uses a home-grown solution for message localization.However, while playing around with this, I came across a usability-issue around
MessageFormatter::formatMessage()
and especiallyMessageFormatter::__construct()
:As the formatting patterns can be pretty complex, it's likely that they contain parsing errors (especially in my case as I was just getting into this), so it would be helpful to get to details of such parsing errors.
Unfortunately,
MessageFormatter::formatMessage()
viaintl_get_error_message()
would just report a genericU_PATTERN_SYNTAX_ERROR
and, even worse,MessageFormatter:__construct()
would turn any possible internal error into a genericConstructor failed
error message.It doesn't have to be that way though: ICU is capable of reporting additional information about a parser error and indeed, the
intl
extension is already making use of this in other places.So this PR contains two commits that
MessageFormatter::formatMessage()
andintl_get_error_message()
to report the additional parsing error message (see updated tests)MessageFormatter::__construct()
to report the actual error message rather than a generic "Constructor failed"