PHP NumberFormatter добавляет группировку для 5+-значных чисел?

Я пытаюсь исправить ошибку форматирования в классе PHP NumberFormatter для моего языка, болгарского: группировка тысяч вводится только для чисел, состоящих из 5+ цифр, т. е. «5 000» неверно.

Есть ли предопределенная константа, которую я могу использовать?

Я думал, что это будет NumberFormatter::GROUPING_SIZE, но это не учитывает вышеуказанное правило. Должен ли я искать какой-то другой атрибут или то, что я пытаюсь сделать, невозможно?

Не уверен, что это можно указать с помощью любого из параметров; возможно, вам придется создать свой собственный DecimalFormat шаблон. Если вы проверите объяснение на unicode-org.github.io/icu-docs/apidoc/released/icu4c/…, оно покажет, что шаблон #,##,##0, примененный к значению 123456789, приведет к 12,34,56,789 - поэтому ваш шаблон будет иметь тогда это будет что-то вроде ### #####0.

CBroe 22.03.2024 12:34

@CBroe, спасибо! Возможно, для меня это слишком сложно, но я попробую. Однако я заметил, что в приведенном вами описании примера упоминаются grouping_size и secondary_grouping_size. Могут ли они быть тем, что мне нужно? В документации страницы PHP ничего не упоминается об их значении, что очень бесполезно.

cheeseus 22.03.2024 13:15

Только что провел пару тестов, используя $num->setAttribute(NumberFormatter::GROUPING_SIZE, 4); и $num->setAttribute(NumberFormatter::SECONDARY_GROUPING_SIZE, 3);, но результаты не те, которые мне нужны, например. число 2,806,766 отображается как 280 6766. Я также пробовал переключать значения, но результаты все равно не имеют смысла.

cheeseus 22.03.2024 13:23

Начнем с того, что это просто размеры групп, но они не указывают, какой разделитель ставится между группами. Поскольку вам по сути нужны разные разделители между вашими группами, это не поможет.

CBroe 22.03.2024 13:30

Я понимаю. Ну, я попробовал прочитать про DecimalFormat, но не смог понять, как создать свой собственный узор, поэтому просто оставлю этот вопрос.

cheeseus 22.03.2024 13:35

группировка по тысячам вводится только для чисел, состоящих из 5+ цифр, т.е. "5 000" неверно" - а, так это значит, что для более длинного числа перед последними тремя цифрами будет пробел? 1 234 567 890 тогда было бы правильно? Я думаю, что это невозможно сделать даже с помощью средства форматирования шаблонов - потому что вам придется применить другой шаблон в зависимости от величины числа.

CBroe 22.03.2024 13:42

К сожалению, это будет невозможно с SECONDARY_GROUPING_SIZE, поскольку этот параметр ВО ВСЕХ СЛУЧАЯХ применяется к группам, расположенным дальше первой. $a = new \NumberFormatter("bg-BG", \NumberFormatter::DECIMAL); $a->setAttribute(NumberFormatter::GROUPING_SIZE, 4); $a->setAttribute(NumberFormatter::SECONDARY_GROUPING_SIZE, 3); echo $a->format(10005000) произведет 1 000 5000.

b126 22.03.2024 13:48

@CBroe, верно. Болгарский язык – и я думаю, русский, чешский и т. д. – вводит разделитель тысяч только для чисел, состоящих из 5+ цифр. Итак, 5 000 неправильно, но 1 200 500 правильно. Я надеялся, что в последних версиях (8.x) разработчики PHP обратят внимание на этот факт.

cheeseus 22.03.2024 14:02

Фактическая функциональность, лежащая в основе этого, не реализована самими разработчиками PHP, насколько я знаю, они просто предоставляют «оболочку» PHP, которая передает это в некоторую библиотеку C/C++ - так что это не совсем их дело.

CBroe 22.03.2024 14:14

Ранее вы задавали аналогичный вопрос. Если это действительно отдельные проблемы, это нормально, но если они связаны и могут быть объединены в один единый вопрос, это, вероятно, будет лучше.

Chris Haas 22.03.2024 18:42

@ChrisHaas, это похоже только в той степени, в которой проблема вызвана классом NumberFormatter. Я почти уверен, что если бы я написал о двух отдельных проблемах, требующих отдельного решения, в одной теме, вопрос был бы закрыт.

cheeseus 23.03.2024 17:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
11
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хотя это вряд ли удастся сделать напрямую, вы можете использовать класс-оболочку, который изменяет выходные данные в соответствии с вашими ожиданиями:

class BulgarianNumberFormatter extends \NumberFormatter
{
    public function __construct(
        string|null $locale = 'bg_BG',
        int $style = null,
        string $pattern = null
    ) {
        parent::__construct($locale, $style, $pattern);
    }

    public function format(
        int|float $num,
        int $type = self::TYPE_DEFAULT
    ): string|false {
        $numOfWholeDigits = $num != 0 ? floor(log10($num) + 1) : 1;
        $formatted = parent::format($num, $type);
        if ($numOfWholeDigits < 6) {
            $formatted = str_replace(
                $this->getSymbol(static::GROUPING_SEPARATOR_SYMBOL),
                '',
                $formatted
            );
        }
        return $formatted;
    }
}

Использовать:

require_once('/path/to/BulgarianNumberFormatter.php');
// or
use Namespace\Of\BulgarianNumberFormatter;

$formatter = new BulgarianNumberFormatter(style:\NumberFormatter::DECIMAL);

$formatter->format(5000);       // 5000
$formatter->format(120500);     // 120 500
$formatter->format(10005000);   // 10 005 000
$formatter->format(3210005000); // 3 210 005 000

Обратите внимание: расширение INTL не запускается непосредственно PHP. Это оболочка библиотеки ICU, которая доступна практически в каждой системе и используется для форматирования и перевода — даже в веб-браузерах. Если вы считаете, что это следует изменить в библиотеке ICU, вы можете запросить изменения здесь: https://icu.unicode.org/bugs

Спасибо, я просил внести изменения. Посмотрим, реализовано ли это. Я скоро проверю ваш ответ, но, похоже, он сработает. Ценю!

cheeseus 23.03.2024 17:12

Вот ошибка, которую я получил, когда попытался создать экземпляр этого класса: Fatal error: "static::" is not allowed in compile-time constants in C:\wamp64\www\AsphodelWorks.Projects\inc\numformat.class.php on line 16. Я без понятия что это значит.

cheeseus 23.03.2024 17:22

Я заменил static на self, как рекомендовано здесь: stackoverflow.com/questions/28792904/…, и это сработало. Мне нужно было всего лишь изменить < 6 на < 5. Теперь я попытаюсь выяснить, как изменить GROUPING_SEPARATOR_SYMBOL на неразрывное пространство.

cheeseus 23.03.2024 17:29

Я добавил функцию if ($numOfWholeDigits >= 5) { $this->setSymbol(self::GROUPING_SEPARATOR_SYMBOL, '&#160;'); } to the format`, и она, похоже, работает! Ура!

cheeseus 23.03.2024 17:40

Извиняюсь, я забыл static в этом контексте запрещено. Рад, что вы смогли разобраться и изменить его под свои нужды!

Jim 23.03.2024 19:05

Другие вопросы по теме