44
55namespace MediaWiki \Skins \Citizen \Components ;
66
7- use IntlException ;
87use MediaWiki \Config \Config ;
98use MediaWiki \Language \Language ;
9+ use MediaWiki \Languages \LanguageNameUtils ;
10+ use MediaWiki \MainConfigNames ;
1011use MediaWiki \SiteStats \SiteStats ;
12+ use Locale ;
1113use MessageLocalizer ;
1214use NumberFormatter ;
15+ use RuntimeException ;
16+ use ValueError ;
1317
1418/**
1519 * CitizenComponentSiteStats component
@@ -24,51 +28,92 @@ class CitizenComponentSiteStats implements CitizenComponent {
2428 'edits ' => 'edit '
2529 ];
2630
31+ private ?NumberFormatter $ fmt = null ;
32+
2733 public function __construct (
2834 private readonly Config $ config ,
2935 private readonly MessageLocalizer $ localizer ,
30- private readonly Language $ lang
36+ private readonly Language $ lang ,
37+ private readonly LanguageNameUtils $ langNameUtils
3138 ) {
3239 }
3340
34- /**
35- * Get and format sitestat value
36- */
37- private function getSiteStatValue ( string $ key , ?NumberFormatter $ fmt ): string {
41+ private function createNumberFormatter ( string $ locale ): ?NumberFormatter {
42+ try {
43+ return new NumberFormatter (
44+ $ locale ,
45+ // PHP 8.4 introduced NumberFormatter::DECIMAL_COMPACT_SHORT
46+ defined ( 'NumberFormatter::DECIMAL_COMPACT_SHORT ' )
47+ ? NumberFormatter::DECIMAL_COMPACT_SHORT
48+ : 14
49+ );
50+ } catch ( ValueError $ exception ) {
51+ // Value Errors are thrown since php8.4 for invalid locales (T376711)
52+ return null ;
53+ }
54+ }
55+
56+ private function getNumberFormatter (): NumberFormatter {
57+ if ( $ this ->fmt ) {
58+ return $ this ->fmt ;
59+ }
60+
61+ $ locale = $ this ->lang ->getCode ();
62+
63+ if ( !(
64+ $ this ->config ->get ( MainConfigNames::TranslateNumerals )
65+ && $ this ->langNameUtils ->isValidCode ( $ locale )
66+ ) ) {
67+ $ locale = Locale::getDefault (); // POSIX system default locale
68+ }
69+
70+ $ fmt = $ this ->createNumberFormatter ( $ locale );
71+
72+ if ( !$ fmt ) {
73+ $ fallbacks = $ this ->lang ->getFallbackLanguages ( $ locale );
74+ foreach ( $ fallbacks as $ fallbackCode ) {
75+ $ fmt = $ this ->createNumberFormatter ( $ fallbackCode );
76+ if ( $ fmt ) {
77+ break ;
78+ }
79+ }
80+ if ( !$ fmt ) {
81+ throw new RuntimeException (
82+ 'Could not instance NumberFormatter for ' . $ locale . ' and all fallbacks '
83+ );
84+ }
85+ }
86+
87+ $ fmt ->setAttribute ( NumberFormatter::ROUNDING_MODE , NumberFormatter::ROUND_DOWN );
88+ $ fmt ->setAttribute ( NumberFormatter::MAX_FRACTION_DIGITS , 1 );
89+
90+ $ this ->fmt = $ fmt ;
91+
92+ return $ this ->fmt ;
93+ }
94+
95+ private function getSiteStatValue ( string $ key ): string {
3896 $ value = SiteStats::$ key ();
3997
4098 if ( !$ value ) {
4199 return '' ;
42100 }
43101
44- return $ fmt ? $ fmt -> format ( $ value ) : number_format ( $ value );
102+ return ( string ) $ this -> getNumberFormatter ()-> format ( $ value );
45103 }
46104
47105 public function getTemplateData (): array {
48- $ config = $ this ->config ;
49- if ( !$ config ->get ( 'CitizenEnableDrawerSiteStats ' ) ) {
106+ if ( !$ this ->config ->get ( 'CitizenEnableDrawerSiteStats ' ) ) {
50107 return [];
51108 }
52109
53110 $ items = [];
54- $ fmt = null ;
55-
56- // Get NumberFormatter here so that we don't have to call it for every stats
57- if ( $ config ->get ( 'CitizenUseNumberFormatter ' ) && class_exists ( NumberFormatter::class ) ) {
58- $ locale = $ this ->lang ->getHtmlCode () ?? 'en_US ' ;
59-
60- try {
61- $ fmt = new NumberFormatter ( $ locale , NumberFormatter::PADDING_POSITION );
62- $ fmt ->setAttribute ( NumberFormatter::ROUNDING_MODE , NumberFormatter::ROUND_DOWN );
63- $ fmt ->setAttribute ( NumberFormatter::MAX_FRACTION_DIGITS , 1 );
64- } catch ( IntlException $ exception ) {}
65- }
66111
67112 foreach ( self ::SITESTATS_ICON_MAP as $ key => $ icon ) {
68113 $ items [] = [
69114 'id ' => $ key ,
70115 'icon ' => $ icon ,
71- 'value ' => $ this ->getSiteStatValue ( $ key, $ fmt ),
116+ 'value ' => $ this ->getSiteStatValue ( $ key ),
72117 'label ' => $ this ->localizer ->msg ( "citizen-sitestats- $ key-label " )->text (),
73118 ];
74119 }
0 commit comments