PHP查找由setlocale设置的字符集



我所有的网站都使用UTF-8作为字符集。但是,当设置setlocale并从strftime获取月份名称和星期名称的本地化字符串时,存在一些问题。

  1. 问题:本地化月份名称在服务器上不起作用。
  2. 问题:如何知道区域设置字符串是否在UTF-8或ISO?

Concrete:我这样设置区域设置:

$locales = ['de_DE.utf-8/utf-8', 'de_DE@euro/utf-8', 'de_DE', 'de-DE', 'german', 'de', 'ge'];
$locale = setlocale(LC_ALL, $locales);

在我的开发系统(Windows 10, XAMPP)上,它找到并设置$locale = 'de-DE'。
在我的服务器(Linux, Apache)上,它查找并设置$locale = 'de_DE'。

因为PHP内置的DateTime类不支持本地化名称,所以我创建了一个类来扩展DateTime类:

class DateTimeExt extends DateTime {
private function isUTF8() : bool {
$locale = setlocale(LC_ALL, null);
if (!$locale) return false;
$locale = strtoupper($locale);
return strpos($locale, 'UTF8') !== false || strpos($locale, 'UTF-8') !== false;
}
public function weekdayName() : string {
$weekday = strftime('%A', $this->getTimestamp());
if (!$weekday) return 'unknown';
return $this->isUTF8() ? $weekday : utf8_encode($weekday);
}
public function monthName() : string {
$month = strftime('%B', $this->getTimestamp());
if (!$month) return 'unknown';
return $this->isUTF8() ? $month : utf8_encode($month);
}
}

使用

进行测试
$date = new DateTimeExt('2021-03-02');
echo $date->weekdayName().'<br />';
echo $date->monthName().'<br />';

在开发环境下的结果:

// Dienstag
// März

都是正确的。如果没有UTF-8编码,它将返回:

// Dienstag
// M�rz

但是在服务器上它的结果是:

// Dienstag
// March

WTF ? ?服务器可以对工作日进行本地化,但不能对月份进行本地化,默认为英文?为什么呢?这是第一期。

问题2是检测设置的区域设置是否支持UTF-8。我的函数isUTF8只是获取当前语言环境并搜索其中的模式'UTF8''UTF-8',如果是,我假设UTF-8,否则我假设ISO和所需的UTF-8编码。我不认为这是最聪明的方法,而且很容易出错。有没有更好的办法?

区域设置依赖于系统。确保您想要的区域设置显示在locale -a中。

使用setLocale()是全局的,可能会产生意想不到的副作用,我建议使用IntlDateFormatter:

$d = new DateTime('2021-03-15');
$mon_formatter = new IntlDateFormatter('de_DE', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$mon_formatter->setPattern('MMMM');
$day_formatter = new IntlDateFormatter('de_DE', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$day_formatter->setPattern('EEEE');
var_dump(
$mon_formatter->format($d),
$day_formatter->format($d)
);

输出
string(5) "März"
string(6) "Montag"

或者,更可能的是,使用您定义的模式格式化整个日期。

最新更新