-
Notifications
You must be signed in to change notification settings - Fork 7.7k
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
\IntlDateFormatter
constructor throws an exception for unknown locales since 8.1.25
#12561
Comments
@devnexen I'd appreciate to hear your thoughts on this |
What can eventually be done is for 8.1/8.2 just returning a failure instead but keeping the exception otherwise. |
Should |
We just hit this issue as well in a test case where we used
So yes IMO setDefault should definitely throw as well to make this more obvious where the failure comes from. And I'd say maybe |
@Seldaek wrote:
I agree. According to https://learn.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?view=msvc-170 it would seem that Perhaps the IntlDateFormatter needs to define fallback logic instead? |
For all PHP version. <?php
$coll = collator_create( 'C' );
$res_val = collator_get_locale( $coll, Locale::VALID_LOCALE );
$res_act = collator_get_locale( $coll, Locale::ACTUAL_LOCALE );
printf( "Valid locale name: %s\nActual locale name: %s\n",
$res_val, $res_act );
?> Expected result:
<?php
Locale::setDefault('');
$a = new IntlDateFormatter('', IntlDateFormatter::FULL, IntlDateFormatter::FULL);
var_dump(Locale::getDefault(), $a->getLocale(ULOC_VALID_LOCALE));
?> Expected result:
Convert native ICU from "C" to "en_US_POSIX" <?php
Locale::canonicalize(Locale::getDefault()); https://github.com/php/php-src/blob/master/ext/intl/locale/locale_methods.c#L798-L805 get_icu_value_src_php function |
If there is a root locale, maybe the |
Fixed by #12568 |
Just to clarify: The fix is to revert the BC break on 8.1/8.2 and postpone it to 8.3? |
Hello! Sorry, but I don't understand very well about the fix and the postpone... Are The next releases of PHP 8.1/8.2 going to return to the previous behaviour (not throwing exception)? |
https://github.com/Icinga/icingaweb2/blob/main/modules/monitoring/application/views/scripts/partials/event-history.phtml#L164 |
Thanks for the reply. This means I need to wait for the devs from icinga to update the modules. |
$dateFormatter = new IntlDateFormatter(setlocale(LC_TIME, 0), IntlDateFormatter::FULL, IntlDateFormatter::NONE); This produce en_US_POSIX. <?php
// setLocale(LC_ALL, 'C');
$var = setlocale(LC_TIME, 0); // Maybe standards POSIX default locale is C
if('C' == $var) {
$var = Locale::canonicalize('C');
}
var_dump($var); // en_US_POSIX
$dateFormatter = new IntlDateFormatter($var, IntlDateFormatter::FULL, IntlDateFormatter::NONE);
var_dump($dateFormatter->getLocale(ULOC_VALID_LOCALE)); // en_US_POSIX
?> Thank @adriangalbincea, I updated the previous message now it indicates error instead of exception. |
This change will be a constant source of confusion and surprises for a lot of people in the years to come :-) |
PHP 8.2.13 and 8.1.26 introduced another error preventing the CI to pass with default POSIX locale. We now have a wrapper to get the locale and replace C with a valid locale. @see php/php-src#12561 Fixes shaarli#2029
icinga-dev here. If I understand this correctly, php accepts <?php
echo "initial locale: ";
$initial = setlocale(LC_TIME, 0);
echo "$initial\n";
echo "setting invalid locale: ";
setlocale(LC_TIME, 'invalid');
echo setlocale(LC_TIME, 0) . "\n";
echo "setting non-existing locale: ";
$nonExisting = 'en_US.UTF-8';
setlocale(LC_TIME, $nonExisting);
echo setlocale(LC_TIME, 0) . "\n";
echo "setting existing locale: ";
$existing = 'de_DE.UTF-8';
setlocale(LC_TIME, $existing);
echo setlocale(LC_TIME, 0) . "\n";
echo "now onto intl...\n";
function intltest($locale) {
echo "how does intl handle $locale?\n";
$dateFormatter = new IntlDateFormatter($locale, IntlDateFormatter::FULL, IntlDateFormatter::NONE);
try {
$dateFormatter->format(0);
echo "well\n";
} catch (Throwable $e) {
echo "not well\n";
}
}
echo "checking the default\n";
intltest($initial);
echo "checking a non-existing but valid locale\n";
intltest($nonExisting);
echo "checking an existing and valid locale\n";
intltest($existing);
echo "checking en_US_POSIX\n";
intltest('en_US_POSIX');
echo "but how does setlocale?\n";
echo (setlocale(LC_TIME, 'en_US_POSIX') ?: "not well") . "\n";
echo "out of curiosity.. what does Locale::canonicalize('C') do?\n";
echo "this: " . Locale::canonicalize('C') . "\n";
But the thing is, why does PHP support something and intl does not? I mean, shouldn't both be interoperable? I can accept that intl supports more than the builtin php functions, given the fact that it's a extension module, but I think it should also accept what php accepts, especially the default So what you recommend is guarding every usage of e.g. $var = setlocale(LC_TIME, 0); // Maybe standards POSIX default locale is C
if('C' == $var) {
$var = Locale::canonicalize('C');
}
$dateFormatter = new IntlDateFormatter($var, IntlDateFormatter::FULL, IntlDateFormatter::NONE); Though, for me, I'm baffled at the moment, to say the least. But please enlighten me about this behavior. I'd willingly accept this with a plausible explanation. |
Use local IDs in ICU format. "Standards posix" C is supported by the locale of your operating system if necessary, if true en_US_POSIX is the ICU locale id format supported. <?php
error_reporting(PHP_INT_MAX);
ini_set("intl.error_level", E_WARNING);
if(setlocale(LC_ALL, 'C')) {
echo 'Set';
} // Return false on Error
$LocaleDefault1 = Locale::getDefault();
$LocaleDefault2 = 'C';
if('C' == $LocaleDefault1) {
$LocaleDefault1 = strtr(Locale::canonicalize('C'), array('C' => 'en_US'));
Locale::setDefault($LocaleDefault1);
if(!$LocaleDefault2) {
$LocaleDefault2 = $LocaleDefault1;
}
}
if('C' == $LocaleDefault2) {
$LocaleDefault2 = strtr(Locale::canonicalize('C'), array('C' => 'en_US'));
}
$LocaleDefault3 = null;
try {
$dateFormatter = new IntlDateFormatter($LocaleDefault2, IntlDateFormatter::FULL, IntlDateFormatter::NONE);
$LocaleDefault3 = $dateFormatter->getLocale(ULOC_VALID_LOCALE);
} catch(IntlException $e) {
}
$b = intl_get_error_code();
var_dump($b, $LocaleDefault3, $LocaleDefault1);
?> It's not valid ICU format locale IDS Locale::setDefault('C');
var_dump(Locale::getDefault()); // C ICU format locale ids
@nilmerg Not using a POSIX operating system? |
Because
ext/intl is a wrapper around ICU, if ICU doesn't support this, then yes you need to do this. I don't know what to say other than |
Okay. I accept the reasoning for this change being about conformity and standardization.
Though, it's quite unfortunate that this change is included in bugfix releases. It broke with 8.1.25 and 8.2.12 and has yet to be fixed as 8.1.26 and 8.2.13 are still affected. That 8.3.0 includes it, is probably fine. Though, the error differs from what has been documented. I suspect this is already being tracked somewhere, (didn't find anything though) so I summed this up for clarity only. Even if just for myself.. |
Tracking in #12943 |
Hi @nilmerg , do you have an eta for the icingaweb fix? History is still broken. Maybe you have a temp patch we can use? |
@adriangalbincea read #12943 (comment) this accept C but not C.UTF-8 |
Hi @hormus thanks for your message. I am a regular use of Icinga Monitoring and to understand, it is something the maintainer has to fix. Am I right? |
@adriangalbincea If you're on php 8.1.x or 8.2.x you'd just have to wait for 8.1.28 or 8.2.14, respectively. (At least, I hope both will include the fix. Please correct me if I'm wrong) |
Hi @nilmerg I am using php 8.2.14 and the issue is still there. Maybe in a future release? |
8.2.15 will include a fix. |
That is good news. Fingers crossed. Thanks for the update. |
@nielsdos This is unfortunate. It broke with 8.1.25, one day before active support ended. In a patch release. Such a thing happens of course, but shouldn't. Please reconsider. |
Yes it is unfortunate. |
Hi, I changed php version to 8.3.1 but the issue is still there. Is there a fix planned with 8.3 too? |
This looks expected: https://www.php.net/manual/en/migration83.other-changes.php#migration83.other-changes.functions.intl |
Would it be possible for you to give a quick try to the future 8.3.2 version ? it is a release candidate, just to test locally. |
Thanks. I just did a workaround as I need the history of events... I replaced |
I would love to help but I am not that advanced to install RC on top of the current one for testing... |
Description
Since PHP 8.1.25 and due to the changes in #12282, the following code throws an
IntlException
:There may be many reasons why the
locale
value is invalid – it might be taken from theLANG
environment variable and be set toC
, it might be parsed from request parameters (the reason behind #12533), or it might be a locale name that is valid on one system but is not in the list of generated/supported locales on another system.While I agree that ideally, all these conditions should be checked and caught beforehand, and I also agree that fixing #12282 without a sensible locale to assume might be difficult, my point is that turning this condition into an exception in a bugfix release is a breaking change that should be reverted.
PHP Version
PHP 8.1.25
Operating System
No response
The text was updated successfully, but these errors were encountered: